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)) | ||||
{ | { | ||||