Skip to content

Commit

Permalink
Rewrote preview functionality
Browse files Browse the repository at this point in the history
Preview now operates *on the layer* with a backup buffer stored for
'clearing'. This is faster and allows 'persistant' previews via not
flushing during processing.

This is a BREAKING CHANGE, as now bsz_gimp_lib has a simple
"gegl_preview" arg that lets the app know the main function is a
'gegl op', aka works by modifying the current drawable's buffer.

Not quite ready for a new release. Gonna revise Pixel Math and work out
edge cases for the new preview system, as I already expect a few.
  • Loading branch information
Beinsezii committed Dec 29, 2020
1 parent 1a94a7f commit ee79047
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 97 deletions.
11 changes: 0 additions & 11 deletions bsz-dualbloom/bsz-dualbloom.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,6 @@ def dual_bloom(self, drawable, thresh_high, thresh_low,
# }}}


# Preview function. Just runs the same thing on a copy
def dual_bloom_preview(image, drawable, *args):
# {{{
preview_layer = drawable.copy()
image.insert_layer(preview_layer, None, 0)
dual_bloom(image, preview_layer, *args)
return preview_layer
# }}}


# Parameters from bsz_gimp_lib
# {{{
thresh_high = ParamNumber("Threshold High", 0.80, 0, 1,
Expand Down Expand Up @@ -174,7 +164,6 @@ def dual_bloom_preview(image, drawable, *args):
description="Provides light and dark bloom using thresholds. \
Based on my own custom bloom methods.",
images="RGB*, GRAY*",
preview_function=dual_bloom_preview,
)

# register the plugin's Procedure class with gimp
Expand Down
11 changes: 0 additions & 11 deletions bsz-dualbloom2/bsz-dualbloom2.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,6 @@ def dual_bloom_2(image, drawable, amount_high, amount_low,
# }}}


# Preview function. Just runs the same thing on a copy
def dual_bloom_2_preview(image, drawable, *args):
# {{{
preview_layer = drawable.copy()
image.insert_layer(preview_layer, None, 0)
dual_bloom_2(image, preview_layer, *args)
return preview_layer
# }}}


# Parameters from bsz_gimp_lib
# {{{
amount_desc = "Glow-area brightness threshold"
Expand Down Expand Up @@ -162,7 +152,6 @@ def dual_bloom_2_preview(image, drawable, *args):
description="Produces both a light and dark bloom. \
Based on gimp/gegl's existing bloom.",
images="RGB*, GRAY*",
preview_function=dual_bloom_2_preview,
)

# register the plugin's Procedure class with gimp
Expand Down
11 changes: 0 additions & 11 deletions bsz-filmic-chroma/bsz-filmic-chroma.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,6 @@ def filmic_chroma(image, drawable, scale, offset, invert):
# }}}


# Preview function. Just runs the same thing on a copy
def filmic_chroma_preview(image, drawable, *args):
# {{{
preview_layer = drawable.copy()
image.insert_layer(preview_layer, None, 0)
filmic_chroma(image, preview_layer, *args)
return preview_layer
# }}}


# create the plugin from bsz_gimp_lib
plugin = PlugIn(
"Filmic Chroma", # name
Expand All @@ -129,7 +119,6 @@ def filmic_chroma_preview(image, drawable, *args):
description="Reduces/increases chroma based on intensity.\n"
"Inspired by Blender's new 'Filmic' tonemapper.",
images="RGB*",
preview_function=filmic_chroma_preview,
)

# register the plugin's Procedure class with gimp
Expand Down
24 changes: 0 additions & 24 deletions bsz-goat-exercise/bsz-goat-exercise.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,29 +92,6 @@ def goat_exercise_preview(image, drawable, *args):
# }}}


# Parameters from bsz_gimp_lib
# {{{
source_code = "Could not find source code."
with open(os.path.realpath(__file__), mode='r', encoding='UTF-8') as f:
source_code = f.read()

Source_Code_View = ParamString(
"Source Code",
source_code,
description="Source View. Not actually used in-script",
ui_multiline=True,
ui_min_height=900,
ui_min_width=900,
)

Brightness_Controller = ParamNumber(
"Brightness", 0, -1, 1,
description="Adjust the image's brightness after the inversion.",
ui_step=0.1,
)
# }}}


# create the plugin from bsz_gimp_lib
plugin = PlugIn(
"BSZ Goat Exercise", # name
Expand All @@ -126,7 +103,6 @@ def goat_exercise_preview(image, drawable, *args):
description="Exercise a goat BSZ style.",
images="*",
path="<Image>/Filters/Development/Goat exercises/",
preview_function=goat_exercise_preview,
)

# register the plugin's Procedure class with gimp
Expand Down
11 changes: 0 additions & 11 deletions bsz-lightgrain/bsz-lightgrain.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,6 @@ def lightgrain(image, drawable, dulling, noise_l, noise_c, noise_h, invert):
# }}}


# Preview function. Just runs the same thing on a copy
def lightgrain_preview(image, drawable, *args):
# {{{
preview_layer = drawable.copy()
image.insert_layer(preview_layer, None, 0)
lightgrain(image, preview_layer, *args)
return preview_layer
# }}}


# create the plugin from bsz_gimp_lib
plugin = PlugIn(
"Lightgrain", # name
Expand All @@ -129,7 +119,6 @@ def lightgrain_preview(image, drawable, *args):
ParamBool("Invert", False),
description="LCH Noise masked to Lightness.",
images="RGB*, GRAY*",
preview_function=lightgrain_preview,
)

# register the plugin's Procedure class with gimp
Expand Down
11 changes: 0 additions & 11 deletions bsz-pixel-math/bsz-pixel-math.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,6 @@ def pixel_math(image, drawable, babl_format, code,):
# }}}


# Preview function. Just runs the same thing on a copy
def pixel_math_preview(image, drawable, *args):
# {{{
preview_layer = drawable.copy()
image.insert_layer(preview_layer, None, 0)
pixel_math(image, preview_layer, *args)
return preview_layer
# }}}


# create the plugin from bsz_gimp_lib
plugin = PlugIn(
"Pixel Math", # name
Expand All @@ -103,7 +93,6 @@ def pixel_math_preview(image, drawable, *args):
ui_min_width=400),
description="Enter custom Python algorithms for pixel math.",
images="RGB*, GRAY*",
preview_function=pixel_math_preview,
)

