This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git.
The branch, master has been updated via 024061fd56190b6434c9b74a25a19374ca4c02c8 (commit) from 9c29fb0086bf7531c018827337848b9ba5681242 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- http://repo.or.cz/w/gfxprim.git/commit/024061fd56190b6434c9b74a25a19374ca4c0...
commit 024061fd56190b6434c9b74a25a19374ca4c02c8 Author: Cyril Hrubis metan@ucw.cz Date: Sun Nov 13 23:51:09 2011 +0100
filters: Dithering from RGB888 to any pixel, enjoy!
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c index 2f8596a..0122417 100644 --- a/demos/grinder/grinder.c +++ b/demos/grinder/grinder.c @@ -361,16 +361,48 @@ static GP_RetCode blur(GP_Context **c, const char *params)
/* dithering */
+//TODO: this should be generated +static const char *dither_formats[] = { + "g1", + "g2", + "g4", + "g8", + "rgb333", + "rgb565", + "rgb666", +}; + +static const GP_PixelType dither_pixel_types[] = { + GP_PIXEL_G1, + GP_PIXEL_G2, + GP_PIXEL_G4, + GP_PIXEL_G8, + GP_PIXEL_xRGB7333, + GP_PIXEL_RGB565, + GP_PIXEL_RGB666, +}; + static struct param dither_params[] = { + {"format", PARAM_ENUM, "pixel type to be used", dither_formats, NULL}, {NULL, 0, NULL, NULL, NULL} };
static GP_RetCode dither(GP_Context **c, const char *params) { - if (param_parse(params, dither_params, "dither", param_err)) + int fmt = -1; + + if (param_parse(params, dither_params, "dither", param_err, &fmt)) + return GP_EINVAL; + + if (fmt == -1) { + print_error("dither: invalid format or format param missing"); return GP_EINVAL; + }
- GP_Context *bw = GP_FilterFloydSteinberg(*c, NULL, progress_callback); + GP_Context *bw; + bw = GP_FilterFloydSteinberg_from_RGB888(*c, NULL, + dither_pixel_types[fmt], + progress_callback);
//TODO: so far we convert the context back to RGB888 //(so we can do further work with it) diff --git a/gfxprim_config.py b/gfxprim_config.py index d0de8d1..2876af0 100644 --- a/gfxprim_config.py +++ b/gfxprim_config.py @@ -76,6 +76,14 @@ config = GfxPrimConfig( ('R', 12, 6), ('G', 6, 6), ('B', 0, 6)]), + + # + # Added for dithering tests + # + PixelType(name='xRGB7333', pixelsize=PS_16BPP, chanslist=[ + ('R', 6, 3), + ('G', 3, 3), + ('B', 0, 3)]), # # Palette types # diff --git a/include/filters/GP_Dither.h b/include/filters/GP_Dither.h index 37fac43..3ecf7bf 100644 --- a/include/filters/GP_Dither.h +++ b/include/filters/GP_Dither.h @@ -32,9 +32,31 @@ #include "GP_Filter.h"
/* - * Experimental Floyd Steinberg that coverts any pixel type to G1 + * Floyd Steinberg */ -GP_Context *GP_FilterFloydSteinberg(const GP_Context *src, GP_Context *dst, - GP_ProgressCallback *callback); +GP_Context *GP_FilterFloydSteinberg_to_G1(const GP_Context *src, GP_Context *dst, + GP_ProgressCallback *callback); + +/* + * Floyd Steinberg + */ +GP_Context *GP_FilterFloydSteinberg_from_RGB888(const GP_Context *src, GP_Context *dst, + GP_PixelType pixel_type, + GP_ProgressCallback *callback); + +/* + * Converts RGB888 to RGB or Grayscale bitmap. + */ +int GP_FilterFloydSteinberg_RGB888_to_XXX_Raw(const GP_Context *src, + GP_Context *dst, + GP_ProgressCallback *callback); + +/* + * Converts any bitmap to 1-bit Grayscale. + */ +int GP_FilterFloydSteinberg_XXX_to_G1_Raw(const GP_Context *src, + GP_Context *dst, + GP_ProgressCallback *callback); +
#endif /* FILTERS_GP_DITHER_H */ diff --git a/libs/filters/GP_Dither.c b/libs/filters/GP_Dither.c index ffe7354..84932ec 100644 --- a/libs/filters/GP_Dither.c +++ b/libs/filters/GP_Dither.c @@ -22,40 +22,31 @@
#include "core/GP_Core.h" #include "core/GP_FnPerBpp.h" +#include "core/GP_Pixel.h"
#include "GP_Dither.h"
#include <string.h>
-static void print_err(float *d, int size) -{ - int i; - - printf("["); - - for (i = 0; i < size; i++) - printf("%2.2f, ", d[i]); - - printf("]n"); -} - /* * Experimental Floyd Steinberg XXX -> G1 */ -int GP_FilterFloydSteinberg_Raw(const GP_Context *src, GP_Context *dst, - GP_ProgressCallback *callback) +int GP_FilterFloydSteinberg_to_G1_Raw(const GP_Context *src, GP_Context *dst, + GP_ProgressCallback *callback) { float errors[2][src->w]; - GP_DEBUG(1, "Floyd Steiberg %ux%u", src->w, src->h); + GP_DEBUG(1, "Floyd Steinberg %s to %s size %ux%u", + GP_PixelTypeName(src->pixel_type), + GP_PixelTypeName(GP_PIXEL_G1), src->w, src->h);
GP_Coord x, y;
memset(errors[0], 0, src->w * sizeof(float)); memset(errors[1], 0, src->w * sizeof(float));
- for (y = 0; y < src->h; y++) { - for (x = 0; x < src->w; x++) { + for (y = 0; y < (GP_Coord)src->h; y++) { + for (x = 0; x < (GP_Coord)src->w; x++) { GP_Pixel pix = GP_GetPixel(src, x, y); float val = GP_ConvertPixel(pix, src->pixel_type, GP_PIXEL_G8);
@@ -71,7 +62,7 @@ int GP_FilterFloydSteinberg_Raw(const GP_Context *src, GP_Context *dst, GP_PutPixel_Raw_1BPP_LE(dst, x, y, 0); }
- if (x + 1 < src->w) + if (x + 1 < (GP_Coord)src->w) errors[y%2][x+1] += 7 * err / 16;
if (x > 1) @@ -79,21 +70,22 @@ int GP_FilterFloydSteinberg_Raw(const GP_Context *src, GP_Context *dst, errors[!(y%2)][x] += 5 * err / 16;
- if (x + 1 < src->w) + if (x + 1 < (GP_Coord)src->w) errors[!(y%2)][x+1] += err / 16; }
memset(errors[y%2], 0, src->w * sizeof(float)); - // if (GP_ProgressCallbackReport(callback, 2 * y, src->h, src->w)) - // return 1; + + if (GP_ProgressCallbackReport(callback, y, src->h, src->w)) + return 1; }
-// GP_ProgressCallbackDone(callback); + GP_ProgressCallbackDone(callback); return 0; }
-GP_Context *GP_FilterFloydSteinberg(const GP_Context *src, GP_Context *dst, - GP_ProgressCallback *callback) +GP_Context *GP_FilterFloydSteinberg_to_G1(const GP_Context *src, GP_Context *dst, + GP_ProgressCallback *callback) { GP_Context *ret = dst;
@@ -106,7 +98,31 @@ GP_Context *GP_FilterFloydSteinberg(const GP_Context *src, GP_Context *dst, } }
- if (GP_FilterFloydSteinberg_Raw(src, ret, callback)) { + if (GP_FilterFloydSteinberg_to_G1_Raw(src, ret, callback)) { + if (dst == NULL) + free(ret); + return NULL; + } + + return ret; +} + +GP_Context *GP_FilterFloydSteinberg_from_RGB888(const GP_Context *src, GP_Context *dst, + GP_PixelType pixel_type, + GP_ProgressCallback *callback) +{ + GP_Context *ret = dst; + + if (ret == NULL) { + ret = GP_ContextAlloc(src->w, src->h, pixel_type); + + if (ret == NULL) { + GP_DEBUG(1, "Malloc failed :("); + return NULL; + } + } + + if (GP_FilterFloydSteinberg_RGB888_to_XXX_Raw(src, ret, callback)) { if (dst == NULL) free(ret); return NULL; diff --git a/libs/filters/GP_Dither.gen.c.t b/libs/filters/GP_Dither.gen.c.t new file mode 100644 index 0000000..8b9e237 --- /dev/null +++ b/libs/filters/GP_Dither.gen.c.t @@ -0,0 +1,120 @@ + +%% extends "base.c.t" + +%% block descr +Floyd Steinberg dithering RGB888 -> any pixel +%% endblock + +%% block body + +#include "core/GP_Core.h" +#include "core/GP_Pixel.h" +#include "GP_Filter.h" + +#include <string.h> + +%% macro distribute_error(errors, x, y, w, err) + if ({{ x }} + 1 < {{ w }}) + {{ errors }}[{{ y }}%2][{{ x }}+1] += 7 * {{ err }} / 16; + + if ({{ x }} > 1) + {{ errors }}[!({{ y }}%2)][{{ x }}-1] += 3 * {{ err }} / 16; + + {{ errors }}[!({{ y }}%2)][{{ x }}] += 5 * {{ err }} / 16; + + if ({{ x }} + 1 < {{ w }}) + {{ errors }}[!({{ y }}%2)][{{ x }}+1] += {{ err }} / 16; +%% endmacro + +%% for pt in pixeltypes +%% if not pt.is_unknown() and not pt.is_alpha() and not pt.is_palette() +/* + * Floyd Steinberg RGB888 to {{ pt.name }} + */ +int GP_FilterFloydSteinberg_RGB888_to_{{ pt.name }}_Raw(const GP_Context *src, GP_Context *dst, + GP_ProgressCallback *callback) +{ +%% for c in pt.chanslist + float errors_{{ c[0] }}[2][src->w]; +%% endfor + + GP_DEBUG(1, "Floyd Steinberg %s to %s %ux%u", + GP_PixelTypeName(src->pixel_type), + GP_PixelTypeName(GP_PIXEL_{{ pt.name }}), + src->w, src->h); + + GP_Coord x, y; + +%% for c in pt.chanslist + memset(errors_{{ c[0] }}[0], 0, src->w * sizeof(float)); + memset(errors_{{ c[0] }}[1], 0, src->w * sizeof(float)); +%% endfor + + for (y = 0; y < (GP_Coord)src->h; y++) { + for (x = 0; x < (GP_Coord)src->w; x++) { + GP_Pixel pix = GP_GetPixel(src, x, y); + +%% for c in pt.chanslist +%% if pt.is_gray() + float val_{{ c[0] }} = GP_Pixel_GET_R_RGB888(pix) + + GP_Pixel_GET_G_RGB888(pix) + + GP_Pixel_GET_B_RGB888(pix); +%% else + float val_{{ c[0] }} = GP_Pixel_GET_{{ c[0] }}_RGB888(pix); +%% endif + val_{{ c[0] }} += errors_{{ c[0] }}[y%2][x]; + + float err_{{ c[0] }} = val_{{ c[0] }}; + +%% if pt.is_gray() + GP_Pixel res_{{ c[0] }} = {{ 2 ** c[2] - 1}} * val_{{ c[0] }} / (3 * 255); + err_{{ c[0] }} -= res_{{ c[0] }} * (3 * 255) / {{ 2 ** c[2] - 1}}; +%% else + GP_Pixel res_{{ c[0] }} = {{ 2 ** c[2] - 1}} * val_{{ c[0] }} / 255; + err_{{ c[0] }} -= res_{{ c[0] }} * 255 / {{ 2 ** c[2] - 1}}; +%% endif + +{{ distribute_error("errors_%s"|format(c[0]), 'x', 'y', '(GP_Coord)src->w', 'err_%s'|format(c[0])) }} +%% endfor + +%% if pt.is_gray() + GP_PutPixel_Raw_{{ pt.pixelsize.suffix }}(dst, x, y, res_V); +%% else + GP_Pixel res = GP_Pixel_CREATE_{{ pt.name }}(res_{{ pt.chanslist[0][0] }}{% for c in pt.chanslist[1:] %}, res_{{ c[0] }}{% endfor %}); + + GP_PutPixel_Raw_{{ pt.pixelsize.suffix }}(dst, x, y, res); +%% endif + } + +%% for c in pt.chanslist + memset(errors_{{ c[0] }}[y%2], 0, src->w * sizeof(float)); +%% endfor + + if (GP_ProgressCallbackReport(callback, y, src->h, src->w)) + return 1; + } + + GP_ProgressCallbackDone(callback); + return 0; +} + +%% endif +%% endfor + +int GP_FilterFloydSteinberg_RGB888_to_XXX_Raw(const GP_Context *src, + GP_Context *dst, + GP_ProgressCallback *callback) +{ + switch (dst->pixel_type) { +%% for pt in pixeltypes +%% if not pt.is_unknown() and not pt.is_alpha() and not pt.is_palette() + case GP_PIXEL_{{ pt.name }}: + return GP_FilterFloydSteinberg_RGB888_to_{{ pt.name }}_Raw(src, dst, callback); +%% endif +%% endfor + default: + return 1; + } +} + +%% endblock body diff --git a/libs/filters/Makefile b/libs/filters/Makefile index 8133fb0..1608647 100644 --- a/libs/filters/Makefile +++ b/libs/filters/Makefile @@ -1,6 +1,6 @@ TOPDIR=../.. GENSOURCES=GP_Brightness.gen.c GP_Contrast.gen.c GP_Invert.gen.c- GP_MirrorV.gen.c GP_Rotate.gen.c + GP_MirrorV.gen.c GP_Rotate.gen.c GP_Dither.gen.c GENHEADERS= CSOURCES=$(filter-out $(wildcard *.gen.c),$(wildcard *.c)) LIBNAME=filters
-----------------------------------------------------------------------
Summary of changes: demos/grinder/grinder.c | 36 +++++++++++- gfxprim_config.py | 8 +++ include/filters/GP_Dither.h | 28 ++++++++- libs/filters/GP_Dither.c | 66 ++++++++++++++-------- libs/filters/GP_Dither.gen.c.t | 120 ++++++++++++++++++++++++++++++++++++++++ libs/filters/Makefile | 2 +- 6 files changed, 229 insertions(+), 31 deletions(-) create mode 100644 libs/filters/GP_Dither.gen.c.t
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.