libtthimage/Lib/dither.c
2023-10-11 22:36:16 +02:00

282 lines
6.6 KiB
C
Raw Blame History

/*
dither.c 31 Aout 1999
-------- ------------
*/
#include <stdio.h>
#include <stdlib.h>
#include "../tthimage.h"
/*::------------------------------------------------------------------::*/
/*
en entree, on doit avoir une image RGB, sinon, "segfault"
le parametre 'uh' represente l'intensite de la couleur 'on'
*/
int Image_dither_Bayer_0(Image_Desc *s, Image_Desc *d, int uh)
{
int dx, dy, x, y, r, g, b;
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, s, d, uh);
/* directement copie de la page 389 de "Bitmapped graphics" de
Steve Rimmer. */
static char pattern[8][8] =
{
{ 0, 32, 8, 40, 2, 34, 10, 42 },
{ 48, 16, 56, 24, 50, 18, 58, 26 },
{ 12, 44, 4, 36, 14, 46, 6, 38 },
{ 60, 28, 52, 20, 62, 30, 54, 22 },
{ 3, 35, 11, 43, 1, 33, 9, 41 },
{ 51, 19, 59, 27, 49, 17, 57, 25 },
{ 15, 47, 7, 39, 13, 45, 5, 37 },
{ 63, 31, 55, 23, 61, 29, 53, 21 }
};
dx = s->width; dy = s->height;
for (y=0; y<dy; y++)
{
for (x=0; x<dx; x++)
{
r = s->Rpix[y][x];
if ((r>>2) > pattern[x&7][y&7]) d->Rpix[y][x] = uh;
else d->Rpix[y][x] = 0;
g = s->Gpix[y][x];
if ((g>>2) > pattern[x&7][y&7]) d->Gpix[y][x] = uh;
else d->Gpix[y][x] = 0;
b = s->Bpix[y][x];
if ((b>>2) > pattern[x&7][y&7]) d->Bpix[y][x] = uh;
else d->Bpix[y][x] = 0;
}
}
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
/*
* 19 Juin 2000: dithering on a 2x2 matrice.
* 15 Nov 2001: 'uh' parameter is _now_ working ;-}
*/
int Image_dither_crude(Image_Desc *s, Image_Desc *d, int uh)
{
int x, y, r, g, b;
int som;
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, s, d, uh);
if (s != d) Image_clear(d, 0, 0, 0);
for (x=0; x<(s->width-1); x+=2) {
for (y=0; y<(s->height-1); y+=2) {
r = g = b = 0;
r += Image_R_pixel(s, x, y);
r += Image_R_pixel(s, x+1, y);
r += Image_R_pixel(s, x, y+1);
r += Image_R_pixel(s, x+1, y+1);
g += Image_G_pixel(s, x, y);
g += Image_G_pixel(s, x+1, y);
g += Image_G_pixel(s, x, y+1);
g += Image_G_pixel(s, x+1, y+1);
b += Image_B_pixel(s, x, y);
b += Image_B_pixel(s, x+1, y);
b += Image_B_pixel(s, x, y+1);
b += Image_B_pixel(s, x+1, y+1);
if (r < 512) Image_plotRGB(d, x, y, 0, 0, 0);
else Image_plotRGB(d, x, y, uh, 0, 0);
if (g < 512) Image_plotRGB(d, x+1, y, 0, 0, 0);
else Image_plotRGB(d, x+1, y, 0, uh, 0);
if (b < 512) Image_plotRGB(d, x, y+1, 0, 0, 0);
else Image_plotRGB(d, x, y+1, 0, 0, uh);
som = r + g + b;
if (som < 2048) Image_plotRGB(d, x+1, y+1, 0, 0, 0);
else Image_plotRGB(d, x+1, y+1, uh, uh, uh);
}
}
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
/*
* <09>a ne marche pas tr<74>s fort, ce truc...
*/
int Image_dither_2x2(Image_Desc *s, Image_Desc *d, int uh)
{
int x, y, xm, ym;
int r, g, b, v;
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, s, d, uh);
x = s->width; xm = (x&1) ? (x-1) : x;
y = s->height; ym = (y&1) ? (y-1) : y;
if (s != d) Image_clear(d, 0, 0, 0);
#if DEBUG_LEVEL
fprintf(stderr, "dither 2x2: %d %d %d %d\n", x, xm, y, ym);
#endif
for (x=0; x<xm; x+=2) {
for (y=0; y<ym; y+=2) {
/*
* bon sang, mais que faire ici ?
*/
r = s->Rpix[y][x];
if (r > 127) Image_plotRGB(d, x, y, uh, 0, 0);
else Image_plotRGB(d, x, y, 0, 0, 0);
g = s->Gpix[y][x];
if (g > 127) Image_plotRGB(d, x+1, y, 0, uh, 0);
else Image_plotRGB(d, x+1, y, 0, 0, 0);
b = s->Bpix[y][x];
if (b > 127) Image_plotRGB(d, x, y+1, 0, 0, uh);
else Image_plotRGB(d, x, y+1, 0, 0, 0);
v = 0xf0 & ((r+g+b)/3);
Image_plotRGB(d, x+1, y+1, v, v, v);
}
}
return FUNC_IS_ALPHA;
}
/*::------------------------------------------------------------------::*/
int Image_dither_seuil_random(Image_Desc *s, Image_Desc *d, int uh)
{
int x, y, r, g, b;
int foo;
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, s, d, uh);
if ( (foo=Image_compare_desc(s, d)) ) {
fprintf(stderr, "%s: images are differents %d\n", __func__, foo);
return foo;
}
if (s != d) Image_clear(d, 0, 0, 0);
for (y=0; y<s->height; y++) {
for (x=0; x<s->width; x++) {
if (s->Rpix[y][x] < rand() % 256) r = 0;
else r = uh;
if (Image_G_pixel(s, x, y) < rand() % 256) g = 0;
else g = uh;
if (Image_B_pixel(s, x, y) < rand() % 256) b = 0;
else b = uh;
(d->Rpix[y])[x] = r;
(d->Gpix[y])[x] = g;
(d->Bpix[y])[x] = b;
}
}
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
/*
* algo tire de Interactive Computer Graphics p. 135
*
* subtle bug: uh _must_ be 255 ?
*/
int Image_dither_simple_error(Image_Desc *s, Image_Desc *d, int uh)
{
int x, y, xa, xb, inc, errR, errG, errB;
int r, g, b, dr, dg, db;
int foo;
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, s, d, uh);
if ( (foo=Image_compare_desc(s, d)) ) {
fprintf(stderr, "%s: images are differents %d\n", __func__, foo);
return foo;
}
if (s != d) Image_clear(d, 0, 0, 0);
errR = errG = errB = 0;
for (y=0; y<s->height; y++) {
if (y & 1) {
xa = 0; xb = s->width - 1; inc = 1;
}
else {
xa = s->width - 1; xb = 0; inc = -1;
}
for (x=xa; x!=xb; x+=inc) {
r = (s->Rpix[y])[x];
if ( (r + errR) > 127 ) dr = uh;
else dr = 0;
errR = (r + errR) - dr;
g = (s->Gpix[y])[x];
if ( (g + errG) > 127 ) dg = uh;
else dg = 0;
errG = (g + errG) - dg;
b = (s->Bpix[y])[x];
if ( (b + errB) > 127 ) db = uh;
else db = 0;
errB = (b + errB) - db;
(d->Rpix[y])[x] = dr;
(d->Gpix[y])[x] = dg;
(d->Bpix[y])[x] = db;
}
}
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
/*
* parameters 'sa' and 'sb' must be carefully tuned.
* 29 Jan 2002: may be I can buid a func for automagically
* computing of right values ?
*/
int Image_dither_double_seuil(Image_Desc *s, Image_Desc *d, int sa, int sb, int uh)
{
int x, y, r, g, b, foo;
if ( (foo=Image_compare_desc(s, d)) ) {
fprintf(stderr, "dither double seuil: images are differents %d\n", foo);
return foo;
}
if ( sa >= sb ) {
fprintf(stderr, "dither double seuil: lo %d > hi %d !\n", sa, sb);
}
for (y=0; y<s->height; y++) {
for (x=0; x<s->width; x++) {
r = (s->Rpix[y])[x];
if (r < sa) r = 0;
else if (r > sb) r = uh;
else r = (x&1 && y&1) ? 0 : uh;
g = (s->Gpix[y])[x];
if (g < sa) g = 0;
else if (g > sb) g = uh;
else g = (!(x&1) && y&1) ? 0 : uh;
b = (s->Bpix[y])[x];
if (b < sa) b = 0;
else if (b > sb) b = uh;
else b = (x&1 && !(y&1)) ? 0 : uh;
(d->Rpix[y])[x] = r;
(d->Gpix[y])[x] = g;
(d->Bpix[y])[x] = b;
}
}
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/