Files
argyllcms/rspl/revbench.c
T
2026-08-20 20:28:40 +01:00

312 lines
7.1 KiB
C

/************************************************/
/* Benchmark RSPL reverse lookup */
/************************************************/
/* Author: Graeme Gill
* Date: 31/10/96
* Derived from tnd.c
* Copyright 1999 - 2000 Graeme W. Gill
*
* This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
* see the License.txt file for licencing details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <math.h>
#include <time.h>
#include "copyright.h"
#include "aconfig.h"
#include "rspl.h"
#include "numlib.h"
//#include "ui.h"
#undef DOLIMIT /* Define to have ink limit */
#define LIMITVAL 2.5 /* Total ink limit sum */
#undef DOCHECK
#define TESTNN /* Test Nearest Clipping */
#define SHOW_OUTPUT /* Define for printf on each conversion */
/* 11, 19 give about 60 seconds */
#define GRES 17 /* Default grid resolution */
#define RRES 43 /* Default reverse test resolution */
#define DI 4 /* Dimensions in */
#define FDI 3 /* Function (out) Dimensions */
#define NIP 10 /* Number of solutions allowed */
#define flimit(vv) ((vv) < 0.0 ? 0.0 : ((vv) > 1.0 ? 1.0 : (vv)))
#define fmin(a,b) ((a) < (b) ? (a) : (b))
#define fmin3(a,b,c) (fmin((a), fmin((b),(c))))
#define fmax(a,b) ((a) > (b) ? (a) : (b))
#define fmax3(a,b,c) (fmax((a), fmax((b),(c))))
/* Fwd function approximated by rspl */
/* Dummy cmyk->rgb conversion. This simulates our device */
void func(
void *cbctx,
double *out,
double *in) {
double kk;
double ci = in[0];
double mi = in[1];
double yi = in[2];
double ki = in[3];
double r,g,b;
ci += ki; /* Add black back in */
mi += ki;
yi += ki;
kk = fmax3(ci,mi,yi);
if (kk > 1.0) {
ci /= kk;
mi /= kk;
yi /= kk;
}
r = 1.0 - ci;
g = 1.0 - mi;
b = 1.0 - yi;
out[0] = flimit(r);
out[1] = flimit(g);
out[2] = flimit(b);
}
/* Simplex ink limit function */
double limitf(
void *lcntx,
float *in
) {
int i;
double ov;
for (ov = 0.0, i = 0; i < DI; i++) {
ov += in[i];
}
return ov;
}
void usage(void) {
fprintf(stderr,"Benchmark rspl reverse, Version %s\n",ARGYLL_VERSION_STR);
fprintf(stderr,"usage: revbench [-f fwdres] [-r revres] [-v level] iccin iccout\n");
fprintf(stderr," -v Verbose\n");
fprintf(stderr," -f res Set forward grid res\n");
fprintf(stderr," -r res Set reverse test res\n");
exit(1);
}
int
main(int argc, char *argv[]) {
int fa,nfa; /* argument we're looking at */
int clutres = GRES;
int rres = RRES;
int verb = 0;
int gres[MXDI];
int e;
clock_t stime,ttime;
rspl *rss; /* Multi-resolution regularized spline structure */
error_program = argv[0];
/* Process the arguments */
for(fa = 1;fa < argc;fa++) {
nfa = fa; /* skip to nfa if next argument is used */
if (argv[fa][0] == '-') { /* Look for any flags */
char *na = NULL; /* next argument after flag, null if none */
if (argv[fa][2] != '\000')
na = &argv[fa][2]; /* next is directly after flag */
else {
if ((fa+1) < argc) {
if (argv[fa+1][0] != '-') {
nfa = fa + 1;
na = argv[nfa]; /* next is seperate non-flag argument */
}
}
}
if (argv[fa][1] == '?')
usage();
/* Verbosity */
else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
verb = 1;
}
else if (argv[fa][1] == 'f' || argv[fa][1] == 'F') {
fa = nfa;
if (na == NULL) usage();
clutres = atoi(na);
}
else if (argv[fa][1] == 'r' || argv[fa][1] == 'R') {
fa = nfa;
if (na == NULL) usage();
rres = atoi(na);
}
else
usage();
} else
break;
}
printf("Started benchmark\n");
/* Create the object */
rss = new_rspl(RSPL_NOFLAGS, DI, FDI);
for (e = 0; e < DI; e++)
gres[e] = clutres;
printf("Rspl allocated\n");
rss->set_rspl(rss, 0, (void *)NULL, func,
NULL, NULL, gres, NULL, NULL);
printf("Rspl set\n");
/* Start exploring the reverse test grid */
{
int ops = 0;
double secs;
rpsh counter;
unsigned rcount;
int ii[10];
int f, rgres[MXDO];
int flags = 0; /* rev hint flags */
co tp[NIP]; /* Test point */
double cvec[4]; /* Text clip vector */
int auxm[4]; /* Auxiliary target value valid flag */
#ifdef DOCHECK
int j;
#endif
#ifdef NEVER
double lmin[4], lmax[4]; /* Locus min/max values */
#endif
#ifdef DOCHECK
char *check; /* Check that we hit every cell */
#endif /* DOCHECK */
/* Set auxiliary target mask */
auxm[0] = 0;
auxm[1] = 0;
auxm[2] = 0;
auxm[3] = 1;
#ifdef DOLIMIT
rss->rev_set_limit(rss,
limitf,
NULL,
LIMITVAL /* limit maximum value */
);
#endif /* DOLIMIT */
printf("Forward resolution %d\n",clutres);
printf("Reverse resolution %d\n",rres);
#ifdef DOCHECK
if ((check = (char *)calloc(1, rcount)) == NULL)
error("Malloc of check array\n");
#endif /* DOCHECK */
for (f = 0; f < FDI; f++)
rgres[f] = rres;
rcount = rpsh_init(&counter, FDI, (unsigned int *)rgres, ii); /* Initialise counter */
stime = clock();
#ifdef TESTNN
flags |= RSPL_NEARCLIP;
#endif
/* Itterate though the grid */
for (ops = 0;; ops++) {
int r;
int e; /* Table index */
#ifdef DOCHECK
check[((ii[2] * rres + ii[1]) * rres) + ii[0]] = 1;
#endif /* DOCHECK */
for (e = 0; e < FDI; e++) { /* Input tables */
tp[0].v[e] = ii[e]/(rres-1.0); /* Vertex coordinates */
}
if (verb)
printf("Input = %f %f %f\n",tp[0].v[0], tp[0].v[1], tp[0].v[2]);
#ifdef NEVER /* Do locus lookup explicitly ? */
/* Lookup the locus for the auxiliary (Black) chanel */
if ((r = rss->rev_locus(rss,
auxm, /* auxm Auxiliary mask flags */
tp, /* Input and auxiliary values */
lmin, /* Locus min/max return values */
lmax
)) == 0) {
/* Rev locus failed - means that it will clip ? */
tp[0].p[3] = 0.5;
flags = RSPL_WILLCLIP; /* Since there was no locus, we expect to clip */
} else {
/* Set the auxiliary target */
tp[0].p[3] = (lmin[3] + lmax[3])/2.0;
flags = RSPL_EXACTAUX; /* Since we got locus, expect exact auxiliary match */
}
#else
tp[0].p[3] = 0.5;
flags = RSPL_AUXLOCUS; /* Auxiliary target is proportion of locus */
#endif /* NEVER */
/* Clip vector to 0.5 */
cvec[0] = 0.5 - tp[0].v[0];
cvec[1] = 0.5 - tp[0].v[1];
cvec[2] = 0.5 - tp[0].v[2];
cvec[3] = 0.5 - tp[0].v[3];
/* Do reverse interpolation */
if ((r = rss->rev_interp(rss,
flags, /* Hint flags */
NIP, /* Number of solutions allowed */
auxm, /* auxm Auxiliary mask flags */
cvec, /* cvec Clip vector direction & length */
tp) /* Input and output values */
) == 0) {
error("rev_interp failed\n");
}
r &= RSPL_NOSOLNS; /* Get number of solutions */
if (verb)
printf("Output 1 of %d: %f, %f, %f, %f%s\n",
r & RSPL_NOSOLNS, tp[0].p[0], tp[0].p[1], tp[0].p[2], tp[0].p[3],
(r & RSPL_DIDCLIP) ? " [Clipped]" : "");
if (rpsh_inc(&counter, ii))
break;
} /* Next grid point */
ttime = clock() - stime;
secs = (double)ttime/CLOCKS_PER_SEC;
printf("Done - %d ops in %f seconds, rate = %f ops/sec\n",ops, secs,ops/secs);
#ifdef DOCHECK
for (j = 0; j < rcount; j++) {
if (check[j] != 1) {
printf("~~CHeck error at %d\n",j);
}
}
#endif /* DOCHECK */
}
rss->del(rss);
return 0;
}