diff options
Diffstat (limited to 'icc/mkDispProf.c')
-rw-r--r-- | icc/mkDispProf.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/icc/mkDispProf.c b/icc/mkDispProf.c new file mode 100644 index 0000000..bc70154 --- /dev/null +++ b/icc/mkDispProf.c @@ -0,0 +1,331 @@ + + +/* + * Create an ICC V2.4 compatible matrix display profile. + * + * Author: Graeme W. Gill + * Date: 8/2/2008 + * Version: 1.00 + * + * Copyright 2006 - 2014 Graeme W. Gill + * + * This material is licensed with an "MIT" free use license:- + * see the License.txt file in this directory for licensing details. + * + * Based on icc/lutest.c + */ + + +/* + * TTBD: + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <fcntl.h> +#include <string.h> +#include <math.h> +#include <time.h> +#include "icc.h" + +void error(char *fmt, ...), warning(char *fmt, ...); + +void usage(void) { + fprintf(stderr,"Create a Matrix Display ICC profile\n"); + fprintf(stderr,"Author: Graeme W. Gill\n"); + fprintf(stderr,"usage: mkDispProf [-v level] outfile\n"); + fprintf(stderr," -v Verbose\n"); + exit(1); +} + +/* sRGB like device gamma encoded value to linear value 0.0 .. 1.0 */ +static double gdv2dv(double iv) { + double ov; + + if (iv < 0.04045) + ov = iv/12.92; + else + ov = pow((iv + 0.055)/1.055, 2.4); + return ov; +} + +int +main( +int argc, +char *argv[] +) { + int fa,nfa; + char out_name[1000]; + icmFile *wr_fp; + icc *wr_icco; + int rv = 0; + int verb = 0; + + if (argc < 2) + usage(); + + /* 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(); + + /* Verbosity */ + else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') { + verb = 1; + } + + else + usage(); + } + else + break; + } + + if (fa >= argc || argv[fa][0] == '-') usage(); + strcpy(out_name,argv[fa]); + + /* ---------------------------------------- */ + /* Create a matrix/shaper based XYZ profile */ + /* ---------------------------------------- */ + + /* Open up the file for writing */ + if ((wr_fp = new_icmFileStd_name(out_name,"w")) == NULL) + error ("Write: Can't open file '%s'",out_name); + + if ((wr_icco = new_icc()) == NULL) + error ("Write: Creation of ICC object failed"); + + /* Add all the tags required */ + + /* The header: */ + { + icmHeader *wh = wr_icco->header; + + /* Values that must be set before writing */ + wh->deviceClass = icSigDisplayClass; + wh->colorSpace = icSigRgbData; /* It's RGB space */ + wh->pcs = icSigXYZData; + wh->renderingIntent = icPerceptual; + + /* Values that should be set before writing */ + wh->manufacturer = str2tag("????"); + wh->model = str2tag("????"); + } + /* Profile Description Tag: */ + { + icmTextDescription *wo; + char *dst; + + dst = "sRGB like Matrix Display profile"; + if ((wo = (icmTextDescription *)wr_icco->add_tag( + wr_icco, icSigProfileDescriptionTag, icSigTextDescriptionType)) == NULL) + error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err); + + wo->size = strlen(dst)+1; /* Allocated and used size of desc, inc null */ + wo->scCode = 0; + wo->scSize = strlen(dst)+1; + if (wo->scSize > 67) + error("Description scriptCode string longer than 67"); + wo->allocate((icmBase *)wo);/* Allocate space */ + strcpy(wo->desc, dst); /* Copy the string in */ + strcpy((char *)wo->scDesc, dst); /* Copy the string in */ + } + /* Copyright Tag: */ + { + icmText *wo; + char *crt = "Copyright tag goes here"; + if ((wo = (icmText *)wr_icco->add_tag( + wr_icco, icSigCopyrightTag, icSigTextType)) == NULL) + error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err); + + wo->size = strlen(crt)+1; /* Allocated and used size of text, inc null */ + wo->allocate((icmBase *)wo);/* Allocate space */ + strcpy(wo->data, crt); /* Copy the text in */ + } + + /* Could add other relevant tags here, such as: + + Device Manufacturers Description Tag + Device Model Description Tag + Device technology Tag + Viewing conditions Description Tag + Viewing conditions + Display Luminance Tag + Measurement information Tag + + etc. + */ + + /* Setup the primaries */ + { + /* Compute primaries as XYZ */ + icmXYZNumber wrgb[4] = { /* Primaries in Yxy from the standard */ + { 1.0, 0.3127, 0.3290 }, /* White */ + { 1.0, 0.6400, 0.3300 }, /* Red */ + { 1.0, 0.3000, 0.6000 }, /* Green */ + { 1.0, 0.1500, 0.0600 } /* Blue */ + }; + double mat[3][3]; + int i; + + /* Convert Yxy to XYZ */ + for (i = 0; i < 4; i++) { + double v[3]; + + icmXYZ2Ary(v, wrgb[i]); + icmYxy2XYZ(v, v); + icmAry2XYZ(wrgb[i], v); + } + + /* Convert XYZ to normalised 3x3 matrix */ + icmRGBprim2matrix(wrgb[0], wrgb[1], wrgb[2], wrgb[3], mat); + +#ifdef NEVER /* Dump XYZ of matrix */ + printf("sRGB: XYZ\n"); + printf("{ %f, %f, %f }, /* Red */\n" + "{ %f, %f, %f }, /* Green */\n" + "{ %f, %f, %f }, /* Blue */\n" + "{ %f, %f, %f } /* White */\n", + mat[0][0], mat[0][1], mat[0][2], + mat[1][0], mat[1][1], mat[1][2], + mat[2][0], mat[2][1], mat[2][2], + wrgb[0].X, wrgb[0].Y, wrgb[0].Z); +#endif + + /* White Point Tag: */ + { + icmXYZArray *wo; + + if ((wo = (icmXYZArray *)wr_icco->add_tag( + wr_icco, icSigMediaWhitePointTag, icSigXYZArrayType)) == NULL) + error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err); + + wo->size = 1; + wo->allocate((icmBase *)wo); /* Allocate space */ + wo->data[0].X = wrgb[0].X; + wo->data[0].Y = wrgb[0].Y; + wo->data[0].Z = wrgb[0].Z; + } + /* Black Point Tag: */ + { + icmXYZArray *wo; + + if ((wo = (icmXYZArray *)wr_icco->add_tag( + wr_icco, icSigMediaBlackPointTag, icSigXYZArrayType)) == NULL) + error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err); + + wo->size = 1; + wo->allocate((icmBase *)wo); /* Allocate space */ + wo->data[0].X = 0.00; + wo->data[0].Y = 0.00; + wo->data[0].Z = 0.00; + } + /* Red, Green and Blue Colorant Tags: */ + { + icmXYZArray *wor, *wog, *wob; + double fromAbs[3][3]; + double d50m[3][3]; + + /* Convert to D50 adapated */ + icmChromAdaptMatrix(ICM_CAM_BRADFORD, icmD50, wrgb[0], fromAbs); + icmMulBy3x3(d50m[0], fromAbs, mat[0]); + icmMulBy3x3(d50m[1], fromAbs, mat[1]); + icmMulBy3x3(d50m[2], fromAbs, mat[2]); + + /* Make sure rounding doesn't wreck white point */ + quantizeRGBprimsS15Fixed16(d50m); + + if ((wor = (icmXYZArray *)wr_icco->add_tag( + wr_icco, icSigRedColorantTag, icSigXYZArrayType)) == NULL) + error("add_tag failed: %d, %s",rv,wr_icco->err); + if ((wog = (icmXYZArray *)wr_icco->add_tag( + wr_icco, icSigGreenColorantTag, icSigXYZArrayType)) == NULL) + error("add_tag failed: %d, %s",rv,wr_icco->err); + if ((wob = (icmXYZArray *)wr_icco->add_tag( + wr_icco, icSigBlueColorantTag, icSigXYZArrayType)) == NULL) + error("add_tag failed: %d, %s",rv,wr_icco->err); + + wor->size = wog->size = wob->size = 1; + wor->allocate((icmBase *)wor); /* Allocate space */ + wog->allocate((icmBase *)wog); + wob->allocate((icmBase *)wob); + wor->data[0].X = d50m[0][0]; wor->data[0].Y = d50m[0][1]; wor->data[0].Z = d50m[0][2]; + wog->data[0].X = d50m[1][0]; wog->data[0].Y = d50m[1][1]; wog->data[0].Z = d50m[1][2]; + wob->data[0].X = d50m[2][0]; wob->data[0].Y = d50m[2][1]; wob->data[0].Z = d50m[2][2]; + } + } + /* Red, Green and Blue Gamma Curve Tags: */ + { + icmCurve *wor, *wog, *wob; + int i; + + if ((wor = (icmCurve *)wr_icco->add_tag( + wr_icco, icSigRedTRCTag, icSigCurveType)) == NULL) + error("add_tag failed: %d, %s",rv,wr_icco->err); + wor->flag = icmCurveSpec; + wor->size = 1024; + wor->allocate((icmBase *)wor); /* Allocate space */ + for (i = 0; i < wor->size; i++) + wor->data[i] = gdv2dv(i/(wor->size-1.0)); + + /* Link other channels to the red */ + if ((wog = (icmCurve *)wr_icco->link_tag( + wr_icco, icSigGreenTRCTag, icSigRedTRCTag)) == NULL) + error("link_tag failed: %d, %s",rv,wr_icco->err); + if ((wob = (icmCurve *)wr_icco->link_tag( + wr_icco, icSigBlueTRCTag, icSigRedTRCTag)) == NULL) + error("link_tag failed: %d, %s",rv,wr_icco->err); + } + + /* Write the file out */ + if ((rv = wr_icco->write(wr_icco,wr_fp,0)) != 0) + error ("Write file: %d, %s",rv,wr_icco->err); + + wr_icco->del(wr_icco); + wr_fp->del(wr_fp); + + return 0; +} + +/* ------------------------------------------------ */ +/* Basic printf type error() and warning() routines */ + +void +error(char *fmt, ...) { + va_list args; + + fprintf(stderr,"mkDispProf: Error - "); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + exit (-1); +} + +void +warning(char *fmt, ...) { + va_list args; + + fprintf(stderr,"mkDispProf: Warning - "); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); +} |