281 lines
6.6 KiB
C
281 lines
6.6 KiB
C
|
|
/*
|
|
* Argyll Color Correction System
|
|
* x11 style .txt to ICC Named Color converter
|
|
*
|
|
* Author: Graeme W. Gill
|
|
* Date: 24/20/2014
|
|
*
|
|
* Copyright 2014 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
|
|
*/
|
|
|
|
#undef DEBUG
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <sys/types.h>
|
|
#include <time.h>
|
|
#include "copyright.h"
|
|
#include "aconfig.h"
|
|
#ifndef SALONEINSTLIB
|
|
#include "numlib.h"
|
|
#include "icc.h"
|
|
#else
|
|
#include "numsup.h"
|
|
#endif
|
|
#include "cgats.h"
|
|
#include "xspect.h"
|
|
#include "ui.h"
|
|
|
|
void usage(char *diag, ...) {
|
|
fprintf(stderr,"x11 .txt to ICC Named Colors\n");
|
|
fprintf(stderr,"Author: Graeme W. Gill\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: txt2iccNC [-v level] description infile outfile\n");
|
|
exit(1);
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[]) {
|
|
int fa,nfa; /* argument we're looking at */
|
|
int verb = 0;
|
|
static char desc[MAXNAMEL+1];
|
|
static char inname[MAXNAMEL+1];
|
|
static char outname[MAXNAMEL+1];
|
|
FILE *ifp;
|
|
#define BUFSZ 512
|
|
char buf[BUFSZ];
|
|
icmFile *wr_fp;
|
|
icmErr err = { 0, { '\000'} };
|
|
icc *wr_icco;
|
|
int i, rv;
|
|
|
|
/* 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);
|
|
|
|
else if (argv[fa][1] == 'v')
|
|
verb = 1;
|
|
|
|
else
|
|
usage("Unknown option '%c'",argv[fa][1]);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (fa >= argc || argv[fa][0] == '-') usage("Missing description");
|
|
strncpy(desc,argv[fa++],MAXNAMEL); desc[MAXNAMEL] = '\000';
|
|
|
|
if (fa >= argc || argv[fa][0] == '-') usage("Missing input filename");
|
|
strncpy(inname,argv[fa++],MAXNAMEL); inname[MAXNAMEL] = '\000';
|
|
|
|
if (fa >= argc || argv[fa][0] == '-') usage("Missing output filename");
|
|
strncpy(outname,argv[fa++],MAXNAMEL); outname[MAXNAMEL] = '\000';
|
|
|
|
if ((ifp = fopen(inname,"r"))==NULL) {
|
|
error("Read: Can't open file '%s'",inname);
|
|
}
|
|
|
|
/* Open up the file for writing */
|
|
if ((wr_fp = new_icmFileStd_name(&err,outname,"w")) == NULL)
|
|
error ("Write: Can't open file '%s' (0x%x, '%s')",outname,err.c,err.m);
|
|
|
|
if ((wr_icco = new_icc(&err)) == NULL)
|
|
error ("Write: Creation of ICC object failed (0x%x, '%s')",err.c,err.m);
|
|
|
|
/* Values that must be set before writing */
|
|
wr_icco->header->deviceClass = icSigNamedColorClass;
|
|
wr_icco->header->colorSpace = icSigRgbData;
|
|
wr_icco->header->pcs = icSigLabData;
|
|
wr_icco->header->renderingIntent = icRelativeColorimetric;
|
|
|
|
/* Add the description tag */
|
|
{
|
|
icmCommonTextDescription *wo;
|
|
if ((wo = (icmCommonTextDescription *)wr_icco->add_tag(
|
|
wr_icco, icSigProfileDescriptionTag, icmSigCommonTextDescriptionType)) == NULL)
|
|
error("Failed to add icmCommonTextDescription");
|
|
|
|
wo->count = strlen(desc)+1; /* Allocated and used size of desc, inc null */
|
|
wo->allocate(wo);/* Allocate space */
|
|
strcpy(wo->desc, desc); /* Copy the string in */
|
|
}
|
|
|
|
/* Copyright Tag: */
|
|
{
|
|
icmCommonTextDescription *wo;
|
|
char *crt;
|
|
|
|
crt = "";
|
|
|
|
if ((wo = (icmCommonTextDescription *)wr_icco->add_tag(
|
|
wr_icco, icSigCopyrightTag, icmSigCommonTextDescriptionType)) == NULL)
|
|
error("add_tag failed: %d, %s",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
wo->count = strlen(crt)+1; /* Allocated and used size of text, inc null */
|
|
wo->allocate(wo);/* Allocate space */
|
|
strcpy(wo->desc, crt); /* Copy the text in */
|
|
}
|
|
|
|
/* White Point Tag: */
|
|
/* Use the orgininal, non PCS adapted white point */
|
|
{
|
|
icmXYZArray *wo;
|
|
/* Note that tag types icSigXYZType and icSigXYZArrayType are identical */
|
|
if ((wo = (icmXYZArray *)wr_icco->add_tag(
|
|
wr_icco, icSigMediaWhitePointTag, icSigXYZArrayType)) == NULL)
|
|
error("add_tag failed: %d, %s",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
wo->count = 1;
|
|
wo->allocate(wo); /* Allocate space */
|
|
wo->data[0] = icmD65; /* sRGB is D65 */
|
|
}
|
|
|
|
/* Add a named color tag */
|
|
{
|
|
icmNamedColor *wo;
|
|
|
|
if ((wo = (icmNamedColor *)wr_icco->add_tag(
|
|
wr_icco, icSigNamedColor2Tag, icSigNamedColor2Type)) == NULL)
|
|
error("Adding icmNamedColor tag failed");
|
|
|
|
wo->count = 0;
|
|
|
|
/* Read lines and count the colors */
|
|
for (;;) {
|
|
double rgb[3];
|
|
char s1[BUFSZ];
|
|
char s2[BUFSZ];
|
|
char s3[BUFSZ];
|
|
|
|
if (fgets(buf, BUFSZ, ifp) == NULL)
|
|
break;
|
|
|
|
if ((rv = sscanf(buf, " %lf %lf %lf %s %s %s\n",&rgb[0], &rgb[1], &rgb[2], s1, s2, s3)) >= 4) {
|
|
wo->count++;
|
|
}
|
|
}
|
|
|
|
wo->nDeviceCoords = 3; /* Num of device coordinates */
|
|
wo->pcount = 1;
|
|
wo->scount = 1;
|
|
|
|
wo->allocate(wo); /* Allocate strings and named color structures */
|
|
|
|
strcpy(wo->prefix,""); /* Prefix for each color name, null terminated */
|
|
strcpy(wo->suffix,""); /* Suffix for each color name, null terminated */
|
|
|
|
if (verb)
|
|
printf("Counted %d colors\n",wo->count);
|
|
|
|
/* Read lines and colors */
|
|
rewind(ifp);
|
|
for (i = 0; i < wo->count; i++) {
|
|
double rgb[3], lab[3];
|
|
char s1[BUFSZ];
|
|
char s2[BUFSZ];
|
|
char s3[BUFSZ];
|
|
unsigned int j;
|
|
|
|
if (fgets(buf, BUFSZ, ifp) == NULL)
|
|
break;
|
|
|
|
if ((rv = sscanf(buf, " %lf %lf %lf %s %s %s\n",&rgb[0], &rgb[1], &rgb[2], s1, s2, s3)) >= 4) {
|
|
rgb[0] /= 255.0;
|
|
rgb[1] /= 255.0;
|
|
rgb[2] /= 255.0;
|
|
if (rv >= 5) {
|
|
strcat(s1, " ");
|
|
strcat(s1, s2);
|
|
}
|
|
if (rv >= 6) {
|
|
strcat(s1, " ");
|
|
strcat(s1, s3);
|
|
}
|
|
/* Convert from sRGB to Bradford adapted D50 */
|
|
icx_sRGB2XYZ(lab, icmD50_ary3, rgb);
|
|
icmXYZ2Lab(&icmD50, lab, lab);
|
|
|
|
if (verb)
|
|
printf("Got %f %f %f '%s'\n",rgb[0], rgb[1], rgb[2], s1);
|
|
|
|
s1[31] = '\000'; /* truncate if needed */
|
|
wo->data[i].rcount = strlen(s1) + 1;
|
|
wo->allocate(wo); /* Allocate root name string */
|
|
strcpy(wo->data[i].root, s1);
|
|
|
|
for (j = 0; j < wo->nDeviceCoords; j++)
|
|
wo->data[i].deviceCoords[j] = rgb[j];
|
|
for (j = 0; j < 3; j++)
|
|
wo->data[i].pcsCoords[j] = lab[j];
|
|
}
|
|
}
|
|
fclose(ifp);
|
|
}
|
|
|
|
if ((rv = wr_icco->write(wr_icco, wr_fp, 0)) != 0)
|
|
error ("Write file: %d, %s",rv,wr_icco->e.m);
|
|
|
|
wr_icco->del(wr_icco);
|
|
wr_fp->del(wr_fp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|