Browse Source

* Dithering algorithms no longer modify the original image.

git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2670 92316355-f0b4-4df1-b90c-862c8a59935f
remotes/tiles
sam 16 years ago
parent
commit
18dd51e1a5
4 changed files with 38 additions and 52 deletions
  1. +10
    -15
      pipi/dither/dbs.c
  2. +11
    -14
      pipi/dither/floydsteinberg.c
  3. +7
    -10
      pipi/dither/ordered.c
  4. +10
    -13
      pipi/dither/ostromoukhov.c

+ 10
- 15
pipi/dither/dbs.c View File

@@ -35,14 +35,14 @@
/* FIXME: though the algorithm is supposed to stop, we do not have a real, /* FIXME: though the algorithm is supposed to stop, we do not have a real,
* guaranteed stop condition here. */ * guaranteed stop condition here. */


pipi_image_t *pipi_dither_dbs(pipi_image_t *src)
pipi_image_t *pipi_dither_dbs(pipi_image_t *img)
{ {
double kernel[NN * NN]; double kernel[NN * NN];
double t = 0.; double t = 0.;
pipi_image_t *dst, *tmp1, *tmp2;
pipi_pixels_t *srcp, *dstp, *tmp1p, *tmp2p;
pipi_image_t *src, *dst, *tmp1, *tmp2;
pipi_pixels_t *dstp, *tmp1p, *tmp2p;
int *changelist; int *changelist;
float *srcdata, *dstdata, *tmp1data, *tmp2data;
float *dstdata, *tmp1data, *tmp2data;
int i, j, x, y, w, h, cw, ch; int i, j, x, y, w, h, cw, ch;


/* Build our human visual system kernel. */ /* Build our human visual system kernel. */
@@ -61,31 +61,26 @@ pipi_image_t *pipi_dither_dbs(pipi_image_t *src)
for(i = 0; i < NN; i++) for(i = 0; i < NN; i++)
kernel[j * NN + i] /= t; kernel[j * NN + i] /= t;


w = src->w;
h = src->h;
w = img->w;
h = img->h;


cw = (w + CELL - 1) / CELL; cw = (w + CELL - 1) / CELL;
ch = (h + CELL - 1) / CELL; ch = (h + CELL - 1) / CELL;
changelist = malloc(cw * ch * sizeof(int)); changelist = malloc(cw * ch * sizeof(int));
memset(changelist, 0, cw * ch * sizeof(int)); memset(changelist, 0, cw * ch * sizeof(int));


srcp = pipi_getpixels(src, PIPI_PIXELS_Y_F);
srcdata = (float *)srcp->pixels;
src = pipi_copy(img);
pipi_getpixels(src, PIPI_PIXELS_Y_F);


tmp1 = pipi_convolution(src, NN, NN, kernel); tmp1 = pipi_convolution(src, NN, NN, kernel);
tmp1p = pipi_getpixels(tmp1, PIPI_PIXELS_Y_F); tmp1p = pipi_getpixels(tmp1, PIPI_PIXELS_Y_F);
tmp1data = (float *)tmp1p->pixels; tmp1data = (float *)tmp1p->pixels;


/* The initial dither is an empty image. So is its blurred version,
* but I leave the pipi_convolution() call here in case we choose
* to change the way to create the initial dither. */
dst = pipi_new(w, h);
dst = pipi_dither_floydsteinberg(src, PIPI_SCAN_SERPENTINE);
dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F); dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F);
dstdata = (float *)dstp->pixels; dstdata = (float *)dstp->pixels;


for(y = 0; y < h; y++)
for(x = 0; x < w; x++)
dstdata[y * w + x] = srcdata[y * w + x] > 0.5 ? 1.0 : 0.0;
pipi_free(src);


tmp2 = pipi_convolution(dst, NN, NN, kernel); tmp2 = pipi_convolution(dst, NN, NN, kernel);
tmp2p = pipi_getpixels(tmp2, PIPI_PIXELS_Y_F); tmp2p = pipi_getpixels(tmp2, PIPI_PIXELS_Y_F);


+ 11
- 14
pipi/dither/floydsteinberg.c View File

@@ -22,20 +22,17 @@
#include "pipi.h" #include "pipi.h"
#include "pipi_internals.h" #include "pipi_internals.h"


pipi_image_t *pipi_dither_floydsteinberg(pipi_image_t *src, pipi_scan_t scan)
pipi_image_t *pipi_dither_floydsteinberg(pipi_image_t *img, pipi_scan_t scan)
{ {
pipi_image_t *dst; pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
float *srcdata, *dstdata;
pipi_pixels_t *dstp;
float *dstdata;
int x, y, w, h; int x, y, w, h;


w = src->w;
h = src->h;
w = img->w;
h = img->h;


srcp = pipi_getpixels(src, PIPI_PIXELS_Y_F);
srcdata = (float *)srcp->pixels;

dst = pipi_new(w, h);
dst = pipi_copy(img);
dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F); dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F);
dstdata = (float *)dstp->pixels; dstdata = (float *)dstp->pixels;


@@ -49,7 +46,7 @@ pipi_image_t *pipi_dither_floydsteinberg(pipi_image_t *src, pipi_scan_t scan)
int x2 = reverse ? w - 1 - x : x; int x2 = reverse ? w - 1 - x : x;
int s = reverse ? -1 : 1; int s = reverse ? -1 : 1;


