halftoning pattern. git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2767 92316355-f0b4-4df1-b90c-862c8a59935fremotes/tiles
| @@ -30,6 +30,7 @@ pipi_image_t *pipi_load(char const *name) | |||||
| { | { | ||||
| if(!strncmp(name, "random:", 7) || | if(!strncmp(name, "random:", 7) || | ||||
| !strncmp(name, "ediff:", 6) || | !strncmp(name, "ediff:", 6) || | ||||
| !strncmp(name, "halftone:", 6) || | |||||
| !strncmp(name, "bayer:", 6)) | !strncmp(name, "bayer:", 6)) | ||||
| return pipi_load_stock(name); | return pipi_load_stock(name); | ||||
| @@ -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_random(int, int); | ||||
| extern pipi_image_t *pipi_render_bayer(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_rgb(pipi_image_t *, pipi_image_t *, pipi_image_t *); | ||||
| extern pipi_image_t *pipi_red(pipi_image_t *); | extern pipi_image_t *pipi_red(pipi_image_t *); | ||||
| @@ -22,6 +22,7 @@ | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include <math.h> | |||||
| #include "pipi.h" | #include "pipi.h" | ||||
| #include "pipi_internals.h" | #include "pipi_internals.h" | ||||
| @@ -64,3 +65,61 @@ pipi_image_t *pipi_render_bayer(int w, int h) | |||||
| return ret; | 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; | |||||
| } | |||||
| @@ -46,6 +46,21 @@ pipi_image_t *pipi_load_stock(char const *name) | |||||
| return pipi_render_bayer(w, h); | 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. */ | /* Generate an error diffusion matrix. */ | ||||
| if(!strncmp(name, "ediff:", 6)) | if(!strncmp(name, "ediff:", 6)) | ||||
| { | { | ||||