Python Filters module
---------------------

The python binding maps mostly to the C API with the 'gp_filter_' prefix
stripped.

The filter functions could be called directly as +filters.Foo(img, ..)+ or
from submodule as +img.filters.Foo(..)+. Note that in the second case the
image is passed automatically as a first parameter.

If filter is aborted from a callback 'OSError' with errno set to
'ECANCELED' is raised, see
link:core_python.html#Progress_Callback[progress callback] for more
information.

Point Filters
~~~~~~~~~~~~~

Invert
^^^^^^

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Inverts image in-place
    img.filters.Invert(img, callback=None)

    # Returns newly allocated inverted image
    res = img.filters.InvertAlloc(callback=None)

-------------------------------------------------------------------------------

The pixel channel values are counted as +chann_max - val+.

include::images/invert/images.txt[]

Brightness
^^^^^^^^^^

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Increses images brightness in-place by channel_max * 0.2
    img.filters.Brightness(img, 0.2, callback=None)

    # Returns image with brightness decreased by channel_max * -0.5
    res = img.filters.BrightnessAlloc(img, -0.5, callback=None)

-------------------------------------------------------------------------------

The pixel channel values are counted as +val + chann_max * p+.

include::images/brightness/images.txt[]

Contrast
^^^^^^^^

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Increses images contrast by 1.2
    img.filters.Contrast(img, 1.2, callback=None)

    # Returns image with contrast decreased by 0.2
    res = img.filters.ContrastAlloc(img, 0.2, callback=None)

-------------------------------------------------------------------------------

The pixel channel values are counted as +val * p+.

include::images/contrast/images.txt[]

BrightnessContrast
^^^^^^^^^^^^^^^^^^

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Increses images contrast by 1.2 decreases brightness by -0.2
    img.filters.BrightnessContrast(img, -0.2, 1.2, callback=None)

    # Returns image with contrast decreased by 0.2 brightness increased by .5
    res = img.filters.BrightnessContrastAlloc(img, 0.5, 0.2, callback=None)

-------------------------------------------------------------------------------

The pixel channel values are counted as +val * c + chann_max * b+.

include::images/brightness_contrast/images.txt[]

Posterize
^^^^^^^^^

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Posterizes image using 2 steps
    img.filters.Posterize(img, 2, callback=None)

    # Returns image posterized into 4 levels
    res = img.filters.PosterizeAlloc(img, 4, callback=None)

-------------------------------------------------------------------------------

The pixel channel values are quantized into number of levels.

include::images/posterize/images.txt[]

Rotations and Mirroring
~~~~~~~~~~~~~~~~~~~~~~~

MirrorH
^^^^^^^

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Mirrors in-place image horizontally
    img.filters.MirrorH(img, callback=None)

    # Mirrors image horizontally
    res = img.filters.MirrorHAlloc(callback=None)

-------------------------------------------------------------------------------

Mirrors image horizontally.

include::images/mirror_h/images.txt[]

MirrorV
^^^^^^^

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Mirrors in-place image vertically
    img.filters.MirrorV(img, callback=None)

    # Mirrors image vertically
    res = img.filters.MirrorVAlloc(callback=None)

-------------------------------------------------------------------------------

Mirrors image vertically.

include::images/mirror_v/images.txt[]

Rotate90
^^^^^^^^

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Rotate in-place by 90 degrees
    img.filters.Rotate90(img, callback=None)

    # Rotate by 90 degrees
    res = img.filters.Rotate90Alloc(callback=None)

-------------------------------------------------------------------------------

Rotate image by 90 degrees clockwise.

include::images/rotate_90/images.txt[]

Rotate180
^^^^^^^^^

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Rotate in-place by 180 degrees
    img.filters.Rotate180(img, callback=None)

    # Rotate by 180 degrees
    res = img.filters.Rotate180Alloc(callback=None)

-------------------------------------------------------------------------------

Rotate image by 180 degrees clockwise.

include::images/rotate_180/images.txt[]

Rotate270
^^^^^^^^^

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Rotate in-place by 270 degrees
    img.filters.Rotate270(img, callback=None)

    # Rotate by 270 degrees
    res = img.filters.Rotate270Alloc(callback=None)

-------------------------------------------------------------------------------

Rotate image by 270 degrees clockwise.

include::images/rotate_270/images.txt[]

Gaussian Additive Noise
~~~~~~~~~~~~~~~~~~~~~~~

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Adds Gaussian noise in-place with sigma=0.2 mu=0.0
    filters.GaussianNoiseAdd(img, img, 0.2, 0.0, callback=None)

    # Returns newly allocated noisy image
    res = img.filters.GaussianNoiseAddAlloc(0.2, 0.0, callback=None)

-------------------------------------------------------------------------------

Gaussian additive noise filter adds gaussian distributed noise to an image
with a defined sigma and mu. Both sigma and mu weights mapped to '[0,1]'
interval.

include::images/gaussian_noise/images.txt[]


