/* * fimg-math.c * * */ #include #include #include #include #include #include /* for FLT_MAX */ #include #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 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; fooR[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; fooR[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; idxR[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; } /* ---------------------------------------------------------------- */ /* new: Fri Oct 6 19:51:28 UTC 2023 * * can compute the maxima of a lot of pictures... */ int fimg_max_of_max(FloatImg *img, float maxes[3]) { float localmax[3]; int idx, surface; float fval; localmax[0] = localmax[1] = localmax[2] = -1e9; surface = img->width * img->height; for (idx=0; idxR[idx]; if (fval > localmax[0]) localmax[0] = fval; fval = img->G[idx]; if (fval > localmax[1]) localmax[1] = fval; fval = img->B[idx]; if (fval > localmax[2]) localmax[2] = fval; } if (localmax[0] > maxes[0]) maxes[0] = localmax[0]; if (localmax[1] > maxes[1]) maxes[1] = localmax[1]; if (localmax[2] > maxes[2]) maxes[2] = localmax[2]; 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; idxR[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'apres 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; idxR[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; idxR[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; idxR[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; idxR[idx] *= value; fi->G[idx] *= value; fi->B[idx] *= value; } } if (fi->type == FIMG_TYPE_GRAY) { for (idx=0; idxR[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; idxR[idx] /= value; fi->G[idx] /= value; fi->B[idx] /= value; } } if (fi->type == FIMG_TYPE_GRAY) { for (idx=0; idxR[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; idxR[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; fprintf(stderr, "in %s, drand48() is %f\n", __func__, drand48()); for (idx=0; idxR[idx] = drand48() * kmul; fi->G[idx] = drand48() * kmul; fi->B[idx] = drand48() * kmul; } } /* ---------------------------------------------------------------- */