libtthimage/Lib/filtres.c
2022-09-21 00:06:11 +02:00

428 lines
11 KiB
C
Raw Blame History

/*
filtrages sur les images
------------------------
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "../tthimage.h"
/*::------------------------------------------------------------------::*/
void Image_filtre_display(FILE *ou, int *mat)
{
int cumul, foo;
for (cumul=foo=0; foo<9; foo++) cumul+=mat[foo];
fprintf(ou, "\t+------ Filtre ------+----- Coefs ------+\n");
fprintf(ou, "\t| %4d %4d %4d | divisor: %4d |\n",
mat[0], mat[1], mat[2], mat[9]);
fprintf(ou, "\t| %4d %4d %4d | offset: %4d |\n",
mat[3], mat[4], mat[5], mat[10]);
fprintf(ou, "\t| %4d %4d %4d | cumul: %4d |\n",
mat[6], mat[7], mat[8], cumul);
fprintf(ou, "\t+--------------------+------------------+\n");
fflush(ou);
}
/*::------------------------------------------------------------------::*/
void Image_rotate_filtre(int *m)
{
register int foo;
foo = m[0];
m[0] = m[3];
m[3] = m[6];
m[6] = m[7];
m[7] = m[8];
m[8] = m[5];
m[5] = m[2];
m[2] = m[1];
m[1] = foo;
}
/*::------------------------------------------------------------------::*/
int Image_convolueur3(Image_Desc *in, Image_Desc *out, int *mat)
{
int foo;
#if DEBUG_LEVEL
fprintf(stderr, "warning: %s is (maybe) obsolete\n", __func__);
#endif
foo = Image_convolueur_2(in, out, mat, "rgb");
return foo;
}
/*::------------------------------------------------------------------::*/
int Image_convolueur_2(Image_Desc *in, Image_Desc *out, int *mat, char *planes)
{
int foo, x, y;
long lval;
int masque = 0;
if (in == out) {
fprintf(stderr, "%s: out overwrite in.\n", __func__);
return IMG_OVERWRITE;
}
if ( (foo=Image_compare_desc(in, out)) ) {
fprintf(stderr, "%s: images are differents %d\n", __func__, foo);
return foo;
}
#if DEBUG_LEVEL > 1
Image_dump_descriptor(in, "image d'entree convolueur");
Image_dump_descriptor(out, "image de sortie convolueur");
#endif
#if DEBUG_LEVEL > 2
Image_filtre_display(stdout, mat);
#endif
if (mat[9] == 0) {
fprintf(stderr, "%s: fsck, divisor is ZERO !\n", __func__);
/*
! c'est sur, avec un message comme c,a je vais pas
! pouvoir transmettre mon code aux australiens
! parfois, ils sont tres cons, les australiens :)
*/
return DIVISOR_IS_ZERO;
}
/*
* preparation of the binary mask from the parameter string
*/
for (foo=0; foo<(int)strlen(planes); foo++) {
switch (planes[foo]) {
case 'r': case 'R':
masque |= 8;
break;
case 'g': case 'G':
masque |= 4;
break;
case 'b': case 'B':
masque |= 2;
break;
case 'a': case 'A':
masque |= 1;
break;
}
}
#if DEBUG_LEVEL > 1
printf("masque convolueur = %02x\n", masque);
#endif
if ( (masque & 1) && (in->Apix == NULL) ) {
fprintf(stderr, "%s: filtering NULL alpha plane is _bad_\n", __func__);
return WRONG_CHANNEL;
}
for (y=1; y<((in->height)-1); y++) {
for (x=1; x<((in->width)-1); x++) {
if (masque & 8) {
lval = mat[0] * in->Rpix[y-1][x-1] +
mat[1] * in->Rpix[y-1][x] +
mat[2] * in->Rpix[y-1][x+1] +
mat[3] * in->Rpix[y] [x-1] +
mat[4] * in->Rpix[y] [x] +
mat[5] * in->Rpix[y] [x+1] +
mat[6] * in->Rpix[y+1][x-1] +
mat[7] * in->Rpix[y+1][x] +
mat[8] * in->Rpix[y+1][x+1] ;
lval = (lval / mat[9]) + mat[10];
if (lval > 255) lval = 255;
else if (lval < 0) lval = 0;
out->Rpix[y][x] = (uint8_t)lval;
}
if (masque & 4) {
lval = mat[0] * in->Gpix[y-1][x-1] +
mat[1] * in->Gpix[y-1][x] +
mat[2] * in->Gpix[y-1][x+1] +
mat[3] * in->Gpix[y] [x-1] +
mat[4] * in->Gpix[y] [x] +
mat[5] * in->Gpix[y] [x+1] +
mat[6] * in->Gpix[y+1][x-1] +
mat[7] * in->Gpix[y+1][x] +
mat[8] * in->Gpix[y+1][x+1] ;
lval = (lval / mat[9]) + mat[10];
if (lval > 255) lval = 255;
else if (lval < 0) lval = 0;
out->Gpix[y][x] = (uint8_t)lval;
}
if (masque & 2) {
lval = mat[0] * in->Bpix[y-1][x-1] +
mat[1] * in->Bpix[y-1][x] +
mat[2] * in->Bpix[y-1][x+1] +
mat[3] * in->Bpix[y] [x-1] +
mat[4] * in->Bpix[y] [x] +
mat[5] * in->Bpix[y] [x+1] +
mat[6] * in->Bpix[y+1][x-1] +
mat[7] * in->Bpix[y+1][x] +
mat[8] * in->Bpix[y+1][x+1] ;
lval = (lval / mat[9]) + mat[10];
if (lval > 255) lval = 255;
else if (lval < 0) lval = 0;
out->Bpix[y][x] = (uint8_t)lval;
}
if (masque & 1) {
lval = mat[0] * in->Apix[y-1][x-1] +
mat[1] * in->Apix[y-1][x] +
mat[2] * in->Apix[y-1][x+1] +
mat[3] * in->Apix[y] [x-1] +
mat[4] * in->Apix[y] [x] +
mat[5] * in->Apix[y] [x+1] +
mat[6] * in->Apix[y+1][x-1] +
mat[7] * in->Apix[y+1][x] +
mat[8] * in->Apix[y+1][x+1] ;
lval = (lval / mat[9]) + mat[10];
if (lval > 255) lval = 255;
else if (lval < 0) lval = 0;
out->Apix[y][x] = (uint8_t)lval;
}
}
}
out->modified = 1;
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
int Image_raz_sides(Image_Desc *im)
{
int foo;
for (foo=0; foo<im->width; foo++) {
(im->Rpix[0])[foo] = 0;
(im->Gpix[0])[foo] = 0;
(im->Bpix[0])[foo] = 0;
(im->Rpix[im->height-1])[foo] = 0;
(im->Gpix[im->height-1])[foo] = 0;
(im->Bpix[im->height-1])[foo] = 0;
}
for (foo=0; foo<im->height; foo++) {
(im->Rpix[foo])[0] = 0;
(im->Gpix[foo])[0] = 0;
(im->Bpix[foo])[0] = 0;
(im->Rpix[foo])[im->width-1] = 0;
(im->Gpix[foo])[im->width-1] = 0;
(im->Bpix[foo])[im->width-1] = 0;
}
im->modified = 1;
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
/*
* Arf, le grand classique :)
*/
int Image_lissage_3x3(Image_Desc *in, Image_Desc *out)
{
int foo, x, y;
if (in == out) {
fprintf(stderr, "%s: out overwrite in\n", __func__);
return IMG_OVERWRITE;
}
if ( (foo=Image_compare_desc(in, out)) ) {
fprintf(stderr, "%s: images have differents size, %d\n", __func__, foo);
return foo;
}
for (y=1; y<((in->height)-1); y++) {
for (x=1; x<((in->width)-1); x++) {
foo = in->Rpix[y-1][x-1] + in->Rpix[y-1][x] + in->Rpix[y-1][x+1] +
in->Rpix[y] [x-1] + in->Rpix[y] [x] + in->Rpix[y] [x+1] +
in->Rpix[y+1][x-1] + in->Rpix[y+1][x] + in->Rpix[y+1][x+1] ;
out->Rpix[y][x] = (uint8_t)(foo / 9);
foo = in->Gpix[y-1][x-1] + in->Gpix[y-1][x] + in->Gpix[y-1][x+1] +
in->Gpix[y] [x-1] + in->Gpix[y] [x] + in->Gpix[y] [x+1] +
in->Gpix[y+1][x-1] + in->Gpix[y+1][x] + in->Gpix[y+1][x+1] ;
out->Gpix[y][x] = (uint8_t)(foo / 9);
foo = in->Bpix[y-1][x-1] + in->Bpix[y-1][x] + in->Bpix[y-1][x+1] +
in->Bpix[y] [x-1] + in->Bpix[y] [x] + in->Bpix[y] [x+1] +
in->Bpix[y+1][x-1] + in->Bpix[y+1][x] + in->Bpix[y+1][x+1] ;
out->Bpix[y][x] = (uint8_t)(foo / 9);
}
}
Image_raz_sides(out);
out->modified = 1;
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
/*
* new 14 Jan 2000
*/
int Image_filtre_Prewitt(Image_Desc *src, Image_Desc *dst, int rotation)
{
static int Prewitt[] = {
1, 1, 1,
0, 0, 0,
-1, -1, -1,
1, 128
};
int filtre[11], foo;
memcpy(filtre, Prewitt, 11*sizeof(int));
for (foo=0; foo<rotation; foo++)
Image_rotate_filtre(filtre);
Image_convolueur_2(src, dst, filtre, "rgb");
return OLL_KORRECT;
}
/*::------------------------------------------------------------------::*/
/*
* XXX cette fonction est incorrecte XXX
*/
int Image_filtre_Sobel(Image_Desc *src, Image_Desc *dst, int rotation)
{
static int Sobel[] = {
1, 2, 1,
0, 0, 0,
-1, -2, -1,
1, 128
};
int filtre[11], foo;
memcpy(filtre, Sobel, 11*sizeof(int));
for (foo=0; foo<rotation; foo++)
Image_rotate_filtre(filtre);
Image_convolueur_2(src, dst, filtre, "rgb");
return OLL_KORRECT;
}
/*
* Voir aussi 'sobel4.c' */
/*::------------------------------------------------------------------::*/
/* new 15 Jan 2000 */
int Image_filtre_passe_bas(Image_Desc *src, Image_Desc *dst)
{
int foo;
static int PasseBas[] = {
1, 2, 1,
2, 4, 2,
1, 2, 1,
16, 0
};
foo = Image_convolueur_2(src, dst, PasseBas, "rgb");
return foo;
}
/*::------------------------------------------------------------------::*/
/* nouveau: 18 Janvier 2001
moral <20> z<>ro, il faut que je fasse p<>daler le 486 ! */
int Image_filtre_random(Image_Desc *src, Image_Desc *dst, int p1, int p2)
{
int filtre[11];
int foo, somme, v, delta;
if (p1 == p2) {
fprintf(stderr, "%s: p1=%d must be different from p2=%d\n",
__func__, p1, p2);
return INVALID_PARAM;
}
somme = 0;
delta = abs(p2 - p1);
#if DEBUG_LEVEL
fprintf(stderr, "%s: delta is %d\n", __func__, delta);
#endif
for (foo=0; foo<9; foo++) {
v = (rand()%delta)+p1;
filtre[foo] = v;
somme += v;
}
filtre[9] = somme;
filtre[10] = 0; /* XXX calcul automatique a faire ! */
Image_filtre_display(stdout, filtre);
foo = Image_convolueur_2(src, dst, filtre, "rgb");
fprintf(stderr, "retour convolueur = %d\n", foo);
return FUNC_IS_BETA;
/* et en plus, ce _truc_ n'a _aucune_ valeur scientifique... */
}
/*::------------------------------------------------------------------::*/
/* nouveau: 3 Fevrier 2001
on s'inspire de la precedente.
*/
int Image_filtre_random_2(Image_Desc *src, Image_Desc *dst,
int p1, int p2, int p3, int p4)
{
int filtre[11];
int foo, somme, v, delta, deltb;
#if DEBUG_LEVEL
fprintf(stderr, "%s: %d %d / %d %d\n", __func__, p1, p2, p3, p4);
#endif
delta = abs(p2 - p1);
deltb = abs(p4 - p3);
#if DEBUG_LEVEL
fprintf(stderr, "Filtre Random 2: delta are %d %d\n", delta, deltb);
#endif
somme = 0;
for (foo=0; foo<9; foo++) {
if (foo != 4) {
v = (rand()%delta)+p1;
}
else {
v = (rand()%deltb)+p3;
}
filtre[foo] = v;
somme += v;
}
filtre[9] = somme;
filtre[10] = 0; /* XXX calcul automatique a faire ! */
Image_filtre_display(stdout, filtre);
foo = Image_convolueur_2(src, dst, filtre, "rgb");
return FUNC_IS_BETA;
}
/*::------------------------------------------------------------------::*/
int Image_filtre_passe_haut(Image_Desc *src, Image_Desc *dst)
{
int foo;
static int PasseHaut[] = {
-1, -1, -1,
-1, 8, -1,
-1, -1, -1,
1, 0
};
foo = Image_convolueur_2(src, dst, PasseHaut, "rgb");
return foo;
}
/*::------------------------------------------------------------------::*/