Laplacian Edge Sharpening
~~~~~~~~~~~~~~~~~~~~~~~~~

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Does in-place Edge Sharpening
    filters.EdgeSharpening(img, img, 0.2, callback=None)

    # Returns newly allocated sharpened image
    res = img.filters.EdgeSharpening(0.2, callback=None)

-------------------------------------------------------------------------------

Laplace based edge sharpening filter, subtracts weighted second derivative
from the original image.

The float paramerter is multiplicative weight applied on the second
derivative. Reasonable results are when the parameter is between '0.1' and
'1'.

////
Generated in filters.txt
////
image:laplacian_edge_sharpening.png["Laplacian Edge Sharpening"]

include::images/edge_sharpening/images.txt[]

Convolution
~~~~~~~~~~~

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Does in-place bilinear convolution with 3x3 box blur kernel
    filters.Convolution(img, img, [[1, 1, 1],
                                   [1, 1, 1],
                                   [1, 1, 1]], 9, callback=None)

    # Does bilinear convolution with 3x3 box blur kernel.
    #
    # The image data from source starting at 20,20 of a size 250x250 are
    # stored at 100,100 in res.
    filters.ConvolutionEx(img, 20, 20, 250, 250, res, 100, 100,
                          [[1, 1, 1],
                           [1, 1, 1],
                           [1, 1, 1]], 9, callback=None)

    # Returns newly allocated image convolution with Laplacian 3x3 kernel
    res = img.filters.ConvolutionAlloc([[ 0.00, -0.25,  0.00],
                                        [-0.25,  1.00, -0.25],
                                        [ 0.00, -0.25,  0.00]],
                                        1, callback=None)

    # Returns newly allocated subimage convolution with Sobel 3x3 kernel
    res = img.filters.ConvolutionExAlloc(50, 50, 100, 100,
                                         [[ 1, 0, -1],
                                          [ 2, 0, -2],
                                          [ 1, 0, -1]], 1, callback=None)
-------------------------------------------------------------------------------

Bilinear convolution. The kernel is specified as two dimensional array of
numbers, the second number is divisor of the kernel weighed sum of pixels.

////
Generated in filters.txt
////

The pixel value is computed as:
image:discrete_linear_convolution_alg1.png["Bilinear Convolution"]

Which is the same as:
image:discrete_linear_convolution_alg2.png["Bilinear Convolution"]

NOTE: The number of kernel rows and columns is expected to be odd number.

TIP: See link:example_py_convolution.html[convolution example].


include::images/convolution/images.txt[]

Blurs
~~~~~

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Does in-place Gaussian blur, the image is modified in-place
    filters.GaussianBlur(img, img, x_sigma, y_sigma, callback=None)

    # Returns newly alocated blurred image
    res = img.filters.GaussianBlur(x_sigma, y_sigma, callback=None)

-------------------------------------------------------------------------------

Gaussian blur (low pass) filters implemented as bilinear separable
convolution.

TIP: See link:example_py_blur.html[blur example].

include::images/blur/images.txt[]

Ditherings
~~~~~~~~~~

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Returns img dithered to 1-bit Grayscale as a new image
    res = img.filters.FloydSteinbergAlloc(core.C.PIXEL_G1, callback=None)

    # Returns img dithered to 1-bit Grayscale as a new image
    res = img.filters.HilbertPeanoAlloc(core.C.PIXEL_G1, callback=None)

-------------------------------------------------------------------------------

Returns new 1-bit Grayscale image which is result from Floyd-Steinberg,
Hilbert-Peano dithering.

The first parameter is pixel type, the second is progress callback.

For more information and example images see link:filters_dithering.html[C
dithering documentation].

TIP: See link:example_py_dithering.html[dithering example].

include::images/convert/images.txt[]
include::images/floyd_steinberg/images.txt[]
include::images/hilbert_peano/images.txt[]

Median
~~~~~~

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Returns result of median filter over a rectangle of a side 2 * 3 + 1 pixels
    res = img.filters.MedianAlloc(3, 3, callback=None)

    # Applies median filter in-place
    img.filters.Median(3, 3, callback=None)
-------------------------------------------------------------------------------

Constant time median filter (the computational complexity is independent of
radius size).

The parameters are radius values for x and y. The algorithm uses x
respectively y pixel neighbors from each side so the result is median of
rectangle of +2 * x + 1+ x +2 * y + 1+ pixels.

include::images/median/images.txt[]

Resize
~~~~~~

[source,python]
-------------------------------------------------------------------------------
import gfxprim.core as core
import gfxprim.filters as filters

    # Nearest neighbour resize, fastest but lowest quality
    res = img.ResizeNNAlloc(100, 100, callback=None)

    # Fast and good quality with low pass on downscaling
    res = img.ResizeLinearLFIntAlloc(100, 100, callback=None)

    # Cubic interpolation, needs low pass (blur) applied before downscaling
    res = img.ResizeCubicIntAlloc(100, 100, callback=None)

    # All of the above, TYPE is numeric enum
    res = img.ResizeAlloc(100, 100, TYPE, callback=None)

-------------------------------------------------------------------------------

Functions to resize (resample) image.

TIP: See link:example_py_resize.html[resize example].
