275 lines
5.9 KiB
C
275 lines
5.9 KiB
C
/*
|
|
calculs.c
|
|
---------
|
|
|
|
voir aussi: distances.c
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
#include "../tthimage.h"
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
/* pour les performances, cette fonction
|
|
pourrait devenir une #macro ?
|
|
*/
|
|
int
|
|
Image_clamp_pixel(int value)
|
|
{
|
|
if (value < 0) return 0;
|
|
if (value > 255) return 255;
|
|
return value;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/* new, 2001 June
|
|
*
|
|
* 23 Fev 2002: parfois (recurse ?) on passe plein de fois dans
|
|
* cette fonction. Est-il raisonnable d'optimiser en passant par
|
|
* les accès direct à la mémoire ? Oui, si on améliore les
|
|
* controles de XY ...
|
|
*/
|
|
int
|
|
Image_stats_zone_0(Image_Desc *img, Image_Rect *zone,
|
|
int *pmr, int *pmg, int *pmb,
|
|
int *pdr, int *pdg, int *pdb)
|
|
{
|
|
int x, y;
|
|
int r, g, b;
|
|
int r0, r1, g0, g1, b0, b1;
|
|
long pixels = 0;
|
|
|
|
if ( (zone->w < 2) || (zone->h < 2) )
|
|
{
|
|
Image_dump_rect(zone, "stat_zone_0: too small!", 0);
|
|
return RECT_TOO_SMALL;
|
|
}
|
|
|
|
*pmr = *pmg = *pmb = 0;
|
|
r0 = g0 = b0 = 300;
|
|
r1 = g1 = b1 = -10;
|
|
|
|
for (x=0; x<zone->w; x++)
|
|
{
|
|
for (y=0; y<zone->h; y++)
|
|
{
|
|
r = (img->Rpix[y+zone->y])[x+zone->x];
|
|
g = (img->Gpix[y+zone->y])[x+zone->x];
|
|
b = (img->Bpix[y+zone->y])[x+zone->x];
|
|
|
|
*pmr += r;
|
|
*pmg += g;
|
|
*pmb += b;
|
|
|
|
if (r > r1) r1 = r;
|
|
if (r < r0) r0 = r;
|
|
|
|
if (g > g1) g1 = g;
|
|
if (g < g0) g0 = g;
|
|
|
|
if (b > b1) b1 = b;
|
|
if (b < b0) b0 = b;
|
|
|
|
pixels ++;
|
|
}
|
|
}
|
|
|
|
#if DEBUG_LEVEL > 3
|
|
fprintf(stderr, "Calc zone 0: sommes %d %d %d\n", *pmr, *pmg, *pmb);
|
|
#endif
|
|
|
|
*pmr /= (zone->w*zone->h);
|
|
*pmg /= (zone->w*zone->h);
|
|
*pmb /= (zone->w*zone->h);
|
|
|
|
if (NULL != pdr) *pdr = r1 - r0;
|
|
if (NULL != pdr) *pdg = g1 - g0;
|
|
if (NULL != pdr) *pdb = b1 - b0;
|
|
|
|
/* XXX TO BE GARDED ABOUT NULL PTRS
|
|
if ( (*pdr<0) || (*pdg<0) || (*pdb<0) )
|
|
{
|
|
Image_dump_rect(zone, "negative in stat_zone_0", 0);
|
|
fprintf(stderr, "%ld / %d %d %d %d %d %d\n",
|
|
pixels, r0, r1, g0, g1, b0, b1);
|
|
}
|
|
XXX */
|
|
return OLL_KORRECT;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* reserved for debugging the library. (never finished work :)
|
|
*/
|
|
int
|
|
Image_quelques_calculs(Image_Desc *image)
|
|
{
|
|
long surface, somme;
|
|
int x, y, r, g, b, idx;
|
|
int *compte4bits;
|
|
|
|
surface = image->width * image->height;
|
|
printf("surface de l'image = %ld pixels\n", surface);
|
|
|
|
if ( (compte4bits = (int *)calloc(1<<12, sizeof(int))) == NULL )
|
|
{
|
|
fprintf(stderr, "erreur calloc(surface)\n");
|
|
return 1;
|
|
}
|
|
|
|
for (x=0; x<image->width; x++)
|
|
{
|
|
for (y=0; y<image->height; y++)
|
|
{
|
|
r = (image->Rpix[y])[x] >> 4;
|
|
g = (image->Gpix[y])[x] >> 4;
|
|
b = (image->Bpix[y])[x] >> 4;
|
|
idx = (r<<8) | (g<<4) | b;
|
|
compte4bits[idx]++;
|
|
}
|
|
}
|
|
|
|
somme = 0;
|
|
|
|
for (idx=0; idx<(1<<12); idx++)
|
|
{
|
|
if (compte4bits[idx]) somme++;
|
|
}
|
|
printf("la somme '4bits' est %ld\n", somme);
|
|
|
|
return 0;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* on pourrait rapprocher cette fonction de la fonction
|
|
* qui calcule la couleur moyenne d'une image.
|
|
* son nom est "Image_??????????????" et elle reside
|
|
* dans le module "colors.c".
|
|
*/
|
|
int
|
|
Image_minmax_RGB(Image_Desc *img, int *res)
|
|
{
|
|
int x, y, r, g, b, minr, ming, minb, maxr, maxg, maxb;
|
|
|
|
minr = ming = minb = 300;
|
|
maxr = maxg = maxb = -42;
|
|
|
|
for (x=0; x<img->width; x++)
|
|
{
|
|
for (y=0; y<img->height; y++)
|
|
{
|
|
r = Image_R_pixel(img, x, y);
|
|
if (r > maxr) maxr = r;
|
|
else if (r < minr) minr = r;
|
|
|
|
g = Image_G_pixel(img, x, y);
|
|
if (g > maxg) maxg = g;
|
|
else if (g < ming) ming = g;
|
|
|
|
b = Image_B_pixel(img, x, y);
|
|
if (b > maxb) maxb = b;
|
|
else if (b < minb) minb = b;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* and now populate the return vector...
|
|
*/
|
|
res[0] = minr; res[1] = maxr;
|
|
res[2] = ming; res[3] = maxg;
|
|
res[4] = minb; res[5] = maxb;
|
|
|
|
/*
|
|
* et c,a serait cool de lui faire traiter le canal alpha...
|
|
*/
|
|
res[6] = res[7] = -1;
|
|
|
|
return 0;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
25 Aout 1999.
|
|
gaffe, les @ des buffers pour les histogrames
|
|
proviennent parfois de 'alloca'...
|
|
*/
|
|
int
|
|
Image_histo_RGB(Image_Desc *im, long *hr, long *hg, long *hb)
|
|
{
|
|
int foo, x, y;
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
fprintf(stderr, "%s : %p --> %p %p %p\n", __func__, im, hr, hg, hb);
|
|
#endif
|
|
|
|
for (foo=0; foo<256; foo++) {
|
|
hr[foo] = 0L;
|
|
hg[foo] = 0L;
|
|
hb[foo] = 0L;
|
|
}
|
|
|
|
for (y=0; y<im->height; y++) {
|
|
for (x=0; x<im->width; x++) {
|
|
hr[(im->Rpix[y])[x]]++;
|
|
hg[(im->Gpix[y])[x]]++;
|
|
hb[(im->Bpix[y])[x]]++;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/*
|
|
* 5 Fev 2001: optimization for spe3ed.
|
|
*/
|
|
int
|
|
Image_LUT_RGB(Image_Desc *src, Image_Desc *dst, int *lr, int *lg, int *lb)
|
|
{
|
|
int x, y, foo;
|
|
|
|
if ( (foo=Image_compare_desc(src, dst)) )
|
|
{
|
|
fprintf(stderr, "Image_LUT_RGB: images differentes %d\n", foo);
|
|
return foo;
|
|
}
|
|
|
|
for (y=0; y<src->height; y++)
|
|
{
|
|
for (x=0; x<src->width; x++)
|
|
{
|
|
dst->Rpix[y][x] = lr[src->Rpix[y][x]];
|
|
dst->Gpix[y][x] = lg[src->Gpix[y][x]];
|
|
dst->Bpix[y][x] = lb[src->Bpix[y][x]];
|
|
}
|
|
}
|
|
|
|
return OLL_KORRECT;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
int Image_LUT_mono(Image_Desc *src, Image_Desc *dst, int *lut)
|
|
{
|
|
int x, y, foo;
|
|
|
|
if ( (foo=Image_compare_desc(src, dst)) )
|
|
{
|
|
fprintf(stderr, "%s: images differentes %d\n", __func__, foo);
|
|
return foo;
|
|
}
|
|
|
|
for (y=0; y<src->height; y++)
|
|
{
|
|
for (x=0; x<src->width; x++)
|
|
{
|
|
dst->Rpix[y][x] = lut[src->Rpix[y][x]];
|
|
dst->Gpix[y][x] = lut[src->Gpix[y][x]];
|
|
dst->Bpix[y][x] = lut[src->Bpix[y][x]];
|
|
}
|
|
}
|
|
|
|
return OLL_KORRECT;
|
|
}
|
|
/*::------------------------------------------------------------------::*/
|
|
/* et en parlant de LUTs, il n'y aurait pas un truc pour les LUTs
|
|
* avec les height-fields ? */
|
|
|