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.
323 lines
7.7 KiB
323 lines
7.7 KiB
/* |
|
* INTERPOLATOR 2070 |
|
* |
|
* +---------------------------------------+ |
|
* ! Do not use that software in real life ! |
|
* +---------------------------------------+ |
|
* |
|
* imported in FloatImg Mon Nov 9 19:08:57 CET 2020 |
|
* |
|
*/ |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <stdint.h> |
|
#include <stdlib.h> |
|
#include <unistd.h> |
|
#include <glob.h> |
|
|
|
#include "../floatimg.h" |
|
|
|
#include "fifo.h" |
|
#include "glitches.h" |
|
#include "crapulator.h" |
|
#include "metriques.h" |
|
#include "filterstack.h" |
|
|
|
int verbosity; |
|
|
|
/* -------------------------------------------------------------- */ |
|
/* on va essayer de trier l'ordre d'apparition des images |
|
* selon une metrique approximative |
|
*/ |
|
typedef struct { |
|
int idx; /* in globbuf.gl_pathv[n] */ |
|
float value; /* from metric analyse */ |
|
} IdxValue; |
|
|
|
static int negative = 0; |
|
|
|
static int cmp_idxvalues(const void *pa, const void *pb) |
|
{ |
|
if (negative) |
|
return ( ((IdxValue *)pa)->value < ((IdxValue *)pb)->value); |
|
else |
|
return ( ((IdxValue *)pa)->value > ((IdxValue *)pb)->value); |
|
} |
|
|
|
int tentative_triage(glob_t *ptr_glob, IdxValue **ptr_idxval, |
|
int method, double *p_average) |
|
{ |
|
int idx, foo, nombre; |
|
float metrique; |
|
double average; |
|
char *filename; |
|
IdxValue *idxvalues; |
|
|
|
#if DEBUG_LEVEL |
|
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, ptr_glob, |
|
ptr_idxval, method); |
|
#endif |
|
|
|
nombre = ptr_glob->gl_pathc; |
|
|
|
/* allocate the array for the sorting action */ |
|
idxvalues = calloc(nombre, sizeof(IdxValue)); |
|
if (NULL==idxvalues) { |
|
fprintf(stderr, "MEMORY ERROR in %s\n", __func__); |
|
exit(1); |
|
} |
|
fprintf(stderr, "IdxValues array at %p\n", idxvalues); |
|
|
|
*ptr_idxval = idxvalues; |
|
average = 0.0; |
|
|
|
/* compute all the needed values */ |
|
for (idx=0; idx<nombre; idx++) { |
|
filename = ptr_glob->gl_pathv[idx]; |
|
foo = get_float_metric_from_file(filename, &metrique, method); |
|
if (foo) { |
|
fprintf(stderr, "%s: err %d get metric of '%s'\n", |
|
__func__, foo, filename); |
|
return -1; |
|
} |
|
if (verbosity) |
|
fprintf(stderr, "%5d %s %10.3f\r", |
|
idx, filename, metrique); |
|
idxvalues[idx].idx = idx; |
|
idxvalues[idx].value = metrique; |
|
average += (double)metrique; |
|
} |
|
|
|
if (method) { |
|
/* and now, we can massage all our datas */ |
|
fprintf(stderr, "sorting method = %d ...\n", method); |
|
qsort(idxvalues, nombre, sizeof(IdxValue), cmp_idxvalues); |
|
} |
|
|
|
if (verbosity > 1) { |
|
for (idx=0; idx<nombre; idx++) { |
|
printf("%5d %9.3f %5d\n", idx, |
|
idxvalues[idx].value, idxvalues[idx].idx); |
|
fflush(stdout); |
|
} |
|
} |
|
average /= (double)nombre; |
|
*p_average = average; |
|
|
|
fprintf(stderr, "\naverage %f\n", average); |
|
|
|
return 0; |
|
} |
|
|
|
/* -------------------------------------------------------------- */ |
|
/* |
|
* This is the mega working loop |
|
*/ |
|
int interpolator(char *pattern, char *outdir, int Nsteps, |
|
int infx, int outfx, int sort) |
|
{ |
|
FloatImg A, B, Out, *pFirst, *pSecond; |
|
glob_t globbuf; |
|
int foo, idx, ipng, w, h, step; |
|
int curpix; |
|
int iarray[3]; |
|
char *cptr, line[200]; |
|
float coef, value; |
|
double meanmetric; |
|
IdxValue *idx_values; /* gni? */ |
|
|
|
fprintf(stderr, " interpolate from '%s' to '%s' with %d steps.\n", |
|
pattern, outdir, Nsteps); |
|
|
|
if (negative) fprintf(stderr, "%s: negative ON\n", __func__); |
|
|
|
memset(&globbuf, 0, sizeof(glob_t)); |
|
foo = glob(pattern, 0, NULL, &globbuf); |
|
fprintf(stderr, "globbing '%s' -> %d, %d files found\n", |
|
pattern, foo, (int)globbuf.gl_pathc); |
|
if (0 == globbuf.gl_pathc) { |
|
fprintf(stderr, "%s : no file found, aborting\n", __func__); |
|
return -1; |
|
} |
|
|
|
idx_values = NULL; |
|
foo = tentative_triage(&globbuf, &idx_values, sort, &meanmetric); |
|
if (foo) { |
|
fprintf(stderr, "sort of %p -> %d\n\n", idx_values, foo); |
|
return foo; |
|
} |
|
|
|
foo = fimg_fileinfos(globbuf.gl_pathv[0], iarray); |
|
if (FIMG_TYPE_RGB != iarray[2]) { |
|
fprintf(stderr, "can work only on RGB fimg picture, was %d\n", |
|
iarray[2]); |
|
exit(1); /* BLAM! */ |
|
} |
|
|
|
w = iarray[0], h = iarray[1]; |
|
fprintf(stderr, "first image size : %dx%d\n", w, h); |
|
|
|
fimg_create(&A, w, h, 3); pFirst = &A; fimg_clear(&A); |
|
fimg_create(&B, w, h, 3); pSecond = &B; fimg_clear(&B); |
|
fimg_create(&Out, w, h, 3); |
|
|
|
ipng = 0; |
|
for (idx=0; idx<globbuf.gl_pathc; idx++) { |
|
|
|
curpix = idx_values[idx].idx; |
|
cptr = globbuf.gl_pathv[curpix]; /* aliasing filename */ |
|
|
|
/* read the next file in B */ |
|
fprintf(stderr, "%5d / %5d %s\r", idx, |
|
(int)globbuf.gl_pathc, cptr); |
|
foo = fimg_load_from_dump(cptr, &B); |
|
if (foo) { |
|
fprintf(stderr, "load %s from dump -> %d\n", cptr, foo); |
|
continue; |
|
} |
|
value = idx_values[idx].value; |
|
|
|
/* here was the input filter */ |
|
foo = filterstack_run(0, &B, 0); |
|
if (foo) { |
|
fprintf(stderr, "%s: input fx fail %d\n", __func__, foo); |
|
exit(1); |
|
} |
|
|
|
for (step=0; step<Nsteps; step++) { |
|
coef = (float)step / (float)Nsteps; |
|
fimg_interpolate(pSecond, pFirst, &Out, coef); |
|
|
|
foo = filterstack_run(1, &Out, 0); |
|
if (foo) { |
|
fprintf(stderr, "run filt stack--> %d\n", foo); |
|
return foo; |
|
} |
|
|
|
sprintf(line, "%s/%05d.png", outdir, ipng); |
|
foo = fimg_save_as_png(&Out, line, 0); |
|
if (foo) { |
|
fprintf(stderr, "err saving %s\n", line); |
|
return -8; |
|
} |
|
ipng++; |
|
} |
|
|
|
#if 1 |
|
/* temporary hack : move datas */ |
|
fimg_copy_data(&B, &A); |
|
#else |
|
/* swap pointers to the two picz */ |
|
pTmp = pSecond; |
|
pSecond = pFirst; |
|
pFirst = pTmp; |
|
/* XXX THIS CODE DON'T WORK !!! */ |
|
#endif |
|
} |
|
|
|
fprintf(stderr, "\ngenerated %d png files\n", ipng); |
|
|
|
return 0; |
|
} |
|
/* -------------------------------------------------------------- */ |
|
void help(void) |
|
{ |
|
puts("\tINTERPOLATOR"); |
|
puts("usage:\n\tinterpolator [options] <inglob> <outdir> <nbsteep>"); |
|
|
|
/* may be we can make options incoherent, like |
|
* the options of 'fonderie' software ? |
|
*/ |
|
puts("options:"); |
|
puts("\t-E i:bla:k\tinput filter chain"); |
|
puts("\t-F name:j\toutput filter chain"); |
|
puts("\t-n\t\tmake negative"); |
|
puts("\t-S nn\t\tmysterious sort"); |
|
puts("\t-L\t\tlist available filters"); |
|
puts("\t-v\t\tincrease verbosity"); |
|
|
|
if (verbosity) { |
|
list_crapulors("available filters"); |
|
} |
|
|
|
exit(0); |
|
} |
|
/* -------------------------------------------------------------- */ |
|
int main (int argc, char *argv[]) |
|
{ |
|
int foo; |
|
int nbrsteps = 9; |
|
int opt; |
|
// int inFx = 0; |
|
// int outFx = 0; |
|
int sort = 0; |
|
char *InFchain = "0"; |
|
char *OutFchain = "0"; |
|
|
|
fprintf(stderr, "*** %s : compiled by tTh, %s %s\n", __FILE__, |
|
__DATE__, __TIME__); |
|
fimg_print_version(2); |
|
|
|
#if DEBUG_LEVEL |
|
/* this is for the debug off calling shellscript */ |
|
for (foo=0; foo<argc; foo++) |
|
fprintf(stderr, "%5d %s\n", foo, argv[foo]); |
|
#endif |
|
|
|
while ((opt = getopt(argc, argv, "E:F:hLnS:v")) != -1) { |
|
switch(opt) { |
|
case 'E': InFchain = optarg; break; |
|
case 'F': OutFchain = optarg; break; |
|
case 'h': help(); break; |
|
case 'L': |
|
list_crapulors("available filters"); |
|
exit(0); |
|
case 'S': sort = atoi(optarg); break; |
|
case 'v': verbosity++; break; |
|
case 'n': negative = 1; break; |
|
} |
|
} |
|
|
|
#if DEBUG_LEVEL |
|
fprintf(stderr, "%s: argc = %d, optind = %d\n", argv[0], argc, optind); |
|
#endif |
|
|
|
if (3 != (argc-optind)) { |
|
fprintf(stderr, "args: [options] <inglob> <outdir> <nbsteep>\n"); |
|
exit(1); |
|
} |
|
|
|
foo = parse_filter_chain(0, InFchain); |
|
if (foo) { |
|
fprintf(stderr, "err %d parsing '%s'\n", foo, InFchain); |
|
exit(1); |
|
} |
|
foo = parse_filter_chain(1, OutFchain); |
|
if (foo) { |
|
fprintf(stderr, "err %d parsing '%s'\n", foo, OutFchain); |
|
exit(1); |
|
} |
|
|
|
if (verbosity) { |
|
fprintf(stderr, "\tinput glob '%s'\n", argv[optind]); |
|
fprintf(stderr, "\toutput dir '%s'\n", argv[optind+1]); |
|
fprintf(stderr, "\tsrc filter '%s'\n", InFchain); |
|
fprintf(stderr, "\tout filter '%s'\n", OutFchain); |
|
} |
|
|
|
if (verbosity > 1) { |
|
fputs("=========================\n", stderr); |
|
filterstack_list(0, __FILE__); |
|
filterstack_list(1, __FILE__); |
|
fputs("=========================\n", stderr); |
|
} |
|
|
|
nbrsteps = atoi(argv[optind+2]); |
|
foo = interpolator(argv[optind], argv[optind+1], nbrsteps, |
|
0, 0, sort); |
|
|
|
fprintf(stderr, "interpolator give us a %d score\n", foo); |
|
|
|
return 0; |
|
} |
|
/* -------------------------------------------------------------- */
|
|
|