2022-06-26 11:06:35 +02:00
|
|
|
/*
|
|
|
|
Operations diverses sur les images
|
|
|
|
----------------------------------
|
|
|
|
|
|
|
|
25 Aout 1999: certaines fonctions utilisent 'alloca'.
|
|
|
|
|
|
|
|
4 Fevrier 2001: je me rend compte que certaines interfaces sont trop
|
2022-10-28 05:07:32 +02:00
|
|
|
simplistes, et que definir des structures contenant de multiples
|
|
|
|
parametres ne serait peut-etre pas une mauvaise idee...
|
2022-06-26 11:06:35 +02:00
|
|
|
|
|
|
|
16 Oct 2001: je deplace quelques fonctions dans d'autres modules.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#ifdef NEED_ALLOCA_H
|
|
|
|
#include <alloca.h>
|
|
|
|
#endif
|
|
|
|
|
2022-06-27 00:48:18 +02:00
|
|
|
#include "../tthimage.h"
|
2022-06-26 11:06:35 +02:00
|
|
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/*
|
|
|
|
* XXX il y a un "Zero Divide" cache dans cette fonction !
|
|
|
|
*/
|
2022-09-17 11:23:21 +02:00
|
|
|
int Image_adjust_minmax_0(Image_Desc *src, Image_Desc *dst, int yo,
|
2022-06-26 11:06:35 +02:00
|
|
|
int minstone, int maxstone)
|
|
|
|
{
|
|
|
|
long histR[256], histG[256], histB[256];
|
|
|
|
long surface;
|
|
|
|
int foo;
|
|
|
|
long mini, maxi, kmini, kmaxi, delta;
|
|
|
|
int idxmini, idxmaxi, val, lut[256], level;
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
if (yo != 0) {
|
2022-06-26 11:06:35 +02:00
|
|
|
fprintf(stderr, "Yo is %d\n", yo);
|
|
|
|
}
|
|
|
|
|
|
|
|
Image_histo_RGB(src, histR, histG, histB);
|
|
|
|
|
|
|
|
surface = (src->width * src->height);
|
|
|
|
kmini = (minstone * surface) / 100;
|
|
|
|
kmaxi = (maxstone * surface) / 100;
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
fprintf(stderr, "adjust minmax:\n");
|
|
|
|
fprintf(stderr, " minstone= %d\n", minstone);
|
|
|
|
fprintf(stderr, " maxstone= %d\n", maxstone);
|
|
|
|
fprintf(stderr, " surface = %ld\n", surface);
|
|
|
|
fprintf(stderr, " K mini = %ld\n", kmini);
|
|
|
|
fprintf(stderr, " K maxi = %ld\n", kmaxi);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
mini = 0;
|
|
|
|
idxmini = 0;
|
2022-09-17 11:23:21 +02:00
|
|
|
for (foo=0; foo<256; foo++) {
|
2022-06-26 11:06:35 +02:00
|
|
|
mini += (histR[foo] + histG[foo] + histB[foo]);
|
2022-09-17 11:23:21 +02:00
|
|
|
if (mini > kmini) {
|
2022-06-26 11:06:35 +02:00
|
|
|
fprintf(stderr, "MINI %3d %ld\n", foo, mini);
|
|
|
|
idxmini = foo;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
maxi = 0;
|
|
|
|
idxmaxi = 255;
|
2022-09-17 11:23:21 +02:00
|
|
|
for (foo=255; foo>=0; foo--) {
|
2022-06-26 11:06:35 +02:00
|
|
|
maxi += (histR[foo] + histG[foo] + histB[foo]);
|
2022-09-17 11:23:21 +02:00
|
|
|
if (maxi > kmaxi) {
|
2022-06-26 11:06:35 +02:00
|
|
|
fprintf(stderr, "MAXI %3d %ld\n", foo, maxi);
|
|
|
|
idxmaxi = foo;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delta = idxmaxi - idxmini;
|
|
|
|
fprintf(stderr, "idxmini=%d idxmaxi=%d delta=%ld\n", idxmini, idxmaxi, delta);
|
|
|
|
|
|
|
|
for (foo=0; foo<idxmini; foo++) lut[foo] = 0;
|
|
|
|
level = 0;
|
2022-09-17 11:23:21 +02:00
|
|
|
for (foo=idxmini; foo<=idxmaxi; foo++) {
|
2022-06-26 11:06:35 +02:00
|
|
|
val = (level*255) / delta;
|
|
|
|
lut[foo] = val;
|
|
|
|
level++;
|
|
|
|
}
|
|
|
|
for (foo=idxmaxi; foo<256; foo++) lut[foo] = 255;
|
|
|
|
|
|
|
|
/**
|
|
|
|
for (foo=0; foo<256; foo++)
|
|
|
|
fprintf(stderr, "%d\t%d\n", foo, lut[foo]);
|
|
|
|
**/
|
|
|
|
|
|
|
|
foo = Image_LUT_mono(src, dst, lut);
|
|
|
|
dst->modified = 1;
|
|
|
|
|
|
|
|
return FUNC_IS_BETA;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/*
|
|
|
|
* et une fonction de plus ecrite a la rache, avec un nom qui
|
|
|
|
* ne veut probablement rien dire :)
|
|
|
|
*/
|
2022-09-17 11:23:21 +02:00
|
|
|
int Image_luminance(Image_Desc *src, Image_Desc *dst, int factor)
|
2022-06-26 11:06:35 +02:00
|
|
|
{
|
|
|
|
int foo;
|
|
|
|
int x, y;
|
|
|
|
|
2022-09-23 13:28:02 +02:00
|
|
|
#if DEBUG_LEVEL
|
2022-09-17 11:23:21 +02:00
|
|
|
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, src, dst, factor);
|
2022-06-30 20:33:31 +02:00
|
|
|
fprintf(stderr, "luminance factor: %d %f\n", factor, (float)factor / 256.0);
|
2022-09-23 13:28:02 +02:00
|
|
|
#endif
|
2022-06-30 20:33:31 +02:00
|
|
|
|
2022-06-26 11:06:35 +02:00
|
|
|
if ( (foo=Image_compare_desc(src, dst)) ) {
|
2022-09-17 11:23:21 +02:00
|
|
|
fprintf(stderr, "%s: images are differents %d\n", __func__, foo);
|
2022-06-26 11:06:35 +02:00
|
|
|
return foo;
|
|
|
|
}
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
for (y=0; y<src->height; y++) {
|
|
|
|
for (x=0; x<src->width; x++) {
|
2022-06-26 11:06:35 +02:00
|
|
|
dst->Rpix[y][x] = (src->Rpix[y][x] * factor) / 256;
|
|
|
|
dst->Gpix[y][x] = (src->Gpix[y][x] * factor) / 256;
|
|
|
|
dst->Bpix[y][x] = (src->Bpix[y][x] * factor) / 256;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dst->modified = 1;
|
|
|
|
|
|
|
|
return FUNC_IS_BETA;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* p'taing, c'est tellement crade qu'il faut:
|
2022-10-28 05:07:32 +02:00
|
|
|
* 1) retrouver d'ou c,a vient
|
2022-06-26 11:06:35 +02:00
|
|
|
* 2) la virer illico !...
|
|
|
|
*/
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/*
|
|
|
|
** ne fonctionne que sur les images en RGB, pour le moment.
|
|
|
|
|
|
|
|
16 jan 2003: il faudrait faire quelque chose pour les
|
|
|
|
images avec un canal Alpha.
|
|
|
|
|
|
|
|
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
|
|
|
|
le parametre 'yoyo' n'est pas utilise actuellement.
|
|
|
|
*/
|
2022-09-17 11:23:21 +02:00
|
|
|
int Image_egalise_RGB(Image_Desc *src, Image_Desc *dst, int yoyo)
|
2022-06-26 11:06:35 +02:00
|
|
|
{
|
|
|
|
int foo;
|
|
|
|
long *histr, *histg, *histb;
|
|
|
|
int *cumlr, *cumlg, *cumlb;
|
|
|
|
long cr, cg, cb, s;
|
|
|
|
|
|
|
|
if (yoyo != 0) {
|
2022-09-23 13:28:02 +02:00
|
|
|
fprintf(stderr, "%s: yoyo is %d ?\n", __func__, yoyo);
|
2022-06-26 11:06:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( (foo=Image_compare_desc(src, dst)) ) {
|
2022-09-23 13:28:02 +02:00
|
|
|
fprintf(stderr, "%s: images are differents %d\n", __func__, foo);
|
2022-06-26 11:06:35 +02:00
|
|
|
return foo;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* yup, en 2009, il faudrait pas remplacer tout ces 'alloca' par de
|
|
|
|
* la bonne 'kiss' variable automatique ?
|
|
|
|
*/
|
|
|
|
if((histr=(long *)alloca(256*sizeof(long))) == NULL) return BUFFER_NO_MEM;
|
|
|
|
if((histg=(long *)alloca(256*sizeof(long))) == NULL) return BUFFER_NO_MEM;
|
|
|
|
if((histb=(long *)alloca(256*sizeof(long))) == NULL) return BUFFER_NO_MEM;
|
|
|
|
if((cumlr=(int *)alloca(256*sizeof(int))) == NULL) return BUFFER_NO_MEM;
|
|
|
|
if((cumlg=(int *)alloca(256*sizeof(int))) == NULL) return BUFFER_NO_MEM;
|
|
|
|
if((cumlb=(int *)alloca(256*sizeof(int))) == NULL) return BUFFER_NO_MEM;
|
|
|
|
|
|
|
|
Image_histo_RGB(src, histr, histg, histb);
|
|
|
|
|
|
|
|
cr = cg = cb = 0L;
|
|
|
|
s = (src->width * src->height);
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL
|
2022-09-23 13:28:02 +02:00
|
|
|
fprintf(stderr, "%s: surface = %ld\n", __func__, s);
|
2022-06-26 11:06:35 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
for (foo=0; foo<256; foo++) {
|
|
|
|
cr += histr[foo]; cumlr[foo] = (int)((cr*255)/s);
|
|
|
|
cg += histg[foo]; cumlg[foo] = (int)((cg*255)/s);
|
|
|
|
cb += histb[foo]; cumlb[foo] = (int)((cb*255)/s);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL > 1
|
|
|
|
fprintf(stderr, "* histo RGB: cumuls: %d %d %d surface: %ld\n",
|
|
|
|
cumlr[255], cumlg[255], cumlb[255], s);
|
2022-09-17 11:23:21 +02:00
|
|
|
for (foo=0; foo<256; foo++) {
|
2022-06-26 11:06:35 +02:00
|
|
|
fprintf(stderr, "%3d | %7ld %7ld %7ld | %7d %7d %7d\n",
|
|
|
|
foo,
|
|
|
|
histr[foo], histg[foo], histb[foo],
|
|
|
|
cumlr[foo], cumlg[foo], cumlb[foo]);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Image_LUT_RGB(src, dst, cumlr, cumlg, cumlb);
|
|
|
|
dst->modified = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/*
|
|
|
|
cette fonction doit absolument etre re-ecrite
|
|
|
|
pour optimiser l'occupation de la memoire.
|
|
|
|
et il faudrait aussi explique ce qu'elle fait :)
|
|
|
|
|
|
|
|
le parametre 'yoyo' n'est pas utilise actuellement.
|
|
|
|
*/
|
2022-09-17 11:23:21 +02:00
|
|
|
int Image_egalise_mono_0(Image_Desc *src, Image_Desc *dst, int yoyo)
|
2022-06-26 11:06:35 +02:00
|
|
|
{
|
|
|
|
int foo;
|
|
|
|
long c, cc, s3;
|
|
|
|
long *histr, *histg, *histb;
|
|
|
|
int cumul[256];
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
if ( (foo=Image_compare_desc(src, dst)) ) {
|
|
|
|
fprintf(stderr, "%s: images are differents %d\n", __func__, foo);
|
2022-06-26 11:06:35 +02:00
|
|
|
return foo;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (yoyo != 0)
|
|
|
|
fprintf(stderr, "%s : yoyo must be 0\n", __func__);
|
|
|
|
|
|
|
|
if((histr=(long *)alloca(256*sizeof(long))) == NULL) return BUFFER_NO_MEM;
|
|
|
|
if((histg=(long *)alloca(256*sizeof(long))) == NULL) return BUFFER_NO_MEM;
|
|
|
|
if((histb=(long *)alloca(256*sizeof(long))) == NULL) return BUFFER_NO_MEM;
|
|
|
|
|
|
|
|
Image_histo_RGB(src, histr, histg, histb);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* diviseur en fonction de la surface
|
|
|
|
*/
|
|
|
|
s3 = (3 * src->width * src->height);
|
|
|
|
|
|
|
|
cc = 0L;
|
2022-09-17 11:23:21 +02:00
|
|
|
for (foo=0; foo<256; foo++) {
|
2022-06-26 11:06:35 +02:00
|
|
|
c = histr[foo] + histg[foo] + histb[foo];
|
|
|
|
cc += c;
|
|
|
|
cumul[foo] = (int)((cc*255) / s3);
|
|
|
|
}
|
|
|
|
|
|
|
|
Image_LUT_mono(src, dst, cumul);
|
|
|
|
dst->modified = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/*
|
|
|
|
complement d'une image complete (c.a.d tous
|
|
|
|
les canaux contenus dans cette image)
|
|
|
|
*/
|
2022-09-17 11:23:21 +02:00
|
|
|
int Image_negate(Image_Desc *image, Image_Desc *resultat)
|
2022-06-26 11:06:35 +02:00
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
if (image->type == 3) {
|
|
|
|
for (y=0; y<image->height; y++) {
|
|
|
|
for (x=0; x<image->width; x++) {
|
2022-06-26 11:06:35 +02:00
|
|
|
resultat->Rpix[y][x] = image->Rpix[y][x] ^ 0xff;
|
|
|
|
resultat->Gpix[y][x] = image->Gpix[y][x] ^ 0xff;
|
|
|
|
resultat->Bpix[y][x] = image->Bpix[y][x] ^ 0xff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
fprintf(stderr, "%s: unknow image type %d, %s\n",
|
|
|
|
__func__, image->type, Image_type2str(image->type));
|
|
|
|
|
2022-06-26 11:06:35 +02:00
|
|
|
return IMAGE_BAD_TYPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
int
|
|
|
|
Image_and_pix( Image_Desc *image, uint8_t ar, uint8_t ag, uint8_t ab )
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
if (image->type == 3)
|
|
|
|
{
|
|
|
|
for (y=0; y<image->height; y++)
|
|
|
|
{
|
|
|
|
for (x=0; x<image->width; x++)
|
|
|
|
{
|
|
|
|
image->Rpix[y][x] &= ar;
|
|
|
|
image->Gpix[y][x] &= ag;
|
|
|
|
image->Bpix[y][x] &= ab;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "Image And Pix: unknow image type %d\n", image->type);
|
|
|
|
return IMAGE_BAD_TYPE;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
int
|
|
|
|
Image_or_pix( Image_Desc *image, int ar, int ag, int ab )
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
if (image->type == 3)
|
|
|
|
{
|
|
|
|
for (y=0; y<image->height; y++)
|
|
|
|
{
|
|
|
|
for (x=0; x<image->width; x++)
|
|
|
|
{
|
|
|
|
image->Rpix[y][x] |= (ar & 0xff);
|
|
|
|
image->Gpix[y][x] |= (ag & 0xff);
|
|
|
|
image->Bpix[y][x] |= (ab & 0xff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "Image_OrPix: unknow image type %d\n", image->type);
|
|
|
|
return IMAGE_BAD_TYPE;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/* new 11 octobre 2001 */
|
|
|
|
int
|
|
|
|
Image_clear_component(Image_Desc *img, char component, int value)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
if (img->type != 3)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Clear Component: only type 3 img\n");
|
|
|
|
return IMAGE_BAD_TYPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (y=0; y<img->height; y++)
|
|
|
|
{
|
|
|
|
for (x=0; x<img->width; x++)
|
|
|
|
{
|
|
|
|
switch (component)
|
|
|
|
{
|
|
|
|
case 'r': case 'R':
|
|
|
|
(img->Rpix[y])[x] = value; break;
|
|
|
|
case 'g': case 'G':
|
|
|
|
(img->Gpix[y])[x] = value; break;
|
|
|
|
case 'b': case 'B':
|
|
|
|
(img->Bpix[y])[x] = value; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
img->modified = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/*
|
|
|
|
* cette func recopie les pixels de la source dont une composante RGB
|
|
|
|
* est superieure aux seuils dans l'image de destination
|
|
|
|
*
|
|
|
|
* 1er Fev 2000: ya quelque chose a faire avec la transparence ?
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
Image_copie_seuil(Image_Desc *s, Image_Desc *d, int sr, int sg, int sb)
|
|
|
|
{
|
|
|
|
int x, y, r, g, b;
|
|
|
|
|
|
|
|
for (y=0; y<s->height; y++)
|
|
|
|
{
|
|
|
|
for (x=0; x<s->width; x++)
|
|
|
|
{
|
|
|
|
r = Image_R_pixel(s, x, y);
|
|
|
|
g = Image_G_pixel(s, x, y);
|
|
|
|
b = Image_B_pixel(s, x, y);
|
|
|
|
if (r>sr || g>sg || b>sb)
|
|
|
|
Image_plotRGB(d, x, y, r, g, b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
d->modified = 0; /* 2001-02-08 */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/*
|
|
|
|
* pourquoi il n'y a pas de test de debordement ?
|
|
|
|
* ce truc ne marche pas bien si il y a de l'Alpha
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
Image_overlay(Image_Desc *s, Image_Desc *d, int xpos, int ypos)
|
|
|
|
{
|
|
|
|
int x, y, r, g, b;
|
|
|
|
int xd, yd;
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
fprintf(stderr, "%s ( %p on %p at %d,%d )\n", __func__,
|
|
|
|
s, d, xpos, ypos);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (y=0; y<s->height; y++)
|
|
|
|
{
|
|
|
|
yd = y+ypos;
|
|
|
|
for (x=0; x<s->width; x++)
|
|
|
|
{
|
|
|
|
xd = x+xpos;
|
|
|
|
if ( (xd>=0) && (xd<d->width-1) && (yd>=0) && (yd<d->height-1) )
|
|
|
|
{
|
|
|
|
r = (s->Rpix[y])[x];
|
|
|
|
g = (s->Gpix[y])[x];
|
|
|
|
b = (s->Bpix[y])[x];
|
|
|
|
Image_plotRGB(d, xd, yd, r, g, b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
d->modified = 1; /* 2001-02-08 */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
int
|
|
|
|
Image_overlay_mix(Image_Desc *s, Image_Desc *d, int xpos, int ypos, int k)
|
|
|
|
{
|
|
|
|
int x, y, sr, sg, sb;
|
|
|
|
int xd, yd;
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL < 10
|
|
|
|
fprintf(stderr, "%s ( %p on %p at %d,%d )\n", __func__,
|
|
|
|
s, d, xpos, ypos);
|
|
|
|
fprintf(stderr, " coef = %d\n", k);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (y=0; y<s->height; y++)
|
|
|
|
{
|
|
|
|
yd = y+ypos;
|
|
|
|
for (x=0; x<s->width; x++)
|
|
|
|
{
|
|
|
|
xd = x+xpos;
|
|
|
|
if ( (xd>=0) && (xd<d->width-1) && (yd>=0) && (yd<d->height-1) )
|
|
|
|
{
|
|
|
|
sr = (s->Rpix[y])[x];
|
|
|
|
sg = (s->Gpix[y])[x];
|
|
|
|
sb = (s->Bpix[y])[x];
|
|
|
|
Image_plotRGB(d, xd, yd, sr, sg, sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
d->modified = 1; /* 2001-02-08 */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/* ce truc sert a quoi ? */
|
|
|
|
static uint16_t rotate_left(uint16_t byte)
|
|
|
|
{
|
|
|
|
byte = byte << 1;
|
|
|
|
if (byte & 0x100) byte |= 1;
|
|
|
|
else byte &= 0xfe;
|
|
|
|
return (byte & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint16_t rotate_right(uint16_t byte)
|
|
|
|
{
|
|
|
|
uint16_t lowbit = byte & 1;
|
|
|
|
byte = byte >> 1;
|
|
|
|
if (lowbit) byte |= 0x80;
|
|
|
|
else byte &= 0x7f;
|
|
|
|
return (byte & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
Image_operator(Image_Desc *in, char op, int val, Image_Desc *out)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
if ( (in->type != 3) || (out->type != 3) )
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Image operator: bad type of image\n");
|
|
|
|
return IMAGE_BAD_TYPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
retval = 0;
|
|
|
|
|
|
|
|
for (y=0; y<in->height; y++)
|
|
|
|
{
|
|
|
|
for (x=0; x<in->width; x++)
|
|
|
|
{
|
|
|
|
switch(op)
|
|
|
|
{
|
|
|
|
case '+':
|
|
|
|
out->Rpix[y][x] = in->Rpix[y][x] + val;
|
|
|
|
out->Gpix[y][x] = in->Gpix[y][x] + val;
|
|
|
|
out->Bpix[y][x] = in->Bpix[y][x] + val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '/':
|
|
|
|
out->Rpix[y][x] = in->Rpix[y][x] / val;
|
|
|
|
out->Gpix[y][x] = in->Gpix[y][x] / val;
|
|
|
|
out->Bpix[y][x] = in->Bpix[y][x] / val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '&': case 'A':
|
|
|
|
out->Rpix[y][x] = in->Rpix[y][x] & val;
|
|
|
|
out->Gpix[y][x] = in->Gpix[y][x] & val;
|
|
|
|
out->Bpix[y][x] = in->Bpix[y][x] & val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '|': case 'O':
|
|
|
|
out->Rpix[y][x] = in->Rpix[y][x] | val;
|
|
|
|
out->Gpix[y][x] = in->Gpix[y][x] | val;
|
|
|
|
out->Bpix[y][x] = in->Bpix[y][x] | val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '^':
|
|
|
|
out->Rpix[y][x] = in->Rpix[y][x] ^ val;
|
|
|
|
out->Gpix[y][x] = in->Gpix[y][x] ^ val;
|
|
|
|
out->Bpix[y][x] = in->Bpix[y][x] ^ val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '*':
|
|
|
|
out->Rpix[y][x] = in->Rpix[y][x] * val;
|
|
|
|
out->Gpix[y][x] = in->Gpix[y][x] * val;
|
|
|
|
out->Bpix[y][x] = in->Bpix[y][x] * val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '<':
|
|
|
|
out->Rpix[y][x] = rotate_left(in->Rpix[y][x]);
|
|
|
|
out->Gpix[y][x] = rotate_left(in->Gpix[y][x]);
|
|
|
|
out->Bpix[y][x] = rotate_left(in->Bpix[y][x]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '>':
|
|
|
|
out->Rpix[y][x] = rotate_right(in->Rpix[y][x]);
|
|
|
|
out->Gpix[y][x] = rotate_right(in->Gpix[y][x]);
|
|
|
|
out->Bpix[y][x] = rotate_right(in->Bpix[y][x]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
out->Rpix[y][x] = in->Rpix[y][x];
|
|
|
|
out->Gpix[y][x] = in->Gpix[y][x];
|
|
|
|
out->Bpix[y][x] = in->Bpix[y][x];
|
|
|
|
retval = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out->modified = 1; /* 2001-09-28 */
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
int Image_seuil_RGB(Image_Desc *s, Image_Desc *d, int r, int g, int b)
|
2022-06-26 11:06:35 +02:00
|
|
|
{
|
|
|
|
int foo, x, y;
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
if ( (s->type != 3) || (d->type != 3) ) {
|
2022-06-26 11:06:35 +02:00
|
|
|
fprintf(stderr, "Image Seuil RGB: an image is not of type 3\n");
|
|
|
|
return IMAGE_BAD_TYPE;
|
|
|
|
}
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
if ( (foo=Image_compare_desc(s, d)) != 0 ) {
|
2022-06-26 11:06:35 +02:00
|
|
|
fprintf(stderr, "Image Seuil RGB: images are differents %d\n", foo);
|
|
|
|
return foo;
|
|
|
|
}
|
|
|
|
|
2022-09-17 11:23:21 +02:00
|
|
|
for (y=0; y<s->height; y++) {
|
|
|
|
for (x=0; x<s->width; x++) {
|
2022-06-26 11:06:35 +02:00
|
|
|
if(s->Rpix[y][x] > r) d->Rpix[y][x] = 255;
|
|
|
|
else d->Rpix[y][x] = 0;
|
|
|
|
if(s->Gpix[y][x] > g) d->Gpix[y][x] = 255;
|
|
|
|
else d->Gpix[y][x] = 0;
|
|
|
|
if(s->Bpix[y][x] > b) d->Bpix[y][x] = 255;
|
|
|
|
else d->Bpix[y][x] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
d->modified = 1; /* 2001-02-08 */
|
|
|
|
return OLL_KORRECT;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/* XXX a tester et a documenter XXX */
|
|
|
|
int
|
|
|
|
Image_AutoSeuilRGB(Image_Desc *s, Image_Desc *d)
|
|
|
|
{
|
|
|
|
int foo, sr, sg, sb;
|
|
|
|
long *histr, *histg, *histb;
|
|
|
|
long surf2, cr, cg, cb;
|
|
|
|
|
|
|
|
if((histr=(long *)alloca(256*sizeof(long))) == NULL)
|
|
|
|
return BUFFER_NO_MEM;
|
|
|
|
if((histg=(long *)alloca(256*sizeof(long))) == NULL)
|
|
|
|
return BUFFER_NO_MEM;
|
|
|
|
if((histb=(long *)alloca(256*sizeof(long))) == NULL)
|
|
|
|
return BUFFER_NO_MEM;
|
|
|
|
|
|
|
|
foo = Image_histo_RGB(s, histr, histg, histb);
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
fprintf(stderr, "in %s histo_RGB -> %d\n", __func__, foo);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
sr = sg = sb = 0;
|
|
|
|
cr = cg = cb = 0L;
|
|
|
|
surf2 = (s->width*s->height)/2;
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
fprintf(stderr, "Auto Seuil RGB sur %p - surf2 = %ld\n", s, surf2);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for (foo=0; foo<256; foo++)
|
|
|
|
{
|
|
|
|
cr += histr[foo];
|
|
|
|
if (cr < surf2) sr = foo;
|
|
|
|
cg += histg[foo];
|
|
|
|
if (cg < surf2) sg = foo;
|
|
|
|
cb += histb[foo];
|
|
|
|
if (cb < surf2) sb = foo;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG_LEVEL
|
|
|
|
fprintf(stderr, "Auto Seuil RGB sur %p - seuils calcules: %d %d %d\n",
|
|
|
|
s, sr, sg, sb);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
foo = Image_seuil_RGB(s, d, sr, sg, sb);
|
|
|
|
|
|
|
|
/* FIXME : this function need a test framework */
|
|
|
|
|
|
|
|
return foo;
|
|
|
|
}
|
|
|
|
/*::------------------------------------------------------------------::*/
|
|
|
|
/*::------------------------------------------------------------------::*/
|