# [Gimp-developer] Porting GIMP plugins to GEGL operations - GSOC 2011

```Here are the other 3 files . I had to post in two different mails on account
of size exceeding the limit of mail```
```
*Gaussian blur-*
*
*
Functions -

1.iir_young_find_constants (gfloat sigma, gdouble *B, gdouble *b) -
Based on sigma( standard deviation of Gaussian distribution ) we calculate
the constants. If sigma == 0 then to prevent ringing at the tile boundaries
we define *B = 1 and b[0]=1,b[1]=b[2]=b[3]=0 else the value of the constants
depend upon the parameter 'q'.

2. iir_young_blur_1D (gfloat * buf,gint offset, gint delta_offset, gdouble
B, gdouble * b, gfloat *w, gint w_len)-
in the forward filter we increase the offset every time we iterate by an
amount = delta_offset till we reach the end.
In backward filter we begin from the other extreme and every time we
iterate to the left we decrease the offset by an amount = delta_offset
3. iir_young_hor_blur (GeglBuffer *src, const GeglRectangle
*src_rect,GeglBuffer *dst,const GeglRectangle *dst_rect, gdouble B,  gdouble
*b) -
This is for INFINITE IMPULSE RESPONSE.Produces the horizontal blurring in
the image.It expects the source and destination to be of same height and 0 y
offset.

4. iir_young_ver_blur (GeglBuffer *src, const GeglRectangle
*src_rect,GeglBuffer *dst,const GeglRectangle *dst_rect, gdouble B,  gdouble
*b) -
This is for INFINITE IMPULSE RESPONSE.Produces the vertical blurring in the
image.It expects the source and destination to be of same width and 0 x
offset.

5. fir_calc_convolve_matrix_length (gdouble sigma) -
calculates the length of convolution matrix depending upon the standard
deviation.

6. fir_gen_convolve_matrix (gdouble sigma, gdouble **cmatrix_p) -
produces the convolution matrix cmatrix_p which is applied to the original
image to produce gaussian blur.Each pixel's new value is set to a weighted
average of that pixel's neighborhood. The original pixel's value receives
the heaviest weight (having the highest Gaussian value) and neighboring
pixels receive smaller weights as their distance to the original pixel
increases.

7. fir_young_hor_blur (GeglBuffer *src, const GeglRectangle
*src_rect,GeglBuffer *dst,const GeglRectangle *dst_rect, gdouble B,  gdouble
*b) -
Calculates horizontal blur for FINITE IMPULSE RESPONSE.It expects the source
and destination to be of same height and 0 y offset.

8. fir_young_ver_blur (GeglBuffer *src, const GeglRectangle
*src_rect,GeglBuffer *dst,const GeglRectangle *dst_rect, gdouble B,  gdouble
*b) -
Calculates vertical blur for FINITE IMPULSE RESPONSE.It expects the source
and destination to be of same width and 0 x offset.

9.process (GeglOperation *operation, GeglBuffer *input,GeglBuffer *output,
const GeglRectangle *result)-

GeglOperationAreaFilter base class allows defining operations where output
data depends upon a neighbourhood with an input window that extends beyond
the output window, the information about needed extra pixels in different
directions should be set up in the prepare callback for the operation.Based
on 'iir' or 'fir' it blurifies the image first horizontally and then
vertically with different sets of functions used for both cases.

*Extras -*
*
*
*Cartoon - *
*
*
header file - libgimp/gimp.h makes all basic plugin elements available to
us.

Structures defined-
threshold - relative intensity difference which will result in darkening
pct_black - decides the amount of black color added to the image

Local Variables -
1. cvals - storing default values for the parameters of the structure
CartoonVals.

2. GimpPlugInInfo PLUG_IN_INFO - Contains four pointers to different
functions which are called during plugin execution.
a)init - optional(can have null value) and is called as GIMP starts up. It
can be called if we want to register some procedure conditionally on some
files prescence.
b)quit - also optional( can have null value ) and is called when GIMP is
going to close.
c)query - called when the plugin comes into existence or every time when it
is modified.
d)run - it is the plugin processing function which receives the plugin
name, input parameters, number of return values, pointer to output
parameters.

MAIN() - it is a macro defined for calling the initialisation and calling
appropriate functions that our plugin needs during its life time.

Functions -

1. query() - defines the input arguments
Structure GimpParamDef contains - type, name and description.
It registers the function in the path specified as here under
"<Image>/Filters/Artistic"

2. cartoon_dialog (GimpDrawable *drawable) -
opens a dialog box for the user for specifying the basic input parameters.
This also function holds the basic layout informaion for the dialog box. It
clearly mentions the existence of two scale bars ( mask radius, percent
black ), preview window and ok button. User can change the value of
parameters and have a preview for every changed argument.The widget does not
gets destroyed until the ok button( signal - GTK_RESPONSE_OK ) or cancel
button is pressed and the final parameters are then saved.

3. cartoon(GimpDrawable *drawable,GimpPreview  *preview) -

Every variable of the GimpDrawable struct has a drawable id, width,
height,bytes per pixel,number of tile rows, number of tile columns, normal
tiles and shadow tiles. Here we check if the drawable has an alpha channel
associated with it. Alpha channel can be there with the layer types such as
RGB, GRAYSCALE and it defines the amount of opacity of the layer.
Initialise 7 memory locations val_p1,val_p2,val_m1,val_m2,src,dest1,dest2.
Initialise the pixel region pointed by 'src_rgn', new region being attached
to drawable region,(0,0) as initial coordinates, width as drawable->width,
height as drawable->height.

Now calculate the value of needed constants from the 'Gaussian-blur helper
function' - find_constants.

Start the analysis of image by taking vertical strips into consideration
begining from column 0 till width. gimp_pixel_rgn_get_col(col+x1, y1 ) gets
all pixels in a column from (col+x1,y1) to (col+x1, y1+height-1 ) and fills
the buffer src with it.sp_p1 holds the value for first pixel and sp_m1 holds
the value for the last pixel and with these values and the values calculated
by the find_constants functions we calculate every pixel along a column and
then use the user defined function 'transfer_pixels' to transfer these pixel
to the destination. gimp_progress_update() updates the progress bar for the
current plugin.

Similary we analyse it now by taking horizontal strips begining from row 0
to row height.Initialise 4 memory locations for holding the values, 2 for
the source buffer( src1, src2 ).Initialise the initial pixels i.e the
starting row pixel 0 and width-1 and with the help of the values calculated
from the gaussian function calculate every pixel along a row and use
transfer_pixels() function to transfer these pixels to the destination.
Thus we first move column-wise and then row-wise to analyse every pixel.

Compute the ramp value which sets 'pct_black' % of the darkened pixels
black.Initialise and register the pixel region . dest1 deals with the
calculations for blur radius and dest2 deals with the calculations for the
mask radius.For every pixel calculate the diff as the ratio of the blur
intensity to that of the average intensity.if the difference > threshold
then multiplying factor = 1 else check if ramp != 0 then mult = (ramp - MIN
(ramp, (cvals.threshold - diff))) / ramp. The final intensity for every
pixel calculated as blur_ptr[col]*mult is CLAMPED between 0  to 255. If
number of bytes per pixel is less than 3 then initialise denstination pixels
directly and transfer the alpha value as well if the source has any.
Otherwise if( bpp > 3 ) i.e RGB layers exist then convert the RGB values to
the corresponding HLS values.
R[0-255](Red) G[0-255](Green) B[0-255](Blue)
H[0-360](Hue) L[0-255](Lightness) S[0-255](Saturation)
With it we set the lightness and again convert back the to RGB
And after it we merge the shadow tile and update the drawable.

4. transfer_pixels (gdouble *src1, gdouble *src2, guchar *dest, gint jump,
gint bytes, gint width) -

It is a gaussian blur helper function which transfer the pixels from source
pointed by src1 and src2 to the destination 'dest'.
If there are more than two bytes per pixel( if RGB ) then it computes the
luminance value corresponding to the RGB triplet. The lightness value is
computed as -
L = (max(R, G, B) + min (R, G, B)) / 2

5. compute_ramp (guchar  *dest1, guchar  *dest2, gint length, gdouble
pct_black) -

It computes the ratio between the two destination images( blur, mask ) and
it calculates the number of pixels 'count' for which this difference is < 1.
Now it calcultes the average such that avg = ( hist[0] + hist[1] + hist[2] +
.............+ hist[n] ) /count where 'n' is the index where avg > pct_black
and at that point where we reach the desired pct_black the function returns
the ramp as ( 1 - n/100 )

*Photocopy - *
*
*
header file - libgimp/gimp.h makes all basic plugin elements available to
us.

Structures defined-
1. PhotocopyVals - holds parameters -
mask_radius - controls the size of the pixel neighbourhood over which the
average intensity is computed and then compared to each pixel in the
neighborhood to decide whether or not to darken it. Large values result in
very thick black areas bordering the regions of white and much less detail
for black areas. Small values result in less toner overall and more details
everywhere.
sharpness - defines photocopy sharpness.
threshold - relative intensity difference which will result in darkening
pct_black - decides the amount of black color added to the image
pct_white - white pixel percentage.

Local Variables -
1. pvals - storing default values for the parameters of the structure
PhotocopyVals.

2. GimpPlugInInfo PLUG_IN_INFO - Contains four pointers to different
functions which are called during plugin execution.
a)init - optional(can have null value) and is called as GIMP starts up. It
can be called if we want to register some procedure conditionally on some
files prescence.
b)quit - also optional( can have null value ) and is called when GIMP is
going to close.
c)query - called when the plugin comes into existence or every time when it
is modified.
d)run - it is the plugin processing function which receives the plugin
name, input parameters, number of return values, pointer to output
parameters.

MAIN() - it is a macro defined for calling the initialisation and calling
appropriate functions that our plugin needs during its life time.

Functions -

1. query() - defines the input arguments
Structure GimpParamDef contains - type, name and description.
It registers the function in the path specified as here under
"<Image>/Filters/Artistic"

2.  photocopy_dialog (GimpDrawable *drawable) -
opens a dialog box for the user for specifying the basic input parameters.
This also function holds the basic layout informaion for the dialog box. It
clearly mentions the existence of 4 scale bars ( mask radius, sharpness,
percent white, percent black ), preview window and ok button. User can
change the value of parameters and have a preview for every changed
argument.The widget does not gets destroyed until the ok button( signal -
GTK_RESPONSE_OK ) or cancel button is pressed and the final parameters are
then saved.

3. photocopy(GimpDrawable *drawable,GimpPreview  *preview) -

Every variable of the GimpDrawable struct has a drawable id, width,
height,bytes per pixel,number of tile rows, number of tile columns, normal
tiles and shadow tiles. Here we check if the drawable has an alpha channel
associated with it. Alpha channel can be there with the layer types such as
RGB, GRAYSCALE and it defines the amount of opacity of the layer.
Initialise 6 memory locations val_p1,val_p2,val_m1,val_m2,dest1(blur
'src_rgn', new region being attached to drawable region,(0,0) as initial
coordinates, width as drawable->width, height as drawable->height.
It desaturates the image, computes transfer and then calculates the
standard deviations - sharpness and mask radius. Now calculate the value of
needed constants from the 'Gaussian-blur helper function' - find_constants.

Start the analysis of image by taking vertical strips into consideration
begining from column 0 till width. gimp_pixel_rgn_get_col(col+x1, y1 ) gets
all pixels in a column from (col+x1,y1) to (col+x1, y1+height-1 ) and fills
the buffer src with it.sp_p1 holds the value for first pixel and sp_m1 holds
the value for the last pixel and with these values and the values calculated
by the find_constants functions we calculate every pixel along a column and
then use the user defined function 'transfer_pixels' to transfer these pixel
to the destination. gimp_progress_update() updates the progress bar for the
current plugin.

Similary we analyse it now by taking horizontal strips begining from row 0
to row height.Initialise 4 memory locations for holding the values, 2 for
the source buffer( src1, src2 ).Initialise the initial pixels i.e the
starting row pixel 0 and width-1 and with the help of the values calculated
from the gaussian function calculate every pixel along a row and use
transfer_pixels() function to transfer these pixels to the destination.
Thus we first move column-wise and then row-wise to analyse every pixel.

Compute the ramp values - ramp_up and ramp_down.ramp_up sets the pct_black
whereas ramp_down sets the pct_white of the pixels.

Initialise and register the pixel region . dest1 deals with the calculations
for blur radius and dest2 deals with the calculations for the mask
radius.For every pixel calculate the diff as the ratio of the blur intensity
to that of the average intensity.
If diff < threshold and if ramp_down != 0 then mult = (ramp_down - MIN
(ramp_down, (pvals.threshold - diff))) / ramp_down. The lightness for every
pixel calculated as blur_ptr[col]*mult is CLAMPED between 0  to 255.
Else if diff > threshold and ramp_up ! = 0 then mult = MIN (ramp_up, (diff
- pvals.threshold)) / ramp_up. The lightness for every pixel calculated as
255 - (1.0 - mult) * (255 - blur_ptr[col]) CLAMPED between 0  to 255.

Check If number of bytes per pixel is less than 3(grayscale /
grayscale+alpha) or bpp > 3 ( RBG/RGB+alpha ) and accordingly set the
destnation pixel.
And after it we merge the shadow tile and update the drawable.And free the
unused buffers.

4. transfer_pixels (gdouble *src1, gdouble *src2, guchar *dest, gint jump,
gint bytes, gint width) -
It is a gaussian blur helper function which transfer the pixels from source
pointed by src1 and src2 to the destination 'dest'.

5. compute_ramp (guchar  *dest1, guchar  *dest2, gint length, gdouble
pct_black) -

It computes the ratio between the two destination images( blur, mask ) and
checks if the diff is under_threshold or not.It calculates the number of
pixels 'count' for which this difference is < threshold ,diff > threshold &&
diff < 2
Now it calculates the average such that avg = ( hist[0] + hist[1] + hist[2]
+ .............+ hist[n] ) /count where 'n' is the index where avg > pct,
now check if diff was under_threshold then return (pvals.threshold -
(gdouble) n / 1000.0) else return ((gdouble) n / 1000.0 - pvals.threshold)
*
*
*
*
This was what I understood to the best of my knowledge and looking forward
for suggestions to improve it or do some other task.
Besides this I will submit the sample implementation of new GEGL OP as a
patch against the gegl main branch by today evening.

--
Shivani Maheshwari
```_______________________________________________