330 lines
7.9 KiB
C
330 lines
7.9 KiB
C
/*
|
|
* 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 %p)\n", __func__, ptr_glob,
|
|
ptr_idxval, method, p_average);
|
|
#endif
|
|
|
|
if (0==method && verbosity) {
|
|
fprintf(stderr, "\tWTF? in %s, sort method was ZERO?\n", __func__);
|
|
}
|
|
|
|
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 of ??? is %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;
|
|
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, ABEND\n", __func__);
|
|
exit(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];
|
|
if (verbosity) 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, "\n%s: load %s from dump -> %d\n", __func__,
|
|
cptr, foo);
|
|
continue;
|
|
}
|
|
|
|
/* 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\n\tcompiled on %s %s\n", argv[0],
|
|
__DATE__, __TIME__);
|
|
if (verbosity) 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;
|
|
default: exit(1);
|
|
}
|
|
}
|
|
|
|
#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);
|
|
fprintf(stderr, "\tsort %d\n", sort);
|
|
}
|
|
|
|
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;
|
|
}
|
|
/* -------------------------------------------------------------- */
|