Index: /libpipi/trunk/examples/edd.c
===================================================================
--- /libpipi/trunk/examples/edd.c	(revision 2644)
+++ /libpipi/trunk/examples/edd.c	(revision 2644)
@@ -0,0 +1,95 @@
+/*
+ *  edd           error diffusion displacement
+ *  Copyright (c) 2008 Sam Hocevar <sam@zoy.org>
+ *                All Rights Reserved
+ *
+ *  $Id$
+ *
+ *  This program 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.
+ */
+
+/* This program computes the Floyd-Steinberg error diffusion algorithm's
+ * displacement on the given input image. Error diffusion displacement is
+ * introduced in the paper "Reinstating Floyd-Steinberg: Improved Metrics
+ * for Quality Assessment of Error Diffusion Algorithms.", ICISP 2008
+ * Proceedings. Lecture Notes in Computer Science 5099 Springer 2008, ISBN
+ * 978-3-540-69904-0.
+ *
+ * The resulting dx/dy values are usually around 0.16/0.26 for images that
+ * are not entirely black and white. */
+
+#include "config.h"
+#include "common.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pipi.h>
+
+#define Z 3
+
+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;
+    pipi_image_t *img, *gauss, *dither, *tmp;
+    int dx, dy;
+
+    if(argc < 2)
+    {
+        fprintf(stderr, "%s: too few arguments\n", argv[0]);
+        fprintf(stderr, "Usage: %s <image>\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    /* Load image, convert it to grayscale, dither it with Floyd-Steinberg */
+    img = pipi_load(argv[1]);
+    pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
+    pipi_getpixels(img, PIPI_PIXELS_Y_F);
+    gauss = pipi_gaussian_blur(img, sigma);
+    dither = pipi_floydsteinberg(img);
+    pipi_free(img);
+
+    /* Compute the standard error */
+    tmp = pipi_gaussian_blur(dither, sigma);
+    e0 = pipi_measure_rmsd(gauss, tmp);
+    pipi_free(tmp);
+
+    /* Compute displacement */
+    while(step > precision)
+    {
+        for(dy = 0; dy <= Z; dy++)
+            for(dx = 0; dx <= Z; dx++)
+            {
+                tmp = pipi_gaussian_blur_ext(dither, sigma, sigma,
+                                             fx + step * dx / Z,
+                                             fy + step * dy / Z);
+                e = pipi_measure_rmsd(gauss, tmp);
+                pipi_free(tmp);
+                if(e < best)
+                {
+                    best = e;
+                    bfx = fx + step * dx / Z;
+                    bfy = fy + step * dy / Z;
+                }
+            }
+
+        fx = bfx - step / Z;
+        fy = bfy - step / Z;
+        step = step * 2 / Z;
+    }
+
+    printf("E: %g E_min: %g dx: %g dy: %g\n", e0, best, fx, fy);
+
+    pipi_free(dither);
+    pipi_free(gauss);
+
+    return 0;
+}
+
Index: /libpipi/trunk/examples/Makefile.am
===================================================================
--- /libpipi/trunk/examples/Makefile.am	(revision 2643)
+++ /libpipi/trunk/examples/Makefile.am	(revision 2644)
@@ -3,9 +3,12 @@
 AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/pipi
 
-bin_PROGRAMS = img2rubik blur
+bin_PROGRAMS = blur edd img2rubik
 
 blur_SOURCES = blur.c
 blur_LDADD = ../pipi/libpipi.la
 
+edd_SOURCES = edd.c
+edd_LDADD = ../pipi/libpipi.la
+
 img2rubik_SOURCES = img2rubik.c
 img2rubik_LDADD = ../pipi/libpipi.la
Index: /libpipi/trunk/.gitignore
===================================================================
--- /libpipi/trunk/.gitignore	(revision 2643)
+++ /libpipi/trunk/.gitignore	(revision 2644)
@@ -12,4 +12,5 @@
 genethumb/genethumb
 examples/blur
+examples/edd
 examples/img2rubik
 test/u8tof32tou8
