409 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			409 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						||
 *		fimg-math.c
 | 
						||
 *
 | 
						||
 *
 | 
						||
 */
 | 
						||
 | 
						||
#include  <stdio.h>
 | 
						||
#include  <stdlib.h>
 | 
						||
#include  <stdint.h>
 | 
						||
#include  <unistd.h>
 | 
						||
#include  <string.h>
 | 
						||
#include  <float.h>		/* for FLT_MAX */
 | 
						||
#include  <math.h>
 | 
						||
 | 
						||
#include  "../floatimg.h"
 | 
						||
 | 
						||
extern int verbosity;		/* must be declared around main() */
 | 
						||
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
/* 	nouveau 27 fevrier 2022 */
 | 
						||
float fimg_get_plane_maxvalue(FloatImg *psrc, char plane)
 | 
						||
{
 | 
						||
float		*ptrplane;
 | 
						||
float		maxval;
 | 
						||
int		area, foo;
 | 
						||
 | 
						||
#if DEBUG_LEVEL
 | 
						||
fprintf(stderr, ">>> %s ( %p '%c' )\n", __func__, psrc, plane);
 | 
						||
#endif
 | 
						||
 | 
						||
switch (plane) {
 | 
						||
	case 'r':	case 'R':
 | 
						||
		ptrplane = psrc->R;		break;
 | 
						||
	case 'g':	case 'G':
 | 
						||
		ptrplane = psrc->G;		break;
 | 
						||
	case 'b':	case 'B':
 | 
						||
		ptrplane = psrc->B;		break;
 | 
						||
	case 'a':	case 'A':
 | 
						||
		ptrplane = psrc->A;		break;
 | 
						||
	default:
 | 
						||
		fprintf(stderr, "%s: plane error\n", __func__);
 | 
						||
		abort();			break;
 | 
						||
		}
 | 
						||
 | 
						||
area = psrc->width * psrc->height;
 | 
						||
maxval = 0.0;
 | 
						||
 | 
						||
for (foo=0; foo<area; foo++) {
 | 
						||
	if (ptrplane[foo] > maxval)	maxval = ptrplane[foo];
 | 
						||
	}
 | 
						||
 | 
						||
return maxval;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
float fimg_get_maxvalue(FloatImg *head)
 | 
						||
{
 | 
						||
float		maxval;
 | 
						||
int		foo, surface;
 | 
						||
 | 
						||
if (head->type != FIMG_TYPE_RGB && head->type != FIMG_TYPE_GRAY) {
 | 
						||
	fprintf(stderr, "%s : type %d invalide\n",
 | 
						||
				__func__, head->type);
 | 
						||
	return nanf("wtf ?");
 | 
						||
	}
 | 
						||
 | 
						||
maxval = 0.0;		/* no negative values allowed */
 | 
						||
 | 
						||
surface = head->width*head->height;
 | 
						||
 | 
						||
switch (head->type) {
 | 
						||
	case FIMG_TYPE_RGB:
 | 
						||
		for (foo=0; foo<surface; foo++) {
 | 
						||
		if (head->R[foo] > maxval) maxval = head->R[foo];
 | 
						||
		if (head->G[foo] > maxval) maxval = head->G[foo];
 | 
						||
		if (head->B[foo] > maxval) maxval = head->B[foo];
 | 
						||
		}
 | 
						||
		break;
 | 
						||
	case FIMG_TYPE_GRAY:
 | 
						||
		for (foo=0; foo<surface; foo++) {
 | 
						||
		if (head->R[foo] > maxval) maxval = head->R[foo];
 | 
						||
		}
 | 
						||
		break;
 | 
						||
	}
 | 
						||
 | 
						||
return maxval;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
/*
 | 
						||
 *	mmval[0] <- min(R)    mmval[1] <- max(R)
 | 
						||
 */
 | 
						||
int fimg_get_minmax_rgb(FloatImg *head, float mmvals[6])
 | 
						||
{
 | 
						||
int		idx, surface;
 | 
						||
float		fval;
 | 
						||
 | 
						||
if (head->type != FIMG_TYPE_RGB) {
 | 
						||
	fprintf(stderr, "%s : type %d invalide\n",
 | 
						||
				__func__, head->type);
 | 
						||
	return -2;
 | 
						||
	}
 | 
						||
 | 
						||
surface = head->width * head->height;
 | 
						||
mmvals[0] = FLT_MAX;	mmvals[1] = -FLT_MAX;
 | 
						||
mmvals[2] = FLT_MAX;	mmvals[3] = -FLT_MAX;
 | 
						||
mmvals[4] = FLT_MAX;	mmvals[5] = -FLT_MAX;
 | 
						||
 | 
						||
for (idx=0; idx<surface; idx++) {
 | 
						||
	fval = head->R[idx];
 | 
						||
	if      (fval < mmvals[0])	mmvals[0] = fval;
 | 
						||
	else if (fval > mmvals[1])	mmvals[1] = fval;
 | 
						||
	fval = head->G[idx];
 | 
						||
	if      (fval < mmvals[2])	mmvals[2] = fval;
 | 
						||
	else if (fval > mmvals[3])	mmvals[3] = fval;
 | 
						||
	fval = head->B[idx];
 | 
						||
	if      (fval < mmvals[4])	mmvals[4] = fval;
 | 
						||
	else if (fval > mmvals[5])	mmvals[5] = fval;
 | 
						||
	}
 | 
						||
 | 
						||
return -0;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
int fimg_meanvalues(FloatImg *head, float means[4])
 | 
						||
{
 | 
						||
int		idx, surface;
 | 
						||
double		accus[4];
 | 
						||
 | 
						||
surface = head->width * head->height;
 | 
						||
if (surface < 1)	return -1;
 | 
						||
 | 
						||
memset(accus, 0, 4*sizeof(double));
 | 
						||
 | 
						||
for (idx=0; idx<surface; idx++) {
 | 
						||
	accus[0] += (double)head->R[idx];
 | 
						||
	if (head->type > 2) {			/* WTF ? */
 | 
						||
		accus[1] += (double)head->G[idx];
 | 
						||
		accus[2] += (double)head->B[idx];
 | 
						||
		}
 | 
						||
	}
 | 
						||
 | 
						||
for (idx=0; idx<4; idx++) {
 | 
						||
	means[idx] = (float)(accus[idx]/(double)surface);
 | 
						||
	}
 | 
						||
 | 
						||
return 0;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
/* d'après Wikipedia Fr :
 | 
						||
                        | c = 0
 | 
						||
                        | s = x1
 | 
						||
                        | pour j de 2 à n
 | 
						||
                        |   s = s+xj
 | 
						||
                        |   c = c+(j xj − s)2/(j(j−1))
 | 
						||
                        | renvoyer c/n
 | 
						||
 | 
						||
Mais c,a ne semble pas etre la bonne methode. Il faut aller voir :
 | 
						||
https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
 | 
						||
*/
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
/*
 | 
						||
 *	more elaborate functions are in fimg-2gray.c
 | 
						||
 */
 | 
						||
int fimg_to_gray(FloatImg *head)
 | 
						||
{
 | 
						||
float		add;
 | 
						||
int		foo;
 | 
						||
 | 
						||
if (head->type != FIMG_TYPE_RGB) {
 | 
						||
	fprintf(stderr, "%s : type %d invalide\n",
 | 
						||
				__func__, head->type);
 | 
						||
	return -3;
 | 
						||
	}
 | 
						||
 | 
						||
for (foo=0; foo<(head->width*head->height); foo++) {
 | 
						||
	add  = head->R[foo];
 | 
						||
	add += head->G[foo];
 | 
						||
	add += head->B[foo];
 | 
						||
	head->R[foo] = head->G[foo] = head->B[foo] = add / 3.0;
 | 
						||
	}
 | 
						||
return 0;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
int fimg_add_cste(FloatImg *fi, float value)
 | 
						||
{
 | 
						||
int		nbre, idx;
 | 
						||
 | 
						||
if (fi->type != FIMG_TYPE_RGB) {
 | 
						||
	fprintf(stderr, "%s : type %d invalide\n",
 | 
						||
				__func__, fi->type);
 | 
						||
	return -44;
 | 
						||
	}
 | 
						||
 | 
						||
nbre = fi->width * fi->height ;
 | 
						||
#if DEBUG_LEVEL
 | 
						||
fprintf(stderr, "%s, nbre is %d\n", __func__, nbre);
 | 
						||
#endif
 | 
						||
for (idx=0; idx<nbre; idx++) {
 | 
						||
	fi->R[idx] += value;
 | 
						||
	fi->G[idx] += value;
 | 
						||
	fi->B[idx] += value;
 | 
						||
	}
 | 
						||
return 0;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
long fimg_count_negativ(FloatImg *fi)
 | 
						||
{
 | 
						||
int		nbre, idx;
 | 
						||
long		count;
 | 
						||
 | 
						||
if (fi->type != FIMG_TYPE_RGB) {
 | 
						||
	fprintf(stderr, "%s : type %d invalide\n",
 | 
						||
				__func__, fi->type);
 | 
						||
	return -1;
 | 
						||
	}
 | 
						||
 | 
						||
nbre = fi->width * fi->height;
 | 
						||
 | 
						||
count = 0;
 | 
						||
for (idx=0; idx<nbre; idx++) {
 | 
						||
	if (fi->R[idx] < 0.0)	count++;
 | 
						||
	if (fi->G[idx] < 0.0)	count++;
 | 
						||
	if (fi->B[idx] < 0.0)	count++;
 | 
						||
	}
 | 
						||
 | 
						||
return count;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
/* nouveau 29 fevrier 2020 */
 | 
						||
long fimg_clamp_negativ(FloatImg *fi)
 | 
						||
{
 | 
						||
int		nbre, idx;
 | 
						||
long		count;
 | 
						||
 | 
						||
if (fi->type != FIMG_TYPE_RGB) {
 | 
						||
	fprintf(stderr, "%s : type %d invalide\n",
 | 
						||
				__func__, fi->type);
 | 
						||
	return -1;
 | 
						||
	}
 | 
						||
 | 
						||
nbre = fi->width * fi->height;
 | 
						||
 | 
						||
count = 0;
 | 
						||
for (idx=0; idx<nbre; idx++) {
 | 
						||
	if (fi->R[idx] < 0.0) {
 | 
						||
		fi->R[idx] = 0.0;	count++;
 | 
						||
		}
 | 
						||
	if (fi->G[idx] < 0.0) {
 | 
						||
		fi->G[idx] = 0.0;	count++;
 | 
						||
		}
 | 
						||
	if (fi->B[idx] < 0.0) {
 | 
						||
		fi->B[idx] = 0.0;	count++;
 | 
						||
		}
 | 
						||
	}
 | 
						||
 | 
						||
/* WTF 12 avril 2020, valgrind me cause mal ?
 | 
						||
==28943== Conditional jump or move depends on uninitialised value(s)
 | 
						||
==28943==    at 0x4045E9: fimg_clamp_negativ (fimg-math.c:208)
 | 
						||
==28943==    by 0x4018C9: essai_filtrage_3x3 (t.c:128)
 | 
						||
==28943==    by 0x4024D5: main (t.c:444)
 | 
						||
==28943==  Uninitialised value was created by a heap allocation
 | 
						||
==28943==    at 0x483577F: malloc (vg_replace_malloc.c:299)
 | 
						||
==28943==    by 0x40284D: fimg_create (fimg-core.c:107)
 | 
						||
==28943==    by 0x402AB3: fimg_clone (fimg-core.c:174)
 | 
						||
==28943==    by 0x401861: essai_filtrage_3x3 (t.c:118)
 | 
						||
==28943==    by 0x4024D5: main (t.c:444)
 | 
						||
*/
 | 
						||
 | 
						||
return count;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
int  fimg_mul_cste(FloatImg *fi, float value)
 | 
						||
{
 | 
						||
int		nbre, idx;
 | 
						||
 | 
						||
if ( (fi->type != FIMG_TYPE_RGB) && (fi->type != FIMG_TYPE_GRAY) ) {
 | 
						||
	fprintf(stderr, "%s : type %d invalide\n",
 | 
						||
				__func__, fi->type);
 | 
						||
	return -44;
 | 
						||
	}
 | 
						||
 | 
						||
nbre = fi->width * fi->height;
 | 
						||
#if DEBUG_LEVEL
 | 
						||
fprintf(stderr, "%s, nbre of datum is %d\n", __func__, nbre);
 | 
						||
#endif
 | 
						||
if (fi->type == FIMG_TYPE_RGB) {
 | 
						||
	for (idx=0; idx<nbre; idx++) {
 | 
						||
		fi->R[idx] *= value;
 | 
						||
		fi->G[idx] *= value;
 | 
						||
		fi->B[idx] *= value;
 | 
						||
		}
 | 
						||
	}
 | 
						||
if (fi->type == FIMG_TYPE_GRAY) {
 | 
						||
	for (idx=0; idx<nbre; idx++) {
 | 
						||
		fi->R[idx] *= value;
 | 
						||
		}
 | 
						||
	}
 | 
						||
return 0;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
/*				nouveau 17 septembre 2022 */
 | 
						||
int   fimg_div_cste(FloatImg *fi, float value)
 | 
						||
{
 | 
						||
int		nbre, idx;
 | 
						||
 | 
						||
if ( (fi->type != FIMG_TYPE_RGB) && (fi->type != FIMG_TYPE_GRAY) ) {
 | 
						||
	fprintf(stderr, "%s : type %d invalide\n",
 | 
						||
				__func__, fi->type);
 | 
						||
	return -44;
 | 
						||
	}
 | 
						||
 | 
						||
nbre = fi->width * fi->height;
 | 
						||
if (fi->type == FIMG_TYPE_RGB) {
 | 
						||
	for (idx=0; idx<nbre; idx++) {
 | 
						||
		fi->R[idx] /= value;
 | 
						||
		fi->G[idx] /= value;
 | 
						||
		fi->B[idx] /= value;
 | 
						||
		}
 | 
						||
	}
 | 
						||
if (fi->type == FIMG_TYPE_GRAY) {
 | 
						||
	for (idx=0; idx<nbre; idx++) {
 | 
						||
		fi->R[idx] /= value;
 | 
						||
		}
 | 
						||
	}
 | 
						||
return 0;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
/*
 | 
						||
 *	oh, please explain the usecase of this function !
 | 
						||
 */
 | 
						||
int fimg_ajust_from_grab(FloatImg *fi, double maxima, int notused)
 | 
						||
{
 | 
						||
double		coef;
 | 
						||
 | 
						||
if (notused) {
 | 
						||
	fprintf(stderr, "notused was %d, must be 0 in %s\n",
 | 
						||
				notused, 		__func__);
 | 
						||
	}
 | 
						||
 | 
						||
if (fi->type != FIMG_TYPE_RGB) {
 | 
						||
	fprintf(stderr, "%s : type %d invalide\n",
 | 
						||
				__func__, fi->type);
 | 
						||
	return -99;
 | 
						||
	}
 | 
						||
 | 
						||
if (fi->count < 1) {
 | 
						||
	fprintf(stderr, "%s : count %d is invalid\n", __func__, fi->count);
 | 
						||
	return -98;
 | 
						||
	}
 | 
						||
 | 
						||
/*
 | 
						||
 *		mmmm, is this real ?
 | 
						||
 *	how to accuratly check the value of 'I.fval' ?
 | 
						||
 */
 | 
						||
coef = 1.0 / ((double)fi->count * (double)fi->fval);
 | 
						||
 | 
						||
if (verbosity) {
 | 
						||
	fprintf(stderr, "image @    %p\n", fi);
 | 
						||
	fprintf(stderr, "fval       %f\n", fi->fval);
 | 
						||
	fprintf(stderr, "count      %d\n", fi->count);
 | 
						||
	fprintf(stderr, "maxima     %f\n", maxima);
 | 
						||
	fprintf(stderr, "coef       %f\n", coef);
 | 
						||
	}
 | 
						||
 | 
						||
fimg_mul_cste(fi, coef);
 | 
						||
 | 
						||
return 0;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
int fimg_absolute(FloatImg *fi)
 | 
						||
{
 | 
						||
int		surface, idx;
 | 
						||
 | 
						||
surface = fi->width * fi->height;
 | 
						||
 | 
						||
for (idx=0; idx<surface; idx++) {
 | 
						||
	fi->R[idx] = fabsf(fi->R[idx]);
 | 
						||
	fi->G[idx] = fabsf(fi->G[idx]);
 | 
						||
	fi->B[idx] = fabsf(fi->B[idx]);
 | 
						||
	}
 | 
						||
 | 
						||
return 0;
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
 | 
						||
/*            Warning: this function is _very_ slow                 */
 | 
						||
void fimg_drand48(FloatImg *fi, float kmul)
 | 
						||
{
 | 
						||
int		nbre, idx;
 | 
						||
 | 
						||
#if DEBUG_LEVEL
 | 
						||
fprintf(stderr, ">>> %s ( %p %g )\n", __func__, fi, kmul);
 | 
						||
#endif
 | 
						||
 | 
						||
if (fi->type != FIMG_TYPE_RGB) {
 | 
						||
	fprintf(stderr, "%s : type %d invalide\n",
 | 
						||
				__func__, fi->type);
 | 
						||
	return;
 | 
						||
	}
 | 
						||
nbre = fi->width * fi->height;
 | 
						||
for (idx=0; idx<nbre; idx++) {
 | 
						||
	fi->R[idx] = drand48() * kmul;
 | 
						||
	fi->G[idx] = drand48() * kmul;
 | 
						||
	fi->B[idx] = drand48() * kmul;
 | 
						||
	}
 | 
						||
 | 
						||
}
 | 
						||
/* ---------------------------------------------------------------- */
 | 
						||
 | 
						||
 |