diff --git a/pipi/Makefile.am b/pipi/Makefile.am index 22c0512..0fd9e56 100644 --- a/pipi/Makefile.am +++ b/pipi/Makefile.am @@ -66,6 +66,7 @@ quantize_sources = \ dither_sources = \ dither/ediff.c \ dither/ordered.c \ + dither/halftone.c \ dither/ostromoukhov.c \ dither/dbs.c \ dither/random.c diff --git a/pipi/context.c b/pipi/context.c index 9c461c0..4c8cde7 100644 --- a/pipi/context.c +++ b/pipi/context.c @@ -112,6 +112,20 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) pipi_free(ctx->images[ctx->nimages - 2]); ctx->nimages--; } + else if(!strncmp(method, "halftone", 8)) + { + double r, angle = .0; + method = strchr(method, ':'); + if(!method) + return -1; + r = atof(method + 1); + method = strchr(method + 1, ':'); + if(method) + angle = atof(method + 1); + if(r < 1.) + r = 1.; + dst = pipi_dither_halftone(src, r, angle); + } else if(!strcmp(method, "random")) dst = pipi_dither_random(src); else if(!strcmp(method, "dbs")) diff --git a/pipi/dither/halftone.c b/pipi/dither/halftone.c new file mode 100644 index 0000000..f50580e --- /dev/null +++ b/pipi/dither/halftone.c @@ -0,0 +1,83 @@ +/* + * 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. + */ + +/* + * halftone.c: screening halftone dithering functions + */ + +#include "config.h" +#include "common.h" + +#include + +#include "pipi.h" +#include "pipi_internals.h" + +pipi_image_t *pipi_dither_halftone(pipi_image_t *img, double r, double angle) +{ + double sint, cost; + pipi_image_t *dst; + pipi_pixels_t *dstp; + float *dstdata; + int x, y, w, h; + + w = img->w; + h = img->h; + + cost = cos(angle * (M_PI / 180)); + sint = sin(angle * (M_PI / 180)); + + dst = pipi_copy(img); + dstp = pipi_getpixels(dst, PIPI_PIXELS_Y_F); + dstdata = (float *)dstp->pixels; + + for(y = 0; y < h; y++) + { + for(x = 0; x < w; x++) + { + double x2, y2, i, j, dist; + float p, threshold = .5; + int invert = 0; + + x2 = x + .5; + y2 = y + .5; + i = (cost * x2 - sint * y2) / r; + j = (cost * y2 + sint * x2) / r; + i = i - (int)i + (i < 0.); + j = j - (int)j + (j < 0.); + + if(j > 0.5) + { + i = 1. - i; + j = 1. - j; + } + if(i > 0.5) + { + invert = 1; + i = 1. - i; + } + + dist = (i - .25) * (i - .25) + (j - .25) * (j - .25); + threshold = dist * 4; + if(invert) + threshold = 1. - threshold; + + p = dstdata[y * w + x]; + dstdata[y * w + x] = p > threshold ? 1. : 0.; + } + } + + return dst; +} + diff --git a/pipi/pipi.h b/pipi/pipi.h index 3325267..6e3b64b 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -150,6 +150,7 @@ 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_ordered(pipi_image_t *, pipi_image_t *); +extern pipi_image_t *pipi_dither_halftone(pipi_image_t *, double, double); extern pipi_image_t *pipi_dither_random(pipi_image_t *); extern pipi_image_t *pipi_dither_ostromoukhov(pipi_image_t *, pipi_scan_t); extern pipi_image_t *pipi_dither_dbs(pipi_image_t *);