Bibliothèque de traitements d'images en virgule flottante.
http://la.buvette.org/photos/cumul/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
7.5 KiB
321 lines
7.5 KiB
/* |
|
* 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; |
|
} |
|
|
|
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; |
|
} |
|
/* ---------------------------------------------------------------- */ |
|
/* |
|
* oh, please explain the usecase of this function ! |
|
*/ |
|
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; |
|
} |
|
|
|
} |
|
/* ---------------------------------------------------------------- */ |
|
|
|
|
|
|