428 lines
11 KiB
C
428 lines
11 KiB
C
/*
|
||
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;
|
||
}
|
||
/*::------------------------------------------------------------------::*/
|