From 87f8e922ab38d7615011668379ac85493696380d Mon Sep 17 00:00:00 2001 From: sam Date: Sun, 3 Aug 2008 11:48:07 +0000 Subject: [PATCH] * Error diffusion methods now support either raster or serpentine scan. git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2656 92316355-f0b4-4df1-b90c-862c8a59935f --- examples/dither.c | 18 ++++++++++++------ examples/edd.c | 2 +- pipi/dither/floydsteinberg.c | 8 +++++--- pipi/dither/ostromoukhov.c | 8 +++++--- pipi/pipi.h | 13 +++++++++++-- 5 files changed, 34 insertions(+), 15 deletions(-) diff --git a/examples/dither.c b/examples/dither.c index 246df80..7bdd3e6 100644 --- a/examples/dither.c +++ b/examples/dither.c @@ -17,9 +17,11 @@ int main(int argc, char *argv[]) fprintf(stderr, "%s: too few arguments\n", argv[0]); fprintf(stderr, "Usage: %s \n", argv[0]); fprintf(stderr, "Where is one of:\n"); - fprintf(stderr, " 1 Floyd-Steinberg (serpentine)\n"); - fprintf(stderr, " 2 Ostromoukhov (serpentine)\n"); - fprintf(stderr, " 3 Direct binary search\n"); + fprintf(stderr, " 1 Floyd-Steinberg (raster)\n"); + fprintf(stderr, " 2 Floyd-Steinberg (serpentine)\n"); + fprintf(stderr, " 3 Ostromoukhov (raster)\n"); + fprintf(stderr, " 4 Ostromoukhov (serpentine)\n"); + fprintf(stderr, " 5 Direct binary search\n"); return EXIT_FAILURE; } @@ -30,13 +32,17 @@ int main(int argc, char *argv[]) switch(atoi(argv[2])) { - case 3: + case 5: newimg = pipi_dbs(img); break; + case 4: + newimg = pipi_ostromoukhov(img, PIPI_SCAN_SERPENTINE); break; + case 3: + newimg = pipi_ostromoukhov(img, PIPI_SCAN_RASTER); break; case 2: - newimg = pipi_ostromoukhov(img); break; + newimg = pipi_floydsteinberg(img, PIPI_SCAN_SERPENTINE); break; case 1: default: - newimg = pipi_floydsteinberg(img); break; + newimg = pipi_floydsteinberg(img, PIPI_SCAN_RASTER); break; } pipi_free(img); diff --git a/examples/edd.c b/examples/edd.c index baa576a..92a59a9 100644 --- a/examples/edd.c +++ b/examples/edd.c @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) img = pipi_load(argv[1]); pipi_getpixels(img, PIPI_PIXELS_Y_F); gauss = pipi_gaussian_blur(img, sigma); - dither = pipi_floydsteinberg(img); + dither = pipi_floydsteinberg(img, PIPI_SCAN_RASTER); pipi_free(img); /* Compute the standard error */ diff --git a/pipi/dither/floydsteinberg.c b/pipi/dither/floydsteinberg.c index 46f692d..5df7fac 100644 --- a/pipi/dither/floydsteinberg.c +++ b/pipi/dither/floydsteinberg.c @@ -22,7 +22,7 @@ #include "pipi.h" #include "pipi_internals.h" -pipi_image_t *pipi_floydsteinberg(pipi_image_t *src) +pipi_image_t *pipi_floydsteinberg(pipi_image_t *src, pipi_scan_t scan) { pipi_image_t *dst; pipi_pixels_t *srcp, *dstp; @@ -41,11 +41,13 @@ pipi_image_t *pipi_floydsteinberg(pipi_image_t *src) for(y = 0; y < h; y++) { + int reverse = (y & 1) && (scan == PIPI_SCAN_SERPENTINE); + for(x = 0; x < w; x++) { float p, q, e; - int x2 = (y & 1) ? x : w - 1 - x; - int s = (y & 1) ? 1 : -1; + int x2 = reverse ? w - 1 - x : x; + int s = reverse ? -1 : 1; p = srcdata[y * w + x2]; q = p < 0.5 ? 0. : 1.; diff --git a/pipi/dither/ostromoukhov.c b/pipi/dither/ostromoukhov.c index ce7d9f7..74bc1c5 100644 --- a/pipi/dither/ostromoukhov.c +++ b/pipi/dither/ostromoukhov.c @@ -66,7 +66,7 @@ static int const table[][3] = {385, 112, 103}, {65, 18, 17}, {395, 104, 101}, {4, 1, 1} }; -pipi_image_t *pipi_ostromoukhov(pipi_image_t *src) +pipi_image_t *pipi_ostromoukhov(pipi_image_t *src, pipi_scan_t scan) { pipi_image_t *dst; pipi_pixels_t *srcp, *dstp; @@ -85,13 +85,15 @@ pipi_image_t *pipi_ostromoukhov(pipi_image_t *src) for(y = 0; y < h; y++) { + int reverse = (y & 1) && (scan == PIPI_SCAN_SERPENTINE); + for(x = 0; x < w; x++) { float p, q, e; int x2, s, i; - x2 = (y & 1) ? x : w - 1 - x; - s = (y & 1) ? 1 : -1; + x2 = reverse ? w - 1 - x : x; + s = reverse ? -1 : 1; p = srcdata[y * w + x2]; q = p < 0.5 ? 0. : 1.; diff --git a/pipi/pipi.h b/pipi/pipi.h index d95b14b..c942e58 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -24,6 +24,15 @@ extern "C" { #endif +/* pipi_scan_t: this enum is a list of all possible scanning methods when + * parsing an image’s pixels. Not all functions support all scanning paths. */ +typedef enum +{ + PIPI_SCAN_RASTER = 0, + PIPI_SCAN_SERPENTINE = 1 +} +pipi_scan_t; + /* pipi_format_t: this enum is a list of all possible pixel formats for * our internal images. RGBA32 is the most usual format when an image has * just been loaded, but RGBA_F is a lot better for complex operations. */ @@ -68,8 +77,8 @@ extern pipi_image_t *pipi_gaussian_blur(pipi_image_t *, float); extern pipi_image_t *pipi_gaussian_blur_ext(pipi_image_t *, float, float, float, float); -extern pipi_image_t *pipi_floydsteinberg(pipi_image_t *); -extern pipi_image_t *pipi_ostromoukhov(pipi_image_t *); +extern pipi_image_t *pipi_floydsteinberg(pipi_image_t *, pipi_scan_t); +extern pipi_image_t *pipi_ostromoukhov(pipi_image_t *, pipi_scan_t); extern pipi_image_t *pipi_dbs(pipi_image_t *); extern void pipi_dither_24to16(pipi_image_t *);