1 
2 /*
3  * Argyll Color Correction System
4  * x11 style .txt to ICC Named Color converter
5  *
6  * Author: Graeme W. Gill
7  * Date:   24/20/2014
8  *
9  * Copyright 2014 Graeme W. Gill
10  * All rights reserved.
11  *
12  * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
13  * see the License.txt file for licencing details.
14  */
15 
16 /*
17  * TTBD
18  */
19 
20 #undef DEBUG
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <math.h>
25 #include <sys/types.h>
26 #include <time.h>
27 #include "copyright.h"
28 #include "aconfig.h"
29 #ifndef SALONEINSTLIB
30 #include "numlib.h"
31 #include "icc.h"
32 #else
33 #include "numsup.h"
34 #endif
35 #include "xspect.h"
36 #include "ui.h"
37 
usage(char * diag,...)38 void usage(char *diag, ...) {
39 	fprintf(stderr,"x11 .txt to ICC Named Colors\n");
40 	fprintf(stderr,"Author: Graeme W. Gill\n");
41 	if (diag != NULL) {
42 		va_list args;
43 		fprintf(stderr,"  Diagnostic: ");
44 		va_start(args, diag);
45 		vfprintf(stderr, diag, args);
46 		va_end(args);
47 		fprintf(stderr,"\n");
48 	}
49 	fprintf(stderr,"usage: txt2iccNC [-v level] description infile outfile\n");
50 	exit(1);
51 }
52 
53 int
main(int argc,char * argv[])54 main(int argc, char *argv[]) {
55 	int fa,nfa;				/* argument we're looking at */
56 	int verb = 0;
57 	char desc[MAXNAMEL+1];
58 	char inname[MAXNAMEL+1];
59 	char outname[MAXNAMEL+1];
60 	FILE *ifp;
61 #define BUFSZ 512
62 	char buf[BUFSZ];
63 	icmFile *wr_fp;
64 	icc *wr_icco;
65 	int i, rv;
66 
67 	/* Process the arguments */
68 	for(fa = 1;fa < argc;fa++) {
69 		nfa = fa;					/* skip to nfa if next argument is used */
70 		if (argv[fa][0] == '-')	{	/* Look for any flags */
71 			char *na = NULL;		/* next argument after flag, null if none */
72 
73 			if (argv[fa][2] != '\000')
74 				na = &argv[fa][2];		/* next is directly after flag */
75 			else {
76 				if ((fa+1) < argc) {
77 					if (argv[fa+1][0] != '-') {
78 						nfa = fa + 1;
79 						na = argv[nfa];		/* next is seperate non-flag argument */
80 					}
81 				}
82 			}
83 
84 			if (argv[fa][1] == '?')
85 				usage(NULL);
86 
87 			else if (argv[fa][1] == 'v')
88 				verb = 1;
89 
90 			else
91 				usage("Unknown option '%c'",argv[fa][1]);
92 		}
93 		else
94 			break;
95 	}
96 
97 	if (fa >= argc || argv[fa][0] == '-') usage("Missing description");
98 	strncpy(desc,argv[fa++],MAXNAMEL); desc[MAXNAMEL] = '\000';
99 
100 	if (fa >= argc || argv[fa][0] == '-') usage("Missing input filename");
101 	strncpy(inname,argv[fa++],MAXNAMEL); inname[MAXNAMEL] = '\000';
102 
103 	if (fa >= argc || argv[fa][0] == '-') usage("Missing output filename");
104 	strncpy(outname,argv[fa++],MAXNAMEL); outname[MAXNAMEL] = '\000';
105 
106 	if ((ifp = fopen(inname,"r"))==NULL) {
107 		error("Read: Can't open file '%s'",inname);
108 	}
109 
110 	/* Open up the file for writing */
111 	if ((wr_fp = new_icmFileStd_name(outname,"w")) == NULL)
112 		error ("Write: Can't open file '%s'",outname);
113 
114 	if ((wr_icco = new_icc()) == NULL)
115 		error ("Write: Creation of ICC object failed");
116 
117 	/* Values that must be set before writing */
118 	wr_icco->header->deviceClass     = icSigNamedColorClass;
119    	wr_icco->header->colorSpace      = icSigRgbData;
120    	wr_icco->header->pcs             = icSigLabData;
121    	wr_icco->header->renderingIntent = icRelativeColorimetric;
122 
123 	/* Add the description tag */
124 	{
125 		icmTextDescription *wo;
126 		if ((wo = (icmTextDescription *)wr_icco->add_tag(
127 		           wr_icco, icSigProfileDescriptionTag,	icSigTextDescriptionType)) == NULL)
128 			error("Failed to add icmTextDescription");
129 
130 		wo->size = strlen(desc)+1; 	/* Allocated and used size of desc, inc null */
131 		wo->allocate((icmBase *)wo);/* Allocate space */
132 		strcpy(wo->desc, desc);		/* Copy the string in */
133 	}
134 
135 	/* Copyright Tag: */
136 	{
137 		icmText *wo;
138 		char *crt;
139 
140 		crt = "";
141 
142 		if ((wo = (icmText *)wr_icco->add_tag(
143 		           wr_icco, icSigCopyrightTag,	icSigTextType)) == NULL)
144 			error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err);
145 
146 		wo->size = strlen(crt)+1; 	/* Allocated and used size of text, inc null */
147 		wo->allocate((icmBase *)wo);/* Allocate space */
148 		strcpy(wo->data, crt);		/* Copy the text in */
149 	}
150 
151 	/* White Point Tag: */
152 	/* Use the orgininal, non PCS adapted white point */
153 	{
154 		icmXYZArray *wo;
155 		/* Note that tag types icSigXYZType and icSigXYZArrayType are identical */
156 		if ((wo = (icmXYZArray *)wr_icco->add_tag(
157 		           wr_icco, icSigMediaWhitePointTag, icSigXYZArrayType)) == NULL)
158 			error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err);
159 
160 		wo->size = 1;
161 		wo->allocate((icmBase *)wo);	/* Allocate space */
162 		wo->data[0] = icmD65;			/* sRGB is D65 */
163 	}
164 
165 	/* Add a named color tag */
166 	{
167 		icmNamedColor *wo;
168 
169 		if ((wo = (icmNamedColor *)wr_icco->add_tag(
170 	           wr_icco, icSigNamedColor2Tag, icSigNamedColor2Type)) == NULL)
171 			error("Adding icmNamedColor tag failed");
172 
173 	   	wo->count = 0;
174 
175 		/* Read lines and count the colors */
176 		for (;;) {
177 			double rgb[3];
178 			char s1[BUFSZ];
179 			char s2[BUFSZ];
180 			char s3[BUFSZ];
181 
182 			if (fgets(buf, BUFSZ, ifp) == NULL)
183 				break;
184 
185 			if ((rv = sscanf(buf, " %lf %lf %lf %s %s %s\n",&rgb[0], &rgb[1], &rgb[2], s1, s2, s3)) >= 4) {
186 				wo->count++;
187 			}
188 		}
189 
190 	   	wo->nDeviceCoords =	3;	/* Num of device coordinates */
191 		strcpy(wo->prefix,""); /* Prefix for each color name, max 32, null terminated */
192 		strcpy(wo->suffix,""); /* Suffix for each color name, max 32, null terminated */
193 
194 		wo->allocate((icmBase *)wo);	/* Allocate named color structures */
195 
196 		if (verb)
197 			printf("Counted %d colors\n",wo->count);
198 
199 		/* Read lines and colors */
200 		rewind(ifp);
201 		for (i = 0; i < wo->count; i++) {
202 			double rgb[3], lab[3];
203 			char s1[BUFSZ];
204 			char s2[BUFSZ];
205 			char s3[BUFSZ];
206 			unsigned int j;
207 
208 			if (fgets(buf, BUFSZ, ifp) == NULL)
209 				break;
210 
211 			if ((rv = sscanf(buf, " %lf %lf %lf %s %s %s\n",&rgb[0], &rgb[1], &rgb[2], s1, s2, s3)) >= 4) {
212 				rgb[0] /= 255.0;
213 				rgb[1] /= 255.0;
214 				rgb[2] /= 255.0;
215 				if (rv >= 5) {
216 					strcat(s1, " ");
217 					strcat(s1, s2);
218 				}
219 				if (rv >= 6) {
220 					strcat(s1, " ");
221 					strcat(s1, s3);
222 				}
223 				/* Convert from sRGB to Bradford adapted D50 */
224 				icx_sRGB2XYZ(lab, icmD50_ary3, rgb);
225 				icmXYZ2Lab(&icmD50, lab, lab);
226 
227 				if (verb)
228 					printf("Got %f %f %f '%s'\n",rgb[0], rgb[1], rgb[2], s1);
229 
230 				strncpy(wo->data[i].root,s1,31);
231 				wo->data[i].root[31] = '\000';
232 
233 				for (j = 0; j < wo->nDeviceCoords; j++)
234 					wo->data[i].deviceCoords[j] = rgb[j];
235 				for (j = 0; j < 3; j++)
236 					wo->data[i].pcsCoords[j] = lab[j];
237 			}
238 		}
239 		fclose(ifp);
240 	}
241 
242 	if ((rv = wr_icco->write(wr_icco, wr_fp, 0)) != 0)
243 		error ("Write file: %d, %s",rv,wr_icco->err);
244 
245 	wr_icco->del(wr_icco);
246 	wr_fp->del(wr_fp);
247 
248 	return 0;
249 }
250 
251 
252 
253 
254 
255 
256 
257 
258 
259 
260 
261 
262 
263 
264 
265 
266 
267 
268 
269 
270 
271 
272 
273 
274