1
2 /*
3 * Extract a CGATS file from an ICC profile tag.
4 * (Can also extract a tag of unknown format as a binary lump).
5 *
6 * Author: Graeme W. Gill
7 * Date: 2008/5/18
8 * Version: 1.00
9 *
10 * Copyright 2008 Graeme W. Gill
11 * All rights reserved.
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 * Should uncompress ZXML type tag using zlib.
20 *
21 */
22
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <fcntl.h>
28 #include <string.h>
29 #include <math.h>
30 #include "copyright.h"
31 #include "aconfig.h"
32 #include "numlib.h"
33 #include "icc.h"
34 #include "xicc.h"
35
36 #define MXTGNMS 30
37
usage(char * diag,...)38 void usage(char *diag, ...) {
39 int i;
40 fprintf(stderr,"Extract a text tag from an ICC profile, Version %s\n",ARGYLL_VERSION_STR);
41 fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
42 if (diag != NULL) {
43 va_list args;
44 fprintf(stderr,"Diagnostic: ");
45 va_start(args, diag);
46 vfprintf(stderr, diag, args);
47 va_end(args);
48 fprintf(stderr,"\n");
49 }
50 fprintf(stderr,"usage: extractttag [-v] infile%s outfile\n",ICC_FILE_EXT);
51 fprintf(stderr," -v Verbose\n");
52 fprintf(stderr," -t tag Extract this tag rather than default 'targ'\n");
53 fprintf(stderr," -c Extract calibration file from 'targ' tag\n");
54 exit(1);
55 }
56
57 int
main(int argc,char * argv[])58 main(int argc, char *argv[]) {
59 int fa,nfa; /* argument we're looking at */
60 char in_name[MAXNAMEL+1]; /* TIFF input name */
61 char out_name[MAXNAMEL+1]; /* ICC output name */
62 char tag_name[MXTGNMS] = { 't','a','r','g' };
63 int docal = 0;
64 icc *icco;
65 icTagSignature sig;
66 icmText *ro;
67 icmUnknown *uro;
68 icmFile *ifp, *ofp;
69 int verb = 0;
70 int size = 0;
71 void *buf = NULL;
72 int rv = 0;
73
74 error_program = argv[0];
75
76 if (argc < 3)
77 usage("Too few parameters");
78
79 /* Process the arguments */
80 for(fa = 1;fa < argc;fa++) {
81 nfa = fa; /* skip to nfa if next argument is used */
82 if (argv[fa][0] == '-') { /* Look for any flags */
83 char *na = NULL; /* next argument after flag, null if none */
84
85 if (argv[fa][2] != '\000')
86 na = &argv[fa][2]; /* next is directly after flag */
87 else {
88 if ((fa+1) < argc) {
89 if (argv[fa+1][0] != '-') {
90 nfa = fa + 1;
91 na = argv[nfa]; /* next is seperate non-flag argument */
92 }
93 }
94 }
95
96 if (argv[fa][1] == '?')
97 usage(NULL);
98
99 /* Verbosity */
100 else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
101 verb = 1;
102 }
103
104 /* Tag name */
105 else if (argv[fa][1] == 't' || argv[fa][1] == 'T') {
106 fa = nfa;
107 if (na == NULL) usage("Expect tag name after -t");
108 strncpy(tag_name,na,4);
109 tag_name[4] = '\000';
110 }
111
112 /* Calibration */
113 else if (argv[fa][1] == 'c' || argv[fa][1] == 'C') {
114 docal = 1;
115 }
116
117 else
118 usage("Unknown flag '%c'",argv[fa][1]);
119 } else
120 break;
121 }
122
123 if (fa >= argc || argv[fa][0] == '-') usage("Missing input ICC profile");
124 strncpy(in_name,argv[fa++],MAXNAMEL); in_name[MAXNAMEL] = '\000';
125
126 if (fa >= argc || argv[fa][0] == '-') usage("Missing output filename");
127 strncpy(out_name,argv[fa++],MAXNAMEL); out_name[MAXNAMEL] = '\000';
128
129 /* - - - - - - - - - - - - - - - */
130
131 /* Open up the file for reading */
132 if ((ifp = new_icmFileStd_name(in_name,"r")) == NULL)
133 error ("Can't open file '%s'",in_name);
134
135 if ((icco = new_icc()) == NULL)
136 error ("Creation of ICC object failed");
137
138 if ((rv = icco->read(icco,ifp,0)) != 0)
139 error ("%d, %s",rv,icco->err);
140
141 sig = str2tag(tag_name);
142
143 if ((ro = (icmText *)icco->read_tag_any(icco, sig)) == NULL) {
144 error("%d, %s",icco->errc, icco->err);
145 }
146
147 if (ro->ttype == icmSigUnknownType) {
148 uro = (icmUnknown *)ro;
149 } else if (ro->ttype != icSigTextType) {
150 error("Tag isn't TextType or UnknownType");
151 }
152
153 if (docal) {
154 cgatsFile *cgf;
155 cgats *icg;
156 int tab, oi;
157 xcal *cal;
158
159 if ((icg = new_cgats()) == NULL) {
160 error("new_cgats() failed");
161 }
162 if ((cgf = new_cgatsFileMem(ro->data, ro->size)) == NULL) {
163 error("new_cgatsFileMem() failed");
164 }
165 icg->add_other(icg, "CTI3");
166 oi = icg->add_other(icg, "CAL");
167
168 if (icg->read(icg, cgf) != 0) {
169 error("failed to parse tag contents as a CGATS file");
170 }
171
172 for (tab = 0; tab < icg->ntables; tab++) {
173 if (icg->t[tab].tt == tt_other && icg->t[tab].oi == oi) {
174 break;
175 }
176 }
177 if (tab >= icg->ntables) {
178 error("Failed to locate CAL table in CGATS");
179 }
180
181 if ((cal = new_xcal()) == NULL) {
182 error("new_xcal() failed");
183 }
184 if (cal->read_cgats(cal, icg, tab, in_name) != 0) {
185 error("Parsing CAL table failed");
186 }
187 icg->del(icg);
188 cgf->del(cgf);
189
190 if (cal->write(cal, out_name) != 0) {
191 error("writing to file '%s' failed\n",out_name);
192 }
193 } else {
194 if ((ofp = new_icmFileStd_name(out_name, "w")) == NULL) {
195 error("unable to open output file '%s'",out_name);
196 }
197
198 if (ro->ttype == icmSigUnknownType) {
199 if (ofp->write(ofp, uro->data, 1, uro->size) != (uro->size)) {
200 error("writing to file '%s' failed",out_name);
201 }
202 } else {
203 if (ofp->write(ofp, ro->data, 1, ro->size-1) != (ro->size-1)) {
204 error("writing to file '%s' failed",out_name);
205 }
206 }
207
208 if (ofp->del(ofp) != 0) {
209 error("closing file '%s' failed",out_name);
210 }
211 }
212
213 icco->del(icco);
214 ifp->del(ifp);
215
216 return 0;
217 }
218