225 lines
5.3 KiB
C
225 lines
5.3 KiB
C
|
|
/*
|
|
* Extract a CGATS file from an ICC profile tag.
|
|
* (Can also extract a tag of unknown format as a binary lump).
|
|
*
|
|
* Author: Graeme W. Gill
|
|
* Date: 2008/5/18
|
|
* Version: 1.00
|
|
*
|
|
* Copyright 2008 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.
|
|
*/
|
|
|
|
/*
|
|
* TTBD:
|
|
*
|
|
* Should uncompress ZXML type tag using zlib.
|
|
*
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include "copyright.h"
|
|
#include "aconfig.h"
|
|
#include "numlib.h"
|
|
#include "icc.h"
|
|
#include "conv.h"
|
|
#include "xicc.h"
|
|
|
|
#define MXTGNMS 30
|
|
|
|
void usage(char *diag, ...) {
|
|
int i;
|
|
fprintf(stderr,"Extract a text tag from an ICC profile, Version %s\n",ARGYLL_VERSION_STR);
|
|
fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
|
|
if (diag != NULL) {
|
|
va_list args;
|
|
fprintf(stderr,"Diagnostic: ");
|
|
va_start(args, diag);
|
|
vfprintf(stderr, diag, args);
|
|
va_end(args);
|
|
fprintf(stderr,"\n");
|
|
}
|
|
fprintf(stderr,"usage: extractttag [-v] infile%s outfile\n",ICC_FILE_EXT);
|
|
fprintf(stderr," -v Verbose\n");
|
|
fprintf(stderr," -t tag Extract this tag rather than default 'targ'\n");
|
|
fprintf(stderr," -c Extract calibration file from 'targ' tag\n");
|
|
exit(1);
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[]) {
|
|
int fa,nfa; /* argument we're looking at */
|
|
static char in_name[MAXNAMEL+1]; /* TIFF input name */
|
|
static char out_name[MAXNAMEL+1]; /* ICC output name */
|
|
char tag_name[MXTGNMS] = { 't','a','r','g' };
|
|
int docal = 0;
|
|
icc *icco;
|
|
icTagSignature sig;
|
|
icmText *ro;
|
|
icmUnknown *uro;
|
|
icmFile *ifp, *ofp;
|
|
icmErr err = { 0, { '\000'} };
|
|
int verb = 0;
|
|
int size = 0;
|
|
void *buf = NULL;
|
|
int rv = 0;
|
|
|
|
|
|
error_program = argv[0];
|
|
|
|
if (argc < 3)
|
|
usage("Too few parameters");
|
|
|
|
/* 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(NULL);
|
|
|
|
/* Verbosity */
|
|
else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
|
|
verb = 1;
|
|
}
|
|
|
|
/* Tag name */
|
|
else if (argv[fa][1] == 't' || argv[fa][1] == 'T') {
|
|
fa = nfa;
|
|
if (na == NULL) usage("Expect tag name after -t");
|
|
strncpy(tag_name,na,4);
|
|
tag_name[4] = '\000';
|
|
}
|
|
|
|
/* Calibration */
|
|
else if (argv[fa][1] == 'c' || argv[fa][1] == 'C') {
|
|
docal = 1;
|
|
}
|
|
|
|
else
|
|
usage("Unknown flag '%c'",argv[fa][1]);
|
|
} else
|
|
break;
|
|
}
|
|
|
|
if (fa >= argc || argv[fa][0] == '-') usage("Missing input ICC profile");
|
|
strncpy(in_name,argv[fa++],MAXNAMEL); in_name[MAXNAMEL] = '\000';
|
|
|
|
if (fa >= argc || argv[fa][0] == '-') usage("Missing output filename");
|
|
strncpy(out_name,argv[fa++],MAXNAMEL); out_name[MAXNAMEL] = '\000';
|
|
|
|
|
|
/* - - - - - - - - - - - - - - - */
|
|
|
|
/* Open up the file for reading */
|
|
if ((ifp = new_icmFileStd_name(&err,in_name,"r")) == NULL)
|
|
error ("Can't open file '%s' (0x%x, '%s')",in_name,err.c,err.m);
|
|
|
|
if ((icco = new_icc(&err)) == NULL)
|
|
error ("Creation of ICC object failed (0x%x, '%s')",err.c,err.m);
|
|
|
|
if ((rv = icco->read(icco,ifp,0)) != 0)
|
|
error ("%d, %s",rv,icco->e.m);
|
|
|
|
sig = icmstr2tag(tag_name);
|
|
|
|
if ((ro = (icmText *)icco->read_tag_any(icco, sig)) == NULL) {
|
|
error("%d, %s",icco->e.c, icco->e.m);
|
|
}
|
|
|
|
if (ro->ttype == icmSigUnknownType) {
|
|
uro = (icmUnknown *)ro;
|
|
} else if (ro->ttype != icSigTextType) {
|
|
error("Tag isn't TextType or UnknownType");
|
|
}
|
|
|
|
|
|
if (docal) {
|
|
cgatsFile *cgf;
|
|
cgats *icg;
|
|
int tab, oi;
|
|
xcal *cal;
|
|
|
|
if ((icg = new_cgats()) == NULL) {
|
|
error("new_cgats() failed");
|
|
}
|
|
if ((cgf = new_cgatsFileMem(ro->desc, ro->count)) == NULL) {
|
|
error("new_cgatsFileMem() failed");
|
|
}
|
|
icg->add_other(icg, "CTI3");
|
|
oi = icg->add_other(icg, "CAL");
|
|
|
|
if (icg->read(icg, cgf) != 0) {
|
|
error("failed to parse tag contents as a CGATS file");
|
|
}
|
|
|
|
for (tab = 0; tab < icg->ntables; tab++) {
|
|
if (icg->t[tab].tt == tt_other && icg->t[tab].oi == oi) {
|
|
break;
|
|
}
|
|
}
|
|
if (tab >= icg->ntables) {
|
|
error("Failed to locate CAL table in CGATS");
|
|
}
|
|
|
|
if ((cal = new_xcal()) == NULL) {
|
|
error("new_xcal() failed");
|
|
}
|
|
if (cal->read_cgats(cal, icg, tab, in_name) != 0) {
|
|
error("Parsing CAL table failed");
|
|
}
|
|
icg->del(icg);
|
|
cgf->del(cgf);
|
|
|
|
if (cal->write(cal, out_name) != 0) {
|
|
error("writing to file '%s' failed\n",out_name);
|
|
}
|
|
} else {
|
|
if ((ofp = new_icmFileStd_name(&err, out_name, "w")) == NULL) {
|
|
error("unable to open output file '%s' (0x%x, '%s')",out_name,err.c,err.m);
|
|
}
|
|
|
|
if (ro->ttype == icmSigUnknownType) {
|
|
if (ofp->write(ofp, uro->data, 1, uro->count) != (uro->count)) {
|
|
error("writing to file '%s' failed",out_name);
|
|
}
|
|
} else {
|
|
if (ofp->write(ofp, ro->desc, 1, ro->count-1) != (ro->count-1)) {
|
|
error("writing to file '%s' failed",out_name);
|
|
}
|
|
}
|
|
|
|
if (ofp->del(ofp) != 0) {
|
|
error("closing file '%s' failed",out_name);
|
|
}
|
|
}
|
|
|
|
icco->del(icco);
|
|
ifp->del(ifp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|