|
|
@@ -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; |
|
|
|
} |
|
|
|
|