p = srcdata[y * w + x2];
p = dstdata[y * w + x2];
q = p < 0.5 ? 0. : 1.; q = p < 0.5 ? 0. : 1.;
dstdata[y * w + x2] = q; dstdata[y * w + x2] = q;


@@ -57,14 +54,14 @@ pipi_image_t *pipi_dither_floydsteinberg(pipi_image_t *src, pipi_scan_t scan)
* error diffusion kernel for serpentine scan. */ * error diffusion kernel for serpentine scan. */
e = p - q; e = p - q;
if(x < w - 1) if(x < w - 1)
srcdata[y * w + x2 + s] += e * .4375;
dstdata[y * w + x2 + s] += e * .4375;
if(y < h - 1) if(y < h - 1)
{ {
if(x > 0) if(x > 0)
srcdata[(y + 1) * w + x2 - s] += e * .1875;
srcdata[(y + 1) * w + x2] += e * .3125;
dstdata[(y + 1) * w + x2 - s] += e * .1875;
dstdata[(y + 1) * w + x2] += e * .3125;
if(x < w - 1) if(x < w - 1)
srcdata[(y + 1) * w + x2 + s] += e * .0625;
dstdata[(y + 1) * w + x2 + s] += e * .0625;
} }
} }
} }


+ 7
- 10
pipi/dither/ordered.c View File

@@ -34,20 +34,17 @@ static const int kernel8x8[8 * 8] =
63, 31, 55, 23, 61, 29, 53, 21, 63, 31, 55, 23, 61, 29, 53, 21,
}; };


pipi_image_t *pipi_dither_ordered(pipi_image_t *src)
pipi_image_t *pipi_dither_ordered(pipi_image_t *img)
{ {
pipi_image_t *dst; pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
float *srcdata, *dstdata;
pipi_pixels_t *dstp;
float *dstdata;
int x, y, w, h; int x, y, w, h;


w = src->w;
h = src->h;
w = img->w;
h = img->h;


srcp = pipi_getpixels(src, PIPI_PIXELS_Y_F);
srcdata = (float *)srcp->pixels;

dst = pipi_new(w, h);
dst = pipi_copy(img);
dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F); dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F);
dstdata = (float *)dstp->pixels; dstdata = (float *)dstp->pixels;


@@ -57,7 +54,7 @@ pipi_image_t *pipi_dither_ordered(pipi_image_t *src)
{ {
float p, q; float p, q;


p = srcdata[y * w + x];
p = dstdata[y * w + x];
q = p > (1. + kernel8x8[(y % 8) * 8 + (x % 8)]) / 65. ? 1. : 0.; q = p > (1. + kernel8x8[(y % 8) * 8 + (x % 8)]) / 65. ? 1. : 0.;
dstdata[y * w + x] = q; dstdata[y * w + x] = q;
} }


+ 10
- 13
pipi/dither/ostromoukhov.c View File

@@ -66,20 +66,17 @@ static int const table[][3] =
{385, 112, 103}, {65, 18, 17}, {395, 104, 101}, {4, 1, 1} {385, 112, 103}, {65, 18, 17}, {395, 104, 101}, {4, 1, 1}
}; };


pipi_image_t *pipi_dither_ostromoukhov(pipi_image_t *src, pipi_scan_t scan)
pipi_image_t *pipi_dither_ostromoukhov(pipi_image_t *img, pipi_scan_t scan)
{ {
pipi_image_t *dst; pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
float *srcdata, *dstdata;
pipi_pixels_t *dstp;
float *dstdata;
int x, y, w, h; int x, y, w, h;


w = src->w;
h = src->h;
w = img->w;
h = img->h;


srcp = pipi_getpixels(src, PIPI_PIXELS_Y_F);
srcdata = (float *)srcp->pixels;

dst = pipi_new(w, h);
dst = pipi_copy(img);
dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F); dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F);
dstdata = (float *)dstp->pixels; dstdata = (float *)dstp->pixels;


@@ -95,7 +92,7 @@ pipi_image_t *pipi_dither_ostromoukhov(pipi_image_t *src, pipi_scan_t scan)
x2 = reverse ? w - 1 - x : x; x2 = reverse ? w - 1 - x : x;
s = reverse ? -1 : 1; s = reverse ? -1 : 1;


p = srcdata[y * w + x2];
p = dstdata[y * w + x2];
q = p < 0.5 ? 0. : 1.; q = p < 0.5 ? 0. : 1.;
dstdata[y * w + x2] = q; dstdata[y * w + x2] = q;


@@ -106,12 +103,12 @@ pipi_image_t *pipi_dither_ostromoukhov(pipi_image_t *src, pipi_scan_t scan)
e /= table[i][0] + table[i][1] + table[i][2]; e /= table[i][0] + table[i][1] + table[i][2];


if(x < w - 1) if(x < w - 1)
srcdata[y * w + x2 + s] += e * table[i][0];
dstdata[y * w + x2 + s] += e * table[i][0];
if(y < h - 1) if(y < h - 1)
{ {
if(x > 0) if(x > 0)
srcdata[(y + 1) * w + x2 - s] += e * table[i][1];
srcdata[(y + 1) * w + x2] += e * table[i][2];
dstdata[(y + 1) * w + x2 - s] += e * table[i][1];
dstdata[(y + 1) * w + x2] += e * table[i][2];
} }
} }
} }


Loading…
Cancel
Save