1
2 /*
3 * Argyll Color Correction System
4 *
5 * Read in the device data from Colorblind device files,
6 * and convert it into a .ti3 CGATs format suitable for
7 * the Argyll CMM.
8 *
9 * Derived from kodak2cgats.c
10 * Author: Graeme W. Gill
11 * Date: 16/11/00
12 *
13 * Copyright 2000, 2010, Graeme W. Gill
14 *
15 * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
16 * see the License.txt file for licencing details.
17 */
18
19 #define VERSION "1.0"
20
21 /* TTBD
22 */
23
24 #undef DEBUG
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <math.h>
29 #include <sys/types.h>
30 #include <time.h>
31 #include <string.h>
32 #include <stdarg.h>
33 #include "copyright.h"
34 #include "aconfig.h"
35 #include "numlib.h"
36 #include "cgats.h"
37
38 void
usage(void)39 usage(void) {
40 fprintf(stderr,"Convert Colorblind raw device profile data to Argyll data, Version %s\n",ARGYLL_VERSION_STR);
41 fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
42 fprintf(stderr,"usage: cb2ti3 [-v] [-l limit] infile outfile\n");
43 fprintf(stderr," -v Verbose mode\n");
44 fprintf(stderr," -l limit Set inklimit in .ti3 file\n");
45 fprintf(stderr," infile Base name for input.CMY and input.nCIE file\n");
46 fprintf(stderr," outfile Base name for output.ti3 file\n");
47 exit(1);
48 }
49
main(int argc,char * argv[])50 int main(int argc, char *argv[])
51 {
52 int i;
53 int fa,nfa; /* current argument we're looking at */
54 int verb = 0;
55 static char tarname[200] = { 0 }; /* Input .CMY file */
56 static char inname[200] = { 0 }; /* Input .nCIE file */
57 static char outname[200] = { 0 }; /* Output cgats .ti3 file base name */
58 cgats *cmy; /* Input RGB reference file */
59 int f_id1, f_c, f_m, f_y; /* Field indexes */
60 cgats *ncie; /* Inpit CIE readings file */
61 int f_id2, f_xx, f_yy, f_zz; /* Field indexes */
62 cgats *ocg; /* output cgats structure */
63 time_t clk = time(0);
64 struct tm *tsp = localtime(&clk);
65 char *atm = asctime(tsp); /* Ascii time */
66 int npat = 0; /* Number of patches */
67
68 error_program = "cb2ti3";
69
70 if (argc <= 1)
71 usage();
72
73 /* Process the arguments */
74 for(fa = 1;fa < argc;fa++)
75 {
76 nfa = fa; /* skip to nfa if next argument is used */
77 if (argv[fa][0] == '-') /* Look for any flags */
78 {
79 char *na = NULL; /* next argument after flag, null if none */
80
81 if (argv[fa][2] != '\000')
82 na = &argv[fa][2]; /* next is directly after flag */
83 else
84 {
85 if ((fa+1) < argc)
86 {
87 if (argv[fa+1][0] != '-')
88 {
89 nfa = fa + 1;
90 na = argv[nfa]; /* next is seperate non-flag argument */
91 }
92 }
93 }
94
95 if (argv[fa][1] == '?')
96 usage();
97
98 else if (argv[fa][1] == 'v' || argv[fa][1] == 'V')
99 verb = 1;
100 else
101 usage();
102 }
103 else
104 break;
105 }
106
107 /* Get the file name argument */
108 if (fa >= argc || argv[fa][0] == '-') usage();
109
110 strcpy(inname,argv[fa]);
111 strcpy(tarname,argv[fa++]);
112 strcat(inname,".CMY");
113 strcat(tarname,".nCIE");
114
115 if (fa >= argc || argv[fa][0] == '-') usage();
116 strcpy(outname, argv[fa++]);
117 strcat(outname,".ti3");
118
119 /* Open up the Input CMY reference file */
120 cmy = new_cgats(); /* Create a CGATS structure */
121 cmy->add_other(cmy, "CBTA"); /* Colorblind Target file */
122 if (cmy->read_name(cmy, inname))
123 error ("Read: Can't open file '%s'",inname);
124 if (cmy->ntables == 0 || cmy->t[0].tt != tt_other || cmy->t[0].oi != 0)
125 error ("Input file isn't a 'CBTA' format file");
126 if (cmy->ntables != 1)
127 fprintf(stderr,"Input file '%s' doesn't contain exactly one table",inname);
128
129 if ((npat = cmy->t[0].nsets) <= 0)
130 error("No patches");
131
132 if ((f_id1 = cmy->find_field(cmy, 0, "SAMPLE_ID")) < 0)
133 error("Input file doesn't contain field SAMPLE_ID");
134 if (cmy->t[0].ftype[f_id1] != nqcs_t)
135 error("Field SAMPLE_ID is wrong type");
136
137 if ((f_c = cmy->find_field(cmy, 0, "C")) < 0)
138 error("Input file doesn't contain field C");
139 if (cmy->t[0].ftype[f_c] != r_t)
140 error("Field C is wrong type");
141
142 if ((f_m = cmy->find_field(cmy, 0, "M")) < 0)
143 error("Input file doesn't contain field M");
144 if (cmy->t[0].ftype[f_m] != r_t)
145 error("Field M is wrong type");
146
147 if ((f_y = cmy->find_field(cmy, 0, "Y")) < 0)
148 error("Input file doesn't contain field Y");
149 if (cmy->t[0].ftype[f_y] != r_t)
150 error("Field Y is wrong type");
151
152 /* Open up the input nCIE device data file */
153 ncie = new_cgats(); /* Create a CGATS structure */
154 ncie->add_other(ncie, "CBPR"); /* Colorblind Printer Response file */
155 if (ncie->read_name(ncie, tarname))
156 error ("Read: Can't open file '%s'",tarname);
157 if (ncie->ntables == 0 || ncie->t[0].tt != tt_other || ncie->t[0].oi != 0)
158 error ("Input file isn't a 'CBTA' format file");
159 if (ncie->ntables != 1)
160 fprintf(stderr,"Input file '%s' doesn't contain exactly one table",tarname);
161
162 if (npat != ncie->t[0].nsets)
163 error("Number of patches doesn't match");
164
165 if ((f_id2 = ncie->find_field(ncie, 0, "SAMPLE_ID")) < 0)
166 error("Input file doesn't contain field SAMPLE_ID");
167 if (ncie->t[0].ftype[f_id2] != nqcs_t)
168 error("Field SAMPLE_ID is wrong type");
169
170 if ((f_xx = ncie->find_field(ncie, 0, "XYZ_X")) < 0)
171 error("Input file doesn't contain field XYZ_X");
172 if (ncie->t[0].ftype[f_xx] != r_t)
173 error("Field XYZ_X is wrong type");
174
175 if ((f_yy = ncie->find_field(ncie, 0, "XYZ_Y")) < 0)
176 error("Input file doesn't contain field XYZ_Y");
177 if (ncie->t[0].ftype[f_yy] != r_t)
178 error("Field XYZ_Y is wrong type");
179
180 if ((f_zz = ncie->find_field(ncie, 0, "XYZ_Z")) < 0)
181 error("Input file doesn't contain field XYZ_Z");
182 if (ncie->t[0].ftype[f_zz] != r_t)
183 error("Field XYZ_Z is wrong type");
184
185 /* Setup output cgats file */
186 ocg = new_cgats(); /* Create a CGATS structure */
187 ocg->add_other(ocg, "CTI3"); /* our special type is Calibration Target Information 3 */
188 ocg->add_table(ocg, tt_other, 0); /* Start the first table */
189
190 ocg->add_kword(ocg, 0, "DESCRIPTOR", "Argyll Calibration Target chart information 3",NULL);
191 ocg->add_kword(ocg, 0, "ORIGINATOR", "Argyll target", NULL);
192 atm[strlen(atm)-1] = '\000'; /* Remove \n from end */
193 ocg->add_kword(ocg, 0, "CREATED",atm, NULL);
194 ocg->add_kword(ocg, 0, "DEVICE_CLASS","OUTPUT", NULL); /* What sort of device this is */
195
196 /* Fields we want */
197 ocg->add_field(ocg, 0, "SAMPLE_ID", nqcs_t);
198
199 ocg->add_field(ocg, 0, "RGB_R", r_t);
200 ocg->add_field(ocg, 0, "RGB_G", r_t);
201 ocg->add_field(ocg, 0, "RGB_B", r_t);
202 ocg->add_kword(ocg, 0, "COLOR_REP","RGB_XYZ", NULL);
203 ocg->add_field(ocg, 0, "XYZ_X", r_t);
204 ocg->add_field(ocg, 0, "XYZ_Y", r_t);
205 ocg->add_field(ocg, 0, "XYZ_Z", r_t);
206
207 /* Write out the patch info to the output CGATS file */
208 for (i = 0; i < npat; i++) {
209 char id[100];
210 double rgb[3];
211 double xyz[3];
212
213 if (strcmp(((char *)cmy->t[0].fdata[i][f_id1]),
214 ((char *)ncie->t[0].fdata[i][f_id2])) != 0) {
215 error("Patch label mismatch, patch %d, '%s' != '%s'\n",
216 i, ((char *)cmy->t[0].fdata[i][f_id1]),
217 ((char *)ncie->t[0].fdata[i][f_id2]));
218 }
219
220 rgb[0] = 100.0 - *((double *)cmy->t[0].fdata[i][f_c]); /* Convert to RGB */
221 rgb[1] = 100.0 - *((double *)cmy->t[0].fdata[i][f_m]);
222 rgb[2] = 100.0 - *((double *)cmy->t[0].fdata[i][f_y]);
223
224 xyz[0] = *((double *)ncie->t[0].fdata[i][f_xx]);
225 xyz[1] = *((double *)ncie->t[0].fdata[i][f_yy]);
226 xyz[2] = *((double *)ncie->t[0].fdata[i][f_zz]);
227
228 sprintf(id, "%d", i+1);
229 ocg->add_set(ocg, 0, id, rgb[0], rgb[1], rgb[2],
230 xyz[0], xyz[1], xyz[2]);
231 }
232
233 if (ocg->write_name(ocg, outname))
234 error("Write error : %s",ocg->err);
235
236 ncie->del(ncie); /* Clean up */
237 cmy->del(cmy);
238 ocg->del(ocg);
239
240 return 0;
241 }
242
243
244
245