From ac072123b4af39dad70cc24f368e785724de3738 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 25 Aug 2008 19:13:50 +0000 Subject: [PATCH] * screen.c: add pipi_render_halftone() to create a 45-degree clustered dot halftoning pattern. git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2767 92316355-f0b4-4df1-b90c-862c8a59935f --- pipi/codec.c | 1 + pipi/pipi.h | 1 + pipi/render/screen.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ pipi/stock.c | 15 +++++++++++ 4 files changed, 76 insertions(+) diff --git a/pipi/codec.c b/pipi/codec.c index 032594c..e61172b 100644 --- a/pipi/codec.c +++ b/pipi/codec.c @@ -30,6 +30,7 @@ pipi_image_t *pipi_load(char const *name) { if(!strncmp(name, "random:", 7) || !strncmp(name, "ediff:", 6) || + !strncmp(name, "halftone:", 6) || !strncmp(name, "bayer:", 6)) return pipi_load_stock(name); diff --git a/pipi/pipi.h b/pipi/pipi.h index 2091b3a..88bbb37 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -107,6 +107,7 @@ extern pipi_image_t *pipi_resize(pipi_image_t *, int, int); extern pipi_image_t *pipi_render_random(int, int); extern pipi_image_t *pipi_render_bayer(int, int); +extern pipi_image_t *pipi_render_halftone(int, int); extern pipi_image_t *pipi_rgb(pipi_image_t *, pipi_image_t *, pipi_image_t *); extern pipi_image_t *pipi_red(pipi_image_t *); diff --git a/pipi/render/screen.c b/pipi/render/screen.c index 663450d..c65bf1a 100644 --- a/pipi/render/screen.c +++ b/pipi/render/screen.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "pipi.h" #include "pipi_internals.h" @@ -64,3 +65,61 @@ pipi_image_t *pipi_render_bayer(int w, int h) return ret; } +typedef struct +{ + int x, y; + double dist; +} +dot_t; + +static int cmpdot(const void *p1, const void *p2) +{ + return ((dot_t const *)p1)->dist > ((dot_t const *)p2)->dist; +} + +pipi_image_t *pipi_render_halftone(int w, int h) +{ + pipi_image_t *ret; + pipi_pixels_t *pix; + float *data; + dot_t *circle; + int x, y, n; + + if(w <= 0 || h <= 0) + return NULL; + + circle = malloc(w * h * sizeof(dot_t)); + + for(y = 0; y < h; y++) + for(x = 0; x < w; x++) + { + double dy = ((double)y + .07) / h - .5; + double dx = (double)x / w - .5; + /* Using dx²+dy² here creates another interesting halftone. */ + double r = - cos(M_PI * (dx - dy)) - cos(M_PI * (dx + dy)); + circle[y * w + x].x = x; + circle[y * w + x].y = y; + circle[y * w + x].dist = r; + } + qsort(circle, w * h, sizeof(dot_t), cmpdot); + + ret = pipi_new(w * 2, h * 2); + pix = pipi_getpixels(ret, PIPI_PIXELS_Y_F); + data = (float *)pix->pixels; + + for(n = 0; n < w * h; n++) + { + x = circle[n].x; + y = circle[n].y; + + data[y * (2 * w) + x] = (float)(2 * n + 1) / (w * h * 4 + 1); + data[(y + h) * (2 * w) + x + w] = (float)(2 * n + 2) / (w * h * 4 + 1); + data[(y + h) * (2 * w) + x] = 1. - (float)(2 * n + 1) / (w * h * 4 + 1); + data[y * (2 * w) + x + w] = 1. - (float)(2 * n + 2) / (w * h * 4 + 1); + } + + free(circle); + + return ret; +} + diff --git a/pipi/stock.c b/pipi/stock.c index 7aaf40a..83a250b 100644 --- a/pipi/stock.c +++ b/pipi/stock.c @@ -46,6 +46,21 @@ pipi_image_t *pipi_load_stock(char const *name) return pipi_render_bayer(w, h); } + /* Generate a clustered dithering pattern. */ + if(!strncmp(name, "halftone:", 9)) + { + int w, h = 0; + + w = atoi(name + 9); + name = strchr(name + 9, 'x'); + if(name) + h = atoi(name + 1); + if(!h) + h = w; + + return pipi_render_halftone(w, h); + } + /* Generate an error diffusion matrix. */ if(!strncmp(name, "ediff:", 6)) {