core: Edhance and rewrite debug messages.
[gfxprim.git] / doc / filters.txt
blobfad32b27b05a4a6680a5b88ada867e4be9859756
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 * Each filter returns pointer to destination context or 'NULL' on failure
17 * The first two arguments are source and destination
18 * The last argument is progress callback
20 Each filter function could be used in two modes.
22 By passing non-'NULL' argument as filter destination user requests result to
23 be stored into the destination context. The context must have correct pixel
24 type and the context size must be big enough to store the result.
26 For filters that work 'in-place' (which is explicitly said for each filter)
27 the source and the destination could be the same context. Note that this is
28 not expected to work if you do several overlapping subcontexts and pass these
29 as arguments.
31 When 'NULL' is passed as destination new context for storing the result is
32 allocated and returned. 
34 The return value is either pointer to destination context or 'NULL' either
35 when malloc(2) has failed or if the filter is not implemented for such
36 pixel_type, parameters, etc...
38 [source,c]
39 -------------------------------------------------------------------------------
41  * Filter common API.
42  */
43 GP_Context *GP_FilterFoo(const GP_Context *src, GP_Context *dst,
44                          foo params ...,
45                          GP_ProgressCallback *callback);
46 -------------------------------------------------------------------------------
49 Filters also exists in _Raw variant (that just takes source context,
50 destination context, filters parameters and progress callback). These filter
51 APIs are used for internal implementation and shouldn't be called by user as
52 the destination is expected to be crafted exactly for storing the filter
53 result and there are 'NO' sanity checks in place.
55 'You could use these at your own risk'
57 [source,c]
58 -------------------------------------------------------------------------------
60  * Raw filter common API.
61  */
62 void GP_FilterFoo_Raw(const GP_Context *src, GP_Context *dst,
63                       foo params ...,
64                       GP_ProgressCallback *callback);
65 -------------------------------------------------------------------------------
67 Point operation filters
68 ~~~~~~~~~~~~~~~~~~~~~~~
70 Point operations are filters that works with pixels as with independent values
71 (the value of destination pixel depends only on the pixel on the same
72 coordinates in source image). All of these filters works 'in-place' and the
73 result has always the same size as the source.
75 [source,c]
76 -------------------------------------------------------------------------------
77 #include <GP_Filters.h>
79 GP_Context *GP_FilterBrightness(const GP_Context *src, GP_Context *dst,
80                                 int32_t inc, GP_ProgressCallback *callback);
81 -------------------------------------------------------------------------------
83 Brightness filter, increments all pixel channels by a fixed value.
85 [source,c]
86 -------------------------------------------------------------------------------
87 #include <GP_Filters.h>
89 GP_Context *GP_FilterContrast(const GP_Context *src, GP_Context *dst, 
90                               float mul, GP_ProgressCallback *callback);
91 -------------------------------------------------------------------------------
93 Contrast filter, multiplies all pixel channels by a fixed value.
95 [source,c]
96 -------------------------------------------------------------------------------
97 #include <GP_Filters.h>
99 GP_Context *GP_FilterInvert(const GP_Context *src, GP_Context *dst,
100                             GP_ProgressCallback *callback);
101 -------------------------------------------------------------------------------
103 Inverts the image, for each channel the result value is computed as "chan_max
104 - val".
106 Rotation and Symmetry filters
107 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
109 [source,c]
110 -------------------------------------------------------------------------------
111 #include <GP_Filters.h>
113 int GP_FilterMirrorH(const GP_Context *src, GP_Context *dst,
114                      GP_ProgressCallback *callback);
116 GP_Context *GP_FilterMirrorH_Alloc(const GP_Context *src,
117                                    GP_ProgressCallback *callback);
118 -------------------------------------------------------------------------------
120 Mirrors context horizontally.
122 Works 'in-place'.
124 The destination has to have the same pixel type and the size must be at least
125 as large as source.
127 [source,c]
128 -------------------------------------------------------------------------------
129 #include <GP_Filters.h>
131 int GP_FilterMirrorV(const GP_Context *src, GP_Context *dst,
132                      GP_ProgressCallback *callback);
134 GP_Context *GP_FilterMirrorV_Alloc(const GP_Context *src,
135                                    GP_ProgressCallback *callback);
136 -------------------------------------------------------------------------------
138 Mirrors context vertically.
140 Works 'in-place'.
142 The destination has to have the same pixel type and the size must be at least
143 as large as source.
145 [source,c]
146 -------------------------------------------------------------------------------
147 #include <GP_Filters.h>
149 int GP_FilterRotate90(const GP_Context *src, GP_Context *dst,
150                       GP_ProgressCallback *callback);
152 GP_Context *GP_FilterRotate90_Alloc(const GP_Context *src,
153                                     GP_ProgressCallback *callback);
154 -------------------------------------------------------------------------------
156 Rotate context by 90 degrees.
158 Doesn't work 'in-place' (yet).
160 The destination has to have the same pixel type and size must be large enough to
161 fit rotated context (i.e. W and H are swapped).
163 [source,c]
164 -------------------------------------------------------------------------------
165 #include <GP_Filters.h>
167 int GP_FilterRotate180(const GP_Context *src, GP_Context *dst,
168                        GP_ProgressCallback *callback);
170 GP_Context *GP_FilterRotate180_Alloc(const GP_Context *src,
171                                      GP_ProgressCallback *callback);
172 -------------------------------------------------------------------------------
174 Rotate context by 180 degrees.
176 Doesn't work 'in-place' (yet).
178 The destination has to have the same pixel type and the size must be at least
179 as large as source.
181 [source,c]
182 -------------------------------------------------------------------------------
183 #include <GP_Filters.h>
185 int GP_FilterRotate270(const GP_Context *src, GP_Context *dst,
186                        GP_ProgressCallback *callback);
188 GP_Context *GP_FilterRotate270_Alloc(const GP_Context *src,
189                                      GP_ProgressCallback *callback);
190 -------------------------------------------------------------------------------
192 Rotate context by 270 degrees.
194 Doesn't work 'in-place' (yet).
196 The destination has to have the same pixel type and destination size must be
197 large enough to fit rotated context (eg. W and H are swapped).
199 [source,c]
200 -------------------------------------------------------------------------------
201 typedef enum GP_FilterSymmetries {
202         GP_ROTATE_90,
203         GP_ROTATE_CW = GP_ROTATE_90,
204         GP_ROTATE_180,
205         GP_ROTATE_270,
206         GP_ROTATE_CCW = GP_ROTATE_270,
207         GP_MIRROR_H,
208         GP_MIRROR_V,
209 } GP_FilterSymmetries;
211 GP_Context *GP_FilterSymmetry(const GP_Context *src,
212                               GP_FilterSymmetries symmetry,
213                               GP_ProgressCallback *callback);
215 int GP_FilterSymmetry(const GP_Context *src, GP_Context *dst,
216                       GP_FilterSymmetries symmetry,
217                       GP_ProgressCallback *callback);
218 -------------------------------------------------------------------------------
220 Catch all function for symmetry filters.
223 Linear filters
224 ~~~~~~~~~~~~~~
226 [source,c]
227 -------------------------------------------------------------------------------
228 #include <GP_Filters.h>
230 GP_Context *GP_FilterGaussianBlur(const GP_Context *src, GP_Context *dst,
231                                   float sigma_x, float sigma_y,
232                                   GP_ProgressCallback *callback);
233 -------------------------------------------------------------------------------
235 Gaussian blur filter.
237 Works 'in-place'.
239 'TODO:' this filter is implemented for RGB888 only.
242 Interpolation filters
243 ~~~~~~~~~~~~~~~~~~~~~
245 [source,c]
246 -------------------------------------------------------------------------------
247 #include <GP_Filters.h>
249 typedef enum GP_InterpolationType {
250         GP_INTERP_NN,    /* Nearest Neighbour */
251         GP_INTERP_CUBIC, /* Bicubic           */
252 } GP_InterpolationType;
254 GP_Context *GP_FilterResize(const GP_Context *src, GP_Context *dst,
255                             GP_InterpolationType type,
256                             GP_Size w, GP_Size h,
257                             GP_ProgressCallback *callback);
258 -------------------------------------------------------------------------------
260 Interpolate (resize) the context.
262 Doesn't work 'in-place' (this is quite impossible as the size of the bitmap is
263 changed by the filter).
265 If the filter destination is non 'NULL' and the 'w' and 'h' is smaller than the
266 destination size the source image is interpolated into subcontext of
267 destination defined by 'w' and 'h'.
269 'TODO:' this filter is implemented for RGB888 only.
271 Nearest Neighbour Interpolation
272 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
274 Fast, but produces "pixelated" images. May however work better for images with
275 sharp edges mostly consisting of big one color regions (it doesn't blur the
276 result on upscaling).
278 Bicubic Interpolation
279 ^^^^^^^^^^^^^^^^^^^^^
281 Works well as is on image upscaling. To get decent result on downscaling
282 low-pass filter (Gaussian blur) must be used on original image before actual
283 downscaling. To do this reasonably fast we could cheat a little: first resize
284 big images a little without the low-pass filter, then apply low-pass filter and
285 finally downscale it to desired size.
287 Dithering
288 ~~~~~~~~~
290 Currently there are two dithering algorithms implemented. Both takes an RGB888
291 24bit image as input and are able to produce any RGB or Grayscale image.
292 This filters doesn't work 'in-place' as the result has different pixel type.
294 Floyd-Steinberg
295 ^^^^^^^^^^^^^^^
297 Classical Floyd-Steinberg. Produces good results and is a little faster than
298 the Hilbert-Peano dithering.
300 The error is distributed to neighbor pixels as follows:
302 [width="10%"]
303 |===================
304 |      |   X  | 7/16
305 | 3/16 | 5/16 | 1/16
306 |===================
308 And is throwed away at the image borders.
310 [source,c]
311 -------------------------------------------------------------------------------
312 #include <GP_Filters.h>
314 int GP_FilterFloydSteinberg_RGB888(const GP_Context *src,
315                                    GP_Context *dst,
316                                    GP_ProgressCallback *callback);
317 -------------------------------------------------------------------------------
319 Renders Floyd Steinberg dithering directly into passed context. The
320 destination must be at least as large as source. 
322 If operation was aborted by a callback, non-zero is returned.
324 [source,c]
325 -------------------------------------------------------------------------------
326 #include <GP_Filters.h>
328 GP_Context *GP_FilterFloydSteinberg_RGB888_Alloc(const GP_Context *src,
329                                                  GP_PixelType pixel_type,
330                                                  GP_ProgressCallback *callback);
331 -------------------------------------------------------------------------------
333 Returns pointer to allocated context of given pixel_type.
335 If malloc(2) has failed, or operation was aborted by a callback 'NULL' is
336 returned.
338 Hilbert-Peano
339 ^^^^^^^^^^^^^
341 Hilbert-Peano space filling curve based dithering.
343 The error value is distributed around the Hilbert curve.
345 The result is a little more noisy, but doesn't create repeating patterns like
346 Floyd-Steinberg which looks generally better to human eye. On the other hand
347 edges tend to be less sharp.
349 [source,c]
350 -------------------------------------------------------------------------------
351 #include <GP_Filters.h>
353 int GP_FilterHilbertPeano_RGB888(const GP_Context *src,
354                                  GP_Context *dst,
355                                  GP_ProgressCallback *callback);
356 -------------------------------------------------------------------------------
358 Renders Hilbert Peano dithering directly into passed context. The
359 destination must be at least as large as source. 
361 If operation was aborted by a callback, non-zero is returned.
363 [source,c]
364 -------------------------------------------------------------------------------
365 #include <GP_Filters.h>
367 GP_Context *GP_FilterHilbertPeano_RGB888_Alloc(const GP_Context *src,
368                                                GP_PixelType pixel_type,
369                                                GP_ProgressCallback *callback);
370 -------------------------------------------------------------------------------
372 Returns pointer to allocated context of given pixel_type.
374 If malloc(2) has failed, or operation was aborted by a callback 'NULL' is
375 returned.
377 Example Images
378 ^^^^^^^^^^^^^^
379 All following images were generated using 'grinder'.
380 (Click for bigger size)
382 .Original Image; Floyd-Steinberg, Hilbert-Peano: 1-bit, 2-bit, 4-bit, 8-bit Grayscale; 1-bit, 2-bit, 3-bit (per channel) RGB
383 image:images/dither/lenna_small.png[
384         "Original Image", 
385         link="images/dither/lenna.png"]
386 image:images/dither/lenna_G1_FS_small.png[
387         "1-bit Grayscale Floyd-Steinberg",
388         link="images/dither/lenna_G1_FS.png"]
389 image:images/dither/lenna_G1_HP_small.png[
390         "1-bit Grayscale Hilbert-Peano",
391         link="images/dither/lenna_G1_HP.png"]
392 image:images/dither/lenna_G2_FS_small.png[
393         "2-bit Grayscale Floyd-Steinberg",
394         link="images/dither/lenna_G2_FS.png"]
395 image:images/dither/lenna_G2_HP_small.png[
396         "2-bit Grayscale Hilbert-Peano",
397         link="images/dither/lenna_G2_HP.png"]
398 image:images/dither/lenna_G4_FS_small.png[
399         "4-bit Grayscale Floyd-Steinberg",
400         link="images/dither/lenna_G4_FS.png"]
401 image:images/dither/lenna_G4_HP_small.png[
402         "4-bit Grayscale Hilbert-Peano",
403         link="images/dither/lenna_G4_HP.png"]
404 image:images/dither/lenna_G8_FS_small.png[
405         "8-bit Grayscale Floyd-Steinberg",
406         link="images/dither/lenna_G8_FS.png"]
407 image:images/dither/lenna_G8_HP_small.png[
408         "7-bit Grayscale Hilbert-Peano",
409         link="images/dither/lenna_G8_HP.png"]
410 image:images/dither/lenna_RGB111_FS_small.png[
411         "1-bit RGB Floyd-Steinberg",
412         link="images/dither/lenna_RGB111_FS.png"]
413 image:images/dither/lenna_RGB111_HP_small.png[
414         "1-bit RGB Hilbert-Peano",
415         link="images/dither/lenna_RGB111_HP.png"]
416 image:images/dither/lenna_RGB222_FS_small.png[
417         "2-bit RGB Floyd-Steinberg",
418         link="images/dither/lenna_RGB222_FS.png"]
419 image:images/dither/lenna_RGB222_HP_small.png[
420         "2-bit RGB Hilbert-Peano",
421         link="images/dither/lenna_RGB222_HP.png"]
422 image:images/dither/lenna_RGB333_FS_small.png[
423         "3-bit RGB Floyd-Steinberg",
424         link="images/dither/lenna_RGB333_FS.png"]
425 image:images/dither/lenna_RGB333_HP_small.png[
426         "3-bit RGB Hilbert-Peano",
427         link="images/dither/lenna_RGB333_HP.png"]