Extended preview system for G'MIC-Qt filters

Hello everyone,
A few words about a new feature planned for the next release 3.1.0 of G’MIC (to be released this week if everything goes well). This is related to how the preview can be computed when defining a filter.

Before :
When defining a filter, it was possible to set the zoom-factor associated to the preview (more often è 0or1`), like this:

#@gui My Filter : my_filter, my_filter_preview(1)
  • If the zoom factor is 1 : The input image passed to the preview command my_filter_preview is a thumbnail of the entire image.
  • If the zoom factor is 0 : The input image passed to the preview command is a 1:1 crop of the entire image.

In both cases, these images were not larger than $_preview_width x $_preview_height.

A new preview mode is now possible, by defining your filter like this:

#@gui My Filter : my_filter, my_filter_preview(1)*

In this case, the image passed to the preview command is always the whole image. It’s the role of the preview command to actually render the part of the image that corresponds to what the user sees in the preview widget.
For that, you have access to several pre-defined variables:

  • $_preview_x0, $_preview_y0, $_preview_x1, $_preview_y1 are the upper-left and bottom-right coordinates of the previewed image, expressed in the coordinate space of the full input image.
  • $_preview_width and $_preview_height is the size of the previewed image.
  • $_preview_area_width and $_preview_area_height is the size of the preview area (can be a bit larger than $_preview_width and $_preview_height.

So, with this new preview mode, a preview command must deal with these variables to return an image with the correct size, e.g.

my_filter_preview : 
  my_filter  # Filter applied to the whole image, to get a pixel-perfect preview
  z $_preview_x0,$_preview_y0,$_preview_x1,$_preview_y1  # Crop to correct location
  r $_preview_width,$_preview_height,1,100% # Resize to correct preview size

Doing this ensures you’ll always get an accurate preview, because the filter is actually computed on the whole image (don’t do this for slow filters though), before being cropped/resized to the correct preview size.
I’ll probably add a few commands, like _preview_crop and preview_resize to make it even easier to use.


A typical example :

#@gui Difference of Gaussians : fx_dog, fx_dog_preview(1)*
#@gui : 1st Variance = float(1.4,0,5)
#@gui : 2nd Variance = float(1.5,0,5)
#@gui : Threshold = float(0,0,49)
#@gui : Negative Colors = bool(0)
#@gui : Monochrome = bool(1)
#@gui : sep = separator()
#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal",
#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right",
#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse")
#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0
#@gui : sep = separator()
#@gui : note = note("<small>Author: <i>David Tschumperlé</i>.      Latest Update: <i>2010/29/12</i>.</small>")
fx_dog :
  dog $1%,$2%
  if $5 norm fi
  c $3%,{100-$3}%
  if $4 negate fi
  n 0,255

fx_dog_preview :
  gui_split_preview "gui_preview_crop fx_dog ${^0} gui_resize_preview",${-3--1}

Now, I can’t wait for G’MIC 3.1. I can fix some few filters here, and some new tools with this change. One tool I could add is a color counting tool.

I have finally used this.

For cropped preview:

One could test the Hitomezashi filter, and then play with the Cropped Viewport. It’s absolutely wonderful how much easier the filter is to use with full-size preview support. There are still issues though, and you can verify that by testing it. I taken into account of scenario of whether the input image dimensions are less or greater than the preview area.


  1. Some borders are not showing up.
  2. Point at 100,100 results shows a obvious issue.

Here’s the relevant snip from the new GUI version of Hitomezashi.

point_x,point_y={[$57,$58]} # This is the point used to change the preview crop for the Hitomezashi filter

if !isnan($point_x)
 crop $x0,$y0,$x1,$y1