From 22f703cab05b7cd368f4de9e03991b7664dc5022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 1 Sep 2014 13:56:46 +0200 Subject: Initial import of argyll version 1.5.1-8 --- spectro/synthcal.c | 350 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 spectro/synthcal.c (limited to 'spectro/synthcal.c') diff --git a/spectro/synthcal.c b/spectro/synthcal.c new file mode 100644 index 0000000..75d18be --- /dev/null +++ b/spectro/synthcal.c @@ -0,0 +1,350 @@ + +/* + * Argyll Color Correction System + * Create a linear display calibration file. + * + * Author: Graeme W. Gill + * Date: 15/11/2005 + * + * Copyright 1996 - 2007 Graeme W. Gill + * All rights reserved. + * + * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- + * see the License.txt file for licencing details. + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include "copyright.h" +#include "aconfig.h" +#include "numlib.h" +#include "cgats.h" +#include "xicc.h" + +#include "sort.h" + +#include + +#if defined (NT) +#include +#endif + +void +usage(int level) { + int i; + fprintf(stderr,"Create a synthetic calibration file, Version %s\n",ARGYLL_VERSION_STR); + fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n"); + fprintf(stderr,"usage: synthcal [-options] outfile\n"); + fprintf(stderr," -t N i = input, o = output, d = display (default)\n"); + fprintf(stderr," -d col_comb choose colorant combination from the following (default 3):\n"); + for (i = 0; ; i++) { + char *desc; + if (icx_enum_colorant_comb(i, &desc) == 0) + break; + fprintf(stderr," %d: %s\n",i,desc); + } + fprintf(stderr," -D colorant Add or delete colorant from combination:\n"); + if (level == 0) + fprintf(stderr," (Use -?? to list known colorants)\n"); + else { + fprintf(stderr," %d: %s\n",0,"Additive"); + for (i = 0; ; i++) { + char *desc; + if (icx_enum_colorant(i, &desc) == 0) + break; + fprintf(stderr," %d: %s\n",i+1,desc); + } + } + fprintf(stderr," -o o1,o2,o3, Set non-linear curve offset (default 0.0)\n"); + fprintf(stderr," -s s1,s2,s3, Set non-linear curve scale (default 1.0)\n"); + fprintf(stderr," -p p1,p2,p3, Set non-linear curve powers (default 1.0)\n"); + fprintf(stderr," -E description Set the profile dEscription string\n"); + fprintf(stderr," outfile Base name for output .cal file\n"); + exit(1); + } + +int main(int argc, char *argv[]) +{ + int fa,nfa; /* current argument we're looking at */ + int j; + int verb = 0; + char outname[MAXNAMEL+1] = { 0 }; /* Output cgats file base name */ + char *profDesc = NULL; /* Description */ + int devtype = 2; /* debice type, 0 = in, 1 = out, 2 = display */ + inkmask devmask = 0; /* ICX ink mask of device space */ + int devchan; /* Number of chanels in device space */ + char *ident; /* Ink combination identifier (includes possible leading 'i') */ + char *bident; /* Base ink combination identifier */ + double off[MAX_CHAN]; /* Output offset */ + double sca[MAX_CHAN]; /* Output scale */ + double gam[MAX_CHAN]; /* Gamma applied */ + + for (j = 0; j < MAX_CHAN; j++) + off[j] = 0.0, sca[j] = gam[j] = 1.0; + + error_program = "synthcal"; + if (argc <= 1) + usage(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] == '?' || argv[fa][1] == '-') { + if (argv[fa][2] == '?' || argv[fa][2] == '-') + usage(1); + usage(0); + } + + else if (argv[fa][1] == 'v') + verb = 1; + + /* Select the device type */ + else if (argv[fa][1] == 't' || argv[fa][1] == 'T') { + fa = nfa; + if (na == NULL) usage(0); + if (na[0] == 'i' || na[0] == 'I') + devtype = 0; + else if (na[0] == 'o' || na[0] == 'O') + devtype = 1; + else if (na[0] == 'd' || na[0] == 'D') + devtype = 2; + else + usage(0); + } + + /* Select the ink enumeration */ + else if (argv[fa][1] == 'd') { + int ix; + fa = nfa; + if (na == NULL) usage(0); + ix = atoi(na); + if (ix == 0 && na[0] != '0') + usage(0); + if ((devmask = icx_enum_colorant_comb(ix, NULL)) == 0) + usage(0); + } + + /* Toggle the colorant in ink combination */ + else if (argv[fa][1] == 'D') { + int ix, tmask; + fa = nfa; + if (na == NULL) usage(0); + ix = atoi(na); + if (ix == 0 && na[0] != '0') + usage(0); + if (ix == 0) + tmask = ICX_ADDITIVE; + else + if ((tmask = icx_enum_colorant(ix-1, NULL)) == 0) + usage(0); + devmask ^= tmask; + } + + /* curve offset */ + else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') { + fa = nfa; + if (na == NULL) usage(0); + for (j = 0; j < MAX_CHAN; j++) { + int i; + for (i = 0; ; i++) { + if (na[i] == ','){ + na[i] = '\000'; + break; + } + if (na[i] == '\000') { + i = 0; + break; + } + } + off[j] = atof(na); + if (i == 0) + break; + na += i+1; + } + } + + /* curve scale */ + else if (argv[fa][1] == 's' || argv[fa][1] == 'S') { + fa = nfa; + if (na == NULL) usage(0); + for (j = 0; j < MAX_CHAN; j++) { + int i; + for (i = 0; ; i++) { + if (na[i] == ','){ + na[i] = '\000'; + break; + } + if (na[i] == '\000') { + i = 0; + break; + } + } + sca[j] = atof(na); + if (i == 0) + break; + na += i+1; + } + } + + /* curve power */ + else if (argv[fa][1] == 'p' || argv[fa][1] == 'P') { + fa = nfa; + if (na == NULL) usage(0); + for (j = 0; j < MAX_CHAN; j++) { + int i; + for (i = 0; ; i++) { + if (na[i] == ','){ + na[i] = '\000'; + break; + } + if (na[i] == '\000') { + i = 0; + break; + } + } + gam[j] = atof(na); + if (i == 0) + break; + na += i+1; + } + } + + /* Profile Description */ + else if (argv[fa][1] == 'E') { + fa = nfa; + if (na == NULL) usage(0); + profDesc = na; + } + + + else + usage(0); + } else + break; + } + + /* Get the file name argument */ + if (fa >= argc || argv[fa][0] == '-') usage(0); + strcpy(outname,argv[fa]); + if (strlen(outname) < 4 || strcmp(".cal",outname + strlen(outname)-4) != 0) + strcat(outname,".cal"); + + /* Implement defaults */ + if (devmask == 0) { + if (devtype == 0 || devtype == 2) + devmask = ICX_RGB; + else + devmask = ICX_CMYK; + } + + ident = icx_inkmask2char(devmask, 1); + bident = icx_inkmask2char(devmask, 0); + devchan = icx_noofinks(devmask); + + if (verb) { + if (devtype == 0) + printf("Device type: input\n"); + else if (devtype == 1) + printf("Device type: output\n"); + else + printf("Device type: display\n"); + + printf("Colorspace: %s\n", ident); + + printf("Curve parameters:\n"); + for (j = 0; j < devchan; j++) + printf("off[%d] = %f, sca[%d] = %f, gam[%d] = %f\n",j,off[j],j,sca[j],j, gam[j]); + } + + /* Write out the resulting calibration file */ + { + int i, j, calres = 256; /* 256 steps in calibration */ + cgats *ocg; /* output cgats structure */ + time_t clk = time(0); + struct tm *tsp = localtime(&clk); + char *atm = asctime(tsp); /* Ascii time */ + cgats_set_elem *setel; /* Array of set value elements */ + int nsetel = 0; + char buf[200]; + + ocg = new_cgats(); /* Create a CGATS structure */ + ocg->add_other(ocg, "CAL"); /* our special type is Calibration file */ + + ocg->add_table(ocg, tt_other, 0); /* Add a table for RAMDAC values */ + ocg->add_kword(ocg, 0, "DESCRIPTOR", "Argyll Device Calibration Curves",NULL); + ocg->add_kword(ocg, 0, "ORIGINATOR", "Argyll synthcal", NULL); + atm[strlen(atm)-1] = '\000'; /* Remove \n from end */ + ocg->add_kword(ocg, 0, "CREATED",atm, NULL); + + if (devtype == 0) + ocg->add_kword(ocg, 0, "DEVICE_CLASS","INPUT", NULL); + else if (devtype == 1) + ocg->add_kword(ocg, 0, "DEVICE_CLASS","OUTPUT", NULL); + else + ocg->add_kword(ocg, 0, "DEVICE_CLASS","DISPLAY", NULL); + + ocg->add_kword(ocg, 0, "COLOR_REP", ident, NULL); + + if (profDesc != NULL) + ocg->add_kword(ocg, 0, "DESCRIPTION", profDesc, NULL); + + sprintf(buf, "%s_I",bident); + ocg->add_field(ocg, 0, buf, r_t); + nsetel++; + for (j = 0; j < devchan; j++) { + inkmask imask = icx_index2ink(devmask, j); + sprintf(buf, "%s_%s",bident,icx_ink2char(imask)); + ocg->add_field(ocg, 0, buf, r_t); + nsetel++; + } + if ((setel = (cgats_set_elem *)malloc(sizeof(cgats_set_elem) * nsetel)) == NULL) + error("Malloc failed!"); + + for (i = 0; i < calres; i++) { + double vv = i/(calres-1.0); + + setel[0].d = vv; + for (j = 0; j < devchan; j++) { + setel[j+1].d = off[j] + sca[j] * pow(vv, gam[j]); + if (setel[j+1].d < 0.0) + setel[j+1].d = 0.0; + else if (setel[j+1].d > 1.0) + setel[j+1].d = 1.0; + } + + ocg->add_setarr(ocg, 0, setel); + } + + free(setel); + + if (ocg->write_name(ocg, outname)) + error("Write error : %s",ocg->err); + + ocg->del(ocg); /* Clean up */ + } + return 0; +} + + -- cgit v1.2.3