292 lines
6.7 KiB
C
292 lines
6.7 KiB
C
/*
|
|
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;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, s, d, uh);
|
|
#endif
|
|
|
|
/* 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;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, s, d, uh);
|
|
#endif
|
|
|
|
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;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* Il ne marche pas tres 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;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, s, d, uh);
|
|
#endif
|
|
|
|
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;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, s, d, uh);
|
|
#endif
|
|
|
|
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;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, s, d, uh);
|
|
#endif
|
|
|
|
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;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|