# register the plugin's Procedure class with gimp
Expand Down
53 changes: 35 additions & 18 deletions bsz_gimp_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp
# gi.require_version('Gegl', '0.4')
# from gi.repository import Gegl
gi.require_version('Gegl', '0.4')
from gi.repository import Gegl
from gi.repository import GObject
from gi.repository import GLib
# from gi.repository import Gio
Expand Down Expand Up @@ -439,7 +439,7 @@ class PlugIn():
# Get & save properties
def __init__(self, name: str, function: callable, *params: Param,
description: str, alt_description: str = None,
preview_function: callable = None,
gegl_preview: bool = True,
procedure_name: str = None, images: str = "RGB*",
path: str = "<Image>/Beinsezii/", icon=GimpUi.ICON_GEGL,
authors: str = "Beinsezii", copyright: str = None,
Expand Down Expand Up @@ -528,7 +528,7 @@ def do_create_procedure(self2, name2):
self.name = name
self.function = function
self.params = params
self.preview_function = preview_function
self.gegl_preview = gegl_preview
# }}}

# I decided to name the function called by the PDB procedure 'run'
Expand Down Expand Up @@ -584,16 +584,33 @@ def reset_fn(widget):
param.ui_reset()
reset_button = bszgw.Button("Reset", reset_fn)

self.preview_layers = []
Gegl.init(None)
self.buffer = drawable.get_buffer().dup()
self.has_preview = False
self.flush = False

# if any preview layers, delete them and thaw
# TODO: hide base layers when preview is up
def clear_preview(*args):
# {{{
if self.preview_layers:
for layer in self.preview_layers:
image.remove_layer(layer)
self.preview_layers = []
if self.has_preview:
# self.drawable.buffer = self.buffer
intersect, x, y, width, height = drawable.mask_intersect()
if intersect:
Gegl.init(None)
tree = Gegl.Node()
target = drawable.get_buffer()
Input = tree.create_child("gegl:buffer-source")
Input.set_property("buffer", self.buffer)
Output = tree.create_child("gegl:write-buffer")
Output.set_property("buffer", target)
Input.link(Output)
Output.process()
if self.flush:
target.flush()
drawable.update(x, y, width, height)
Gimp.displays_flush()
self.has_preview = False
while not image.undo_is_enabled():
image.undo_thaw()
# }}}
Expand All @@ -602,26 +619,25 @@ def clear_preview(*args):
# self.preview_function and add them to self.preview_layers
def preview_fn(*args):
# {{{
if self.preview_function is not None:
if self.gegl_preview:
clear_preview()
if preview_check.value:
image.undo_freeze()
result = self.preview_function(
image, drawable,
*ui_vals())
if isinstance(result, Gimp.Layer):
self.preview_layers.append(result)
elif isinstance(result, list):
self.preview_layers += result
self.function(image, drawable, *ui_vals())
self.has_preview = True
# }}}

# creates preview_check, starts the live preview thread,
# and has the widgets connect to function
preview_thread = PreviewThread(preview_fn)
preview_thread.start()
if self.preview_function is not None:
if self.gegl_preview:
# {{{
preview_check = bszgw.CheckButton("'Live' Preview", True)

def onclick(*args):
self.flush = not preview_check.value
preview_check.connect("clicked", onclick)
preview_check.connect("clicked", preview_fn)
for param in self.params:
param.connect_preview(preview_thread.request_preview)
Expand Down Expand Up @@ -660,6 +676,7 @@ def preview_fn(*args):
# clear preview on destroy
def destroy_fn(*args):
preview_thread.stop()
self.flush = True
clear_preview()
app.connect("destroy", destroy_fn)

Expand Down

0 comments on commit ee79047

Please sign in to comment.