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.
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
43 -------------------------------------------------------------------------------
47 int GP_FilterFoo(const GP_Context *src, GP_Context *dst,
49 GP_ProgressCallback *callback);
51 GP_Context *GP_FilterFooAlloc(const GP_Context *src,
53 GP_ProgressCallback *callback);
54 -------------------------------------------------------------------------------
60 Point operations are filters that works with pixels as with independent values
61 (the value of destination pixel depends only on the pixel on the same
62 coordinates in source image). All of these filters works 'in-place' and the
63 result has always the same size as the source.
69 -------------------------------------------------------------------------------
72 #include <filters/GP_Point.h>
74 int GP_FilterInvert(const GP_Context *src, GP_Context *dst,
75 GP_ProgressCallback *callback);
77 GP_Context *GP_FilterInvertAlloc(const GP_Context *src,
78 GP_ProgressCallback *callback);
79 -------------------------------------------------------------------------------
81 The pixel channel values are counted as +chann_max - val+.
83 include::images/invert/images.txt[]
89 -------------------------------------------------------------------------------
92 #include <filters/GP_Point.h>
94 int GP_FilterBrightness(const GP_Context *src, GP_Context *dst,
95 float p, GP_ProgressCallback *callback);
97 GP_Context *GP_FilterBrightnessAlloc(const GP_Context *src, float p,
98 GP_ProgressCallback *callback);
99 -------------------------------------------------------------------------------
101 The pixel channel values are counted as +val + chann_max * p+.
103 include::images/brightness/images.txt[]
109 -------------------------------------------------------------------------------
112 #include <filters/GP_Point.h>
114 int GP_FilterContrast(const GP_Context *src, GP_Context *dst,
115 float p, GP_ProgressCallback *callback);
117 GP_Context *GP_FilterContrastAlloc(const GP_Context *src, float p,
118 GP_ProgressCallback *callback);
119 -------------------------------------------------------------------------------
121 The pixel channel values are counted as +val * p+.
123 include::images/contrast/images.txt[]
129 -------------------------------------------------------------------------------
132 #include <filters/GP_Point.h>
134 int GP_FilterBrightnessContrast(const GP_Context *src, GP_Context *dst,
136 GP_ProgressCallback *callback);
138 GP_Context *GP_FilterBrightnessContrastAlloc(const GP_Context *src,
140 GP_ProgressCallback *callback);
141 -------------------------------------------------------------------------------
143 The pixel channel values are counted as +val * c + chann_max * b+.
145 include::images/brightness_contrast/images.txt[]
151 -------------------------------------------------------------------------------
154 #include <filters/GP_Point.h>
156 int GP_FilterPosterize(const GP_Context *src, GP_Context *dst,
157 unsigned int levels, GP_ProgressCallback *callback);
159 GP_Context *GP_FilterPosterizeAlloc(const GP_Context *src, unsigned int levels,
160 GP_ProgressCallback *callback);
161 -------------------------------------------------------------------------------
163 The pixel channel values are quantized into number of levels.
165 include::images/posterize/images.txt[]
168 Gaussian additive noise filter
169 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
172 -------------------------------------------------------------------------------
173 #include <GP_Filters.h>
175 #include <filters/GP_GaussianNoise.h>
177 int GP_FilterGaussianNoiseAddEx(const GP_Context *src,
178 GP_Coord x_src, GP_Coord y_src,
179 GP_Size w_src, GP_Size h_src,
181 GP_Coord x_dst, GP_Coord y_dst,
182 float sigma, float mu,
183 GP_ProgressCallback *callback);
185 GP_Context *GP_FilterGaussianNoiseAddExAlloc(const GP_Context *src,
186 GP_Coord x_src, GP_Coord y_src,
187 GP_Size w_src, GP_Size h_src,
188 float sigma, float mu,
189 GP_ProgressCallback *callback);
191 static inline int GP_FilterGaussianNoiseAdd(const GP_Context *src,
193 float sigma, float mu,
194 GP_ProgressCallback *callback);
196 static inline GP_Context *
197 GP_FilterGaussianNoiseAddAlloc(const GP_Context *src,
198 float sigma, float mu,
199 GP_ProgressCallback *callback);
200 -------------------------------------------------------------------------------
202 Gaussian additive noise filter adds gaussian distributed noise to an image
203 with a defined sigma and mu. Both sigma and mu weights mapped to [0,1]
206 TIP: See the link:example_gaussian_noise.html[gaussian noise example].
208 include::images/gaussian_noise/images.txt[]
213 Arithmetic filters do take two contexts as an input and combines them into one
216 The pixel type of both input contexts must match.
218 If size of the input contexts differs, minimum is used.
221 -------------------------------------------------------------------------------
222 #include <filters/GP_Arithmetic.h>
226 int GP_FilterAddition(const GP_Context *src_a,
227 const GP_Context *src_b,
229 GP_ProgressCallback *callback);
231 GP_Context *GP_FilterAdditionAlloc(const GP_Context *src_a,
232 const GP_Context *src_b,
233 GP_ProgressCallback *callback);
234 -------------------------------------------------------------------------------
236 Produces saturated (clamped) addition of two contexts.
239 -------------------------------------------------------------------------------
240 #include <filters/GP_Arithmetic.h>
244 int GP_FilterMultiply(const GP_Context *src_a,
245 const GP_Context *src_b,
247 GP_ProgressCallback *callback);
249 GP_Context *GP_FilterMultiplyAlloc(const GP_Context *src_a,
250 const GP_Context *src_b,
251 GP_ProgressCallback *callback);
252 -------------------------------------------------------------------------------
254 Produces saturated (clamped) multiplication of two contexts.
257 -------------------------------------------------------------------------------
258 #include <filters/GP_Arigthmetic.h>
262 int GP_FilterDifference(const GP_Context *src_a,
263 const GP_Context *src_b,
265 GP_ProgressCallback *callback);
267 GP_Context *GP_FilterDifferenceAlloc(const GP_Context *src_a,
268 const GP_Context *src_b,
269 GP_ProgressCallback *callback);
271 -------------------------------------------------------------------------------
273 Produces symmetric difference (i.e. abs(a - b)).
276 -------------------------------------------------------------------------------
277 #include <filters/GP_Arigthmetic.h>
281 int GP_FilterMax(const GP_Context *src_a,
282 const GP_Context *src_b,
284 GP_ProgressCallback *callback);
286 GP_Context *GP_FilterMaxAlloc(const GP_Context *src_a,
287 const GP_Context *src_b,
288 GP_ProgressCallback *callback);
290 int GP_FilterMin(const GP_Context *src_a,
291 const GP_Context *src_b,
293 GP_ProgressCallback *callback);
295 GP_Context *GP_FilterMinAlloc(const GP_Context *src_a,
296 const GP_Context *src_b,
297 GP_ProgressCallback *callback);
298 -------------------------------------------------------------------------------
300 Maximum and minimum filter.
302 Rotation and Symmetry filters
303 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
306 -------------------------------------------------------------------------------
307 #include <filters/GP_Rotate.h>
311 int GP_FilterMirrorH(const GP_Context *src, GP_Context *dst,
312 GP_ProgressCallback *callback);
314 GP_Context *GP_FilterMirrorHAlloc(const GP_Context *src,
315 GP_ProgressCallback *callback);
316 -------------------------------------------------------------------------------
318 Mirrors context horizontally.
322 The destination has to have the same pixel type and the size must be at least
326 -------------------------------------------------------------------------------
327 #include <filters/GP_Rotate.h>
331 int GP_FilterMirrorV(const GP_Context *src, GP_Context *dst,
332 GP_ProgressCallback *callback);
334 GP_Context *GP_FilterMirrorVAlloc(const GP_Context *src,
335 GP_ProgressCallback *callback);
336 -------------------------------------------------------------------------------
338 Mirrors context vertically.
342 The destination has to have the same pixel type and the size must be at least
346 -------------------------------------------------------------------------------
347 #include <filters/GP_Rotate.h>
351 int GP_FilterRotate90(const GP_Context *src, GP_Context *dst,
352 GP_ProgressCallback *callback);
354 GP_Context *GP_FilterRotate90Alloc(const GP_Context *src,
355 GP_ProgressCallback *callback);
356 -------------------------------------------------------------------------------
358 Rotate context by 90 degrees.
360 Doesn't work 'in-place' (yet).
362 The destination has to have the same pixel type and size must be large enough to
363 fit rotated context (i.e. W and H are swapped).
366 -------------------------------------------------------------------------------
367 #include <filters/GP_Rotate.h>
371 int GP_FilterRotate180(const GP_Context *src, GP_Context *dst,
372 GP_ProgressCallback *callback);
374 GP_Context *GP_FilterRotate180Alloc(const GP_Context *src,
375 GP_ProgressCallback *callback);
376 -------------------------------------------------------------------------------
378 Rotate context by 180 degrees.
380 Doesn't work 'in-place' (yet).
382 The destination has to have the same pixel type and the size must be at least
386 -------------------------------------------------------------------------------
387 #include <filters/GP_Rotate.h>
391 int GP_FilterRotate270(const GP_Context *src, GP_Context *dst,
392 GP_ProgressCallback *callback);
394 GP_Context *GP_FilterRotate270Alloc(const GP_Context *src,
395 GP_ProgressCallback *callback);
396 -------------------------------------------------------------------------------
398 Rotate context by 270 degrees.
400 Doesn't work 'in-place' (yet).
402 The destination has to have the same pixel type and destination size must be
403 large enough to fit rotated context (i.e. W and H are swapped).
406 -------------------------------------------------------------------------------
407 #include <filters/GP_Rotate.h>
411 typedef enum GP_FilterSymmetries {
413 GP_ROTATE_CW = GP_ROTATE_90,
416 GP_ROTATE_CCW = GP_ROTATE_270,
419 } GP_FilterSymmetries;
421 GP_Context *GP_FilterSymmetry(const GP_Context *src,
422 GP_FilterSymmetries symmetry,
423 GP_ProgressCallback *callback);
425 int GP_FilterSymmetry(const GP_Context *src, GP_Context *dst,
426 GP_FilterSymmetries symmetry,
427 GP_ProgressCallback *callback);
428 -------------------------------------------------------------------------------
430 Catch all function for symmetry filters.
436 Linear filters family consists of filters based on discrete linear
437 convolution, that means that computed pixel value depends on linear
438 combination of the image pixels.
441 [latex, discrete_linear_convolution.png, 140]
442 -------------------------------------------------------------------------------
444 O(x,y)=\sum_{i=-\infty}^{\infty}\sum_{j=-\infty}^{\infty}I(x+i,y+j) \cdot K(i,j)
446 -------------------------------------------------------------------------------
448 The K denotes convolution kernel and in practice, due to computational
449 complexity i and j are bounded in relatively small intervals. For example i
450 and j are in (-1,1) and the kernel size is 3x3.
452 Note that pixel values outside the image are undefined. The linear convolution
453 in GFXprim simply uses the closest border pixel values for all pixels outside
456 Particular convolution kernel is called separable if it could be decomposed
457 into two one dimensional kernels (these when combined yields back the original
458 kernel). Such convolution then could be applied as two one dimensional
459 convolutions which is faster operation (especially for big kernels).
461 Generic Linear Convolution
462 ^^^^^^^^^^^^^^^^^^^^^^^^^^
464 Following paragraph describes linear convolution implementation as well as a
465 little of the math background skip it if you just need to use one of the
466 ready-to-use filters.
469 -------------------------------------------------------------------------------
470 #include <filters/GP_Linear.h>
474 int GP_FilterLinearConvolution_Raw(const GP_Context *src,
475 GP_Coord x_src, GP_Coord y_src,
476 GP_Size w_src, GP_Size h_src,
478 GP_Coord x_dst, GP_Coord y_dst,
479 float kernel[], uint32_t kw, uint32_t kh,
480 float kern_div, GP_ProgressCallback *callback);
481 -------------------------------------------------------------------------------
483 Internal generic convolution filter, this is a base for all linear convolution
484 filters with non-separable kernel.
486 The src coordinate and sizes denotes rectangle in the source context that the
489 The dst coordinates defines offset into the dst context.
491 The kernel is two-dimensional array of a size kw * kh indexed as
494 The kern_div is a coefficient that is used to divide the resulting values often
495 used to normalize the result.
497 This filter works 'in-place'.
499 The pixel value is computed as:
500 [latex, discrete_linear_convolution_alg1.png, 140]
501 -------------------------------------------------------------------------------
503 O(x,y)={1 \over kern\_div} \cdot \sum_{i=0}^{kw - 1}\sum_{j=0}^{kh - 1}
504 I(x + i - \lfloor kw/2 \rfloor, y + j - \lfloor kh/2 \rfloor)
507 -------------------------------------------------------------------------------
509 Which is the same as:
511 [latex, discrete_linear_convolution_alg2.png, 140]
512 -------------------------------------------------------------------------------
514 O(x,y)={1 \over kern\_div} \cdot
515 \sum_{i=-\lfloor kw/2 \rfloor}^{\lfloor kw/2 \rfloor}
516 \sum_{j=-\lfloor kh/2 \rfloor}^{\lfloor kh/2 \rfloor}
518 \cdot kernel(i + \lfloor kw/2 \rfloor, j + \lfloor kh/2 \rfloor)
520 -------------------------------------------------------------------------------
522 NOTE: The number of kernel rows and columns is expected to be odd number.
525 -------------------------------------------------------------------------------
526 #include <filters/GP_Linear.h>
530 int GP_FilterHLinearConvolution_Raw(const GP_Context *src,
531 GP_Coord x_src, GP_Coord y_src,
532 GP_Size w_src, GP_Size h_src,
534 GP_Coord x_dst, GP_Coord y_dst,
535 float kernel[], uint32_t kw, float kern_div,
536 GP_ProgressCallback *callback);
538 int GP_FilterVLinearConvolution_Raw(const GP_Context *src,
539 GP_Coord x_src, GP_Coord y_src,
540 GP_Size w_src, GP_Size h_src,
542 GP_Coord x_dst, GP_Coord y_dst,
543 float kernel[], uint32_t kh, float kern_div,
544 GP_ProgressCallback *callback);
546 int GP_FilterVHLinearConvolution_Raw(const GP_Context *src,
547 GP_Coord x_src, GP_Coord y_src,
548 GP_Size w_src, GP_Size h_src,
550 GP_Coord x_dst, GP_Coord y_dst,
551 float hkernel[], uint32_t kw, float hkern_div,
552 float vkernel[], uint32_t kh, float vkern_div,
553 GP_ProgressCallback *callback);
555 void GP_FilterKernelPrint_Raw(float kernel[], int kw, int kh, float kern_div);
556 -------------------------------------------------------------------------------
558 Internal special functions for one dimensional vertical and horizontal
559 convolution these two functions are base for all separable convolution filters.
561 The src coordinate and sizes denotes rectangle in the source context that the
564 The dst coordinates are offset into the dst.
566 The kernel is one-dimensional array of floats of size kw or kh.
568 The kern_div is a coefficient that is used to divide the resulting values.
570 The last function does both vertical and horizontal convolution and takes care
571 of correct progress callback.
573 These filters work 'in-place'.
575 The pixel value is computed as:
576 [latex, discrete_linear_1D_convolution_alg1.png, 140]
577 -------------------------------------------------------------------------------
579 O(x,y)={1 \over kern\_div} \cdot \sum_{i=0}^{kw - 1}
580 I(x + i - \lfloor kw/2 \rfloor, y)
585 O(x,y)={1 \over kern\_div} \cdot \sum_{j=0}^{kw - 1}
586 I(x, y + j - \lfloor kh/2 \rfloor)
589 -------------------------------------------------------------------------------
591 Which is the same as:
593 [latex, discrete_linear_1D_convolution_alg2.png, 140]
594 -------------------------------------------------------------------------------
596 O(x,y)={1 \over kern\_div} \cdot
597 \sum_{i=-\lfloor kw/2 \rfloor}^{\lfloor kw/2 \rfloor}
599 \cdot kernel(i + \lfloor kw/2 \rfloor)
603 O(x,y)={1 \over kern\_div} \cdot
604 \sum_{j=-\lfloor kh/2 \rfloor}^{\lfloor kh/2 \rfloor}
606 \cdot kernel(i, j + \lfloor kh/2 \rfloor)
608 -------------------------------------------------------------------------------
610 NOTE: The number of kernel rows and columns is expected to be odd number.
612 NOTE: The linear convolutions are internally implemented using integer
613 arithmetics, which works fine, but you need to take a care not to
614 overflow 32bit signed integer. If the pixel channel size is 8bit
615 long and 10bits are used for the fixed point part of the number
616 the rest must fit into about 10 bits to be safe.
619 -------------------------------------------------------------------------------
620 #include <filters/GP_Convolution.h>
624 typedef struct GP_FilterKernel2D {
631 int GP_FilterConvolutionEx(const GP_Context *src,
632 GP_Coord x_src, GP_Coord y_src,
633 GP_Size w_src, GP_Coord h_src,
635 GP_Coord x_dst, GP_Coord y_dst,
636 const GP_FilterKernel2D *kernel,
637 GP_ProgressCallback *callback);
639 GP_Context *GP_FilterConvolutionExAlloc(const GP_Context *src,
640 GP_Coord x_src, GP_Coord y_src,
641 GP_Size w_src, GP_Size h_src,
642 const GP_FilterKernel2D *kernel,
643 GP_ProgressCallback *callback);
645 int GP_FilterConvolution(const GP_Context *src, GP_Context *dst,
646 const GP_FilterKernel2D *kernel,
647 GP_ProgressCallback *callback);
649 GP_Context *GP_FilterConvolutionAlloc(const GP_Context *src,
650 const GP_FilterKernel2D *kernel,
651 GP_ProgressCallback *callback);
653 void GP_FilterKernel2DPrint(const GP_FilterKernel2D *kernel);
654 -------------------------------------------------------------------------------
656 Linear convolution filters, you should preferably use this API over the _Raw
659 The Ex variants takes a rectangle on which the filter should operate as well
660 as offset into the destination. The destination must be large enough so that
661 starting with offset there is at least w_dst and h_dst pixels.
663 The kernel is a pointer to a structure initialized with the kernel size, divider
664 and array of kernel values.
666 The last function prints convolution kernel in human-readable format into the
669 WARNING: If filter is executed in-place the work cannot be distributed between
670 threads (as some of the threads will overwrite values read by other
671 threads). In this case convolution filters runs in one thread
672 regardless of if threads are eanbled or not.
675 -------------------------------------------------------------------------------
679 * Example box smoothing filter.
681 static void box_smoothing(GP_Context *img)
683 float box_filter[] = {
689 GP_FilterKernel2D box_kernel = {
693 .kernel = box_filter,
696 GP_FilterConvolution(img, img, &box_kernel, NULL);
698 -------------------------------------------------------------------------------
700 Example function that implements simple 'in-place' smoothing filter.
706 -------------------------------------------------------------------------------
707 #include <GP_Filters.h>
711 int GP_FilterLaplace(const GP_Context *src, GP_Context *dst,
712 GP_ProgressCallback *callback);
714 GP_Context *GP_FilterLaplaceAlloc(const GP_Context *src,
715 GP_ProgressCallback *callback);
716 -------------------------------------------------------------------------------
718 Discrete Laplace filter that produces a second derivative of the original
721 The convolution kernel is defined as:
723 [latex, laplacian_kernel.png, 130]
724 -------------------------------------------------------------------------------
744 -------------------------------------------------------------------------------
746 NOTE: This filter is not separable but could be written as a sum of two one
747 dimensional filters as the kernel definition suggests.
749 Laplacian Edge Sharpening
750 ^^^^^^^^^^^^^^^^^^^^^^^^^
753 -------------------------------------------------------------------------------
754 #include <GP_Filters.h>
758 int GP_FilterEdgeSharpening(const GP_Context *src, GP_Context *dst,
759 float w, GP_ProgressCallback *callback);
761 GP_Context *GP_FilterEdgeSharpeningAlloc(const GP_Context *src, float w,
762 GP_ProgressCallback *callback);
763 -------------------------------------------------------------------------------
765 Laplace based edge sharpening filter, subtracts weighted second derivative
766 from the original image.
768 The w paramerter is multiplicative weight applied on the second derivative.
769 Reasonable results are when the parameter is between '0.1' and '1'.
771 [latex, laplacian_edge_sharpening.png, 140]
772 -------------------------------------------------------------------------------
774 O(x,y) = I(x,y) - w * I''(x,y)
776 -------------------------------------------------------------------------------
778 include::images/edge_sharpening/images.txt[]
784 -------------------------------------------------------------------------------
785 #include <filters/GP_Blur.h>
789 int GP_FilterGaussianBlurEx(const GP_Context *src,
790 GP_Coord x_src, GP_Coord y_src,
791 GP_Size w_src, GP_Size h_src,
793 GP_Coord x_dst, GP_Coord y_dst,
794 float x_sigma, float y_sigma,
795 GP_ProgressCallback *callback);
797 GP_Context *GP_FilterGaussianBlurExAlloc(const GP_Context *src,
798 GP_Coord x_src, GP_Coord y_src,
799 GP_Size w_src, GP_Size h_src,
800 float x_sigma, float y_sigma,
801 GP_ProgressCallback *callback);
803 int GP_FilterGaussianBlur(const GP_Context *src, GP_Context *dst,
804 float x_sigma, float y_sigma,
805 GP_ProgressCallback *callback)
807 GP_Context *GP_FilterGaussianBlurAlloc(const GP_Context *src,
808 float x_sigma, float y_sigma,
809 GP_ProgressCallback *callback)
810 -------------------------------------------------------------------------------
812 Gaussian blur (low pass) filters implemented as bilinear separable
815 The sigma denotes amount of the blur (the radius is computed accordingly
818 The sigma values can be set for vertical and horizontal direction
819 independently which may be useful when Gaussian blur is used as a low pass
820 filter before image is resampled non proportionally.
822 include::images/blur/images.txt[]
824 Interpolation filters
825 ~~~~~~~~~~~~~~~~~~~~~
827 Filters to link:filters_resize.html[resize image].
829 Nearest Neighbour Interpolation
830 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
832 Fast, but produces "pixelated" images. May however work better for images with
833 sharp edges mostly consisting of big one color regions (it doesn't blur the
834 result on upscaling).
836 Also is commonly used to show preview before you resample the image correctly.
838 Bilinear Interpolation
839 ^^^^^^^^^^^^^^^^^^^^^^
841 Bilinear is faster than bicubic interpolation and produces quite good results
842 especially the low pass variant doesn't need additional filter on down-sampling.
844 Bicubic Interpolation
845 ^^^^^^^^^^^^^^^^^^^^^
847 Works well as is on image upscaling. To get decent result on downscaling
848 low-pass filter (Gaussian blur) must be used on original image before actual
849 downscaling. To do this reasonably fast we could cheat a little: first resize
850 big images a little without the low-pass filter, then apply low-pass filter and
851 finally downscale it to desired size.
857 link:filters_dithering.html[Dithering filters] are filters for better loosy
858 (source pixel type has more bits to represent color or grayscale value) pixel
865 -------------------------------------------------------------------------------
866 #include <filters/GP_Median.h>
870 int GP_FilterMedianEx(const GP_Context *src,
871 GP_Coord x_src, GP_Coord y_src,
872 GP_Size w_src, GP_Size h_src,
874 GP_Coord x_dst, GP_Coord y_dst,
876 GP_ProgressCallback *callback);
878 GP_Context *GP_FilterMedianExAlloc(const GP_Context *src,
879 GP_Coord x_src, GP_Coord y_src,
880 GP_Size w_src, GP_Size h_src,
882 GP_ProgressCallback *callback);
884 int GP_FilterMedian(const GP_Context *src,
887 GP_ProgressCallback *callback);
889 GP_Context *GP_FilterMedianAlloc(const GP_Context *src,
891 GP_ProgressCallback *callback);
892 -------------------------------------------------------------------------------
894 Constant time median filter (the computational complexity is independent of
897 The xmed and ymed are radius values for x and y. The algorithm uses xmed
898 respectively ymed pixel neighbors from each side so the result is median of
899 rectangle of 2 * xmed + 1 x 2 * ymed + 1 pixels.
901 include::images/median/images.txt[]