4 Pixel filters for 'gp_pixmap'.
6 The pixmap filter is basically a function that operates on pixmap 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 pixmap 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 pixmap 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,
32 When using non-allocating variant of the filter, the destination pixmap 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 pixmap. Note that this is not
39 expected to work if you do several overlapping sub-pixmaps and pass these as
40 arguments. Filter used 'in-place' may also cause the filter to run
41 single-threaded which is explicit limitation for all but point filters.
44 -------------------------------------------------------------------------------
48 int gp_filter_foo(const gp_pixmap *src, gp_pixmap *dst,
50 gp_progress_cb *callback);
52 gp_pixmap *gp_filter_foo_alloc(const gp_pixmap *src,
54 gp_progress_cb *callback);
55 -------------------------------------------------------------------------------
61 Point operations are filters that works with pixels as with independent values
62 (the value of destination pixel depends only on the pixel on the same
63 coordinates in source image). All of these filters works 'in-place' and the
64 result has always the same size as the source.
70 -------------------------------------------------------------------------------
73 #include <filters/GP_Point.h>
75 int gp_filter_invert(const gp_pixmap *src, gp_pixmap *dst,
76 gp_progress_cb *callback);
78 gp_pixmap *gp_filter_invert_alloc(const gp_pixmap *src,
79 gp_progress_cb *callback);
80 -------------------------------------------------------------------------------
82 The pixel channel values are counted as +chann_max - val+.
84 include::images/invert/images.txt[]
90 -------------------------------------------------------------------------------
93 #include <filters/GP_Point.h>
95 int gp_filter_brightness(const gp_pixmap *src, gp_pixmap *dst,
96 float p, gp_progress_cb *callback);
98 gp_pixmap *gp_filter_brightness_alloc(const gp_pixmap *src, float p,
99 gp_progress_cb *callback);
100 -------------------------------------------------------------------------------
102 The pixel channel values are counted as +val + chann_max * p+.
104 include::images/brightness/images.txt[]
110 -------------------------------------------------------------------------------
113 #include <filters/GP_Point.h>
115 int gp_filter_contrast(const gp_pixmap *src, gp_pixmap *dst,
116 float p, gp_progress_cb *callback);
118 gp_pixmap *gp_filter_contrast_alloc(const gp_pixmap *src, float p,
119 gp_progress_cb *callback);
120 -------------------------------------------------------------------------------
122 The pixel channel values are counted as +val * p+.
124 include::images/contrast/images.txt[]
130 -------------------------------------------------------------------------------
133 #include <filters/GP_Point.h>
135 int gp_filter_brightness_contrast(const gp_pixmap *src, gp_pixmap *dst,
137 gp_progress_cb *callback);
139 gp_pixmap *gp_filter_brightness_contrast_alloc(const gp_pixmap *src,
141 gp_progress_cb *callback);
142 -------------------------------------------------------------------------------
144 The pixel channel values are counted as +val * c + chann_max * b+.
146 include::images/brightness_contrast/images.txt[]
152 -------------------------------------------------------------------------------
155 #include <filters/GP_Point.h>
157 int gp_filter_posterize(const gp_pixmap *src, gp_pixmap *dst,
158 unsigned int levels, gp_progress_cb *callback);
160 gp_pixmap *gp_filter_posterize_alloc(const gp_pixmap *src, unsigned int levels,
161 gp_progress_cb *callback);
162 -------------------------------------------------------------------------------
164 The pixel channel values are quantized into number of levels.
166 include::images/posterize/images.txt[]
169 Gaussian additive noise filter
170 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173 -------------------------------------------------------------------------------
174 #include <gp_filter_s.h>
176 #include <filters/GP_GaussianNoise.h>
178 int gp_filter_gaussian_noise_add_ex(const gp_pixmap *src,
179 gp_coord x_src, gp_coord y_src,
180 gp_size w_src, gp_size h_src,
182 gp_coord x_dst, gp_coord y_dst,
183 float sigma, float mu,
184 gp_progress_cb *callback);
186 gp_pixmap *gp_filter_gaussian_noise_add_ex_alloc(const gp_pixmap *src,
187 gp_coord x_src, gp_coord y_src,
188 gp_size w_src, gp_size h_src,
189 float sigma, float mu,
190 gp_progress_cb *callback);
192 static inline int gp_filter_gaussian_noise_add(const gp_pixmap *src,
194 float sigma, float mu,
195 gp_progress_cb *callback);
197 static inline gp_pixmap *
198 gp_filter_gaussian_noise_add_alloc(const gp_pixmap *src,
199 float sigma, float mu,
200 gp_progress_cb *callback);
201 -------------------------------------------------------------------------------
203 Gaussian additive noise filter adds gaussian distributed noise to an image
204 with a defined sigma and mu. Both sigma and mu weights mapped to [0,1]
207 TIP: See the link:example_gaussian_noise.html[gaussian noise example].
209 include::images/gaussian_noise/images.txt[]
214 Arithmetic filters do take two pixmaps as an input and combines them into one
217 The pixel type of both input pixmaps must match.
219 If size of the input pixmaps differs, minimum is used.
222 -------------------------------------------------------------------------------
223 #include <filters/GP_Arithmetic.h>
227 int gp_filter_addition(const gp_pixmap *src_a,
228 const gp_pixmap *src_b,
230 gp_progress_cb *callback);
232 gp_pixmap *gp_filter_addition_alloc(const gp_pixmap *src_a,
233 const gp_pixmap *src_b,
234 gp_progress_cb *callback);
235 -------------------------------------------------------------------------------
237 Produces saturated (clamped) addition of two pixmaps.
240 -------------------------------------------------------------------------------
241 #include <filters/GP_Arithmetic.h>
245 int gp_filter_multiply(const gp_pixmap *src_a,
246 const gp_pixmap *src_b,
248 gp_progress_cb *callback);
250 gp_pixmap *gp_filter_multiply_alloc(const gp_pixmap *src_a,
251 const gp_pixmap *src_b,
252 gp_progress_cb *callback);
253 -------------------------------------------------------------------------------
255 Produces saturated (clamped) multiplication of two pixmaps.
258 -------------------------------------------------------------------------------
259 #include <filters/GP_Arigthmetic.h>
263 int gp_filter_difference(const gp_pixmap *src_a,
264 const gp_pixmap *src_b,
266 gp_progress_cb *callback);
268 gp_pixmap *gp_filter_difference_alloc(const gp_pixmap *src_a,
269 const gp_pixmap *src_b,
270 gp_progress_cb *callback);
272 -------------------------------------------------------------------------------
274 Produces symmetric difference (i.e. abs(a - b)).
277 -------------------------------------------------------------------------------
278 #include <filters/GP_Arigthmetic.h>
282 int gp_filter_max(const gp_pixmap *src_a,
283 const gp_pixmap *src_b,
285 gp_progress_cb *callback);
287 gp_pixmap *gp_filter_max_alloc(const gp_pixmap *src_a,
288 const gp_pixmap *src_b,
289 gp_progress_cb *callback);
291 int gp_filter_min(const gp_pixmap *src_a,
292 const gp_pixmap *src_b,
294 gp_progress_cb *callback);
296 gp_pixmap *gp_filter_min_alloc(const gp_pixmap *src_a,
297 const gp_pixmap *src_b,
298 gp_progress_cb *callback);
299 -------------------------------------------------------------------------------
301 Maximum and minimum filter.
303 Rotation and Symmetry filters
304 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
307 -------------------------------------------------------------------------------
308 #include <filters/GP_Rotate.h>
312 int gp_filter_mirror_h(const gp_pixmap *src, gp_pixmap *dst,
313 gp_progress_cb *callback);
315 gp_pixmap *gp_filter_mirror_h_alloc(const gp_pixmap *src,
316 gp_progress_cb *callback);
317 -------------------------------------------------------------------------------
319 Mirrors pixmap horizontally.
323 The destination has to have the same pixel type and the size must be at least
326 include::images/mirror_h/images.txt[]
329 -------------------------------------------------------------------------------
330 #include <filters/GP_Rotate.h>
334 int gp_filter_mirror_v(const gp_pixmap *src, gp_pixmap *dst,
335 gp_progress_cb *callback);
337 gp_pixmap *gp_filter_mirror_v_alloc(const gp_pixmap *src,
338 gp_progress_cb *callback);
339 -------------------------------------------------------------------------------
341 Mirrors pixmap vertically.
345 The destination has to have the same pixel type and the size must be at least
348 include::images/mirror_v/images.txt[]
351 -------------------------------------------------------------------------------
352 #include <filters/GP_Rotate.h>
356 int gp_filter_rotate_90(const gp_pixmap *src, gp_pixmap *dst,
357 gp_progress_cb *callback);
359 gp_pixmap *gp_filter_rotate_90_alloc(const gp_pixmap *src,
360 gp_progress_cb *callback);
361 -------------------------------------------------------------------------------
363 Rotate pixmap by 90 degrees.
365 Doesn't work 'in-place' (yet).
367 The destination has to have the same pixel type and size must be large enough to
368 fit rotated pixmap (i.e. W and H are swapped).
370 include::images/rotate_90/images.txt[]
373 -------------------------------------------------------------------------------
374 #include <filters/GP_Rotate.h>
378 int gp_filter_rotate_180(const gp_pixmap *src, gp_pixmap *dst,
379 gp_progress_cb *callback);
381 gp_pixmap *gp_filter_rotate_180_alloc(const gp_pixmap *src,
382 gp_progress_cb *callback);
383 -------------------------------------------------------------------------------
385 Rotate pixmap by 180 degrees.
387 Doesn't work 'in-place' (yet).
389 The destination has to have the same pixel type and the size must be at least
392 include::images/rotate_180/images.txt[]
395 -------------------------------------------------------------------------------
396 #include <filters/GP_Rotate.h>
400 int gp_filter_rotate_270(const gp_pixmap *src, gp_pixmap *dst,
401 gp_progress_cb *callback);
403 gp_pixmap *gp_filter_rotate_270_alloc(const gp_pixmap *src,
404 gp_progress_cb *callback);
405 -------------------------------------------------------------------------------
407 Rotate pixmap by 270 degrees.
409 Doesn't work 'in-place' (yet).
411 The destination has to have the same pixel type and destination size must be
412 large enough to fit rotated pixmap (i.e. W and H are swapped).
414 include::images/rotate_270/images.txt[]
417 -------------------------------------------------------------------------------
418 #include <filters/GP_Rotate.h>
422 typedef enum gp_filter_symmetries {
424 GP_ROTATE_CW = GP_ROTATE_90,
427 GP_ROTATE_CCW = GP_ROTATE_270,
430 } gp_filter_symmetries;
432 gp_pixmap *gp_filter_symmetry_alloc(const gp_pixmap *src,
433 gp_filter_symmetries symmetry,
434 gp_progress_cb *callback);
436 int gp_filter_symmetry(const gp_pixmap *src, gp_pixmap *dst,
437 gp_filter_symmetries symmetry,
438 gp_progress_cb *callback);
439 -------------------------------------------------------------------------------
441 Catch all function for symmetry filters.
447 Linear filters family consists of filters based on discrete linear
448 convolution, that means that computed pixel value depends on linear
449 combination of the image pixels.
452 [latex, discrete_linear_convolution.png, 140]
453 -------------------------------------------------------------------------------
455 O(x,y)=\sum_{i=-\infty}^{\infty}\sum_{j=-\infty}^{\infty}I(x+i,y+j) \cdot K(i,j)
457 -------------------------------------------------------------------------------
459 The K denotes convolution kernel and in practice, due to computational
460 complexity i and j are bounded in relatively small intervals. For example i
461 and j are in (-1,1) and the kernel size is 3x3.
463 Note that pixel values outside the image are undefined. The linear convolution
464 in GFXprim simply uses the closest border pixel values for all pixels outside
467 Particular convolution kernel is called separable if it could be decomposed
468 into two one dimensional kernels (these when combined yields back the original
469 kernel). Such convolution then could be applied as two one dimensional
470 convolutions which is faster operation (especially for big kernels).
475 Following paragraph describes linear convolution implementation as well as a
476 little of the math background skip it if you just need to use one of the
477 ready-to-use filters.
480 -------------------------------------------------------------------------------
481 #include <filters/GP_Linear.h>
485 int gp_filter_linear_convolution_raw(const gp_pixmap *src,
486 gp_coord x_src, gp_coord y_src,
487 gp_size w_src, gp_size h_src,
489 gp_coord x_dst, gp_coord y_dst,
490 float kernel[], uint32_t kw, uint32_t kh,
491 float kern_div, gp_progress_cb *callback);
492 -------------------------------------------------------------------------------
494 Internal generic convolution filter, this is a base for all linear convolution
495 filters with non-separable kernel.
497 The src coordinate and sizes denotes rectangle in the source pixmap that the
500 The dst coordinates defines offset into the dst pixmap.
502 The kernel is two-dimensional array of a size kw * kh indexed as
505 The kern_div is a coefficient that is used to divide the resulting values often
506 used to normalize the result.
508 This filter works 'in-place'.
510 The pixel value is computed as:
511 [latex, discrete_linear_convolution_alg1.png, 140]
512 -------------------------------------------------------------------------------
514 O(x,y)={1 \over kern\_div} \cdot \sum_{i=0}^{kw - 1}\sum_{j=0}^{kh - 1}
515 I(x + i - \lfloor kw/2 \rfloor, y + j - \lfloor kh/2 \rfloor)
518 -------------------------------------------------------------------------------
520 Which is the same as:
522 [latex, discrete_linear_convolution_alg2.png, 140]
523 -------------------------------------------------------------------------------
525 O(x,y)={1 \over kern\_div} \cdot
526 \sum_{i=-\lfloor kw/2 \rfloor}^{\lfloor kw/2 \rfloor}
527 \sum_{j=-\lfloor kh/2 \rfloor}^{\lfloor kh/2 \rfloor}
529 \cdot kernel(i + \lfloor kw/2 \rfloor, j + \lfloor kh/2 \rfloor)
531 -------------------------------------------------------------------------------
533 NOTE: The number of kernel rows and columns is expected to be odd number.
535 include::images/convolution/images.txt[]
538 -------------------------------------------------------------------------------
539 #include <filters/GP_Linear.h>
543 int gp_filter_hlinear_convolution_raw(const gp_pixmap *src,
544 gp_coord x_src, gp_coord y_src,
545 gp_size w_src, gp_size h_src,
547 gp_coord x_dst, gp_coord y_dst,
548 float kernel[], uint32_t kw, float kern_div,
549 gp_progress_cb *callback);
551 int gp_filter_vlinear_convolution_raw(const gp_pixmap *src,
552 gp_coord x_src, gp_coord y_src,
553 gp_size w_src, gp_size h_src,
555 gp_coord x_dst, gp_coord y_dst,
556 float kernel[], uint32_t kh, float kern_div,
557 gp_progress_cb *callback);
559 int gp_filter_vhlinear_convolution_raw(const gp_pixmap *src,
560 gp_coord x_src, gp_coord y_src,
561 gp_size w_src, gp_size h_src,
563 gp_coord x_dst, gp_coord y_dst,
564 float hkernel[], uint32_t kw, float hkern_div,
565 float vkernel[], uint32_t kh, float vkern_div,
566 gp_progress_cb *callback);
568 void gp_filter_kernel_print_raw(float kernel[], int kw, int kh, float kern_div);
569 -------------------------------------------------------------------------------
571 Internal special functions for one dimensional vertical and horizontal
572 convolution these two functions are base for all separable convolution filters.
574 The src coordinate and sizes denotes rectangle in the source pixmap that the
577 The dst coordinates are offset into the dst.
579 The kernel is one-dimensional array of floats of size kw or kh.
581 The kern_div is a coefficient that is used to divide the resulting values.
583 The last function does both vertical and horizontal convolution and takes care
584 of correct progress callback.
586 These filters work 'in-place'.
588 The pixel value is computed as:
589 [latex, discrete_linear_1D_convolution_alg1.png, 140]
590 -------------------------------------------------------------------------------
592 O(x,y)={1 \over kern\_div} \cdot \sum_{i=0}^{kw - 1}
593 I(x + i - \lfloor kw/2 \rfloor, y)
598 O(x,y)={1 \over kern\_div} \cdot \sum_{j=0}^{kw - 1}
599 I(x, y + j - \lfloor kh/2 \rfloor)
602 -------------------------------------------------------------------------------
604 Which is the same as:
606 [latex, discrete_linear_1D_convolution_alg2.png, 140]
607 -------------------------------------------------------------------------------
609 O(x,y)={1 \over kern\_div} \cdot
610 \sum_{i=-\lfloor kw/2 \rfloor}^{\lfloor kw/2 \rfloor}
612 \cdot kernel(i + \lfloor kw/2 \rfloor)
616 O(x,y)={1 \over kern\_div} \cdot
617 \sum_{j=-\lfloor kh/2 \rfloor}^{\lfloor kh/2 \rfloor}
619 \cdot kernel(i, j + \lfloor kh/2 \rfloor)
621 -------------------------------------------------------------------------------
623 NOTE: The number of kernel rows and columns is expected to be odd number.
625 NOTE: The linear convolutions are internally implemented using integer
626 arithmetics, which works fine, but you need to take a care not to
627 overflow 32bit signed integer. If the pixel channel size is 8bit
628 long and 10bits are used for the fixed point part of the number
629 the rest must fit into about 10 bits to be safe.
632 -------------------------------------------------------------------------------
633 #include <filters/GP_Convolution.h>
637 typedef struct gp_filter_kernel_2d {
642 } gp_filter_kernel_2d;
644 int gp_filter_convolution_ex(const gp_pixmap *src,
645 gp_coord x_src, gp_coord y_src,
646 gp_size w_src, gp_coord h_src,
648 gp_coord x_dst, gp_coord y_dst,
649 const gp_filter_Kernel2D *kernel,
650 gp_progress_cb *callback);
652 gp_pixmap *gp_filter_convolution_ex_alloc(const gp_pixmap *src,
653 gp_coord x_src, gp_coord y_src,
654 gp_size w_src, gp_size h_src,
655 const gp_filter_Kernel2D *kernel,
656 gp_progress_cb *callback);
658 int gp_filter_convolution(const gp_pixmap *src, gp_pixmap *dst,
659 const gp_filter_Kernel2D *kernel,
660 gp_progress_cb *callback);
662 gp_pixmap *gp_filter_convolution_alloc(const gp_pixmap *src,
663 const gp_filter_Kernel2D *kernel,
664 gp_progress_cb *callback);
666 void gp_filter_kernel_2d_print(const gp_filter_kernel_2d *kernel);
667 -------------------------------------------------------------------------------
669 Linear convolution filters, you should preferably use this API over the _Raw
672 The _ex variants takes a rectangle on which the filter should operate as well
673 as offset into the destination. The destination must be large enough so that
674 starting with offset there is at least w_dst and h_dst pixels.
676 The kernel is a pointer to a structure initialized with the kernel size, divider
677 and array of kernel values.
679 The last function prints convolution kernel in human-readable format into the
682 WARNING: If filter is executed in-place the work cannot be distributed between
683 threads (as some of the threads will overwrite values read by other
684 threads). In this case convolution filters runs in one thread
685 regardless of if threads are eanbled or not.
688 -------------------------------------------------------------------------------
692 * _example box smoothing filter.
694 static void box_smoothing(gp_pixmap *img)
696 float box_filter[] = {
702 gp_filter_kernel_2d box_kernel = {
706 .kernel = box_filter,
709 gp_filter_convolution(img, img, &box_kernel, NULL);
711 -------------------------------------------------------------------------------
713 _example function that implements simple 'in-place' smoothing filter.
719 -------------------------------------------------------------------------------
720 #include <gp_filter_s.h>
724 int gp_filter_laplace(const gp_pixmap *src, gp_pixmap *dst,
725 gp_progress_cb *callback);
727 gp_pixmap *gp_filter_laplace_alloc(const gp_pixmap *src,
728 gp_progress_cb *callback);
729 -------------------------------------------------------------------------------
731 Discrete Laplace filter that produces a second derivative of the original
734 The convolution kernel is defined as:
736 [latex, laplacian_kernel.png, 130]
737 -------------------------------------------------------------------------------
757 -------------------------------------------------------------------------------
759 NOTE: This filter is not separable but could be written as a sum of two one
760 dimensional filters as the kernel definition suggests.
762 Laplacian Edge Sharpening
763 ^^^^^^^^^^^^^^^^^^^^^^^^^
766 -------------------------------------------------------------------------------
767 #include <gp_filter_s.h>
771 int gp_filter_edge_sharpening(const gp_pixmap *src, gp_pixmap *dst,
772 float w, gp_progress_cb *callback);
774 gp_pixmap *gp_filter_edge_sharpening_alloc(const gp_pixmap *src, float w,
775 gp_progress_cb *callback);
776 -------------------------------------------------------------------------------
778 Laplace based edge sharpening filter, subtracts weighted second derivative
779 from the original image.
781 The w paramerter is multiplicative weight applied on the second derivative.
782 Reasonable results are when the parameter is between '0.1' and '1'.
784 [latex, laplacian_edge_sharpening.png, 140]
785 -------------------------------------------------------------------------------
787 O(x,y) = I(x,y) - w * I''(x,y)
789 -------------------------------------------------------------------------------
791 include::images/edge_sharpening/images.txt[]
797 -------------------------------------------------------------------------------
798 #include <filters/GP_Blur.h>
802 int gp_filter_gaussian_blur_ex(const gp_pixmap *src,
803 gp_coord x_src, gp_coord y_src,
804 gp_size w_src, gp_size h_src,
806 gp_coord x_dst, gp_coord y_dst,
807 float x_sigma, float y_sigma,
808 gp_progress_cb *callback);
810 gp_pixmap *gp_filter_gaussian_blur_ex_alloc(const gp_pixmap *src,
811 gp_coord x_src, gp_coord y_src,
812 gp_size w_src, gp_size h_src,
813 float x_sigma, float y_sigma,
814 gp_progress_cb *callback);
816 int gp_filter_gaussian_blur(const gp_pixmap *src, gp_pixmap *dst,
817 float x_sigma, float y_sigma,
818 gp_progress_cb *callback)
820 gp_pixmap *gp_filter_gaussian_blur_alloc(const gp_pixmap *src,
821 float x_sigma, float y_sigma,
822 gp_progress_cb *callback)
823 -------------------------------------------------------------------------------
825 Gaussian blur (low pass) filters implemented as bilinear separable
828 The sigma denotes amount of the blur (the radius is computed accordingly
831 The sigma values can be set for vertical and horizontal direction
832 independently which may be useful when Gaussian blur is used as a low pass
833 filter before image is resampled non proportionally.
835 include::images/blur/images.txt[]
837 Interpolation filters
838 ~~~~~~~~~~~~~~~~~~~~~
840 Filters to link:filters_resize.html[resize image].
842 Nearest Neighbour Interpolation
843 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
845 Fast, but produces "pixelated" images. May however work better for images with
846 sharp edges mostly consisting of big one color regions (it doesn't blur the
847 result on upscaling).
849 Also is commonly used to show preview before you resample the image correctly.
851 Bilinear Interpolation
852 ^^^^^^^^^^^^^^^^^^^^^^
854 Bilinear is faster than bicubic interpolation and produces quite good results
855 especially the low pass variant doesn't need additional filter on down-sampling.
857 Bicubic Interpolation
858 ^^^^^^^^^^^^^^^^^^^^^
860 Works well as is on image upscaling. To get decent result on downscaling
861 low-pass filter (Gaussian blur) must be used on original image before actual
862 downscaling. To do this reasonably fast we could cheat a little: first resize
863 big images a little without the low-pass filter, then apply low-pass filter and
864 finally downscale it to desired size.
870 link:filters_dithering.html[Dithering filters] are filters for better loosy
871 (source pixel type has more bits to represent color or grayscale value) pixel
878 -------------------------------------------------------------------------------
879 #include <filters/GP_Median.h>
883 int gp_filter_median_ex(const gp_pixmap *src,
884 gp_coord x_src, gp_coord y_src,
885 gp_size w_src, gp_size h_src,
887 gp_coord x_dst, gp_coord y_dst,
889 gp_progress_cb *callback);
891 gp_pixmap *gp_filter_median_ex_alloc(const gp_pixmap *src,
892 gp_coord x_src, gp_coord y_src,
893 gp_size w_src, gp_size h_src,
895 gp_progress_cb *callback);
897 int gp_filter_median(const gp_pixmap *src,
900 gp_progress_cb *callback);
902 gp_pixmap *gp_filter_median_alloc(const gp_pixmap *src,
904 gp_progress_cb *callback);
905 -------------------------------------------------------------------------------
907 Constant time median filter (the computational complexity is independent of
910 The xmed and ymed are radius values for x and y. The algorithm uses xmed
911 respectively ymed pixel neighbors from each side so the result is median of
912 rectangle of 2 * xmed + 1 x 2 * ymed + 1 pixels.
914 include::images/median/images.txt[]