FloatImg/lib/fimg-math.c

307 lines
7.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* fimg-core.c
*
*
*/
#include <stdio.h>
#include <stdlib.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() */
/* ---------------------------------------------------------------- */
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];
}
case FIMG_TYPE_GRAY:
for (foo=0; foo<surface; foo++) {
if (head->R[foo] > maxval) maxval = head->R[foo];
}
}
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;
}
#if 0
for (foo=0; foo<6; foo++) {
fprintf(stderr, "%3d %g\n", foo, mmvals[foo]);
}
#endif
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] += head->R[idx];
if (head->type > 2) {
accus[1] += head->G[idx];
accus[2] += 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(j1))
| 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 -1;
}
/* ---------------------------------------------------------------- */
void 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;
}
nbre = fi->width * fi->height * fi->type;
#if DEBUG_LEVEL
fprintf(stderr, "%s, nbre is %d\n", __func__, nbre);
#endif
for (idx=0; idx<nbre; idx++) {
fi->R[idx] += value;
}
}
/* ---------------------------------------------------------------- */
int fimg_count_negativ(FloatImg *fi)
{
int nbre, idx;
int count;
if (fi->type != FIMG_TYPE_RGB) {
fprintf(stderr, "%s : type %d invalide\n",
__func__, fi->type);
return -1;
}
nbre = fi->width * fi->height * fi->type;
count = 0;
for (idx=0; idx<nbre; idx++) {
if (fi->R[idx] < 0.0) count++;
}
return count;
}
/* ---------------------------------------------------------------- */
/* nouveau 29 fevrier 2020 */
int fimg_clamp_negativ(FloatImg *fi)
{
int nbre, idx;
int count;
if (fi->type != FIMG_TYPE_RGB) {
fprintf(stderr, "%s : type %d invalide\n",
__func__, fi->type);
return -1;
}
nbre = fi->width * fi->height * fi->type;
count = 0;
for (idx=0; idx<nbre; idx++) {
if (fi->R[idx] < 0.0) {
fi->R[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;
}
/* ---------------------------------------------------------------- */
void 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;
}
nbre = fi->width * fi->height * fi->type;
#if DEBUG_LEVEL
fprintf(stderr, "%s, nbre of datum is %d\n", __func__, nbre);
#endif
for (idx=0; idx<nbre; idx++) {
fi->R[idx] *= value;
}
}
/* ---------------------------------------------------------------- */
int fimg_ajust_from_grab(FloatImg *fi, double maxima, int notused)
{
double coef;
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, "coef %f\n", coef);
}
fimg_mul_cste(fi, coef);
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;
}
}
/* ---------------------------------------------------------------- */