build: config.mk: Fix python-config switch
[gfxprim/pasky.git] / doc / filters.txt
blobed3948643c2580d0e272b329bc8f4ff30ff98500
1 Context filters
2 ---------------
4 Pixel filters for 'GP_Context'.
6 The context filter is basically a function that operates on context pixels.
7 The result may be stored into a new bitmap or placed to bitmap passed as
8 argument or, in some cases, the filter could be used 'in place' so the result
9 is stored into the same context as the one passed as filter source.
11 Common filter API
12 ~~~~~~~~~~~~~~~~~
14 For convenience, the filters API is unified:
16 * There are two functions for each filter
17   - first one takes destination as an argument
18   - second one allocates the destination and returns pointer to it
19 * First argument(s) are always source(s)
20 * Then, in case of second variant, destination
21 * Other parameters follow
22 * And the last argument is link:progress_callback.html[progress callback]
24 When using allocating version of the filter, pointer to the newly allocated
25 context is returned, or in case of failure 'NULL' is returned.
27 If 'malloc()' has failed 'NULL' is returned.
29 If filter has been interrupted by a callback, all allocated memory is freed,
30 and 'NULL' is returned.
32 When using non-allocating variant of the filter, the destination context must
33 have correct pixel type and the size must be big enough to store the result.
34 The return value from such filter is either zero, in case of success, or
35 non-zero when filter was interrupted by a callback.
37 For filters that work 'in-place' (which is explicitly said for each filter)
38 the source and the destination could be the same context. Note that this is
39 not expected to work if you do several overlapping sub-contexts and pass these
40 as arguments.
42 [source,c]
43 -------------------------------------------------------------------------------
45  * Filter common API.
46  */
47 int GP_FilterFoo(const GP_Context *src, GP_Context *dst,
48                  foo params ...,
49                  GP_ProgressCallback *callback);
51 GP_Context *GP_FilterFooAlloc(const GP_Context *src,
52                               foo params ...,
53                               GP_ProgressCallback *callback);
54 -------------------------------------------------------------------------------
57 Filters also exists in _Raw variant whose interface is similar to the first
58 type of filter function. These filter APIs are used for internal
59 implementation and shouldn't be called by user as the destination is expected
60 to be crafted exactly for storing the filter result and there are 'NO' sanity
61 checks in place.
63 'You could use these at your own risk'
65 [source,c]
66 -------------------------------------------------------------------------------
68  * Raw filter common API.
69  */
70 int GP_FilterFoo_Raw(const GP_Context *src, GP_Context *dst,
71                      foo params ...,
72                      GP_ProgressCallback *callback);
73 -------------------------------------------------------------------------------
75 Filter Parameters
76 ~~~~~~~~~~~~~~~~~
78 In order to pass, per-channel, filter parameters to a filter, structure called
79 GP_FilterParams was created.
81 [source,c]
82 -------------------------------------------------------------------------------
83 #include <GP.h>
84 /* or */
85 #include <filters/GP_FilterParam.h>
87 typedef union GP_FilterParamVal {
88         float f;
89         uint32_t ui;
90         int32_t i;
91         void *ptr;
92 } GP_FilterParamVal;
94 typedef struct GP_FilterParam {
95         char channel_name[2];
96         union GP_FilterParamVal val;
97 } GP_FilterParam;
98 -------------------------------------------------------------------------------
100 Some filters do take an empty channel_name terminated (empty channel_name is
101 empty string i.e. "\0") array of GP_FilterParam, which is used to describe
102 per-channel parameters.
105 There are two methods how to construct GP_FilterParam structure. First one is
106 to use macro that expands to a code which declares and initializes the array on
107 the stack second uses memory allocated by a malloc(). In both cases the
108 structure is has initialized channel names and terminator.
110 [source,c]
111 -------------------------------------------------------------------------------
112 #include <GP.h>
113 /* or */
114 #include <filters/GP_FilterParam.h>
116 #define GP_FILTER_PARAMS(pixel_type, name) \
117         GP_FilterParam name[GP_PixelTypes[pixel_type].numchannels + 1]; \
118         GP_FilterParamInitChannels(name, pixel_type);
119 -------------------------------------------------------------------------------
121 Macro that declares and initializes GP_FilterParam structure for a given
122 pixel_type.
124 [source,c]
125 -------------------------------------------------------------------------------
126 #include <GP.h>
127 /* or */
128 #include <filters/GP_FilterParam.h>
130 GP_FilterParam *GP_FilterParamCreate(GP_PixelType pixel_type);
132 void GP_FilterParamDestroy(GP_FilterParam *self);
133 -------------------------------------------------------------------------------
135 Second possible way allocates memory using malloc().
137 Functions for manipulating and querying existing GP_FilterParam follows.
139 [source,c]
140 -------------------------------------------------------------------------------
141 #include <GP.h>
142 /* or */
143 #include <filters/GP_FilterParam.h>
145 void GP_FilterParamInitChannels(GP_FilterParam params[],
146                                 GP_PixelType pixel_type);
147 -------------------------------------------------------------------------------
149 Initializes filter param array channel names (accordingly to pixel type) and
150 terminator. The params array must be large enough to hold number of pixel type
151 channels plus one.
153 [source,c]
154 -------------------------------------------------------------------------------
155 #include <GP.h>
156 /* or */
157 #include <filters/GP_FilterParam.h>
159 GP_FilterParam *GP_FilterParamChannel(GP_FilterParam params[],
160                                       const char *channel_name);
161 -------------------------------------------------------------------------------
163 Does lookup for a given channel name and returns, if found, corresponding
164 GP_FilterParam, otherwise 'NULL' is returned.
166 This function is primary used in filters, where filter, at the start, resolves
167 all it's parameters.
169 [source,c]
170 -------------------------------------------------------------------------------
171 #include <GP.h>
172 /* or */
173 #include <filters/GP_FilterParam.h>
175 int GP_FilterParamCheckPixelType(GP_FilterParam params[],
176                                  GP_PixelType pixel_type);
177 -------------------------------------------------------------------------------
179 Matches param structure against pixel_type. Returns zero if params describes
180 exactly same channels like pixel_type, non-zero otherwise.
182 [source,c]
183 -------------------------------------------------------------------------------
184 #include <GP.h>
185 /* or */
186 #include <filters/GP_FilterParam.h>
188 void GP_FilterParamSetIntAll(GP_FilterParam params[], int32_t val);
190 int GP_FilterParamSetInt(GP_FilterParam params[], const char *channel_name,
191                          int32_t val);
193 void GP_FilterParamSetFloatAll(GP_FilterParam params[], float val);
195 int GP_FilterParamSetFloat(GP_FilterParam params[], const char *channel_name,
196                            float val);
198 void GP_FilterParamSetUIntAll(GP_FilterParam params[], uint32_t val);
200 int GP_FilterParamSetUInt(GP_FilterParam params[], const char *channel_name,
201                           uint32_t val);
203 void GP_FilterParamSetPtrAll(GP_FilterParam params[], void *ptr);
205 int GP_FilterParamSetPtr(GP_FilterParam params[], const char *channel_name,
206                          void *ptr);
208 void GP_FilterParamFreePtrAll(GP_FilterParam params[]);
209 -------------------------------------------------------------------------------
211 Parameter setters. Those that sets individual value returns zero on success
212 (i.e. channel was found) and non-zero otherwise.
214 The last one calls free() on all param pointers, which is used to free
215 allocate memory.
217 Point operation filters
218 ~~~~~~~~~~~~~~~~~~~~~~~
220 Point operations are filters that works with pixels as with independent values
221 (the value of destination pixel depends only on the pixel on the same
222 coordinates in source image). All of these filters works 'in-place' and the
223 result has always the same size as the source.
225 [source,c]
226 -------------------------------------------------------------------------------
227 #include <GP_Filters.h>
229 GP_Context *GP_FilterBrightness(const GP_Context *src, GP_Context *dst,
230                                 int32_t inc, GP_ProgressCallback *callback);
231 -------------------------------------------------------------------------------
233 Brightness filter, increments all pixel channels by a fixed value.
235 [source,c]
236 -------------------------------------------------------------------------------
237 #include <GP_Filters.h>
239 GP_Context *GP_FilterContrast(const GP_Context *src, GP_Context *dst,
240                               float mul, GP_ProgressCallback *callback);
241 -------------------------------------------------------------------------------
243 Contrast filter, multiplies all pixel channels by a fixed value.
245 [source,c]
246 -------------------------------------------------------------------------------
247 #include <GP_Filters.h>
249 GP_Context *GP_FilterInvert(const GP_Context *src, GP_Context *dst,
250                             GP_ProgressCallback *callback);
251 -------------------------------------------------------------------------------
253 Inverts the image, for each channel the result value is computed as "chan_max
254 - val".
256 Gaussian additive noise filter
257 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
259 [source,c]
260 -------------------------------------------------------------------------------
261 #include <GP_Filters.h>
262 /* or */
263 #include <filters/GP_GaussianNoise.h>
265 int GP_FilterGaussianNoiseAddEx(const GP_Context *src,
266                                 GP_Coord x_src, GP_Coord y_src,
267                                 GP_Size w_src, GP_Size h_src,
268                                 GP_Context *dst,
269                                 GP_Coord x_dst, GP_Coord y_dst,
270                                 float sigma, float mu,
271                                 GP_ProgressCallback *callback);
273 GP_Context *GP_FilterGaussianNoiseAddExAlloc(const GP_Context *src,
274                                              GP_Coord x_src, GP_Coord y_src,
275                                              GP_Size w_src, GP_Size h_src,
276                                              float sigma, float mu,
277                                              GP_ProgressCallback *callback);
279 static inline int GP_FilterGaussianNoiseAdd(const GP_Context *src,
280                                             GP_Context *dst,
281                                             float sigma, float mu,
282                                             GP_ProgressCallback *callback);
284 static inline GP_Context *
285 GP_FilterGaussianNoiseAddAlloc(const GP_Context *src,
286                                float sigma, float mu,
287                                GP_ProgressCallback *callback);
288 -------------------------------------------------------------------------------
290 Gaussian additive noise filter adds gaussian distributed noise to an image
291 with a defined sigma and mu. Both sigma and mu weights mapped to [0,1]
292 interval.
294 TIP: See the link:example_gaussian_noise.html[gaussian noise example].
296 include::images/gaussian_noise/images.txt[]
298 Arithmetic filters
299 ~~~~~~~~~~~~~~~~~~
301 Arithmetic filters do take two contexts as an input and combines them into one
302 output context.
304 The pixel type of both input contexts must match.
306 If size of the input contexts differs, minimum is used.
308 [source,c]
309 -------------------------------------------------------------------------------
310 #include <filters/GP_Arithmetic.h>
311 /* or */
312 #include <GP.h>
314 int GP_FilterAddition(const GP_Context *src_a,
315                       const GP_Context *src_b,
316                       GP_Context *dst,
317                       GP_ProgressCallback *callback);
319 GP_Context *GP_FilterAdditionAlloc(const GP_Context *src_a,
320                                    const GP_Context *src_b,
321                                    GP_ProgressCallback *callback);
322 -------------------------------------------------------------------------------
324 Produces saturated (clamped) addition of two contexts.
326 [source,c]
327 -------------------------------------------------------------------------------
328 #include <filters/GP_Arithmetic.h>
329 /* or */
330 #include <GP.h>
332 int GP_FilterMultiply(const GP_Context *src_a,
333                       const GP_Context *src_b,
334                       GP_Context *dst,
335                       GP_ProgressCallback *callback);
337 GP_Context *GP_FilterMultiplyAlloc(const GP_Context *src_a,
338                                    const GP_Context *src_b,
339                                    GP_ProgressCallback *callback);
340 -------------------------------------------------------------------------------
342 Produces saturated (clamped) multiplication of two contexts.
344 [source,c]
345 -------------------------------------------------------------------------------
346 #include <filters/GP_Arigthmetic.h>
347 /* or */
348 #include <GP.h>
350 int GP_FilterDifference(const GP_Context *src_a,
351                         const GP_Context *src_b,
352                         GP_Context *dst,
353                         GP_ProgressCallback *callback);
355 GP_Context *GP_FilterDifferenceAlloc(const GP_Context *src_a,
356                                      const GP_Context *src_b,
357                                      GP_ProgressCallback *callback);
359 -------------------------------------------------------------------------------
361 Produces symmetric difference (i.e. abs(a - b)).
363 [source,c]
364 -------------------------------------------------------------------------------
365 #include <filters/GP_Arigthmetic.h>
366 /* or */
367 #include <GP.h>
369 int GP_FilterMax(const GP_Context *src_a,
370                  const GP_Context *src_b,
371                  GP_Context *dst,
372                  GP_ProgressCallback *callback);
374 GP_Context *GP_FilterMaxAlloc(const GP_Context *src_a,
375                               const GP_Context *src_b,
376                               GP_ProgressCallback *callback);
378 int GP_FilterMin(const GP_Context *src_a,
379                  const GP_Context *src_b,
380                  GP_Context *dst,
381                  GP_ProgressCallback *callback);
383 GP_Context *GP_FilterMinAlloc(const GP_Context *src_a,
384                               const GP_Context *src_b,
385                               GP_ProgressCallback *callback);
386 -------------------------------------------------------------------------------
388 Maximum and minimum filter.
390 Rotation and Symmetry filters
391 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
393 [source,c]
394 -------------------------------------------------------------------------------
395 #include <filters/GP_Rotate.h>
396 /* or */
397 #include <GP.h>
399 int GP_FilterMirrorH(const GP_Context *src, GP_Context *dst,
400                      GP_ProgressCallback *callback);
402 GP_Context *GP_FilterMirrorHAlloc(const GP_Context *src,
403                                    GP_ProgressCallback *callback);
404 -------------------------------------------------------------------------------
406 Mirrors context horizontally.
408 Works 'in-place'.
410 The destination has to have the same pixel type and the size must be at least
411 as large as source.
413 [source,c]
414 -------------------------------------------------------------------------------
415 #include <filters/GP_Rotate.h>
416 /* or */
417 #include <GP.h>
419 int GP_FilterMirrorV(const GP_Context *src, GP_Context *dst,
420                      GP_ProgressCallback *callback);
422 GP_Context *GP_FilterMirrorVAlloc(const GP_Context *src,
423                                    GP_ProgressCallback *callback);
424 -------------------------------------------------------------------------------
426 Mirrors context vertically.
428 Works 'in-place'.
430 The destination has to have the same pixel type and the size must be at least
431 as large as source.
433 [source,c]
434 -------------------------------------------------------------------------------
435 #include <filters/GP_Rotate.h>
436 /* or */
437 #include <GP.h>
439 int GP_FilterRotate90(const GP_Context *src, GP_Context *dst,
440                       GP_ProgressCallback *callback);
442 GP_Context *GP_FilterRotate90Alloc(const GP_Context *src,
443                                     GP_ProgressCallback *callback);
444 -------------------------------------------------------------------------------
446 Rotate context by 90 degrees.
448 Doesn't work 'in-place' (yet).
450 The destination has to have the same pixel type and size must be large enough to
451 fit rotated context (i.e. W and H are swapped).
453 [source,c]
454 -------------------------------------------------------------------------------
455 #include <filters/GP_Rotate.h>
456 /* or */
457 #include <GP.h>
459 int GP_FilterRotate180(const GP_Context *src, GP_Context *dst,
460                        GP_ProgressCallback *callback);
462 GP_Context *GP_FilterRotate180Alloc(const GP_Context *src,
463                                      GP_ProgressCallback *callback);
464 -------------------------------------------------------------------------------
466 Rotate context by 180 degrees.
468 Doesn't work 'in-place' (yet).
470 The destination has to have the same pixel type and the size must be at least
471 as large as source.
473 [source,c]
474 -------------------------------------------------------------------------------
475 #include <filters/GP_Rotate.h>
476 /* or */
477 #include <GP.h>
479 int GP_FilterRotate270(const GP_Context *src, GP_Context *dst,
480                        GP_ProgressCallback *callback);
482 GP_Context *GP_FilterRotate270Alloc(const GP_Context *src,
483                                      GP_ProgressCallback *callback);
484 -------------------------------------------------------------------------------
486 Rotate context by 270 degrees.
488 Doesn't work 'in-place' (yet).
490 The destination has to have the same pixel type and destination size must be
491 large enough to fit rotated context (i.e. W and H are swapped).
493 [source,c]
494 -------------------------------------------------------------------------------
495 #include <filters/GP_Rotate.h>
496 /* or */
497 #include <GP.h>
499 typedef enum GP_FilterSymmetries {
500         GP_ROTATE_90,
501         GP_ROTATE_CW = GP_ROTATE_90,
502         GP_ROTATE_180,
503         GP_ROTATE_270,
504         GP_ROTATE_CCW = GP_ROTATE_270,
505         GP_MIRROR_H,
506         GP_MIRROR_V,
507 } GP_FilterSymmetries;
509 GP_Context *GP_FilterSymmetry(const GP_Context *src,
510                               GP_FilterSymmetries symmetry,
511                               GP_ProgressCallback *callback);
513 int GP_FilterSymmetry(const GP_Context *src, GP_Context *dst,
514                       GP_FilterSymmetries symmetry,
515                       GP_ProgressCallback *callback);
516 -------------------------------------------------------------------------------
518 Catch all function for symmetry filters.
521 Linear filters
522 ~~~~~~~~~~~~~~
524 Linear filters family consists of filters based on discrete linear
525 convolution, that means that computed pixel value depends on linear
526 combination of the image pixels.
528 It's defined as:
529 [latex, discrete_linear_convolution.png, 140]
530 -------------------------------------------------------------------------------
532 O(x,y)=\sum_{i=-\infty}^{\infty}\sum_{j=-\infty}^{\infty}I(x+i,y+j) \cdot K(i,j)
534 -------------------------------------------------------------------------------
536 The K denotes convolution kernel and in practice, due to computational
537 complexity i and j are bounded in relatively small intervals. For example i
538 and j are in (-1,1) and the kernel size is 3x3.
540 Note that pixel values outside the image are undefined. The linear convolution
541 in GFXprim simply uses the closest border pixel values for all pixels outside
542 the image.
544 Particular convolution kernel is called separable if it could be decomposed
545 into two one dimensional kernels (these when combined yields back the original
546 kernel). Such convolution then could be applied as two one dimensional
547 convolutions which is faster operation (especially for big kernels).
549 Generic Linear Convolution
550 ^^^^^^^^^^^^^^^^^^^^^^^^^^
552 Following paragraph describes linear convolution implementation as well as a
553 little of the math background skip it if you just need to use one of the
554 ready-to-use filters.
556 [source,c]
557 -------------------------------------------------------------------------------
558 #include <filters/GP_Linear.h>
559 /* or */
560 #include <GP.h>
562 int GP_FilterLinearConvolution_Raw(const GP_Context *src,
563                                    GP_Coord x_src, GP_Coord y_src,
564                                    GP_Size w_src, GP_Size h_src,
565                                    GP_Context *dst,
566                                    GP_Coord x_dst, GP_Coord y_dst,
567                                    float kernel[], uint32_t kw, uint32_t kh,
568                                    float kern_div, GP_ProgressCallback *callback);
569 -------------------------------------------------------------------------------
571 Internal generic convolution filter, this is a base for all linear convolution
572 filters with non-separable kernel.
574 The src coordinate and sizes denotes rectangle in the source context that the
575 filter operates on.
577 The dst coordinates defines offset into the dst context.
579 The kernel is two-dimensional array of a size kw * kh indexed as
580 kernel[x + y*kw].
582 The kern_div is a coefficient that is used to divide the resulting values often
583 used to normalize the result.
585 This filter works 'in-place'.
587 The pixel value is computed as:
588 [latex, discrete_linear_convolution_alg1.png, 140]
589 -------------------------------------------------------------------------------
591 O(x,y)={1 \over kern\_div} \cdot \sum_{i=0}^{kw - 1}\sum_{j=0}^{kh - 1}
592        I(x + i - \lfloor kw/2 \rfloor, y + j - \lfloor kh/2 \rfloor)
593        \cdot kernel(i,j)
595 -------------------------------------------------------------------------------
597 Which is the same as:
599 [latex, discrete_linear_convolution_alg2.png, 140]
600 -------------------------------------------------------------------------------
602 O(x,y)={1 \over kern\_div} \cdot
603        \sum_{i=-\lfloor kw/2 \rfloor}^{\lfloor kw/2 \rfloor}
604        \sum_{j=-\lfloor kh/2 \rfloor}^{\lfloor kh/2 \rfloor}
605        I(x + i, y + j)
606        \cdot kernel(i + \lfloor kw/2 \rfloor, j + \lfloor kh/2 \rfloor)
608 -------------------------------------------------------------------------------
610 NOTE: The number of kernel rows and columns is expected to be odd number.
612 [source,c]
613 -------------------------------------------------------------------------------
614 #include <filters/GP_Linear.h>
615 /* or */
616 #include <GP.h>
618 int GP_FilterHLinearConvolution_Raw(const GP_Context *src,
619                                     GP_Coord x_src, GP_Coord y_src,
620                                     GP_Size w_src, GP_Size h_src,
621                                     GP_Context *dst,
622                                     GP_Coord x_dst, GP_Coord y_dst,
623                                     float kernel[], uint32_t kw, float kern_div,
624                                     GP_ProgressCallback *callback);
626 int GP_FilterVLinearConvolution_Raw(const GP_Context *src,
627                                     GP_Coord x_src, GP_Coord y_src,
628                                     GP_Size w_src, GP_Size h_src,
629                                     GP_Context *dst,
630                                     GP_Coord x_dst, GP_Coord y_dst,
631                                     float kernel[], uint32_t kh, float kern_div,
632                                     GP_ProgressCallback *callback);
634 int GP_FilterVHLinearConvolution_Raw(const GP_Context *src,
635                                      GP_Coord x_src, GP_Coord y_src,
636                                      GP_Size w_src, GP_Size h_src,
637                                      GP_Context *dst,
638                                      GP_Coord x_dst, GP_Coord y_dst,
639                                      float hkernel[], uint32_t kw, float hkern_div,
640                                      float vkernel[], uint32_t kh, float vkern_div,
641                                      GP_ProgressCallback *callback);
643 void GP_FilterKernelPrint_Raw(float kernel[], int kw, int kh, float kern_div);
644 -------------------------------------------------------------------------------
646 Internal special functions for one dimensional vertical and horizontal
647 convolution these two functions are base for all separable convolution filters.
649 The src coordinate and sizes denotes rectangle in the source context that the
650 filter operates on.
652 The dst coordinates are offset into the dst.
654 The kernel is one-dimensional array of floats of size kw or kh.
656 The kern_div is a coefficient that is used to divide the resulting values.
658 The last function does both vertical and horizontal convolution and takes care
659 of correct progress callback.
661 These filters work 'in-place'.
663 The pixel value is computed as:
664 [latex, discrete_linear_1D_convolution_alg1.png, 140]
665 -------------------------------------------------------------------------------
667 O(x,y)={1 \over kern\_div} \cdot \sum_{i=0}^{kw - 1}
668        I(x + i - \lfloor kw/2 \rfloor, y)
669        \cdot kernel(i)
673 O(x,y)={1 \over kern\_div} \cdot \sum_{j=0}^{kw - 1}
674        I(x, y + j - \lfloor kh/2 \rfloor)
675        \cdot kernel(j)
677 -------------------------------------------------------------------------------
679 Which is the same as:
681 [latex, discrete_linear_1D_convolution_alg2.png, 140]
682 -------------------------------------------------------------------------------
684 O(x,y)={1 \over kern\_div} \cdot
685        \sum_{i=-\lfloor kw/2 \rfloor}^{\lfloor kw/2 \rfloor}
686        I(x + i, y)
687        \cdot kernel(i + \lfloor kw/2 \rfloor)
691 O(x,y)={1 \over kern\_div} \cdot
692        \sum_{j=-\lfloor kh/2 \rfloor}^{\lfloor kh/2 \rfloor}
693        I(x, y + j)
694        \cdot kernel(i, j + \lfloor kh/2 \rfloor)
696 -------------------------------------------------------------------------------
698 NOTE: The number of kernel rows and columns is expected to be odd number.
700 NOTE: The linear convolutions are internally implemented using integer
701       arithmetics, which works fine, but you need to take a care not to
702       overflow 32bit signed integer. If the pixel channel size is 8bit
703       long and 10bits are used for the fixed point part of the number
704       the rest must fit into about 10 bits to be safe.
706 [source,c]
707 -------------------------------------------------------------------------------
708 #include <filters/GP_Convolution.h>
709 /* or */
710 #include <GP.h>
712 typedef struct GP_FilterKernel2D {
713         unsigned int w;
714         unsigned int h;
715         float div;
716         float *kernel;
717 } GP_FilterKernel2D;
719 int GP_FilterConvolutionEx(const GP_Context *src,
720                            GP_Coord x_src, GP_Coord y_src,
721                            GP_Size w_src, GP_Coord h_src,
722                            GP_Context *dst,
723                            GP_Coord x_dst, GP_Coord y_dst,
724                            const GP_FilterKernel2D *kernel,
725                            GP_ProgressCallback *callback);
727 GP_Context *GP_FilterConvolutionExAlloc(const GP_Context *src,
728                                         GP_Coord x_src, GP_Coord y_src,
729                                         GP_Size w_src, GP_Size h_src,
730                                         const GP_FilterKernel2D *kernel,
731                                         GP_ProgressCallback *callback);
733 int GP_FilterConvolution(const GP_Context *src, GP_Context *dst,
734                          const GP_FilterKernel2D *kernel,
735                          GP_ProgressCallback *callback);
737 GP_Context *GP_FilterConvolutionAlloc(const GP_Context *src,
738                                       const GP_FilterKernel2D *kernel,
739                                       GP_ProgressCallback *callback);
741 void GP_FilterKernel2DPrint(const GP_FilterKernel2D *kernel);
742 -------------------------------------------------------------------------------
744 Linear convolution filters, you should preferably use this API over the _Raw
745 variants.
747 The Ex variants takes a rectangle on which the filter should operate as well
748 as offset into the destination. The destination must be large enough so that
749 starting with offset there is at least w_dst and h_dst pixels.
751 The kernel is a pointer to a structure initialized with the kernel size, divider
752 and array of kernel values.
754 The last function prints convolution kernel in human-readable format into the
755 stdout.
757 WARNING: If filter is executed in-place the work cannot be distributed between
758          threads (as some of the threads will overwrite values read by other
759          threads). In this case convolution filters runs in one thread
760          regardless of if threads are eanbled or not.
762 [source,c]
763 -------------------------------------------------------------------------------
764 #include <GP.h>
767  * Example box smoothing filter.
768  */
769 static void box_smoothing(GP_Context *img)
771         float box_filter[] = {
772                 1, 1, 1,
773                 1, 1, 1,
774                 1, 1, 1,
775         };
777         GP_FilterKernel2D box_kernel = {
778                 .w = 3,
779                 .h = 3,
780                 .div = 9,
781                 .kernel = box_filter,
782         };
784         GP_FilterConvolution(img, img, &box_kernel, NULL);
786 -------------------------------------------------------------------------------
788 Example function that implements simple 'in-place' smoothing filter.
790 Laplace Filter
791 ^^^^^^^^^^^^^^
793 [source,c]
794 -------------------------------------------------------------------------------
795 #include <GP_Filters.h>
796 /* or */
797 #include <GP.h>
799 int GP_FilterLaplace(const GP_Context *src, GP_Context *dst,
800                      GP_ProgressCallback *callback);
802 GP_Context *GP_FilterLaplaceAlloc(const GP_Context *src,
803                                   GP_ProgressCallback *callback);
804 -------------------------------------------------------------------------------
806 Discrete Laplace filter that produces a second derivative of the original
807 image.
809 The convolution kernel is defined as:
811 [latex, laplacian_kernel.png, 130]
812 -------------------------------------------------------------------------------
814 \begin{bmatrix}
815 0  &  1  &  0 \\
816 0  & -2  &  0 \\
817 0  &  1  &  0
818 \end{bmatrix}
820 \begin{bmatrix}
821 0  &  0  &  0 \\
822 1  & -2  &  1 \\
823 0  &  0  &  0
824 \end{bmatrix}
826 \begin{bmatrix}
827 0  &  1  &  0 \\
828 1  & -4  &  1 \\
829 0  &  1  &  0
830 \end{bmatrix}
832 -------------------------------------------------------------------------------
834 NOTE: This filter is not separable but could be written as a sum of two one
835       dimensional filters as the kernel definition suggests.
837 Laplacian Edge Sharpening
838 ^^^^^^^^^^^^^^^^^^^^^^^^^
840 [source,c]
841 -------------------------------------------------------------------------------
842 #include <GP_Filters.h>
843 /* or */
844 #include <GP.h>
846 int GP_FilterEdgeSharpening(const GP_Context *src, GP_Context *dst,
847                             float w, GP_ProgressCallback *callback);
849 GP_Context *GP_FilterEdgeSharpeningAlloc(const GP_Context *src, float w,
850                                          GP_ProgressCallback *callback);
851 -------------------------------------------------------------------------------
853 Laplace based edge sharpening filter, subtracts weighted second derivative
854 from the original image.
856 The w paramerter is multiplicative weight applied on the second derivative.
857 Reasonable results are when the parameter is between '0.1' and '1'.
859 [latex, laplacian_edge_sharpening.png, 140]
860 -------------------------------------------------------------------------------
862 O(x,y) = I(x,y) - w * I''(x,y)
864 -------------------------------------------------------------------------------
866 include::images/edge_sharpening/images.txt[]
868 Gaussian Blur
869 ^^^^^^^^^^^^^
871 [source,c]
872 -------------------------------------------------------------------------------
873 #include <filters/GP_Blur.h>
874 /* or */
875 #include <GP.h>
877 int GP_FilterGaussianBlurEx(const GP_Context *src,
878                             GP_Coord x_src, GP_Coord y_src,
879                             GP_Size w_src, GP_Size h_src,
880                             GP_Context *dst,
881                             GP_Coord x_dst, GP_Coord y_dst,
882                             float x_sigma, float y_sigma,
883                             GP_ProgressCallback *callback);
885 GP_Context *GP_FilterGaussianBlurExAlloc(const GP_Context *src,
886                                          GP_Coord x_src, GP_Coord y_src,
887                                          GP_Size w_src, GP_Size h_src,
888                                          float x_sigma, float y_sigma,
889                                          GP_ProgressCallback *callback);
891 int GP_FilterGaussianBlur(const GP_Context *src, GP_Context *dst,
892                           float x_sigma, float y_sigma,
893                           GP_ProgressCallback *callback)
895 GP_Context *GP_FilterGaussianBlurAlloc(const GP_Context *src,
896                                        float x_sigma, float y_sigma,
897                                        GP_ProgressCallback *callback)
898 -------------------------------------------------------------------------------
900 Gaussian blur (low pass) filters implemented as bilinear separable
901 convolution.
903 The sigma denotes amount of the blur (the radius is computed accordingly
904 automatically).
906 The sigma values can be set for vertical and horizontal direction
907 independently which may be useful when Gaussian blur is used as a low pass
908 filter before image is resampled non proportionally.
910 include::images/blur/images.txt[]
912 Interpolation filters
913 ~~~~~~~~~~~~~~~~~~~~~
915 Filters to link:filters_resize.html[resize image].
917 Nearest Neighbour Interpolation
918 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
920 Fast, but produces "pixelated" images. May however work better for images with
921 sharp edges mostly consisting of big one color regions (it doesn't blur the
922 result on upscaling).
924 Also is commonly used to show preview before you resample the image correctly.
926 Bilinear Interpolation
927 ^^^^^^^^^^^^^^^^^^^^^^
929 Bilinear is faster than bicubic interpolation and produces quite good results
930 especially the low pass variant doesn't need additional filter on down-sampling.
932 Bicubic Interpolation
933 ^^^^^^^^^^^^^^^^^^^^^
935 Works well as is on image upscaling. To get decent result on downscaling
936 low-pass filter (Gaussian blur) must be used on original image before actual
937 downscaling. To do this reasonably fast we could cheat a little: first resize
938 big images a little without the low-pass filter, then apply low-pass filter and
939 finally downscale it to desired size.
941 [[Dithering]]
942 Dithering
943 ~~~~~~~~~
945 link:filters_dithering.html[Dithering filters] are filters for better loosy
946 (source pixel type has more bits to represent color or grayscale value) pixel
947 type conversions.
949 Median
950 ~~~~~~
952 [source,c]
953 -------------------------------------------------------------------------------
954 #include <filters/GP_Median.h>
955 /* or */
956 #include <GP.h>
958 int GP_FilterMedianEx(const GP_Context *src,
959                       GP_Coord x_src, GP_Coord y_src,
960                       GP_Size w_src, GP_Size h_src,
961                       GP_Context *dst,
962                       GP_Coord x_dst, GP_Coord y_dst,
963                       int xmed, int ymed,
964                       GP_ProgressCallback *callback);
966 GP_Context *GP_FilterMedianExAlloc(const GP_Context *src,
967                                    GP_Coord x_src, GP_Coord y_src,
968                                    GP_Size w_src, GP_Size h_src,
969                                    int xmed, int ymed,
970                                    GP_ProgressCallback *callback);
972 int GP_FilterMedian(const GP_Context *src,
973                     GP_Context *dst,
974                     int xmed, int ymed,
975                     GP_ProgressCallback *callback);
977 GP_Context *GP_FilterMedianAlloc(const GP_Context *src,
978                                  int xmed, int ymed,
979                                  GP_ProgressCallback *callback);
980 -------------------------------------------------------------------------------
982 Constant time median filter (the computational complexity is independent of
983 radius size).
985 The xmed and ymed are radius values for x and y. The algorithm uses xmed
986 respectively ymed pixel neighbors from each side so the result is median of
987 rectangle of 2 * xmed + 1 x 2 * ymed + 1 pixels.
989 include::images/median/images.txt[]