From 44c9b8e15db83d003a2506a995f68c43dbb7f519 Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 23 Aug 2008 13:07:42 +0000 Subject: [PATCH] * Get rid of the specific error diffusion functions, since our stock kernels work perfectly well. git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2759 92316355-f0b4-4df1-b90c-862c8a59935f --- examples/edd.c | 6 ++- pipi/Makefile.am | 3 -- pipi/codec.c | 1 + pipi/context.c | 22 ++++----- pipi/dither/atkinson.c | 75 ------------------------------- pipi/dither/ediff.c | 5 ++- pipi/dither/floydsteinberg.c | 71 ----------------------------- pipi/dither/jajuni.c | 87 ------------------------------------ pipi/pipi.h | 3 -- pipi/stock.c | 45 +++++++++++++++++++ 10 files changed, 63 insertions(+), 255 deletions(-) delete mode 100644 pipi/dither/atkinson.c delete mode 100644 pipi/dither/floydsteinberg.c delete mode 100644 pipi/dither/jajuni.c diff --git a/examples/edd.c b/examples/edd.c index d1e0af7..4ed621d 100644 --- a/examples/edd.c +++ b/examples/edd.c @@ -38,7 +38,7 @@ int main(int argc, char *argv[]) double sigma = 1.2, precision = 0.001, step = 2.; double best = 1., fx = -1., fy = -1., bfx = 0., bfy = 0.; double e, e0, e1; - pipi_image_t *img, *gauss, *dither, *tmp; + pipi_image_t *img, *kernel, *gauss, *dither, *tmp; int dx, dy; if(argc < 2) @@ -52,7 +52,9 @@ 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_dither_floydsteinberg(img, PIPI_SCAN_RASTER); + kernel = pipi_load("ediff:fs"); + dither = pipi_dither_ediff(img, kernel, PIPI_SCAN_RASTER); + pipi_free(kernel); pipi_free(img); /* Compute the standard error */ diff --git a/pipi/Makefile.am b/pipi/Makefile.am index b332630..22c0512 100644 --- a/pipi/Makefile.am +++ b/pipi/Makefile.am @@ -65,9 +65,6 @@ quantize_sources = \ dither_sources = \ dither/ediff.c \ - dither/floydsteinberg.c \ - dither/jajuni.c \ - dither/atkinson.c \ dither/ordered.c \ dither/ostromoukhov.c \ dither/dbs.c \ diff --git a/pipi/codec.c b/pipi/codec.c index 26ae428..032594c 100644 --- a/pipi/codec.c +++ b/pipi/codec.c @@ -29,6 +29,7 @@ pipi_image_t *pipi_load(char const *name) { if(!strncmp(name, "random:", 7) || + !strncmp(name, "ediff:", 6) || !strncmp(name, "bayer:", 6)) return pipi_load_stock(name); diff --git a/pipi/context.c b/pipi/context.c index e480eae..9c461c0 100644 --- a/pipi/context.c +++ b/pipi/context.c @@ -84,19 +84,7 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) va_end(ap); src = ctx->images[ctx->nimages - 1]; dst = NULL; - if(!strcmp(method, "fs")) - dst = pipi_dither_floydsteinberg(src, 0); - else if(!strcmp(method, "sfs")) - dst = pipi_dither_floydsteinberg(src, 1); - else if(!strcmp(method, "jajuni")) - dst = pipi_dither_jajuni(src, 0); - else if(!strcmp(method, "sjajuni")) - dst = pipi_dither_jajuni(src, 1); - else if(!strcmp(method, "atkinson")) - dst = pipi_dither_atkinson(src, 0); - else if(!strcmp(method, "satkinson")) - dst = pipi_dither_atkinson(src, 1); - else if(!strcmp(method, "ost")) + if(!strcmp(method, "ost")) dst = pipi_dither_ostromoukhov(src, 0); else if(!strcmp(method, "sost")) dst = pipi_dither_ostromoukhov(src, 1); @@ -108,6 +96,14 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) pipi_free(ctx->images[ctx->nimages - 2]); ctx->nimages--; } + else if(!strcmp(method, "sediff")) + { + if(ctx->nimages < 2) + return -1; + dst = pipi_dither_ediff(ctx->images[ctx->nimages - 2], src, 1); + pipi_free(ctx->images[ctx->nimages - 2]); + ctx->nimages--; + } else if(!strcmp(method, "ordered")) { if(ctx->nimages < 2) diff --git a/pipi/dither/atkinson.c b/pipi/dither/atkinson.c deleted file mode 100644 index d9e5b96..0000000 --- a/pipi/dither/atkinson.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * libpipi Proper image processing implementation library - * Copyright (c) 2004-2008 Sam Hocevar - * All Rights Reserved - * - * $Id$ - * - * This library is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - */ - -/* - * atkinson.c: Atkinson dithering functions - */ - -#include "config.h" -#include "common.h" - -#include "pipi.h" -#include "pipi_internals.h" - -pipi_image_t *pipi_dither_atkinson(pipi_image_t *img, pipi_scan_t scan) -{ - pipi_image_t *dst; - pipi_pixels_t *dstp; - float *dstdata; - int x, y, w, h; - - w = img->w; - h = img->h; - - dst = pipi_copy(img); - dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F); - dstdata = (float *)dstp->pixels; - - 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 = reverse ? w - 1 - x : x; - int s = reverse ? -1 : 1; - - p = dstdata[y * w + x2]; - q = p < 0.5 ? 0. : 1.; - dstdata[y * w + x2] = q; - - e = (p - q) / 8.; - if(x < w - 1) - dstdata[y * w + x2 + s] += e; - if(x < w - 2) - dstdata[y * w + x2 + s + s] += e; - if(y < h - 1) - { - if(x > 0) - dstdata[(y + 1) * w + x2 - s] += e; - dstdata[(y + 1) * w + x2] += e; - if(x < w - 1) - dstdata[(y + 1) * w + x2 + s] += e; - } - if(y < h - 2) - { - dstdata[(y + 2) * w + x2] += e; - } - } - } - - return dst; -} - diff --git a/pipi/dither/ediff.c b/pipi/dither/ediff.c index 5e5ec08..96408f5 100644 --- a/pipi/dither/ediff.c +++ b/pipi/dither/ediff.c @@ -24,7 +24,10 @@ /* Perform a generic error diffusion dithering. The first non-zero * element in ker is treated as the current pixel. All other non-zero - * elements are the error diffusion coefficients. */ + * elements are the error diffusion coefficients. + * Making the matrix generic is not terribly slower: the performance + * hit is around 4% for Floyd-Steinberg and 13% for JaJuNi, with the + * benefit of a lot less code. */ pipi_image_t *pipi_dither_ediff(pipi_image_t *img, pipi_image_t *ker, pipi_scan_t scan) { diff --git a/pipi/dither/floydsteinberg.c b/pipi/dither/floydsteinberg.c deleted file mode 100644 index b77fc96..0000000 --- a/pipi/dither/floydsteinberg.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * libpipi Proper image processing implementation library - * Copyright (c) 2004-2008 Sam Hocevar - * All Rights Reserved - * - * $Id$ - * - * This library is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - */ - -/* - * floydsteinberg.c: Floyd-Steinberg dithering functions - */ - -#include "config.h" -#include "common.h" - -#include "pipi.h" -#include "pipi_internals.h" - -pipi_image_t *pipi_dither_floydsteinberg(pipi_image_t *img, pipi_scan_t scan) -{ - pipi_image_t *dst; - pipi_pixels_t *dstp; - float *dstdata; - int x, y, w, h; - - w = img->w; - h = img->h; - - dst = pipi_copy(img); - dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F); - dstdata = (float *)dstp->pixels; - - 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 = reverse ? w - 1 - x : x; - int s = reverse ? -1 : 1; - - p = dstdata[y * w + x2]; - q = p < 0.5 ? 0. : 1.; - dstdata[y * w + x2] = q; - - /* FIXME: according to our 2008 paper, [7 4 5 0] is a better - * error diffusion kernel for serpentine scan than [7 3 5 1]. */ - e = (p - q) / 16; - if(x < w - 1) - dstdata[y * w + x2 + s] += e * 7; - if(y < h - 1) - { - if(x > 0) - dstdata[(y + 1) * w + x2 - s] += e * 3; - dstdata[(y + 1) * w + x2] += e * 5; - if(x < w - 1) - dstdata[(y + 1) * w + x2 + s] += e; - } - } - } - - return dst; -} - diff --git a/pipi/dither/jajuni.c b/pipi/dither/jajuni.c deleted file mode 100644 index 45f9aa0..0000000 --- a/pipi/dither/jajuni.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * libpipi Proper image processing implementation library - * Copyright (c) 2004-2008 Sam Hocevar - * All Rights Reserved - * - * $Id$ - * - * This library is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - */ - -/* - * jajuni.c: Jarvis-Judice-Ninke dithering functions - */ - -#include "config.h" -#include "common.h" - -#include "pipi.h" -#include "pipi_internals.h" - -pipi_image_t *pipi_dither_jajuni(pipi_image_t *img, pipi_scan_t scan) -{ - pipi_image_t *dst; - pipi_pixels_t *dstp; - float *dstdata; - int x, y, w, h; - - w = img->w; - h = img->h; - - dst = pipi_copy(img); - dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F); - dstdata = (float *)dstp->pixels; - - 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 = reverse ? w - 1 - x : x; - int s = reverse ? -1 : 1; - - p = dstdata[y * w + x2]; - q = p < 0.5 ? 0. : 1.; - dstdata[y * w + x2] = q; - - e = (p - q) / 48.; - if(x < w - 1) - dstdata[y * w + x2 + s] += e * 7; - if(x < w - 2) - dstdata[y * w + x2 + s + s] += e * 5; - if(y < h - 1) - { - if(x > 1) - dstdata[(y + 1) * w + x2 - s - s] += e * 3; - if(x > 0) - dstdata[(y + 1) * w + x2 - s] += e * 5; - dstdata[(y + 1) * w + x2] += e * 7; - if(x < w - 1) - dstdata[(y + 1) * w + x2 + s] += e * 5; - if(x < w - 2) - dstdata[(y + 1) * w + x2 + s + s] += e * 3; - } - if(y < h - 2) - { - if(x > 1) - dstdata[(y + 2) * w + x2 - s - s] += e; - if(x > 0) - dstdata[(y + 2) * w + x2 - s] += e * 3; - dstdata[(y + 2) * w + x2] += e * 5; - if(x < w - 1) - dstdata[(y + 2) * w + x2 + s] += e * 3; - if(x < w - 2) - dstdata[(y + 2) * w + x2 + s + s] += e; - } - } - } - - return dst; -} - diff --git a/pipi/pipi.h b/pipi/pipi.h index 90a9794..3325267 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -149,9 +149,6 @@ extern pipi_image_t *pipi_reduce(pipi_image_t *, int, double const *); extern pipi_image_t *pipi_dither_ediff(pipi_image_t *, pipi_image_t *, pipi_scan_t); -extern pipi_image_t *pipi_dither_floydsteinberg(pipi_image_t *, pipi_scan_t); -extern pipi_image_t *pipi_dither_jajuni(pipi_image_t *, pipi_scan_t); -extern pipi_image_t *pipi_dither_atkinson(pipi_image_t *, pipi_scan_t); extern pipi_image_t *pipi_dither_ordered(pipi_image_t *, pipi_image_t *); extern pipi_image_t *pipi_dither_random(pipi_image_t *); extern pipi_image_t *pipi_dither_ostromoukhov(pipi_image_t *, pipi_scan_t); diff --git a/pipi/stock.c b/pipi/stock.c index 697bf41..3960cda 100644 --- a/pipi/stock.c +++ b/pipi/stock.c @@ -73,6 +73,51 @@ pipi_image_t *pipi_load_stock(char const *name) return ret; } + /* Generate an error diffusion matrix. */ + if(!strncmp(name, "ediff:", 6)) + { + float const *ker; + int w, h; + + if(!strcmp(name + 6, "fs")) + { + static float const myker[] = + { + 0., 1., 7./16, + 3./16, 5./16, 1./16 + }; + ker = myker; w = 3; h = 2; + } + else if(!strcmp(name + 6, "jajuni")) + { + static float const myker[] = + { + 0., 0., 1., 7./48, 5./48, + 3./48, 5./48, 7./48, 5./48, 3./48, + 1./48, 3./48, 5./48, 3./48, 1./48, + }; + ker = myker; w = 5; h = 3; + } + else if(!strcmp(name + 6, "atkinson")) + { + static float const myker[] = + { + 0., 1., 1./8, 1./8, + 1./8, 1./8, 1./8, 0., + 0., 1./8, 0., 0., + }; + ker = myker; w = 4; h = 3; + } + else + return NULL; + + ret = pipi_new(w, h); + pix = pipi_getpixels(ret, PIPI_PIXELS_Y_F); + memcpy(pix->pixels, ker, w * h * sizeof(float)); + + return ret; + } + /* Generate a completely random image. */ if(!strncmp(name, "random:", 7)) {