3730 lines
101 KiB
C
3730 lines
101 KiB
C
|
|
/*
|
|
* International Color Consortium Format Library (icclib)
|
|
* Library Read/Write test and example code.
|
|
*
|
|
* Author: Graeme W. Gill
|
|
* Date: 1999/11/29
|
|
* Version: 2.15
|
|
*
|
|
* Copyright 1997 - 2012 Graeme W. Gill
|
|
*
|
|
* This material is licensed with an "MIT" free use license:-
|
|
* see the License4.txt file in this directory for licensing details.
|
|
*/
|
|
|
|
/* TTBD:
|
|
*
|
|
* Fix enums to be selected randomly (ie. header)
|
|
*
|
|
* Should add test of ->delete_tag()
|
|
* Should add test of ->rename_tag()
|
|
*
|
|
* Add many extra comments and explanations.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
|
|
This file is intended to serve two purposes. One
|
|
is to minimally test the ability of the icc library
|
|
to read and write all tag types. The other is as
|
|
a source code example of how to read and write
|
|
each tag type, since icc.h might otherwise take
|
|
some effort to understand.
|
|
|
|
(Note XYZ scaling to 1.0, not 100.0)
|
|
|
|
*/
|
|
|
|
#define NTRIALS 100
|
|
|
|
#define TEST_UNICODE 0 /* Test unicode translation code */
|
|
#define TEST_MATXINV 0 /* Test matrix inversion code (invmatrix() must be public) */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#ifdef __sun
|
|
#include <unistd.h>
|
|
#endif
|
|
#include "icc.h"
|
|
|
|
void error(char *fmt, ...), warning(char *fmt, ...);
|
|
|
|
/* Set the seed */
|
|
void set_seed(ORD32 o32);
|
|
|
|
/* Rounded floating test numbers */
|
|
unsigned int rand_int(unsigned int low, unsigned int high);
|
|
unsigned int rand_o8(void), rand_o16(void), rand_o32(void);
|
|
double rand_8f(void), rand_XYZ8(void), rand_L8(void), rand_ab8(void);
|
|
double rand_16f(void), rand_32f(void);
|
|
double rand_XYZ16(void), rand_u8f8(void), rand_L16(void), rand_ab16(void);
|
|
double rand_u16f16(void), rand_s15f16(void);
|
|
double rand_rangef(double min, double max, int bits);
|
|
void rand_Color(double *vals, icColorSpaceSignature sig, int bits);
|
|
int dcomp(double a, double b);
|
|
|
|
/* random ICC specific values */
|
|
void rand_XYZ(icmXYZNumber *pXYZ);
|
|
icScreening rand_ScreenEncodings(void);
|
|
unsigned int rand_DeviceAttributes(void);
|
|
unsigned int rand_ProfileHeaderFlags(void);
|
|
unsigned int rand_AsciiOrBinaryData(void);
|
|
icColorSpaceSignature rand_ColorSpaceSignature(void);
|
|
icColorSpaceSignature rand_PCS(void);
|
|
icTechnologySignature rand_TechnologySignature(void);
|
|
icProfileClassSignature rand_ProfileClassSignature(void);
|
|
icPlatformSignature rand_PlatformSignature(void);
|
|
icMeasurementGeometry rand_MeasurementGeometry(void);
|
|
icRenderingIntent rand_RenderingIntent(void);
|
|
icSpotShape rand_SpotShape(void);
|
|
icStandardObserver rand_StandardObserver(void);
|
|
icIlluminant rand_Illuminant(void);
|
|
icPhColEncoding rand_ColorantEncoding(void);
|
|
icMeasUnitsSig rand_MeasUnitsSig();
|
|
icDevSetMsftIDSignature rand_DevSetMsftIDSignature(void);
|
|
icDevSetMsftMedia rand_DevSetMsftMedia(void);
|
|
icDevSetMsftDither rand_DevSetMsftDither(void);
|
|
|
|
char *rand_ascii_string(int lenmin, int lenmax);
|
|
icmUTF8 *rand_utf8_string(int lenmin, int lenmax);
|
|
icmUTF16 *rand_utf16_string(int lenmin, int lenmax);
|
|
size_t strlen_utf16(icmUTF16 *in);
|
|
int strcmp_utf16(icmUTF16 *in1, icmUTF16 *in2);
|
|
void rand_id(unsigned char id[16]);
|
|
int idcomp(unsigned char a[16], unsigned char b[16]);
|
|
|
|
/* declare some test functions */
|
|
#if TEST_UNICODE > 0
|
|
int unicode_test(void);
|
|
#endif
|
|
#if TEST_MATXINV > 0
|
|
int matxinv_test(void);
|
|
#endif
|
|
int md5_test(void);
|
|
|
|
/*
|
|
I've split the functionality up into two pieces.
|
|
The main() code does the overall file write/read,
|
|
while the tag type code is all in the doit() function.
|
|
The write/read logic is all sandwiched together (distinguished
|
|
by the state of the mode flag), so that the code for each
|
|
tag type is kept adjacent.
|
|
|
|
In a real application, one wouldn't do it this way.
|
|
*/
|
|
|
|
int doit(int pass, int mode, icc *wr_icco, icc *rd_icco, int v3);
|
|
|
|
void usage(void) {
|
|
printf("ICC library regression test, V%s\n",ICCLIB_VERSION_STR);
|
|
fprintf(stderr,"Author: Graeme W. Gill\n");
|
|
fprintf(stderr,"usage: icctest [-v level] [-1] [-n pass] [-w] [-r]\n");
|
|
fprintf(stderr," -v level Verbosity level\n");
|
|
fprintf(stderr," -N No startup description\n");
|
|
fprintf(stderr," -1 Do just first pass\n");
|
|
fprintf(stderr," -n x Do just pass x\n");
|
|
fprintf(stderr," -w Do write side of pass\n");
|
|
fprintf(stderr," -r Do read side of pass\n");
|
|
fprintf(stderr," -2 Only do icclib v2 checks\n");
|
|
fprintf(stderr," -z Always put data at zero offset\n");
|
|
fprintf(stderr," -W Show any warnings\n");
|
|
exit(1);
|
|
}
|
|
|
|
static void Warning(icc *p, int err, const char *fmt, va_list args) {
|
|
fprintf(stderr, "Warning (0x%x): ",err);
|
|
vfprintf(stderr, fmt, args);
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|
|
int
|
|
main(
|
|
int argc,
|
|
char *argv[]
|
|
) {
|
|
int fa,nfa;
|
|
int nointro = 0; /* No introduction vebosity */
|
|
int verb = 0;
|
|
int passn = 0;
|
|
int wonly = 0;
|
|
int ronly = 0;
|
|
int warn = 0;
|
|
int v3 = 1; /* Check icclib V3 additions */
|
|
int zoffset = 0; /* Always use zero file offset */
|
|
icmErr e = { 0, { '\000'} }; /* Place to get error details back */
|
|
char *file_name = "xxxx.icm";
|
|
icmFile *wr_fp = NULL, *rd_fp = NULL;
|
|
icc *wr_icco = NULL, *rd_icco = NULL; /* Keep object separate */
|
|
int rv = 0;
|
|
int i;
|
|
unsigned int offset = 0; /* File write/read offset, 0 for standard icc */
|
|
|
|
/* 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();
|
|
|
|
/* no inro */
|
|
else if (argv[fa][1] == 'N') {
|
|
nointro = 1;
|
|
}
|
|
|
|
/* Verbosity */
|
|
else if (argv[fa][1] == 'v') {
|
|
fa = nfa;
|
|
if (na == NULL)
|
|
verb = 1;
|
|
else
|
|
verb = na[0] - '1';
|
|
}
|
|
|
|
/* Just first pass */
|
|
else if (argv[fa][1] == '1') {
|
|
passn = 1;
|
|
}
|
|
|
|
/* Just pass n */
|
|
else if (argv[fa][1] == 'n') {
|
|
fa = nfa;
|
|
if (na == NULL)
|
|
usage();
|
|
else {
|
|
passn = atoi(na);
|
|
fa = nfa;
|
|
if (passn < 1 || passn > NTRIALS)
|
|
usage();
|
|
}
|
|
}
|
|
|
|
/* just write */
|
|
else if (argv[fa][1] == 'w') {
|
|
wonly = 1;
|
|
}
|
|
|
|
/* Just read */
|
|
else if (argv[fa][1] == 'r') {
|
|
ronly = 1;
|
|
}
|
|
|
|
/* icclib v2 only */
|
|
else if (argv[fa][1] == '2') {
|
|
v3 = 0;
|
|
}
|
|
|
|
/* Zero file offset */
|
|
else if (argv[fa][1] == 'z') {
|
|
zoffset = 1;
|
|
}
|
|
|
|
/* Warn */
|
|
else if (argv[fa][1] == 'W') {
|
|
warn = 1;
|
|
}
|
|
|
|
else
|
|
usage();
|
|
} else
|
|
break;
|
|
}
|
|
|
|
if (!nointro)
|
|
printf("ICC library regression test, V%s\n",ICCLIB_VERSION_STR);
|
|
|
|
/* Do any internal code tests. */
|
|
|
|
#if TEST_UNICODE > 0
|
|
if (unicode_test())
|
|
error ("Unicode translation routines are faulty");
|
|
#endif
|
|
#if TEST_MATXINV > 0
|
|
if (matxinv_test())
|
|
error ("Matrix inversion routine is faulty");
|
|
#endif
|
|
|
|
if (md5_test() != 0)
|
|
error ("MD5 checksum routine is faulty");
|
|
|
|
/* Outer loop does a number of file write/reads, */
|
|
/* in order to exercise random tests, and to test file offsets. */
|
|
|
|
i = 0;
|
|
if (passn != 0)
|
|
i = passn-1;
|
|
for (; i < NTRIALS; i++) {
|
|
unsigned int size; /* Expected write size */
|
|
|
|
set_seed(0x12345678 + i * 73);
|
|
|
|
if (verb) {
|
|
printf("Pass %d/%d:",i+1,NTRIALS); fflush(stdout);
|
|
} else {
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
|
|
if (i > 0) {
|
|
/* choose another file offset to test */
|
|
offset = rand_int(0,72789);
|
|
}
|
|
if (zoffset)
|
|
offset = 0;
|
|
|
|
/* -------------------------- */
|
|
/* Deal with writing the file */
|
|
|
|
icm_err_clear_e(&e);
|
|
|
|
if (!ronly) {
|
|
/* Open up the file for writing */
|
|
if ((wr_fp = new_icmFileStd_name(&e, file_name,"w")) == NULL)
|
|
error("Write: Open file '%s' failed with 0x%x, '%s'",file_name,e.c, e.m);
|
|
} else {
|
|
/* Open up the file for reading rather than writing, so we can seek. */
|
|
if ((wr_fp = new_icmFileStd_name(&e, file_name,"r")) == NULL)
|
|
error("Write: Open file '%s' failed with 0x%x, '%s'",file_name,e.c, e.m);
|
|
}
|
|
|
|
if ((wr_icco = new_icc(&e)) == NULL)
|
|
error("Write: Creation of ICC object failed with 0x%x, '%s'",e.c,e.m);
|
|
|
|
if (warn)
|
|
wr_icco->warning = Warning;
|
|
|
|
/* Default to V2.4 */
|
|
#define TEST_DEFAULT_TV ICMTV_24
|
|
wr_icco->set_version(wr_icco, TEST_DEFAULT_TV);
|
|
|
|
/* Don't check for required tags, so that we can test range of profile */
|
|
/* classes with full range of tags. */
|
|
wr_icco->set_cflag(wr_icco, icmCFlagNoRequiredCheck);
|
|
|
|
/* Relax format so we can use the full range of tagtypes */
|
|
wr_icco->set_cflag(wr_icco, icmCFlagWrFormatWarn);
|
|
wr_icco->set_vcrange(wr_icco, &icmtvrange_all);
|
|
|
|
/* Add all the tags with their tag types */
|
|
if ((rv = doit(i, 0, wr_icco, NULL, v3)) != 0)
|
|
error ("Write tags: %d, 0x%x '%s'",rv,wr_icco->e.c,wr_icco->e.m);
|
|
|
|
/* Write the file (including all tags) out */
|
|
/* The last parameter is the offset to write the */
|
|
/* ICC profile into the file. For a standard ICC profile, */
|
|
/* this needs to be 0, but it might be non-zero if you are writing */
|
|
/* an embedded profile. */
|
|
|
|
/* Check that get_size() is working too. */
|
|
if ((size = wr_icco->get_size(wr_icco)) == 0)
|
|
error ("Write size: %d, 0x%x '%s'",rv,wr_icco->e.c,wr_icco->e.m);
|
|
|
|
if (!ronly) {
|
|
if ((rv = wr_icco->write(wr_icco,wr_fp,offset)) != 0)
|
|
error ("Write file: %d, 0x%x '%s'",rv,wr_icco->e.c,wr_icco->e.m);
|
|
}
|
|
|
|
/* To check that get_size() is correct: */
|
|
{
|
|
icmFileStd *pp = (icmFileStd *)wr_fp; /* Cheat - Look inside icmFile */
|
|
|
|
if (fseek(pp->fp, 0, SEEK_END))
|
|
error ("Write: seek to EOF failed");
|
|
if ((unsigned int)ftell(pp->fp) != offset + size)
|
|
error ("Write: get_size function didn't return correct value - got %d, expected %d",
|
|
ftell(pp->fp),offset+size);
|
|
}
|
|
|
|
/*
|
|
Would normally call wr_icco->del(wr_icco);
|
|
but leave it, so that we can verify the read.
|
|
*/
|
|
|
|
wr_fp->del(wr_fp);
|
|
|
|
if (!wonly) {
|
|
/* -------------------------- */
|
|
/* Deal with reading and verifying the file */
|
|
|
|
icm_err_clear_e(&e);
|
|
|
|
/* Open up the file for reading */
|
|
if ((rd_fp = new_icmFileStd_name(&e, file_name,"r")) == NULL)
|
|
error("Read: Open file '%s' failed with 0x%x, '%s'",file_name,e.c, e.m);
|
|
|
|
if ((rd_icco = new_icc(&e)) == NULL)
|
|
error("Read: Creation of ICC object failed with 0x%x, '%s'",e.c,e.m);
|
|
|
|
if (warn)
|
|
rd_icco->warning = Warning;
|
|
|
|
/* Read the header and tag list */
|
|
/* The last parameter is the offset to read the */
|
|
/* ICC profile from the file. For a standard ICC proifile, */
|
|
/* this needs to be 0, but it might be non-zero if you are writing */
|
|
/* an embedded profile this needs to be 0, but it might be non-zero */
|
|
/* if you are writing an embedded profile. */
|
|
if ((rv = rd_icco->read(rd_icco,rd_fp,offset)) != 0)
|
|
error ("Read: icc read returned %d, 0x%x '%s'",rv,rd_icco->e.c,rd_icco->e.m);
|
|
|
|
/* Read and verify all the tags and their tag types */
|
|
if ((rv = doit(i, 1, wr_icco, rd_icco, v3)) != 0)
|
|
error ("Read: do write/read/verify return %d, 0x%x '%s'",rv,rd_icco->e.c,rd_icco->e.m);
|
|
|
|
/* -------- */
|
|
/* Clean up */
|
|
wr_icco->del(wr_icco);
|
|
|
|
rd_icco->del(rd_icco);
|
|
rd_fp->del(rd_fp);
|
|
|
|
if (verb)
|
|
printf(" OK\n");
|
|
} else {
|
|
wr_icco->del(wr_icco);
|
|
if (verb)
|
|
printf(" Written\n");
|
|
}
|
|
|
|
if (passn != 0 || ronly || wonly)
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* -------------------------------------------------------------- */
|
|
/* Internal routine checks. */
|
|
|
|
#if TEST_UNICODE > 0
|
|
int unicode_test() {
|
|
size_t len, blen;
|
|
icmUTFerr illegal;
|
|
int i;
|
|
|
|
icmUTF8 *in8;
|
|
icmUTF16 *out16;
|
|
ORD8 *out16BE;
|
|
icmUTF8 *check8;
|
|
|
|
icmUTF16 *in16;
|
|
icmUTF8 *out8;
|
|
icmUTF16 *check16;
|
|
|
|
printf("Testing utf-8 -> utf-16 BE -> utf-8:\n");
|
|
for (i = 0; i < TEST_UNICODE; i++) {
|
|
in8 = rand_utf8_string(1, 237);
|
|
len = strlen(in8) + 1;
|
|
|
|
blen = icmUTF8toUTF16Sn(&illegal, NULL, in8, len, 0);
|
|
if (illegal != 0) {
|
|
printf("icmUTF8toUTF16Sn returned error 0x%x\n",illegal);
|
|
return 1;
|
|
}
|
|
if ((out16BE = malloc(blen)) == NULL)
|
|
error("malloc of out16BE failed\n");
|
|
icmUTF8toUTF16Sn(NULL, out16BE, in8, len, 0);
|
|
|
|
len = blen/2;
|
|
|
|
/* Now convert back */
|
|
blen = icmUTF16SntoUTF8(&illegal, NULL, out16BE, len, 0);
|
|
if (illegal != 0) {
|
|
printf("icmUTF16SntoUTF8 returned error 0x%x\n",illegal);
|
|
return 1;
|
|
}
|
|
if ((check8 = malloc(blen)) == NULL)
|
|
error("malloc of check8 failed\n");
|
|
icmUTF16SntoUTF8(NULL, check8, out16BE, len, 0);
|
|
|
|
if (strcmp(in8, check8) != 0) {
|
|
printf("utf-8 BE string didn't verify\n");
|
|
return 1;
|
|
}
|
|
|
|
/* Clean up */
|
|
free(in8);
|
|
free(out16BE);
|
|
free(check8);
|
|
}
|
|
|
|
printf("Testing utf-8 -> utf-16 -> utf-8:\n");
|
|
for (i = 0; i < TEST_UNICODE; i++) {
|
|
in8 = rand_utf8_string(1, 237);
|
|
|
|
blen = icmUTF8toUTF16(&illegal, NULL, in8);
|
|
if (illegal != 0) {
|
|
printf("icmUTF8toUTF16 returned error 0x%x\n",illegal);
|
|
return 1;
|
|
}
|
|
if ((out16 = malloc(blen)) == NULL)
|
|
error("malloc of out16 failed\n");
|
|
icmUTF8toUTF16(NULL, out16, in8);
|
|
|
|
/* Now convert back */
|
|
blen = icmUTF16toUTF8(&illegal, NULL, out16);
|
|
if (illegal != 0) {
|
|
printf("icmUTF16toUTF8 returned error 0x%x\n",illegal);
|
|
return 1;
|
|
}
|
|
if ((check8 = malloc(blen)) == NULL)
|
|
error("malloc of check8 failed\n");
|
|
icmUTF16toUTF8(NULL, check8, out16);
|
|
|
|
if (strcmp(in8, check8) != 0) {
|
|
printf("utf-8 string didn't verify\n");
|
|
return 1;
|
|
}
|
|
|
|
/* Clean up */
|
|
free(in8);
|
|
free(out16);
|
|
free(check8);
|
|
}
|
|
|
|
printf("Testing utf-16 -> utf-8 -> utf-16\n");
|
|
for (i = 0; i < TEST_UNICODE; i++) {
|
|
in16 = rand_utf16_string(1, 237);
|
|
|
|
blen = icmUTF16toUTF8(&illegal, NULL, in16);
|
|
if (illegal != 0) {
|
|
printf("icmUTF16toUTF8 returned error 0x%x\n",illegal);
|
|
return 1;
|
|
}
|
|
if ((out8 = malloc(blen)) == NULL)
|
|
error("malloc of out8 failed\n");
|
|
icmUTF16toUTF8(NULL, out8, in16);
|
|
|
|
/* Now convert back */
|
|
blen = icmUTF8toUTF16(&illegal, NULL, out8);
|
|
if (illegal != 0) {
|
|
printf("icmUTF8toUTF16 returned error 0x%x\n",illegal);
|
|
return 1;
|
|
}
|
|
if ((check16 = malloc(blen)) == NULL)
|
|
error("malloc of check16 failed\n");
|
|
icmUTF8toUTF16(NULL, check16, out8);
|
|
|
|
if (strcmp_utf16(in16, check16) != 0) {
|
|
printf("utf-16 string didn't verify\n");
|
|
return 1;
|
|
}
|
|
|
|
/* Clean up */
|
|
free(in16);
|
|
free(out8);
|
|
free(check16);
|
|
}
|
|
|
|
printf("Testing utf-8 -> ASCII, HTML:\n");
|
|
for (i = 0; i < TEST_UNICODE; i++) {
|
|
len = rand_int(15, 42); /* Max length */
|
|
|
|
printf("%d\n",i+1);
|
|
|
|
in8 = rand_utf8_string(1, len);
|
|
printf(" utf8: '%s'\n",in8);
|
|
|
|
blen = icmUTF8toHTMLESC(&illegal, NULL, NULL, in8);
|
|
if ((out8 = malloc(blen)) == NULL)
|
|
error("malloc of out8 failed\n");
|
|
icmUTF8toHTMLESC(NULL, NULL, out8, in8);
|
|
printf(" html '%s'\n",out8);
|
|
free(out8);
|
|
|
|
blen = icmUTF8toASCII(&illegal, NULL, NULL, in8);
|
|
if ((out8 = malloc(blen)) == NULL)
|
|
error("malloc of out8 failed\n");
|
|
icmUTF8toASCII(NULL, NULL, out8, in8);
|
|
printf(" ascii '%s'\n",out8);
|
|
free(out8);
|
|
|
|
free(in8);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if TEST_MATXINV > 0
|
|
int invmatrix(
|
|
double out[MAX_CHAN][MAX_CHAN],
|
|
double in[MAX_CHAN][MAX_CHAN],
|
|
int n
|
|
);
|
|
|
|
static void dump_mtx(FILE *fp, char *id, char *pfx, double a[MAX_CHAN][MAX_CHAN], int nr, int nc) {
|
|
int i, j;
|
|
fprintf(fp, "%s%s[%d][%d]\n",pfx,id,nr,nc);
|
|
|
|
for (j = 0; j < nr; j++) {
|
|
fprintf(fp, "%s ",pfx);
|
|
for (i = 0; i < nc; i++)
|
|
fprintf(fp, "%f%s",a[j][i], i < (nc-1) ? ", " : "");
|
|
fprintf(fp, "\n");
|
|
}
|
|
}
|
|
|
|
int matxinv_test() {
|
|
double mx[MAX_CHAN][MAX_CHAN];
|
|
double imx[MAX_CHAN][MAX_CHAN];
|
|
double ch[MAX_CHAN][MAX_CHAN];
|
|
int m, n, i, j, k;
|
|
double max;
|
|
|
|
for (m = 0; m < 20; m++) {
|
|
/* Create a random matrix */
|
|
n = rand_int(2,8);
|
|
for (i = 0; i < n; i++) {
|
|
for (j = 0; j < n; j++) {
|
|
mx[i][j] = rand_32f();
|
|
}
|
|
}
|
|
|
|
// dump_mtx(stdout, "mx","",mx,n,n);
|
|
|
|
if (invmatrix(imx, mx, n)) {
|
|
printf("invmatrix failed\n");
|
|
return 1;
|
|
}
|
|
|
|
// dump_mtx(stdout, "imx","",imx,n,n);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
for (j = 0; j < n; j++) {
|
|
ch[i][j] = 0.0;
|
|
for (k = 0; k < n; k++) {
|
|
ch[i][j] += mx[i][k] * imx[k][j];
|
|
}
|
|
}
|
|
}
|
|
|
|
// dump_mtx(stdout, "ch","",ch,n,n);
|
|
|
|
max = 0.0;
|
|
for (i = 0; i < n; i++) {
|
|
for (j = 0; j < n; j++) {
|
|
double vv = ch[i][j];
|
|
if (i == j)
|
|
vv -= 1.0;
|
|
vv = fabs(vv);
|
|
if (vv > max)
|
|
max = vv;
|
|
}
|
|
}
|
|
|
|
printf("max matrix invert error %e\n",max);
|
|
|
|
if (max > 1e-11) {
|
|
dump_mtx(stdout, "ch","",ch,n,n);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/* Test the MD5 function. Return nz if fail. */
|
|
int md5_test() {
|
|
int rv = 0;
|
|
int i, j;
|
|
icc *icco;
|
|
icmErr e = { 0, { '\000'} };
|
|
icmMD5 *m;
|
|
|
|
unsigned char chs1[16];
|
|
unsigned char chs2[16];
|
|
|
|
/* Standard RFC 1321 test cases */
|
|
struct {
|
|
char *s;
|
|
ORD32 sum[4];
|
|
} tc[] = {
|
|
{ "", { 0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e } },
|
|
{ "a", { 0x0cc175b9, 0xc0f1b6a8, 0x31c399e2, 0x69772661 } },
|
|
{ "abc", { 0x90015098, 0x3cd24fb0, 0xd6963f7d, 0x28e17f72 } },
|
|
{ "message digest", { 0xf96b697d, 0x7cb7938d, 0x525a2f31, 0xaaf161d0 } },
|
|
{ "abcdefghijklmnopqrstuvwxyz", { 0xc3fcd3d7, 0x6192e400, 0x7dfb496c, 0xca67e13b } },
|
|
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
|
{ 0xd174ab98, 0xd277d9f5, 0xa5611c2c, 0x9f419d9f } },
|
|
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
|
{ 0x57edf4a2, 0x2be3c955, 0xac49da2e, 0x2107b67a } },
|
|
{ NULL, { 0,0,0,0 } }
|
|
};
|
|
|
|
icm_err_clear_e(&e);
|
|
|
|
if ((icco = new_icc(&e)) == NULL)
|
|
error("Read: Creation of ICC object failed with 0x%x, '%s'",e.c,e.m);
|
|
|
|
if ((m = new_icmMD5_a(&e, icco->al)) == NULL)
|
|
error("Read: Creation of MD5 object failed with 0x%x, '%s'",e.c,e.m);
|
|
|
|
for (i = 0; ; i++) {
|
|
if (tc[i].s == NULL)
|
|
break;
|
|
|
|
m->reset(m);
|
|
|
|
m->add(m, (unsigned char *)tc[i].s, strlen(tc[i].s));
|
|
m->get(m, chs2);
|
|
|
|
/* Convert reference to a byte stream */
|
|
chs1[0] = (tc[i].sum[0] >> 24) & 0xff,
|
|
chs1[1] = (tc[i].sum[0] >> 16) & 0xff,
|
|
chs1[2] = (tc[i].sum[0] >> 8) & 0xff,
|
|
chs1[3] = tc[i].sum[0] & 0xff,
|
|
chs1[4] = (tc[i].sum[1] >> 24) & 0xff,
|
|
chs1[5] = (tc[i].sum[1] >> 16) & 0xff,
|
|
chs1[6] = (tc[i].sum[1] >> 8) & 0xff,
|
|
chs1[7] = tc[i].sum[1] & 0xff,
|
|
chs1[8] = (tc[i].sum[2] >> 24) & 0xff,
|
|
chs1[9] = (tc[i].sum[2] >> 16) & 0xff,
|
|
chs1[10] = (tc[i].sum[2] >> 8) & 0xff,
|
|
chs1[11] = tc[i].sum[2] & 0xff,
|
|
chs1[12] = (tc[i].sum[3] >> 24) & 0xff,
|
|
chs1[13] = (tc[i].sum[3] >> 16) & 0xff,
|
|
chs1[14] = (tc[i].sum[3] >> 8) & 0xff,
|
|
chs1[15] = tc[i].sum[3] & 0xff;
|
|
|
|
for (j = 0; j < 16; j++) {
|
|
if (chs1[j] != chs2[j]) {
|
|
printf("MD5 check on '%s' fails at %d with:\n",tc[i].s,j);
|
|
printf("Sum is %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
|
|
chs2[0], chs2[1], chs2[2], chs2[3], chs2[4], chs2[5], chs2[6], chs2[7],
|
|
chs2[8], chs2[9], chs2[10], chs2[11], chs2[12], chs2[13], chs2[14], chs2[15]);
|
|
printf("Should be %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
|
|
chs1[0], chs1[1], chs1[2], chs1[3], chs1[4], chs1[5], chs1[6], chs1[7],
|
|
chs1[8], chs1[9], chs1[10], chs1[11], chs1[12], chs1[13], chs1[14], chs1[15]);
|
|
rv = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
m->del(m);
|
|
icco->del(icco);
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* -------------------------------------------------------------- */
|
|
/* This is the code that inits and checks the header and tag data. */
|
|
/* Note that to undestand this, you need a copy of the ICC profile */
|
|
/* spec., and a copy of the icc header file (icc34.h in this code) */
|
|
/* All items that begin "icXXX" are from the ICC generic icc34.h file, */
|
|
/* while the items that begin "icmXXX" are machine versions of structures */
|
|
/* that are specific to this library. */
|
|
|
|
int doit(
|
|
int pass, /* Pass number */
|
|
int mode, /* 0 - write, 1 = read/verify */
|
|
icc *wr_icco, /* The write icc object */
|
|
icc *rd_icco, /* The read icc object */
|
|
int v3 /* Do iccib v3 checks */
|
|
) {
|
|
int rv = 0;
|
|
int minc = 0; /* Minimum arrary/number count */
|
|
|
|
if (v3)
|
|
minc = 1; /* For compatibility with SampleIcc */
|
|
|
|
/* ----------- */
|
|
/* The header: */
|
|
if (mode == 0) {
|
|
icmHeader *wh = wr_icco->header;
|
|
|
|
/* Values that must be set before writing */
|
|
wh->deviceClass = rand_ProfileClassSignature();
|
|
wh->colorSpace = rand_ColorSpaceSignature();
|
|
wh->pcs = rand_PCS();
|
|
wh->renderingIntent = rand_RenderingIntent();
|
|
|
|
/* Values that should be set before writing */
|
|
wh->manufacturer = icmstr2tag("tst1");
|
|
wh->model = icmstr2tag("1234");
|
|
wh->attributes.l = rand_DeviceAttributes();
|
|
wh->flags = rand_ProfileHeaderFlags();
|
|
|
|
/* Values that may optionally be set before writing */
|
|
wh->attributes.h = 0x12345678;
|
|
wh->creator = icmstr2tag("tst2");
|
|
|
|
/* Values that are not normally set. Set them to non-defaults for testing */
|
|
wh->cmmId = icmstr2tag("tst3");
|
|
wh->vers.majv = 2; /* Default version 2.1.0 */
|
|
wh->vers.minv = 1;
|
|
wh->vers.bfv = 0;
|
|
wh->date.year = rand_int(1900,3000); /* Defaults to current date */
|
|
wh->date.month = rand_int(1,12);
|
|
wh->date.day = rand_int(1,31);
|
|
wh->date.hours = rand_int(0,23);
|
|
wh->date.minutes = rand_int(0,59);
|
|
wh->date.seconds = rand_int(0,59);
|
|
wh->platform = rand_PlatformSignature();
|
|
wh->illuminant.X = rand_XYZ16(); /* Defaults to D50 */
|
|
wh->illuminant.Y = rand_XYZ16();
|
|
wh->illuminant.Z = rand_XYZ16();
|
|
|
|
/* Avoid device encodings that aren't handled by icctest v2 */
|
|
if (!v3 && (wh->colorSpace == icSigXYZData || wh->colorSpace == icSigLabData
|
|
|| wh->colorSpace == icSigLuvData || wh->colorSpace == icSigYCbCrData
|
|
|| wh->colorSpace == icSigYxyData))
|
|
wh->colorSpace = icSigRgbData; /* ICC doesn't say how to encode these... */
|
|
|
|
} else {
|
|
icmHeader *rh = rd_icco->header;
|
|
icmHeader *wh = wr_icco->header;
|
|
|
|
/* Check all the values */
|
|
rv |= (rh->deviceClass != wh->deviceClass);
|
|
rv |= (rh->colorSpace != wh->colorSpace);
|
|
rv |= (rh->pcs != wh->pcs);
|
|
rv |= (rh->renderingIntent != wh->renderingIntent);
|
|
rv |= (rh->manufacturer != wh->manufacturer);
|
|
rv |= (rh->model != wh->model);
|
|
rv |= (rh->attributes.l != wh->attributes.l);
|
|
rv |= (rh->attributes.h != wh->attributes.h);
|
|
rv |= (rh->flags != wh->flags);
|
|
rv |= (rh->creator != wh->creator);
|
|
rv |= (rh->cmmId != wh->cmmId);
|
|
rv |= (rh->vers.majv != wh->vers.majv);
|
|
rv |= (rh->vers.minv != wh->vers.minv);
|
|
rv |= (rh->vers.bfv != wh->vers.bfv);
|
|
rv |= (rh->date.year != wh->date.year);
|
|
rv |= (rh->date.month != wh->date.month);
|
|
rv |= (rh->date.day != wh->date.day);
|
|
rv |= (rh->date.hours != wh->date.hours);
|
|
rv |= (rh->date.minutes != wh->date.minutes);
|
|
rv |= (rh->date.seconds != wh->date.seconds);
|
|
rv |= (rh->platform != wh->platform);
|
|
rv |= dcomp(rh->illuminant.X, wh->illuminant.X);
|
|
rv |= dcomp(rh->illuminant.Y, wh->illuminant.Y);
|
|
rv |= dcomp(rh->illuminant.Z, wh->illuminant.Z);
|
|
if (rv)
|
|
error ("Header verify failed");
|
|
}
|
|
/* --------------------- */
|
|
/* Unknown */
|
|
{
|
|
icTagSignature sig = ((icTagSignature)icmMakeTag('5','6','7','8'));
|
|
static icmUnknown *wo;
|
|
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
if ((wo = (icmUnknown *)wr_icco->add_tag(
|
|
wr_icco, sig, icmSigUnknownType)) == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
wo->uttype = icmMakeTag('1','2','3','4');
|
|
wo->count = rand_int(minc,1034); /* Space we need for data */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->count; i ++)
|
|
wo->data[i] = rand_o8();
|
|
} else {
|
|
icmUnknown *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmUnknown *)rd_icco->read_tag_any(rd_icco, sig);
|
|
if (ro == NULL) {
|
|
return 1;
|
|
}
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icmSigUnknownType)
|
|
return 1;
|
|
|
|
if (ro->uttype != wo->uttype)
|
|
error ("Unknown uttype doesn't match (%s != %s",icmtag2str(ro->uttype),icmtag2str(wo->uttype));
|
|
|
|
if (ro->count != wo->count)
|
|
error ("Unknown count doesn't match (found %d should be %d)",ro->count,wo->count);
|
|
|
|
for (i = 0; i < wo->count; i++)
|
|
rv |= (ro->data[i] != wo->data[i]);
|
|
|
|
if (rv)
|
|
error ("Unknown verify failed");
|
|
}
|
|
}
|
|
|
|
/* ------------- */
|
|
/* Chromaticity: */
|
|
|
|
if (v3) { /* icclib v2 release doesn't have this */
|
|
static icmChromaticity *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
if ((wo = (icmChromaticity *)wr_icco->add_tag(
|
|
wr_icco, icSigChromaticityTag, icSigChromaticityType)) == NULL) {
|
|
printf("Add icSigChromaticityType failed\n");
|
|
return 1;
|
|
}
|
|
|
|
wo->enc = rand_ColorantEncoding();
|
|
|
|
if (wo->enc != icPhColUnknown) {
|
|
wo->setup(wo); /* Create tag compatible with encoding */
|
|
|
|
} else { /* Invent chromaticities */
|
|
wo->count = rand_int(minc, 15); /* Should actually be same as device colorspace */
|
|
if (wo->allocate(wo)) /* Allocate Chromaticity structures */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
wo->data[i].xy[0] = rand_u16f16();
|
|
wo->data[i].xy[1] = rand_u16f16();
|
|
}
|
|
|
|
}
|
|
} else {
|
|
icmChromaticity *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmChromaticity *)rd_icco->read_tag(rd_icco, icSigChromaticityTag);
|
|
if (ro == NULL) {
|
|
printf("read_tag icSigChromaticityType failed\n");
|
|
return 1;
|
|
}
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigChromaticityType) {
|
|
printf("cast icSigChromaticityType failed\n");
|
|
return 1;
|
|
}
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->enc != wo->enc);
|
|
if (rv) error("Chromaticity verify failed on encoding");
|
|
|
|
rv |= (ro->count != wo->count);
|
|
if (rv) error("Chromaticity verify failed on count");
|
|
|
|
for (i = 0; i < ro->count; i++) {
|
|
rv |= diff_u16f16(ro->data[i].xy[0], wo->data[i].xy[0]);
|
|
rv |= diff_u16f16(ro->data[i].xy[1], wo->data[i].xy[1]);
|
|
if (rv) error("Chromaticity verify failed on values");
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ------------- */
|
|
/* CrdInfo info: */
|
|
{
|
|
char *str1 = "Product Name";
|
|
char *str2[4] = { "Intent zero CRD Name",
|
|
"Intent one CRD Name",
|
|
"Intent two CRD Name",
|
|
"Intent three CRD Name" };
|
|
static icmCrdInfo *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
if ((wo = (icmCrdInfo *)wr_icco->add_tag(
|
|
wr_icco, icSigCrdInfoTag, icSigCrdInfoType)) == NULL)
|
|
return 1;
|
|
|
|
wo->ppcount = strlen(str1)+1; /* Allocated and used size of text, inc null */
|
|
for (i = 0; i < 4; i++)
|
|
wo->crdcount[i] = strlen(str2[i])+1; /* Allocated and used size of text, inc null */
|
|
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
/* Note we could allocate and copy as we go, rather than doing them all at once. */
|
|
|
|
strcpy(wo->ppname, str1); /* Copy the text in */
|
|
for (i = 0; i < 4; i++)
|
|
strcpy(wo->crdname[i], str2[i]); /* Copy the text in */
|
|
} else {
|
|
icmCrdInfo *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmCrdInfo *)rd_icco->read_tag(rd_icco, icSigCrdInfoTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigCrdInfoType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->ppcount != wo->ppcount)
|
|
for (i = 0; i < 4; i++) {
|
|
if (ro->crdcount[i] != wo->crdcount[i])
|
|
error ("CrdInfo crdcount[%d] doesn't match",i);
|
|
}
|
|
|
|
rv |= strcmp(ro->ppname, wo->ppname);
|
|
for (i = 0; i < 4; i++) {
|
|
rv |= strcmp(ro->crdname[i], wo->crdname[i]);
|
|
}
|
|
|
|
if (rv)
|
|
error ("CrdInfo verify failed");
|
|
}
|
|
}
|
|
/* ---------------------- */
|
|
/* Curve - Linear version */
|
|
{
|
|
static icmCurve *wo;
|
|
if (mode == 0) {
|
|
if ((wo = (icmCurve *)wr_icco->add_tag(
|
|
wr_icco, icSigRedTRCTag, icSigCurveType)) == NULL)
|
|
return 1;
|
|
|
|
wo->ctype = icmCurveLin; /* Linear version */
|
|
if (wo->allocate(wo))/* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
} else {
|
|
icmCurve *ro;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmCurve *)rd_icco->read_tag(rd_icco, icSigRedTRCTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigCurveType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->ctype != wo->ctype)
|
|
error ("Curve flag doesn't match for Linear");
|
|
|
|
if (ro->count != wo->count)
|
|
error ("Curve size doesn't match");
|
|
|
|
if (rv)
|
|
error ("Curve verify failed");
|
|
}
|
|
}
|
|
/* --------------------- */
|
|
/* Curve - Gamma version */
|
|
{
|
|
static icmCurve *wo;
|
|
if (mode == 0) {
|
|
if ((wo = (icmCurve *)wr_icco->add_tag(
|
|
wr_icco, icSigGreenTRCTag, icSigCurveType)) == NULL)
|
|
return 1;
|
|
|
|
wo->ctype = icmCurveGamma; /* Gamma version */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
wo->data[0] = rand_u8f8(); /* Gamma value */
|
|
} else {
|
|
icmCurve *ro;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmCurve *)rd_icco->read_tag(rd_icco, icSigGreenTRCTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigCurveType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->ctype != wo->ctype)
|
|
error ("Curve flag doesn't match for Gamma");
|
|
|
|
if (ro->count != wo->count)
|
|
error ("Curve size doesn't match");
|
|
|
|
rv |= dcomp(ro->data[0], wo->data[0]);
|
|
|
|
if (rv)
|
|
error ("Curve verify failed");
|
|
}
|
|
}
|
|
/* ------------------------- */
|
|
/* Curve - Specified version */
|
|
{
|
|
static icmCurve *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
if ((wo = (icmCurve *)wr_icco->add_tag(
|
|
wr_icco, icSigBlueTRCTag, icSigCurveType)) == NULL)
|
|
return 1;
|
|
|
|
wo->ctype = icmCurveSpec; /* Specified version */
|
|
wo->count = rand_int(2,23); /* Number of entries (min must be 2!) */
|
|
if (wo->allocate(wo))/* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->count; i++)
|
|
wo->data[i] = rand_16f(); /* Curve values 0.0 - 1.0 */
|
|
} else {
|
|
icmCurve *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmCurve *)rd_icco->read_tag(rd_icco, icSigBlueTRCTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigCurveType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->ctype != wo->ctype)
|
|
error ("Curve flag doesn't match for specified");
|
|
|
|
if (ro->count != wo->count)
|
|
error ("Curve size doesn't match");
|
|
|
|
for (i = 0; i < wo->count; i++)
|
|
rv |= dcomp(ro->data[i], wo->data[i]);
|
|
|
|
if (rv)
|
|
error ("Curve verify failed");
|
|
}
|
|
}
|
|
/* ------------------- */
|
|
/* Data - text version */
|
|
{
|
|
static icmData *wo;
|
|
char *ts1 = "This is a data string";
|
|
if (mode == 0) {
|
|
if ((wo = (icmData *)wr_icco->add_tag(
|
|
wr_icco, icSigPs2CRD0Tag, icSigDataType)) == NULL)
|
|
return 1;
|
|
|
|
wo->flag = icAsciiData; /* Holding ASCII data */
|
|
wo->count = strlen(ts1)+1; /* Allocated and used size of text, inc null */
|
|
if (wo->allocate(wo))/* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
strcpy((char *)wo->data, ts1); /* Copy the text in */
|
|
} else {
|
|
icmData *ro;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmData *)rd_icco->read_tag(rd_icco, icSigPs2CRD0Tag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigDataType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->flag != wo->flag)
|
|
error ("Data size doesn't match");
|
|
|
|
if (ro->count != wo->count)
|
|
error ("Data size doesn't match");
|
|
|
|
rv |= strcmp((char *)ro->data, (char *)wo->data);
|
|
|
|
if (rv)
|
|
error ("Data verify failed");
|
|
}
|
|
}
|
|
/* --------------------- */
|
|
/* Data - Binary version */
|
|
{
|
|
static icmData *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
if ((wo = (icmData *)wr_icco->add_tag(
|
|
wr_icco, icSigPs2CRD1Tag, icSigDataType)) == NULL)
|
|
return 1;
|
|
|
|
wo->flag = icBinaryData; /* Holding binary data */
|
|
wo->count = rand_int(minc,43); /* Space we need for data */
|
|
if (wo->allocate(wo))/* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->count; i ++)
|
|
wo->data[i] = rand_o8();
|
|
} else {
|
|
icmData *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmData *)rd_icco->read_tag(rd_icco, icSigPs2CRD1Tag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigDataType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->flag != wo->flag)
|
|
error ("Data size doesn't match");
|
|
|
|
if (ro->count != wo->count)
|
|
error ("Data size doesn't match");
|
|
|
|
for (i = 0; i < wo->count; i++)
|
|
rv |= (ro->data[i] != wo->data[i]);
|
|
|
|
if (rv)
|
|
error ("Data verify failed");
|
|
}
|
|
}
|
|
/* --------- */
|
|
/* DateTime: */
|
|
{
|
|
static icmDateTime *wo;
|
|
if (mode == 0) {
|
|
if ((wo = (icmDateTime *)wr_icco->add_tag(
|
|
wr_icco, icSigCalibrationDateTimeTag, icSigDateTimeType)) == NULL)
|
|
return 1;
|
|
|
|
wo->date.year = rand_int(1900, 3000);
|
|
wo->date.month = rand_int(1, 12);
|
|
wo->date.day = rand_int(1, 31);
|
|
wo->date.hours = rand_int(0, 23);
|
|
wo->date.minutes = rand_int(0, 59);
|
|
wo->date.seconds = rand_int(0, 59);
|
|
} else {
|
|
icmDateTime *ro;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmDateTime *)rd_icco->read_tag(rd_icco, icSigCalibrationDateTimeTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigDateTimeType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->date.year != wo->date.year);
|
|
rv |= (ro->date.month != wo->date.month);
|
|
rv |= (ro->date.day != wo->date.day);
|
|
rv |= (ro->date.hours != wo->date.hours);
|
|
rv |= (ro->date.minutes != wo->date.minutes);
|
|
rv |= (ro->date.seconds != wo->date.seconds);
|
|
|
|
if (rv)
|
|
error ("DateTime verify failed");
|
|
}
|
|
}
|
|
/* ----------- */
|
|
/* 16 bit lut: */
|
|
{
|
|
static icmLut1 *wo;
|
|
if (mode == 0) {
|
|
unsigned int i, j, k;
|
|
|
|
if ((wo = (icmLut1 *)wr_icco->add_tag(
|
|
wr_icco, icSigAToB0Tag, icSigLut16Type)) == NULL)
|
|
return 1;
|
|
|
|
wo->inputChan = 2; /* (Hard coded into cLut access) */
|
|
wo->outputChan = 3;
|
|
wo->clutPoints = 5;
|
|
wo->inputEnt = 56;
|
|
wo->outputEnt = 73;
|
|
if (wo->allocate(wo))/* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
/* The matrix is only applicable to XYZ input space */
|
|
for (i = 0; i < 3; i++) /* Matrix */
|
|
for (j = 0; j < 3; j++)
|
|
wo->pe_mx->mx[i][j] = rand_s15f16();
|
|
|
|
/* See icc.getNormFuncs() for normalizing functions */
|
|
/* The input table index range is over the normalized range 0.0 - 1.0. */
|
|
/* The range in input color space can be determined by denormalizing */
|
|
/* the values 0.0 - 1.0. */
|
|
for (i = 0; i < wo->inputChan; i++) /* Input tables */
|
|
for (j = 0; j < wo->inputEnt; j++)
|
|
wo->pe_ic[i]->data[j] = rand_16f();
|
|
|
|
/* Lut */
|
|
/* The multidimensional lut has a normalized index range */
|
|
/* of 0.0 - 1.0 in each dimension. Its entry values are also */
|
|
/* normalized values in the range 0.0 - 1.0. */
|
|
for (i = 0; i < wo->clutPoints; i++) /* Input chan 0 - slow changing */
|
|
for (j = 0; j < wo->clutPoints; j++) /* Input chan 1 - faster changing */
|
|
for (k = 0; k < wo->outputChan; k++) { /* Output chans */
|
|
int idx = (i * wo->clutPoints + j) * wo->outputChan + k;
|
|
wo->pe_cl->clutTable[idx] = rand_16f();
|
|
}
|
|
|
|
/* The output color space values should be normalized to the */
|
|
/* range 0.0 - 1.0 for use as output table entry values. */
|
|
for (i = 0; i < wo->outputChan; i++) /* Output tables */
|
|
for (j = 0; j < wo->outputEnt; j++)
|
|
wo->pe_oc[i]->data[j] = rand_16f();
|
|
|
|
} else {
|
|
icmLut1 *ro;
|
|
unsigned int i, j, k;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmLut1 *)rd_icco->read_tag(rd_icco, icSigAToB0Tag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigLut16Type)
|
|
error ("Lut16 ttype mismatch");
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->inputChan != wo->inputChan);
|
|
rv |= (ro->outputChan != wo->outputChan);
|
|
rv |= (ro->clutPoints != wo->clutPoints);
|
|
rv |= (ro->inputEnt != wo->inputEnt);
|
|
rv |= (ro->outputEnt != wo->outputEnt);
|
|
if (rv) error ("Lut16 dimensions mismatch");
|
|
|
|
for (i = 0; i < 3; i++)
|
|
for (j = 0; j < 3; j++)
|
|
rv |= dcomp(ro->pe_mx->mx[i][j], wo->pe_mx->mx[i][j]);
|
|
if (rv) error ("Lut16 matrix mismatch");
|
|
|
|
for (i = 0; i < wo->inputChan; i++)
|
|
for (j = 0; j < wo->inputEnt; j++) {
|
|
rv |= dcomp(ro->pe_ic[i]->data[j], wo->pe_ic[i]->data[j]);
|
|
if (rv) error ("Lut16 input table mismatch chan %d entry %d, is %f should be %f",
|
|
i,j,ro->pe_ic[i]->data[j], wo->pe_ic[i]->data[j]);
|
|
}
|
|
|
|
for (i = 0; i < wo->clutPoints; i++) /* Input chan 0 - slow changing */
|
|
for (j = 0; j < wo->clutPoints; j++) /* Input chan 1 - faster changing */
|
|
for (k = 0; k < wo->outputChan; k++) { /* Output chans */
|
|
int idx = (i * wo->clutPoints + j) * wo->outputChan + k;
|
|
rv |= dcomp( ro->pe_cl->clutTable[idx], wo->pe_cl->clutTable[idx]);
|
|
}
|
|
if (rv) error ("Lut16 cLut mismatch");
|
|
|
|
for (i = 0; i < wo->outputChan; i++)
|
|
for (j = 0; j < wo->outputEnt; j++)
|
|
rv |= dcomp(ro->pe_oc[i]->data[j], wo->pe_oc[i]->data[j]);
|
|
if (rv) error ("Lut16 output table mismatch");
|
|
}
|
|
}
|
|
/* ------------------ */
|
|
/* 16 bit lut - link: */
|
|
{
|
|
static icmLut1 *wo;
|
|
if (mode == 0) {
|
|
/* Just link to the existing LUT. This is often used when there */
|
|
/* is no distinction between intents, and saves file and memory space. */
|
|
if ((wo = (icmLut1 *)wr_icco->link_tag(
|
|
wr_icco, icSigAToB1Tag, icSigAToB0Tag)) == NULL)
|
|
return 1;
|
|
} else {
|
|
icmLut1 *ro;
|
|
unsigned int i, j, k;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmLut1 *)rd_icco->read_tag(rd_icco, icSigAToB1Tag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigLut16Type)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->inputChan != wo->inputChan);
|
|
rv |= (ro->outputChan != wo->outputChan);
|
|
rv |= (ro->clutPoints != wo->clutPoints);
|
|
rv |= (ro->inputEnt != wo->inputEnt);
|
|
rv |= (ro->outputEnt != wo->outputEnt);
|
|
if (rv) error ("Lut16 link dimensions mismatch");
|
|
|
|
for (i = 0; i < 3; i++)
|
|
for (j = 0; j < 3; j++)
|
|
rv |= dcomp(ro->pe_mx->mx[i][j], wo->pe_mx->mx[i][j]);
|
|
if (rv) error ("Lut16 link matrix mismatch");
|
|
|
|
for (i = 0; i < wo->inputChan; i++)
|
|
for (j = 0; j < wo->inputEnt; j++)
|
|
rv |= dcomp(ro->pe_ic[i]->data[j], wo->pe_ic[i]->data[j]);
|
|
if (rv) error ("Lut16 link input table mismatch");
|
|
|
|
for (i = 0; i < wo->clutPoints; i++) /* Input chan 0 - slow changing */
|
|
for (j = 0; j < wo->clutPoints; j++) /* Input chan 1 - faster changing */
|
|
for (k = 0; k < wo->outputChan; k++) { /* Output chans */
|
|
int idx = (i * wo->clutPoints + j) * wo->outputChan + k;
|
|
rv |= dcomp( ro->pe_cl->clutTable[idx], wo->pe_cl->clutTable[idx]);
|
|
}
|
|
if (rv) error ("Lut16 link cLut mismatch");
|
|
|
|
for (i = 0; i < wo->outputChan; i++)
|
|
for (j = 0; j < wo->outputEnt; j++)
|
|
rv |= dcomp(ro->pe_oc[i]->data[j], wo->pe_oc[i]->data[j]);
|
|
if (rv) error ("Lut16 link output table mismatch");
|
|
}
|
|
}
|
|
/* ---------- */
|
|
/* 8 bit lut: */
|
|
{
|
|
static icmLut1 *wo;
|
|
if (mode == 0) {
|
|
unsigned int i, j, m, k;
|
|
if ((wo = (icmLut1 *)wr_icco->add_tag(
|
|
wr_icco, icSigAToB2Tag, icSigLut8Type)) == NULL)
|
|
return 1;
|
|
|
|
wo->inputChan = 3; /* (Hard coded into cLut access) */
|
|
wo->outputChan = 2;
|
|
wo->clutPoints = 4;
|
|
wo->inputEnt = 256; /* Must be 256 for Lut8 */
|
|
wo->outputEnt = 256;
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
for (i = 0; i < 3; i++) /* Matrix */
|
|
for (j = 0; j < 3; j++)
|
|
wo->pe_mx->mx[i][j] = rand_s15f16();
|
|
|
|
for (i = 0; i < wo->inputChan; i++) /* Input tables */
|
|
for (j = 0; j < wo->inputEnt; j++)
|
|
wo->pe_ic[i]->data[j] = rand_8f();
|
|
|
|
/* Lut */
|
|
for (i = 0; i < wo->clutPoints; i++) /* Input chan 0 */
|
|
for (j = 0; j < wo->clutPoints; j++) /* Input chan 1 */
|
|
for (m = 0; m < wo->clutPoints; m++) /* Input chan 2 */
|
|
for (k = 0; k < wo->outputChan; k++) { /* Output chans */
|
|
int idx = ((i * wo->clutPoints + j)
|
|
* wo->clutPoints + m)
|
|
* wo->outputChan + k;
|
|
wo->pe_cl->clutTable[idx] = rand_8f();
|
|
}
|
|
|
|
for (i = 0; i < wo->outputChan; i++) /* Output tables */
|
|
for (j = 0; j < wo->outputEnt; j++)
|
|
wo->pe_oc[i]->data[j] = rand_8f();
|
|
|
|
} else {
|
|
icmLut1 *ro;
|
|
unsigned int size;
|
|
unsigned int i, j, k, m;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmLut1 *)rd_icco->read_tag(rd_icco, icSigAToB2Tag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigLut8Type)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->inputChan != wo->inputChan);
|
|
rv |= (ro->outputChan != wo->outputChan);
|
|
rv |= (ro->clutPoints != wo->clutPoints);
|
|
rv |= (ro->inputEnt != wo->inputEnt);
|
|
rv |= (ro->outputEnt != wo->outputEnt);
|
|
|
|
for (i = 0; i < 3; i++)
|
|
for (j = 0; j < 3; j++)
|
|
rv |= dcomp(ro->pe_mx->mx[i][j], wo->pe_mx->mx[i][j]);
|
|
if (rv) error ("Lut8 matrix mismatch");
|
|
|
|
for (i = 0; i < wo->inputChan; i++)
|
|
for (j = 0; j < wo->inputEnt; j++)
|
|
rv |= dcomp(ro->pe_ic[i]->data[j], wo->pe_ic[i]->data[j]);
|
|
if (rv) error ("Lut8 input table mismatch");
|
|
|
|
for (i = 0; i < wo->clutPoints; i++) /* Input chan 0 */
|
|
for (j = 0; j < wo->clutPoints; j++) /* Input chan 1 */
|
|
for (m = 0; m < wo->clutPoints; m++) /* Input chan 2 */
|
|
for (k = 0; k < wo->outputChan; k++) { /* Output chans */
|
|
int idx = ((i * wo->clutPoints + j)
|
|
* wo->clutPoints + m)
|
|
* wo->outputChan + k;
|
|
rv |= dcomp( ro->pe_cl->clutTable[idx], wo->pe_cl->clutTable[idx]);
|
|
}
|
|
|
|
if (rv) error ("Lut8 cLut mismatch");
|
|
|
|
for (i = 0; i < wo->outputChan; i++)
|
|
for (j = 0; j < wo->outputEnt; j++)
|
|
rv |= dcomp(ro->pe_oc[i]->data[j], wo->pe_oc[i]->data[j]);
|
|
if (rv) error ("Lut8 output table mismatch");
|
|
}
|
|
}
|
|
/* ----------------- */
|
|
/* Measurement: */
|
|
{
|
|
static icmMeasurement *wo;
|
|
|
|
if (mode == 0) {
|
|
if ((wo = (icmMeasurement *)wr_icco->add_tag(
|
|
wr_icco, icSigMeasurementTag, icSigMeasurementType)) == NULL)
|
|
return 1;
|
|
|
|
/* Standard observer */
|
|
switch(rand_int(0,2)) {
|
|
case 0:
|
|
wo->observer = icStdObsUnknown;
|
|
break;
|
|
case 1:
|
|
wo->observer = icStdObs1931TwoDegrees;
|
|
break;
|
|
case 2:
|
|
wo->observer = icStdObs1964TenDegrees;
|
|
break;
|
|
}
|
|
|
|
/* XYZ for backing color */
|
|
wo->backing.X = rand_XYZ16();
|
|
wo->backing.Y = rand_XYZ16();
|
|
wo->backing.Z = rand_XYZ16();
|
|
|
|
/* Measurement geometry */
|
|
switch(rand_int(0,2)) {
|
|
case 0:
|
|
wo->geometry = icGeometryUnknown;
|
|
break;
|
|
case 1:
|
|
wo->geometry = icGeometry045or450;
|
|
break;
|
|
case 2:
|
|
wo->geometry = icGeometry0dord0;
|
|
break;
|
|
}
|
|
|
|
/* Measurement flare */
|
|
wo->flare = rand_u16f16();
|
|
|
|
/* Illuminant */
|
|
switch(rand_int(0,8)) {
|
|
case 0:
|
|
wo->illuminant = icIlluminantUnknown;
|
|
break;
|
|
case 1:
|
|
wo->illuminant = icIlluminantD50;
|
|
break;
|
|
case 2:
|
|
wo->illuminant = icIlluminantD65;
|
|
break;
|
|
case 3:
|
|
wo->illuminant = icIlluminantD93;
|
|
break;
|
|
case 4:
|
|
wo->illuminant = icIlluminantF2;
|
|
break;
|
|
case 5:
|
|
wo->illuminant = icIlluminantD55;
|
|
break;
|
|
case 6:
|
|
wo->illuminant = icIlluminantA;
|
|
break;
|
|
case 7:
|
|
wo->illuminant = icIlluminantEquiPowerE;
|
|
break;
|
|
case 8:
|
|
wo->illuminant = icIlluminantF8;
|
|
break;
|
|
}
|
|
} else {
|
|
icmMeasurement *ro;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmMeasurement *)rd_icco->read_tag(rd_icco, icSigMeasurementTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigMeasurementType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->observer != wo->observer);
|
|
rv |= dcomp(ro->backing.X, wo->backing.X);
|
|
rv |= dcomp(ro->backing.Y, wo->backing.Y);
|
|
rv |= dcomp(ro->backing.Z, wo->backing.Z);
|
|
rv |= (ro->geometry != wo->geometry);
|
|
rv |= dcomp(ro->flare, wo->flare);
|
|
rv |= (ro->illuminant != wo->illuminant);
|
|
|
|
if (rv)
|
|
error ("Measurement verify failed");
|
|
}
|
|
}
|
|
|
|
|
|
/* ----------------- */
|
|
/* Old style NamedColor: */
|
|
{
|
|
static icmNamedColor *wo;
|
|
if (mode == 0) {
|
|
char *prefix = "Prefix", *suffix = "Suffix";
|
|
char buf[100];
|
|
unsigned int i;
|
|
|
|
if ((wo = (icmNamedColor *)wr_icco->add_tag(
|
|
wr_icco, icSigNamedColorTag, icSigNamedColorType)) == NULL)
|
|
return 1;
|
|
|
|
wo->vendorFlag = rand_int(0,65535) << 16; /* Bottom 16 bits for IC use */
|
|
wo->count = 3; /* Count of named colors */
|
|
wo->pcount = strlen(prefix) + 1;
|
|
wo->scount = strlen(suffix) + 1;
|
|
|
|
if (wo->allocate(wo)) /* Allocate strings and named color structures */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
strcpy(wo->prefix,prefix); /* Prefix for each color name, max 32, null terminated */
|
|
strcpy(wo->suffix,suffix); /* Suffix for each color name, max 32, null terminated */
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
unsigned int j;
|
|
icColorSpaceSignature dsig = wr_icco->header->colorSpace;
|
|
sprintf(buf,"Color %d",i); /* Root name, max 32, null terminated */
|
|
wo->data[i].rcount = strlen(buf) + 1;
|
|
if (wo->allocate(wo)) /* Allocate root string */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
strcpy(wo->data[i].root,buf);
|
|
rand_Color(wo->data[i].deviceCoords, wr_icco->header->colorSpace, 8);
|
|
}
|
|
} else {
|
|
icmNamedColor *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmNamedColor *)rd_icco->read_tag(rd_icco, icSigNamedColorTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigNamedColorType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->vendorFlag != wo->vendorFlag);
|
|
rv |= (ro->count != wo->count);
|
|
rv |= (ro->nDeviceCoords != wo->nDeviceCoords);
|
|
rv |= strcmp(ro->prefix, wo->prefix);
|
|
rv |= strcmp(ro->suffix, wo->suffix);
|
|
|
|
if (rv)
|
|
error ("NamedColor info verify failed");
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
unsigned int j;
|
|
rv |= strcmp(ro->data[i].root, wo->data[i].root);
|
|
if (rv) error ("NamedColor entry %d root verify failed",i);
|
|
for (j = 0; j < wo->nDeviceCoords; j++) {
|
|
rv |= dcomp(ro->data[i].deviceCoords[j], wo->data[i].deviceCoords[j]);
|
|
if (rv) error ("NamedColor entry %d value %d verify failed: is %f should be %f",
|
|
i,j, ro->data[i].deviceCoords[j], wo->data[i].deviceCoords[j]);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
/* ----------------- */
|
|
/* NamedColor2: */
|
|
{
|
|
static icmNamedColor *wo; /* Shares same machine specific structure */
|
|
if (mode == 0) {
|
|
char *prefix = "Prefix-ix", *suffix = "Suffix-ixix";
|
|
char buf[100];
|
|
unsigned int i;
|
|
|
|
if ((wo = (icmNamedColor *)wr_icco->add_tag(
|
|
wr_icco, icSigNamedColor2Tag, icSigNamedColor2Type)) == NULL)
|
|
return 1;
|
|
|
|
wo->vendorFlag = rand_int(0,65535) << 16; /* Bottom 16 bits for ICC use */
|
|
wo->count = 4; /* Count of named colors */
|
|
wo->nDeviceCoords = icmCSSig2nchan(wr_icco->header->colorSpace);
|
|
/* Num of device coordinates */
|
|
wo->pcount = strlen(prefix) + 1;
|
|
wo->scount = strlen(suffix) + 1;
|
|
|
|
if (wo->allocate(wo)) /* Allocate strings and named color structures */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
strcpy(wo->prefix,"Prefix-ix"); /* Prefix for each color name, max 32, null terminated */
|
|
strcpy(wo->suffix,"Suffix-ixix"); /* Suffix for each color name, max 32, null terminated */
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
sprintf(buf,"Pigment %d",i); /* Root name, max 32, null terminated */
|
|
wo->data[i].rcount = strlen(buf) + 1;
|
|
if (wo->allocate(wo)) /* Allocate root string */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
strcpy(wo->data[i].root,buf);
|
|
rand_Color(wo->data[i].pcsCoords, wr_icco->header->pcs, 16);
|
|
rand_Color(wo->data[i].deviceCoords, wr_icco->header->colorSpace, 16);
|
|
}
|
|
} else {
|
|
icmNamedColor *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmNamedColor *)rd_icco->read_tag(rd_icco, icSigNamedColor2Tag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigNamedColor2Type)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->vendorFlag != wo->vendorFlag);
|
|
rv |= (ro->count != wo->count);
|
|
rv |= (ro->nDeviceCoords != wo->nDeviceCoords);
|
|
rv |= strcmp(ro->prefix, wo->prefix);
|
|
rv |= strcmp(ro->suffix, wo->suffix);
|
|
|
|
if (rv)
|
|
error ("NamedColor2 verify failed");
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
unsigned int j;
|
|
rv |= strcmp(ro->data[i].root, wo->data[i].root);
|
|
for (j = 0; j < wo->nDeviceCoords; j++) {
|
|
rv |= dcomp(ro->data[i].deviceCoords[j], wo->data[i].deviceCoords[j]);
|
|
if (rv) error ("NamedColor2 verify entry %d device value %d failed is %f should be %f",i,j,ro->data[i].deviceCoords[j], wo->data[i].deviceCoords[j]);
|
|
}
|
|
for (j = 0; j < 3; j++) {
|
|
rv |= dcomp(ro->data[i].pcsCoords[j], wo->data[i].pcsCoords[j]);
|
|
if (rv) error ("NamedColor2 verify entry %d pcs value %d failed, is %f should be %f",i,j,ro->data[i].pcsCoords[j], wo->data[i].pcsCoords[j]);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
/* ----------------- */
|
|
/* ProfileSequenceDescTag: */
|
|
{
|
|
|
|
static icmProfileSequenceDesc *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
if ((wo = (icmProfileSequenceDesc *)wr_icco->add_tag(
|
|
wr_icco, icSigProfileSequenceDescTag, icSigProfileSequenceDescType)) == NULL)
|
|
return 1;
|
|
|
|
wo->count = 3; /* Number of descriptions in sequence */
|
|
if (wo->allocate(wo)) /* Allocate space for all the DescStructures */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
/* Fill in each description structure in sequence */
|
|
for (i = 0; i < wo->count; i++) {
|
|
icmTextDescription *wp; /* We're assuming ICCV2 here */
|
|
char *ts1, *ts3;
|
|
icmUTF8 *ts2;
|
|
|
|
wo->data[i].deviceMfg = icmstr2tag("mfg7");
|
|
wo->data[i].deviceModel = icmstr2tag("2345");
|
|
wo->data[i].attributes.l = icTransparency | icMatte;
|
|
wo->data[i].attributes.h = 0x98765432;
|
|
wo->data[i].technology = rand_TechnologySignature();
|
|
|
|
/* device Text description */
|
|
ts1 = rand_ascii_string(9, 81);
|
|
ts2 = rand_utf8_string(8, 111);
|
|
ts3 = rand_ascii_string(7, 67-1);
|
|
|
|
wp = (icmTextDescription *)wo->data[i].mfgDesc;
|
|
wp->count = strlen(ts1)+1;
|
|
wp->allocate(wp); /* Allocate space */
|
|
strcpy(wp->desc, ts1); /* Copy the string in */
|
|
|
|
/* utf-8 */
|
|
wp->ucLangCode = 8765; /* UniCode language code */
|
|
wp->uc8count = strlen((char *)ts2)+1;/* Size in chars inc null */
|
|
wp->allocate(wp); /* Allocate space */
|
|
strcpy((char *)wp->uc8desc, (char *)ts2); /* Copy the string in */
|
|
|
|
/* Script code */
|
|
wp->scCode = 37; /* Fudge scriptCode code */
|
|
wp->scCount = strlen(ts3)+1; /* Used size of scDesc in bytes, inc null */
|
|
wp->allocate(wp); /* Allocate space */
|
|
strcpy((char *)wp->scDesc, ts3); /* Copy the string in */
|
|
|
|
free(ts1);
|
|
free(ts2);
|
|
free(ts3);
|
|
|
|
/* model Text description */
|
|
ts1 = rand_ascii_string(9, 81);
|
|
ts2 = rand_utf8_string(8, 111);
|
|
ts3 = rand_ascii_string(7, 67-1);
|
|
|
|
wp = (icmTextDescription *)wo->data[i].modelDesc;
|
|
wp->count = strlen(ts1)+1;
|
|
wp->allocate(wp); /* Allocate space */
|
|
strcpy(wp->desc, ts1); /* Copy the string in */
|
|
|
|
/* We'll fudge up the Unicode string */
|
|
wp->ucLangCode = 7856; /* UniCode language code */
|
|
wp->uc8count = strlen((char *)ts2)+1; /* Size in chars inc null */
|
|
wp->allocate(wp); /* Allocate space */
|
|
strcpy((char *)wp->uc8desc, (char *)ts2); /* Copy string in */
|
|
|
|
wp->scCode = 67; /* Fudge scriptCode code */
|
|
wp->scCount = strlen(ts3)+1; /* Used size of scDesc in bytes, inc null */
|
|
wp->allocate(wp); /* Allocate space */
|
|
strcpy((char *)wp->scDesc, ts3); /* Copy the string in */
|
|
|
|
free(ts1);
|
|
free(ts2);
|
|
free(ts3);
|
|
}
|
|
} else {
|
|
icmProfileSequenceDesc *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmProfileSequenceDesc *)rd_icco->read_tag(rd_icco, icSigProfileSequenceDescTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigProfileSequenceDescType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->count != wo->count)
|
|
error ("ProfileSequenceDesc count doesn't match");
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
icmTextDescription *wp, *rp; /* We're assuming ICCV2 here */
|
|
|
|
rv |= (ro->data[i].deviceMfg != wo->data[i].deviceMfg);
|
|
rv |= (ro->data[i].deviceModel != wo->data[i].deviceModel);
|
|
rv |= (ro->data[i].attributes.l != wo->data[i].attributes.l);
|
|
rv |= (ro->data[i].attributes.h != wo->data[i].attributes.h);
|
|
rv |= (ro->data[i].technology != wo->data[i].technology);
|
|
|
|
wp = (icmTextDescription *)wo->data[i].mfgDesc;
|
|
rp = (icmTextDescription *)ro->data[i].mfgDesc;
|
|
|
|
rv |= (rp->count != wp->count);
|
|
rv |= strcmp(rp->desc, wp->desc);
|
|
|
|
rv |= (rp->ucLangCode != wp->ucLangCode);
|
|
rv |= (rp->uc8count != wp->uc8count);
|
|
rv |= strcmp((char *)rp->uc8desc, (char *)wp->uc8desc);
|
|
|
|
rv |= (rp->scCode != wp->scCode);
|
|
rv |= (rp->scCount != wp->scCount);
|
|
rv |= strcmp((char *)rp->scDesc, (char *)wp->scDesc);
|
|
|
|
wp = (icmTextDescription *)wo->data[i].modelDesc;
|
|
rp = (icmTextDescription *)ro->data[i].modelDesc;
|
|
|
|
rv |= (rp->count != wp->count);
|
|
rv |= strcmp(rp->desc, wp->desc);
|
|
|
|
rv |= (rp->ucLangCode != wp->ucLangCode);
|
|
rv |= (rp->uc8count != wp->uc8count);
|
|
rv |= strcmp((char *)rp->uc8desc, (char *)wp->uc8desc);
|
|
|
|
rv |= (rp->scCode != wp->scCode);
|
|
rv |= (rp->scCount != wp->scCount);
|
|
rv |= strcmp((char *)rp->scDesc, (char *)wp->scDesc);
|
|
}
|
|
|
|
if (rv)
|
|
error ("ProfileSequenceDesc verify failed");
|
|
}
|
|
}
|
|
/* ----------------- */
|
|
/* ResponseCurveSet16: */
|
|
|
|
if (v3) {
|
|
static icmResponseCurveSet16 *wo;
|
|
unsigned int m, n, q;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
if ((wo = (icmResponseCurveSet16 *)wr_icco->add_tag(
|
|
wr_icco, icSigOutputResponseTag, icSigResponseCurveSet16Type)) == NULL)
|
|
return 1;
|
|
|
|
wo->nchan = rand_int(1, 15); /* Should actually be same as device colorspace */
|
|
wo->typeCount = rand_int(1, 4); /* Number of measurement types. */
|
|
if (wo->allocate(wo)) /* Allocate measurement types array. */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
for (m = 0; m < wo->typeCount; m++) {
|
|
icmRCS16Struct *wp = &wo->typeData[m];
|
|
|
|
wp->measUnit = rand_MeasUnitsSig();
|
|
|
|
for (n = 0; n < wo->nchan; n++)
|
|
wp->nMeas[n] = rand_int(11, 23); /* Number of measurements for each channel */
|
|
if (wo->allocate(wo)) /* Allocate respose arrays */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
/* Fill in response device & measurement values for each channel for these units */
|
|
for (n = 0; n < wo->nchan; n++) {
|
|
|
|
rand_XYZ(&wp->pcsData[n]); /* max. colorant value */
|
|
|
|
for (q = 0; q < wp->nMeas[n]; q++) {
|
|
wp->response[n][q].deviceValue = rand_16f();
|
|
wp->response[n][q].measurement = rand_s15f16();
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
icmResponseCurveSet16 *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmResponseCurveSet16 *)rd_icco->read_tag(rd_icco, icSigOutputResponseTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigResponseCurveSet16Type)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->nchan != wo->nchan)
|
|
error ("ResponseCurveSet16 nchan doesn't match");
|
|
|
|
if (ro->typeCount != wo->typeCount)
|
|
error ("ResponseCurveSet16 typeCount doesn't match");
|
|
|
|
for (m = 0; m < wo->typeCount; m++) {
|
|
icmRCS16Struct *wp = &wo->typeData[m];
|
|
icmRCS16Struct *rp = &ro->typeData[m];
|
|
|
|
if (rp->measUnit != wp->measUnit)
|
|
error ("ResponseCurveSet16 %u measUnit doesn't match",m);
|
|
|
|
for (n = 0; n < wo->nchan; n++) {
|
|
if (wp->nMeas[n] != rp->nMeas[n])
|
|
error ("ResponseCurveSet16 %u,%u nMeas doesn't match",m,n);
|
|
|
|
rv |= dcomp(rp->pcsData[n].X, wp->pcsData[n].X);
|
|
rv |= dcomp(rp->pcsData[n].Y, wp->pcsData[n].Y);
|
|
rv |= dcomp(rp->pcsData[n].Z, wp->pcsData[n].Z);
|
|
if (rv) error ("ResponseCurveSet16 %u,%u pcsData failed",m,n);
|
|
|
|
for (q = 0; q < wp->nMeas[n]; q++) {
|
|
rv |= wp->response[n][q].deviceValue != wp->response[n][q].deviceValue;
|
|
rv |= wp->response[n][q].measurement != wp->response[n][q].measurement;
|
|
if (rv) error ("ResponseCurveSet16 %u,%u,%u response failed",m,n,q);
|
|
}
|
|
}
|
|
}
|
|
if (rv)
|
|
error ("ResponseCurveSet16 verify failed");
|
|
}
|
|
}
|
|
|
|
/* -------------- */
|
|
/* DeviceSettings */
|
|
|
|
if (v3) {
|
|
static icmDeviceSettings *wo;
|
|
if (mode == 0) {
|
|
unsigned int h, i, j, k, m;
|
|
if ((wo = (icmDeviceSettings *)wr_icco->add_tag(
|
|
wr_icco, icSigDeviceSettingsTag, icSigDeviceSettingsType)) == NULL) {
|
|
printf("Add icSigDeviceSettingsType failed\n");
|
|
return 1;
|
|
}
|
|
|
|
wo->count = rand_int(0,7); /* Number of platforms */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (h = 0; h < wo->count; h++) {
|
|
icmPlatformEntry *pep = &wo->data[h];
|
|
|
|
if (rand_int(0,2) != 0)
|
|
pep->platform = icSigMicrosoft; /* Make Msft more common */
|
|
else
|
|
pep->platform = rand_PlatformSignature();
|
|
pep->count = rand_int(0,7); /* Number of setting combinations */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
for (i = 0; i < pep->count; i++) {
|
|
icmSettingComb *scp = &pep->data[i];
|
|
|
|
scp->count = rand_int(0,10); /* Number of settings */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
for (j = 0; j < scp->count; j++) {
|
|
icmSettingStruct *ssp = &scp->data[j];
|
|
|
|
if (pep->platform == icSigMicrosoft) {
|
|
ssp->msft.sig = rand_DevSetMsftIDSignature();
|
|
ssp->count = rand_int(0, 4);
|
|
ssp->ssize = rand_int(0, 4); /* in case sig was unknown */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
|
|
if (icSigMsftResolution == ssp->msft.sig) {
|
|
for (k = 0; k < ssp->count; k++) {
|
|
ssp->msft.resolution[k].xres = rand_int(0, 0xffffffff);
|
|
ssp->msft.resolution[k].yres = rand_int(0, 0xffffffff);
|
|
}
|
|
} else if (icSigMsftMedia == ssp->msft.sig) {
|
|
for (k = 0; k < ssp->count; k++)
|
|
ssp->msft.media[k] = rand_DevSetMsftMedia();
|
|
} else if (icSigMsftHalftone == ssp->msft.sig) {
|
|
for (k = 0; k < ssp->count; k++)
|
|
ssp->msft.halftone[k] = rand_DevSetMsftDither();
|
|
} else {
|
|
for (k = 0; k < ssp->count; k++)
|
|
for (m = 0; m < ssp->ssize; m++)
|
|
ssp->msft.unknown[k * ssp->size + m] = rand_int(0,255);
|
|
}
|
|
} else {
|
|
ssp->unknown.sig = rand_int(0, 0xffffffff);
|
|
ssp->count = rand_int(0, 4);
|
|
ssp->ssize = rand_int(0, 4); /* Because this is unknown */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (k = 0; k < ssp->count; k++)
|
|
for (m = 0; m < ssp->ssize; m++)
|
|
ssp->unknown.unknown[k * ssp->size + m] = rand_int(0,255);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
icmDeviceSettings *ro;
|
|
unsigned int h, i, j, k, m;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmDeviceSettings *)rd_icco->read_tag(rd_icco, icSigDeviceSettingsTag);
|
|
if (ro == NULL) {
|
|
printf("read_tag icSigDeviceSettingsType failed\n");
|
|
return 1;
|
|
}
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigDeviceSettingsType) {
|
|
printf("cast icSigDeviceSettingsType failed\n");
|
|
return 1;
|
|
}
|
|
|
|
if (ro->count != wo->count)
|
|
error("DeviceSettings number of platforms doesn't match");
|
|
|
|
/* Now check it out */
|
|
for (h = 0; h < wo->count; h++) {
|
|
icmPlatformEntry *wpep = &wo->data[h];
|
|
icmPlatformEntry *rpep = &ro->data[h];
|
|
|
|
if (rpep->size != wpep->size)
|
|
error("DeviceSettings platform entry size in bytes doesn't match");
|
|
if (rpep->platform != wpep->platform)
|
|
error("DeviceSettings platform doesn't match");
|
|
if (rpep->count != wpep->count)
|
|
error("DeviceSettings number of setting combinations doesn't match");
|
|
|
|
for (i = 0; i < wpep->count; i++) {
|
|
icmSettingComb *wscp = &wpep->data[i];
|
|
icmSettingComb *rscp = &rpep->data[i];
|
|
|
|
if (rscp->size != wscp->size)
|
|
error("DeviceSettings combination size in bytes doesn't match");
|
|
if (rscp->count != wscp->count)
|
|
error("DeviceSettings number of settings doesn't match");
|
|
|
|
for (j = 0; j < wscp->count; j++) {
|
|
icmSettingStruct *wssp = &wscp->data[j];
|
|
icmSettingStruct *rssp = &rscp->data[j];
|
|
|
|
if (wpep->platform == icSigMicrosoft) {
|
|
if (rssp->msft.sig != wssp->msft.sig)
|
|
error("DeviceSettings Msft setting id doesn't match");
|
|
if (rssp->count != wssp->count)
|
|
error("DeviceSettings Msft setting values count doesn't match");
|
|
if (rssp->size != wssp->size)
|
|
error("DeviceSettings Msft setting values size doesn't match");
|
|
|
|
if (icSigMsftResolution == wssp->msft.sig) {
|
|
for (k = 0; k < wssp->count; k++) {
|
|
if (rssp->msft.resolution[k].xres != wssp->msft.resolution[k].xres)
|
|
error("DeviceSettings Msft X resolution doesn't match");
|
|
if (rssp->msft.resolution[k].yres != wssp->msft.resolution[k].yres)
|
|
error("DeviceSettings Msft Y resolution doesn't match");
|
|
}
|
|
} else if (icSigMsftMedia == wssp->msft.sig) {
|
|
for (k = 0; k < wssp->count; k++)
|
|
if (rssp->msft.media[k] != wssp->msft.media[k])
|
|
error("DeviceSettings Msft media doesn't match");
|
|
} else if (icSigMsftHalftone == wssp->msft.sig) {
|
|
for (k = 0; k < wssp->count; k++)
|
|
if (rssp->msft.halftone[k] != wssp->msft.halftone[k])
|
|
error("DeviceSettings Msft halftone doesn't match");
|
|
} else {
|
|
for (k = 0; k < wssp->count; k++)
|
|
for (m = 0; m < wssp->ssize; m++)
|
|
if (rssp->msft.unknown[k * rssp->size + m]
|
|
!= wssp->msft.unknown[k * wssp->size + m])
|
|
error("DeviceSettings Msft unknown value doesn't match");
|
|
}
|
|
} else {
|
|
if (rssp->unknown.sig != wssp->unknown.sig)
|
|
error("DeviceSettings Unknown setting id doesn't match");
|
|
if (rssp->count != wssp->count)
|
|
error("DeviceSettings Unknown setting values count doesn't match");
|
|
if (rssp->size != wssp->size)
|
|
error("DeviceSettings Unknown setting values size doesn't match");
|
|
|
|
for (k = 0; k < wssp->count; k++)
|
|
for (m = 0; m < wssp->ssize; m++)
|
|
if (rssp->unknown.unknown[k * rssp->size + m]
|
|
!= wssp->unknown.unknown[k * wssp->size + m])
|
|
error("DeviceSettings Unknown unknown value doesn't match");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (rv)
|
|
error("DeviceSettings verify failed");
|
|
}
|
|
}
|
|
|
|
/* ----------------- */
|
|
/* S15Fixed16Array: */
|
|
{
|
|
static icmS15Fixed16Array *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
/* There is no standard Tag that uses icSigS15Fixed16ArrayType, so use a 'custom' tag */
|
|
if ((wo = (icmS15Fixed16Array *)wr_icco->add_tag(
|
|
wr_icco, icmstr2tag("sf32"), icSigS15Fixed16ArrayType)) == NULL)
|
|
return 1;
|
|
|
|
wo->count = rand_int(minc,17); /* Number in array */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->count; i++) {
|
|
wo->data[i] = rand_s15f16(); /* Set numbers value */
|
|
}
|
|
} else {
|
|
icmS15Fixed16Array *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmS15Fixed16Array *)rd_icco->read_tag(rd_icco, icmstr2tag("sf32"));
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigS15Fixed16ArrayType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->count != wo->count)
|
|
error ("S15Fixed16Array size doesn't match");
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
rv |= dcomp(ro->data[i], wo->data[i]);
|
|
}
|
|
|
|
if (rv)
|
|
error ("S15Fixed16Array verify failed");
|
|
}
|
|
}
|
|
/* ----------------- */
|
|
/* Screening: */
|
|
{
|
|
static icmScreening *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
if ((wo = (icmScreening *)wr_icco->add_tag(
|
|
wr_icco, icSigScreeningTag, icSigScreeningType)) == NULL)
|
|
return 1;
|
|
|
|
wo->screeningFlags = rand_ScreenEncodings();
|
|
wo->channels = rand_int(1,4); /* Number of channels */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->channels; i++) {
|
|
wo->data[i].frequency = rand_s15f16(); /* Set screening frequency */
|
|
wo->data[i].angle = rand_s15f16(); /* Set screening angle */
|
|
wo->data[i].spotShape = rand_SpotShape(); /* Set spot shape */
|
|
}
|
|
} else {
|
|
icmScreening *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmScreening *)rd_icco->read_tag(rd_icco, icSigScreeningTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigScreeningType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->channels != wo->channels)
|
|
error ("Screening channels doesn't match");
|
|
|
|
rv |= (ro->screeningFlags != wo->screeningFlags);
|
|
|
|
for (i = 0; i < wo->channels; i++) {
|
|
rv |= dcomp(ro->data[i].frequency, wo->data[i].frequency);
|
|
rv |= dcomp(ro->data[i].angle, wo->data[i].angle);
|
|
rv |= (ro->data[i].spotShape != wo->data[i].spotShape);
|
|
}
|
|
|
|
if (rv)
|
|
error ("Screening verify failed");
|
|
}
|
|
}
|
|
/* ----------------- */
|
|
/* Signature: */
|
|
{
|
|
static icmSignature *wo;
|
|
if (mode == 0) {
|
|
if ((wo = (icmSignature *)wr_icco->add_tag(
|
|
wr_icco, icSigTechnologyTag, icSigSignatureType)) == NULL)
|
|
return 1;
|
|
|
|
wo->sig = rand_TechnologySignature();
|
|
} else {
|
|
icmSignature *ro;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmSignature *)rd_icco->read_tag(rd_icco, icSigTechnologyTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigSignatureType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->sig != wo->sig);
|
|
|
|
if (rv)
|
|
error ("Signature verify failed");
|
|
}
|
|
}
|
|
/* ----------------- */
|
|
/* Text Description: */
|
|
{
|
|
static icmTextDescription *wo;
|
|
|
|
if (mode == 0) {
|
|
char *ts1, *ts3;
|
|
icmUTF8 *ts2;
|
|
|
|
if ((wo = (icmTextDescription *)wr_icco->add_tag(
|
|
wr_icco, icSigProfileDescriptionTag, icSigTextDescriptionType)) == NULL)
|
|
return 1;
|
|
|
|
/* Create the test messages */
|
|
ts1 = rand_ascii_string(10, 90);
|
|
ts2 = rand_utf8_string(3, 131);
|
|
ts3 = rand_ascii_string(5, 67-1);
|
|
|
|
/* Data in tag type wojects is always allocated and freed by the woject */
|
|
wo->count = strlen(ts1)+1; /* Allocated and used size of desc, inc null */
|
|
if (wo->allocate(wo))/* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
strcpy(wo->desc, ts1); /* Copy the string in */
|
|
|
|
/* We can treat utf-8 just like an ascii string */
|
|
wo->ucLangCode = 1234; /* UniCode language code */
|
|
wo->uc8count = strlen((char *)ts2)+1; /* Allocated and used size of desc, inc null */
|
|
if (wo->allocate(wo))/* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
strcpy((char *)wo->uc8desc, (char *)ts2); /* Copy the string in */
|
|
|
|
/* Don't really know anything about scriptCode, but fudge some values */
|
|
wo->scCode = 23; /* ScriptCode code */
|
|
wo->scCount = strlen(ts3)+1; /* Used size of scDesc in bytes, inc null */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
if (wo->scCount > 67)
|
|
error("textDescription ScriptCode string longer than 67 (%d)",wo->scCount);
|
|
strcpy((char *)wo->scDesc, ts3); /* Copy the string in */
|
|
|
|
free(ts1);
|
|
free(ts2);
|
|
free(ts3);
|
|
|
|
} else {
|
|
icmTextDescription *ro;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmTextDescription *)rd_icco->read_tag(rd_icco, icSigProfileDescriptionTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
/* We could have left it icmBase, switched on ro->ttype, & then cast appropriately. */
|
|
if (ro->ttype != icSigTextDescriptionType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->count != wo->count);
|
|
rv |= strcmp(ro->desc, wo->desc);
|
|
rv |= (ro->ucLangCode != wo->ucLangCode);
|
|
rv |= (ro->uc8count != wo->uc8count);
|
|
rv |= strcmp((char *)ro->uc8desc, (char *)wo->uc8desc);
|
|
rv |= (ro->scCode != wo->scCode);
|
|
rv |= (ro->scCount != wo->scCount);
|
|
rv |= strcmp((char *)ro->scDesc, (char *)wo->scDesc);
|
|
|
|
if (rv)
|
|
error ("Text Description verify failed");
|
|
}
|
|
}
|
|
/* ----- */
|
|
/* Text: */
|
|
{
|
|
static icmText *wo;
|
|
char *ts1 = "This is Copyright by me!";
|
|
if (mode == 0) {
|
|
if ((wo = (icmText *)wr_icco->add_tag(
|
|
wr_icco, icSigCopyrightTag, icSigTextType)) == NULL)
|
|
return 1;
|
|
|
|
wo->count = strlen(ts1)+1; /* Allocated and used size of text, inc null */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
strcpy(wo->desc, ts1); /* Copy the text in */
|
|
} else {
|
|
icmText *ro;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmText *)rd_icco->read_tag(rd_icco, icSigCopyrightTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigTextType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->count != wo->count)
|
|
error ("Text size doesn't match");
|
|
|
|
rv |= strcmp(ro->desc, wo->desc);
|
|
|
|
if (rv)
|
|
error ("Text verify failed");
|
|
}
|
|
}
|
|
/* ---------------- */
|
|
/* U16Fixed16Array: */
|
|
{
|
|
static icmU16Fixed16Array *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
/* There is no standard Tag that uses icSigU16Fixed16ArrayType, so use a 'custom' tag */
|
|
if ((wo = (icmU16Fixed16Array *)wr_icco->add_tag(
|
|
wr_icco, icmstr2tag("uf32"), icSigU16Fixed16ArrayType)) == NULL)
|
|
return 1;
|
|
|
|
wo->count = rand_int(minc,17); /* Number in array */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->count; i++) {
|
|
wo->data[i] = rand_u16f16(); /* Set numbers value */
|
|
}
|
|
} else {
|
|
icmU16Fixed16Array *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmU16Fixed16Array *)rd_icco->read_tag(rd_icco, icmstr2tag("uf32"));
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigU16Fixed16ArrayType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->count != wo->count)
|
|
error ("U16Fixed16Array size doesn't match");
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
rv |= dcomp(ro->data[i], wo->data[i]);
|
|
}
|
|
|
|
if (rv)
|
|
error ("U16Fixed16Array verify failed");
|
|
}
|
|
}
|
|
/* ------------------- */
|
|
/* UcrBg - full curve: */
|
|
{
|
|
static icmUcrBg *wo;
|
|
char *ts1 = "UcrBg - full curve info";
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
if ((wo = (icmUcrBg *)wr_icco->add_tag(
|
|
wr_icco, icSigUcrBgTag, icSigUcrBgType)) == NULL)
|
|
return 1;
|
|
|
|
wo->UCRcount = rand_int(2,55); /* Number in UCR curve */
|
|
wo->BGcount = rand_int(2,32); /* Number in BG array */
|
|
if (wo->allocate(wo)) /* Allocate space for both curves */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->UCRcount; i++)
|
|
wo->UCRcurve[i] = rand_16f(); /* Set numbers value */
|
|
for (i = 0; i < wo->BGcount; i++)
|
|
wo->BGcurve[i] = rand_16f(); /* Set numbers value */
|
|
wo->count = strlen(ts1)+1; /* Allocated and used size of text, inc null */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
strcpy(wo->string, ts1); /* Copy the text in */
|
|
} else {
|
|
icmUcrBg *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmUcrBg *)rd_icco->read_tag(rd_icco, icSigUcrBgTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigUcrBgType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->UCRcount != wo->UCRcount)
|
|
error ("UcrBg UCRcount doesn't match");
|
|
|
|
if (ro->BGcount != wo->BGcount)
|
|
error ("UcrBg BGcount doesn't match");
|
|
|
|
for (i = 0; i < wo->UCRcount; i++)
|
|
rv |= dcomp(ro->UCRcurve[i], wo->UCRcurve[i]);
|
|
|
|
for (i = 0; i < wo->BGcount; i++)
|
|
rv |= dcomp(ro->BGcurve[i], wo->BGcurve[i]);
|
|
|
|
if (ro->count != wo->count)
|
|
error ("Text size doesn't match");
|
|
|
|
rv |= strcmp(ro->string, wo->string);
|
|
|
|
if (rv)
|
|
error ("UcrBg verify failed");
|
|
}
|
|
}
|
|
/* ------------------- */
|
|
/* UcrBg - percentage: */
|
|
{
|
|
static icmUcrBg *wo;
|
|
char *ts1 = "UcrBg - percentage info";
|
|
if (mode == 0) {
|
|
if ((wo = (icmUcrBg *)wr_icco->add_tag(
|
|
wr_icco, icmstr2tag("bfd%"), icSigUcrBgType)) == NULL)
|
|
return 1;
|
|
|
|
wo->UCRcount = 1; /* 1 == UCR percentage */
|
|
wo->BGcount = 1; /* 1 == BG percentage */
|
|
if (wo->allocate(wo))/* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
wo->UCRcurve[0] = (double) rand_int(0,65535);
|
|
wo->BGcurve[0] = (double) rand_int(0,65535);
|
|
wo->count = strlen(ts1)+1; /* Allocated and used size of text, inc null */
|
|
if (wo->allocate(wo))/* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
strcpy(wo->string, ts1); /* Copy the text in */
|
|
} else {
|
|
icmUcrBg *ro;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmUcrBg *)rd_icco->read_tag(rd_icco, icmstr2tag("bfd%"));
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigUcrBgType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->UCRcount != wo->UCRcount)
|
|
error ("UcrBg UCRcount doesn't match");
|
|
|
|
if (ro->BGcount != wo->BGcount)
|
|
error ("UcrBg BGcount doesn't match");
|
|
|
|
rv |= (ro->UCRcurve[0] != wo->UCRcurve[0]);
|
|
rv |= (ro->BGcurve[0] != wo->BGcurve[0]);
|
|
|
|
if (ro->count != wo->count)
|
|
error ("Text size doesn't match");
|
|
|
|
rv |= strcmp(ro->string, wo->string);
|
|
|
|
if (rv)
|
|
error ("UcrBg verify failed");
|
|
}
|
|
}
|
|
/* ------------ */
|
|
/* UInt16Array: */
|
|
{
|
|
static icmUInt16Array *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
/* There is no standard Tag that uses icSigUInt16ArrayType, so use a 'custom' tag */
|
|
if ((wo = (icmUInt16Array *)wr_icco->add_tag(
|
|
wr_icco, icmstr2tag("ui16"), icSigUInt16ArrayType)) == NULL)
|
|
return 1;
|
|
|
|
if (v3)
|
|
wo->count = rand_int(1,17); /* Number in array */
|
|
else
|
|
wo->count = rand_int(minc,17); /* Number in array */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->count; i++) {
|
|
wo->data[i] = rand_o16(); /* Set numbers value */
|
|
}
|
|
} else {
|
|
icmUInt16Array *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmUInt16Array *)rd_icco->read_tag(rd_icco, icmstr2tag("ui16"));
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigUInt16ArrayType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->count != wo->count)
|
|
error ("UInt16Array size doesn't match");
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
rv |= (ro->data[i] != wo->data[i]);
|
|
}
|
|
|
|
if (rv)
|
|
error ("UInt16Array verify failed");
|
|
}
|
|
}
|
|
/* ------------ */
|
|
/* UInt32Array: */
|
|
{
|
|
static icmUInt32Array *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
/* There is no standard Tag that uses icSigUInt32ArrayType, so use a 'custom' tag */
|
|
if ((wo = (icmUInt32Array *)wr_icco->add_tag(
|
|
wr_icco, icmstr2tag("ui32"), icSigUInt32ArrayType)) == NULL)
|
|
return 1;
|
|
|
|
if (v3)
|
|
wo->count = rand_int(1,18); /* Number in array */
|
|
else
|
|
wo->count = rand_int(minc,18); /* Number in array */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->count; i++) {
|
|
wo->data[i] = rand_o32(); /* Set numbers value */
|
|
}
|
|
} else {
|
|
icmUInt32Array *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmUInt32Array *)rd_icco->read_tag(rd_icco, icmstr2tag("ui32"));
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigUInt32ArrayType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->count != wo->count)
|
|
error ("UInt32Array size doesn't match");
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
rv |= (ro->data[i] != wo->data[i]);
|
|
}
|
|
|
|
if (rv)
|
|
error ("UInt32Array verify failed");
|
|
}
|
|
}
|
|
/* ------------ */
|
|
/* UInt64Array: */
|
|
{
|
|
static icmUInt64Array *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
/* There is no standard Tag that uses icSigUInt64ArrayType, so use a 'custom' tag */
|
|
if ((wo = (icmUInt64Array *)wr_icco->add_tag(
|
|
wr_icco, icmstr2tag("ui64"), icSigUInt64ArrayType)) == NULL)
|
|
return 1;
|
|
|
|
wo->count = rand_int(minc,19); /* Number in array */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->count; i++) {
|
|
wo->data[i].l = rand_o32(); /* Set numbers value - low 32 bits */
|
|
wo->data[i].h = rand_o32(); /* Set numbers value - low 32 bits */
|
|
}
|
|
} else {
|
|
icmUInt64Array *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmUInt64Array *)rd_icco->read_tag(rd_icco, icmstr2tag("ui64"));
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigUInt64ArrayType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->count != wo->count)
|
|
error ("UInt64Array size doesn't match");
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
rv |= (ro->data[i].l != wo->data[i].l);
|
|
rv |= (ro->data[i].h != wo->data[i].h);
|
|
}
|
|
|
|
if (rv)
|
|
error ("UInt64Array verify failed");
|
|
}
|
|
}
|
|
/* ----------- */
|
|
/* UInt8Array: */
|
|
{
|
|
static icmUInt8Array *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
/* There is no standard Tag that uses icSigUInt8ArrayType, so use a 'custom' tag */
|
|
if ((wo = (icmUInt8Array *)wr_icco->add_tag(
|
|
wr_icco, icmstr2tag("ui08"), icSigUInt8ArrayType)) == NULL)
|
|
return 1;
|
|
|
|
wo->count = rand_int(minc,18); /* Number in array */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->count; i++) {
|
|
wo->data[i] = rand_o8(); /* Set numbers value */
|
|
}
|
|
} else {
|
|
icmUInt8Array *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmUInt8Array *)rd_icco->read_tag(rd_icco, icmstr2tag("ui08"));
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigUInt8ArrayType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->count != wo->count)
|
|
error ("UInt8Array size doesn't match");
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
rv |= (ro->data[i] != wo->data[i]);
|
|
}
|
|
|
|
if (rv)
|
|
error ("UInt8Array verify failed");
|
|
}
|
|
}
|
|
/* --------------- */
|
|
/* VideoCardGamma - curves: (ColorSync specific) */
|
|
{
|
|
static icmVideoCardGamma *wo;
|
|
if (mode == 0) {
|
|
unsigned int c, i;
|
|
if ((wo = (icmVideoCardGamma *)wr_icco->add_tag(
|
|
wr_icco, icSigVideoCardGammaTag, icSigVideoCardGammaType)) == NULL)
|
|
return 1;
|
|
|
|
wo->tagType = icVideoCardGammaTable;
|
|
wo->u.table.channels = rand_int(1,3);
|
|
wo->u.table.entryCount = rand_int(2,1024);
|
|
wo->u.table.entrySize = rand_int(1,2);
|
|
if (wo->allocate(wo))
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
if (wo->u.table.entrySize == 1) {
|
|
for (c = 0; c < wo->u.table.channels; c++)
|
|
for (i = 0; i < wo->u.table.entryCount; i++)
|
|
wo->u.table.data[c][i] = rand_8f();
|
|
} else {
|
|
for (c = 0; c < wo->u.table.channels; c++)
|
|
for (i = 0; i < wo->u.table.entryCount; i++)
|
|
wo->u.table.data[c][i] = rand_16f();
|
|
}
|
|
} else {
|
|
icmVideoCardGamma *ro;
|
|
unsigned int c, i;
|
|
|
|
/* Try and read tag from the file */
|
|
ro = (icmVideoCardGamma *)rd_icco->read_tag(rd_icco, icSigVideoCardGammaTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate */
|
|
if (ro->ttype != icSigVideoCardGammaType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->tagType != wo->tagType);
|
|
if (rv) error ("VideoCardGamma table verify tagtype failed");
|
|
rv |= (ro->u.table.channels != wo->u.table.channels);
|
|
rv |= (ro->u.table.entryCount != wo->u.table.entryCount);
|
|
rv |= (ro->u.table.entrySize != wo->u.table.entrySize);
|
|
|
|
for (c = 0; c < wo->u.table.channels; c++) {
|
|
for (i = 0; i < wo->u.table.entryCount; i++) {
|
|
rv |= dcomp(ro->u.table.data[c][i], wo->u.table.data[c][i]);
|
|
if (rv) break;
|
|
}
|
|
}
|
|
if (rv)
|
|
error ("VideoCardGamma table verify failed");
|
|
}
|
|
}
|
|
/* --------------- */
|
|
/* VideoCardGamma - formula: (ColorSync specific) */
|
|
if (v3) {
|
|
static icmVideoCardGamma *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
if ((wo = (icmVideoCardGamma *)wr_icco->add_tag(
|
|
wr_icco, icmstr2tag("vcgf"), icSigVideoCardGammaType)) == NULL)
|
|
return 1;
|
|
|
|
wo->tagType = icVideoCardGammaFormula;
|
|
for (i = 0; i < 3; i++) {
|
|
wo->u.formula.gamma[i] = rand_s15f16();
|
|
wo->u.formula.min[i] = rand_s15f16();
|
|
wo->u.formula.max[i] = rand_s15f16();
|
|
}
|
|
} else {
|
|
icmVideoCardGamma *ro;
|
|
unsigned int c, i;
|
|
|
|
/* Try and read tag from the file */
|
|
ro = (icmVideoCardGamma *)rd_icco->read_tag(rd_icco, icmstr2tag("vcgf"));
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate */
|
|
if (ro->ttype != icSigVideoCardGammaType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= (ro->tagType != wo->tagType);
|
|
if (rv) error ("VideoCardGamma formula verify tagtype failed");
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
rv |= dcomp(ro->u.formula.gamma[i], wo->u.formula.gamma[i]);
|
|
rv |= dcomp(ro->u.formula.min[i], wo->u.formula.min[i]);
|
|
rv |= dcomp(ro->u.formula.max[i], wo->u.formula.max[i]);
|
|
if (rv) break;
|
|
}
|
|
if (rv)
|
|
error ("VideoCardGamma formula verify failed");
|
|
}
|
|
}
|
|
|
|
/* ------------------ */
|
|
/* ViewingConditions: */
|
|
{
|
|
static icmViewingConditions *wo;
|
|
if (mode == 0) {
|
|
if ((wo = (icmViewingConditions *)wr_icco->add_tag(
|
|
wr_icco, icSigViewingConditionsTag, icSigViewingConditionsType)) == NULL)
|
|
return 1;
|
|
|
|
wo->illuminant.X = rand_XYZ16(); /* XYZ of illuminant in cd/m^2 */
|
|
wo->illuminant.Y = rand_XYZ16();
|
|
wo->illuminant.Z = rand_XYZ16();
|
|
wo->surround.X = rand_XYZ16(); /* XYZ of surround in cd/m^2 */
|
|
wo->surround.Y = rand_XYZ16();
|
|
wo->surround.Z = rand_XYZ16();
|
|
wo->stdIlluminant = rand_Illuminant(); /* Standard illuminent type */
|
|
} else {
|
|
icmViewingConditions *ro;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmViewingConditions *)rd_icco->read_tag(rd_icco, icSigViewingConditionsTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigViewingConditionsType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
rv |= dcomp(ro->illuminant.X, wo->illuminant.X);
|
|
rv |= dcomp(ro->illuminant.Y, wo->illuminant.Y);
|
|
rv |= dcomp(ro->illuminant.Z, wo->illuminant.Z);
|
|
rv |= dcomp(ro->surround.X , wo->surround.X);
|
|
rv |= dcomp(ro->surround.Y , wo->surround.Y);
|
|
rv |= dcomp(ro->surround.Z , wo->surround.Z);
|
|
rv |= (ro->stdIlluminant != wo->stdIlluminant);
|
|
|
|
if (rv)
|
|
error ("ViewingConditions verify failed");
|
|
}
|
|
}
|
|
/* ---------- */
|
|
/* XYZ array: */
|
|
{
|
|
static icmXYZArray *wo;
|
|
if (mode == 0) {
|
|
unsigned int i;
|
|
/* Note that tag types icSigXYZType and icSigXYZArrayType are identical */
|
|
if ((wo = (icmXYZArray *)wr_icco->add_tag(
|
|
wr_icco, icSigMediaWhitePointTag, icSigXYZArrayType)) == NULL)
|
|
return 1;
|
|
|
|
wo->count = rand_int(1,7); /* Should be one XYZ number, but test more */
|
|
if (wo->allocate(wo)) /* Allocate space */
|
|
error ("allocate: 0x%x '%s'",wr_icco->e.c,wr_icco->e.m);
|
|
for (i = 0; i < wo->count; i++) {
|
|
wo->data[i].X = rand_XYZ16(); /* Set numbers value */
|
|
wo->data[i].Y = rand_XYZ16();
|
|
wo->data[i].Z = rand_XYZ16();
|
|
}
|
|
} else {
|
|
icmXYZArray *ro;
|
|
unsigned int i;
|
|
|
|
/* Try and read the tag from the file */
|
|
ro = (icmXYZArray *)rd_icco->read_tag(rd_icco, icSigMediaWhitePointTag);
|
|
if (ro == NULL)
|
|
return 1;
|
|
|
|
/* Need to check that the cast is appropriate. */
|
|
if (ro->ttype != icSigXYZArrayType)
|
|
return 1;
|
|
|
|
/* Now check it out */
|
|
if (ro->count != wo->count)
|
|
error ("XYZArray size doesn't match");
|
|
|
|
for (i = 0; i < wo->count; i++) {
|
|
rv |= dcomp(ro->data[i].X, wo->data[i].X);
|
|
rv |= dcomp(ro->data[i].Y, wo->data[i].Y);
|
|
rv |= dcomp(ro->data[i].Z, wo->data[i].Z);
|
|
}
|
|
|
|
if (rv)
|
|
error ("XYZArray verify failed");
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* ------------------------------------------------ */
|
|
/* Floating point random number generators */
|
|
/* These are appropriate for the underlying integer */
|
|
/* representations in the icc format. */
|
|
/* This is simply as a convenience so that we can */
|
|
/* test the full range of representation, and */
|
|
/* get away with exact verification. */
|
|
|
|
/* 32 bit pseudo random sequencer */
|
|
static unsigned int seed = 0x12345678;
|
|
|
|
#define PSRAND(S) ((S) * 1103515245 + 12345)
|
|
|
|
void set_seed(ORD32 o32) {
|
|
if (o32 == 0)
|
|
o32 = 1;
|
|
seed = o32;
|
|
}
|
|
|
|
unsigned int rand_o8() {
|
|
ORD32 o32;
|
|
seed = PSRAND(seed);
|
|
o32 = seed & 0xff;
|
|
return o32;
|
|
}
|
|
|
|
unsigned int rand_o16() {
|
|
ORD32 o32;
|
|
seed = PSRAND(seed);
|
|
o32 = seed & 0xffff;
|
|
return o32;
|
|
}
|
|
|
|
unsigned int rand_o32() {
|
|
ORD32 o32;
|
|
o32 = seed = PSRAND(seed);
|
|
return o32;
|
|
}
|
|
|
|
unsigned int rand_int(unsigned int low, unsigned int high) {
|
|
unsigned int m, i;
|
|
seed = PSRAND(seed);
|
|
m = high - low + 1;
|
|
if (m != 0)
|
|
i = seed % (high - low + 1);
|
|
else
|
|
i = seed;
|
|
return i + low;
|
|
}
|
|
|
|
double rand_u8f8() {
|
|
ORD32 o32;
|
|
seed = PSRAND(seed);
|
|
o32 = seed & 0xffff;
|
|
return (double)o32/256.0;
|
|
}
|
|
|
|
double rand_u16f16() {
|
|
ORD32 o32;
|
|
seed = PSRAND(seed);
|
|
o32 = seed;
|
|
return (double)o32/65536.0;
|
|
}
|
|
|
|
double rand_s15f16() {
|
|
INR32 i32;
|
|
seed = PSRAND(seed);
|
|
i32 = seed;
|
|
return (double)i32/65536.0;
|
|
}
|
|
|
|
/* This really isn't a thing - but will pop up with our random combo's */
|
|
double rand_XYZ8() {
|
|
ORD32 o32;
|
|
seed = PSRAND(seed);
|
|
o32 = seed & 0xff;
|
|
return (double)o32/128.0;
|
|
}
|
|
|
|
double rand_XYZ16() {
|
|
ORD32 o32;
|
|
seed = PSRAND(seed);
|
|
o32 = seed & 0xffff;
|
|
return (double)o32/32768.0;
|
|
}
|
|
|
|
double rand_L8() {
|
|
ORD32 o32;
|
|
seed = PSRAND(seed);
|
|
o32 = seed & 0xff;
|
|
return (double)o32/2.550;
|
|
}
|
|
|
|
double rand_ab8() {
|
|
ORD32 o32;
|
|
seed = PSRAND(seed);
|
|
o32 = seed & 0xff;
|
|
return (double)o32-128.0;
|
|
}
|
|
|
|
double rand_L16() {
|
|
ORD32 o32;
|
|
seed = PSRAND(seed);
|
|
o32 = seed & 0xffff;
|
|
return (double)o32/652.800; /* 0xff00/100.0 */
|
|
}
|
|
|
|
double rand_ab16() {
|
|
ORD32 o32;
|
|
seed = PSRAND(seed);
|
|
o32 = seed & 0xffff;
|
|
return ((double)o32/256.0)-128.0;
|
|
}
|
|
|
|
double rand_8f() {
|
|
unsigned int rv;
|
|
seed = PSRAND(seed);
|
|
rv = seed & 0xff;
|
|
return (double)rv/255.0;
|
|
}
|
|
|
|
double rand_16f() {
|
|
unsigned int rv;
|
|
seed = PSRAND(seed);
|
|
rv = seed & 0xffff;
|
|
return (double)rv/65535.0;
|
|
}
|
|
|
|
/* Generate float between 0.0 and 1.0 */
|
|
double rand_32f() {
|
|
ORD32 sn = 0, ep = 0, ma;
|
|
double op;
|
|
seed = PSRAND(seed);
|
|
|
|
//sn = (seed >> 31) & 0x1; /* Sign */
|
|
sn = 0;
|
|
//ep = (seed >> 23) & 0xff; /* Exponent */
|
|
ep = 126;
|
|
ma = seed & 0x7fffff; /* Mantissa */
|
|
if (ma == 0)
|
|
ep = 0;
|
|
|
|
if (ep == 0) { /* Zero or denormalised */
|
|
op = (double)ma/(double)(1 << 23);
|
|
op *= pow(2.0, (-126.0));
|
|
} else {
|
|
op = (double)(ma | (1 << 23))/(double)(1 << 23);
|
|
op *= pow(2.0, (((int)ep)-127.0));
|
|
}
|
|
if (sn)
|
|
op = -op;
|
|
return op;
|
|
}
|
|
|
|
double rand_rangef(double min, double max, int bits) {
|
|
if (bits == 8)
|
|
return rand_8f() * (max - min) + min;
|
|
else
|
|
return rand_16f() * (max - min) + min;
|
|
}
|
|
|
|
/* bits = 8 or 16 */
|
|
void rand_Color(double *vals, icColorSpaceSignature sig, int bits) {
|
|
int i, nchan = icmCSSig2nchan(sig);
|
|
|
|
switch ((int)sig) {
|
|
case icSigXYZData:
|
|
if (bits == 8) {
|
|
vals[0] = rand_XYZ8();
|
|
vals[1] = rand_XYZ8();
|
|
vals[2] = rand_XYZ8();
|
|
} else {
|
|
vals[0] = rand_XYZ16();
|
|
vals[1] = rand_XYZ16();
|
|
vals[2] = rand_XYZ16();
|
|
}
|
|
break;
|
|
case icSigLabData:
|
|
if (bits == 8) {
|
|
vals[0] = rand_L8();
|
|
vals[1] = rand_ab8();
|
|
vals[2] = rand_ab8();
|
|
} else {
|
|
vals[0] = rand_L16();
|
|
vals[1] = rand_ab16();
|
|
vals[2] = rand_ab16();
|
|
}
|
|
break;
|
|
/* Undefined device spaces */
|
|
/* These aren't actually specified by ICC, so we punt. */
|
|
case icSigLuvData:
|
|
vals[0] = rand_rangef(0.0, 100.0, bits);
|
|
vals[1] = rand_rangef(-128, 127.0 + 255.0/256.0, bits);
|
|
vals[2] = rand_rangef(-128, 127.0 + 255.0/256.0, bits);
|
|
break;
|
|
case icSigYCbCrData:
|
|
vals[0] = rand_rangef(0.0, 1.0, bits);
|
|
vals[1] = rand_rangef(-0.5, 0.5, bits);
|
|
vals[2] = rand_rangef(-0.5, 0.5, bits);
|
|
break;
|
|
case icSigYxyData:
|
|
vals[0] = rand_rangef(0.0, 1.0, bits);
|
|
vals[1] = rand_rangef(0.0, 1.0, bits);
|
|
vals[2] = rand_rangef(0.0, 1.0, bits);
|
|
break;
|
|
/* By default assume a device 0..1 */
|
|
default:
|
|
if (bits == 8) {
|
|
for (i = 0; i < nchan; i++)
|
|
vals[i] = rand_8f();
|
|
} else {
|
|
for (i = 0; i < nchan; i++)
|
|
vals[i] = rand_16f();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Random selectors for ICC flags and enumerayions */
|
|
|
|
icScreening rand_ScreenEncodings() {
|
|
icScreening flags = 0;
|
|
|
|
if (rand_int(0,1) == 0)
|
|
flags |= icPrtrDefaultScreensTrue;
|
|
|
|
if (rand_int(0,1) == 0)
|
|
flags |= icLinesPerInch;
|
|
|
|
return flags;
|
|
}
|
|
|
|
/* Device attributes */
|
|
unsigned int rand_DeviceAttributes() {
|
|
unsigned int flags = 0;
|
|
|
|
if (rand_int(0,1) == 0)
|
|
flags |= icTransparency;
|
|
|
|
if (rand_int(0,1) == 0)
|
|
flags |= icMatte;
|
|
|
|
return flags;
|
|
}
|
|
|
|
/* Profile header flags */
|
|
unsigned int rand_ProfileHeaderFlags() {
|
|
unsigned int flags = 0;
|
|
|
|
if (rand_int(0,1) == 0)
|
|
flags |= icEmbeddedProfileTrue;
|
|
|
|
if (rand_int(0,1) == 0)
|
|
flags |= icUseWithEmbeddedDataOnly;
|
|
|
|
return flags;
|
|
}
|
|
|
|
|
|
unsigned int rand_AsciiOrBinaryData() {
|
|
unsigned int flags = 0;
|
|
|
|
if (rand_int(0,1) == 0)
|
|
flags |= icBinaryData;
|
|
|
|
return flags;
|
|
}
|
|
|
|
void rand_XYZ(icmXYZNumber *pXYZ) {
|
|
pXYZ->X = rand_XYZ16();
|
|
pXYZ->Y = rand_XYZ16();
|
|
pXYZ->Z = rand_XYZ16();
|
|
}
|
|
|
|
icColorSpaceSignature rand_ColorSpaceSignature() {
|
|
switch(rand_int(0,25)) {
|
|
case 0:
|
|
return icSigXYZData;
|
|
case 1:
|
|
return icSigLabData;
|
|
case 2:
|
|
return icSigLuvData;
|
|
case 3:
|
|
return icSigYCbCrData;
|
|
case 4:
|
|
return icSigYxyData;
|
|
case 5:
|
|
return icSigRgbData;
|
|
case 6:
|
|
return icSigGrayData;
|
|
case 7:
|
|
return icSigHsvData;
|
|
case 8:
|
|
return icSigHlsData;
|
|
case 9:
|
|
return icSigCmykData;
|
|
case 10:
|
|
return icSigCmyData;
|
|
case 11:
|
|
return icSigMch6Data;
|
|
case 12:
|
|
return icSig2colorData;
|
|
case 13:
|
|
return icSig3colorData;
|
|
case 14:
|
|
return icSig4colorData;
|
|
case 15:
|
|
return icSig5colorData;
|
|
case 16:
|
|
return icSig6colorData;
|
|
case 17:
|
|
return icSig7colorData;
|
|
case 18:
|
|
return icSig8colorData;
|
|
case 19:
|
|
return icSig9colorData;
|
|
case 20:
|
|
return icSig10colorData;
|
|
case 21:
|
|
return icSig11colorData;
|
|
case 22:
|
|
return icSig12colorData;
|
|
case 23:
|
|
return icSig13colorData;
|
|
case 24:
|
|
return icSig14colorData;
|
|
case 25:
|
|
return icSig15colorData;
|
|
}
|
|
return icMaxEnumColorSpace;
|
|
}
|
|
|
|
icColorSpaceSignature rand_PCS() {
|
|
switch(rand_int(0,1)) {
|
|
case 0:
|
|
return icSigXYZData;
|
|
case 1:
|
|
return icSigLabData;
|
|
}
|
|
return icMaxEnumColorSpace;
|
|
}
|
|
|
|
icTechnologySignature rand_TechnologySignature() {
|
|
switch(rand_int(0,21)) {
|
|
case 0:
|
|
return icSigDigitalCamera;
|
|
case 1:
|
|
return icSigFilmScanner;
|
|
case 2:
|
|
return icSigReflectiveScanner;
|
|
case 3:
|
|
return icSigInkJetPrinter;
|
|
case 4:
|
|
return icSigThermalWaxPrinter;
|
|
case 5:
|
|
return icSigElectrophotographicPrinter;
|
|
case 6:
|
|
return icSigElectrostaticPrinter;
|
|
case 7:
|
|
return icSigDyeSublimationPrinter;
|
|
case 8:
|
|
return icSigPhotographicPaperPrinter;
|
|
case 9:
|
|
return icSigFilmWriter;
|
|
case 10:
|
|
return icSigVideoMonitor;
|
|
case 11:
|
|
return icSigVideoCamera;
|
|
case 12:
|
|
return icSigProjectionTelevision;
|
|
case 13:
|
|
return icSigCRTDisplay;
|
|
case 14:
|
|
return icSigPMDisplay;
|
|
case 15:
|
|
return icSigAMDisplay;
|
|
case 16:
|
|
return icSigPhotoCD;
|
|
case 17:
|
|
return icSigPhotoImageSetter;
|
|
case 18:
|
|
return icSigGravure;
|
|
case 19:
|
|
return icSigOffsetLithography;
|
|
case 20:
|
|
return icSigSilkscreen;
|
|
case 21:
|
|
return icSigFlexography;
|
|
}
|
|
return icMaxEnumTechnology;
|
|
}
|
|
|
|
icProfileClassSignature rand_ProfileClassSignature() {
|
|
switch(rand_int(0,6)) {
|
|
case 0:
|
|
return icSigInputClass;
|
|
case 1:
|
|
return icSigDisplayClass;
|
|
case 2:
|
|
return icSigOutputClass;
|
|
case 3:
|
|
return icSigLinkClass;
|
|
case 4:
|
|
return icSigAbstractClass;
|
|
case 5:
|
|
return icSigColorSpaceClass;
|
|
case 6:
|
|
return icSigNamedColorClass;
|
|
}
|
|
return icMaxEnumClass;
|
|
}
|
|
|
|
icPlatformSignature rand_PlatformSignature() {
|
|
switch(rand_int(0,4)) {
|
|
case 0:
|
|
return icSigMacintosh;
|
|
case 1:
|
|
return icSigMicrosoft;
|
|
case 2:
|
|
return icSigSolaris;
|
|
case 3:
|
|
return icSigSGI;
|
|
case 4:
|
|
return icSigTaligent;
|
|
}
|
|
return icMaxEnumPlatform;
|
|
}
|
|
|
|
icMeasurementGeometry rand_MeasurementGeometry() {
|
|
switch(rand_int(0,2)) {
|
|
case 0:
|
|
return icGeometryUnknown;
|
|
case 1:
|
|
return icGeometry045or450;
|
|
case 2:
|
|
return icGeometry0dord0;
|
|
}
|
|
return icMaxEnumGeometry;
|
|
}
|
|
|
|
icRenderingIntent rand_RenderingIntent() {
|
|
switch(rand_int(0,3)) {
|
|
case 0:
|
|
return icPerceptual;
|
|
case 1:
|
|
return icRelativeColorimetric;
|
|
case 2:
|
|
return icSaturation;
|
|
case 3:
|
|
return icAbsoluteColorimetric;
|
|
}
|
|
return icMaxEnumIntent;
|
|
}
|
|
|
|
icSpotShape rand_SpotShape() {
|
|
switch(rand_int(0,7)) {
|
|
case 0:
|
|
return icSpotShapeUnknown;
|
|
case 1:
|
|
return icSpotShapePrinterDefault;
|
|
case 2:
|
|
return icSpotShapeRound;
|
|
case 3:
|
|
return icSpotShapeDiamond;
|
|
case 4:
|
|
return icSpotShapeEllipse;
|
|
case 5:
|
|
return icSpotShapeLine;
|
|
case 6:
|
|
return icSpotShapeSquare;
|
|
case 7:
|
|
return icSpotShapeCross;
|
|
}
|
|
return icMaxEnumSpot;
|
|
}
|
|
|
|
icStandardObserver rand_StandardObserver() {
|
|
switch(rand_int(0,2)) {
|
|
case 0:
|
|
return icStdObsUnknown;
|
|
case 1:
|
|
return icStdObs1931TwoDegrees;
|
|
case 2:
|
|
return icStdObs1964TenDegrees;
|
|
}
|
|
return icMaxEnumStdObs;
|
|
}
|
|
|
|
icIlluminant rand_Illuminant() {
|
|
switch(rand_int(0,8)) {
|
|
case 0:
|
|
return icIlluminantUnknown;
|
|
case 1:
|
|
return icIlluminantD50;
|
|
case 2:
|
|
return icIlluminantD65;
|
|
case 3:
|
|
return icIlluminantD93;
|
|
case 4:
|
|
return icIlluminantF2;
|
|
case 5:
|
|
return icIlluminantD55;
|
|
case 6:
|
|
return icIlluminantA;
|
|
case 7:
|
|
return icIlluminantEquiPowerE;
|
|
case 8:
|
|
return icIlluminantF8;
|
|
}
|
|
return icMaxEnumIlluminant;
|
|
}
|
|
|
|
icPhColEncoding rand_ColorantEncoding() {
|
|
switch(rand_int(0,8)) {
|
|
case 0:
|
|
case 7:
|
|
case 8:
|
|
return icPhColUnknown;
|
|
case 1:
|
|
return icPhColITU_R_BT_709;
|
|
case 2:
|
|
return icPhColSMPTE_RP145_1994;
|
|
case 3:
|
|
return icPhColEBU_Tech_3213_E;
|
|
case 4:
|
|
return icPhColP22;
|
|
case 5:
|
|
return icPhColP3;
|
|
case 6:
|
|
return icPhColITU_R_BT2020;
|
|
}
|
|
return icMaxEnumPhCol;
|
|
}
|
|
|
|
icMeasUnitsSig rand_MeasUnitsSig() {
|
|
switch(rand_int(0,8)) {
|
|
case 0:
|
|
return icSigStatusA;
|
|
case 1:
|
|
return icSigStatusE;
|
|
case 2:
|
|
return icSigStatusI;
|
|
case 3:
|
|
return icSigStatusT;
|
|
case 4:
|
|
return icSigStatusM;
|
|
case 5:
|
|
return icSigDN;
|
|
case 6:
|
|
return icSigDNP;
|
|
case 7:
|
|
return icSigDNN;
|
|
case 8:
|
|
return icSigDNN;
|
|
}
|
|
return icMaxEnumMeasUnits;
|
|
}
|
|
|
|
icDevSetMsftIDSignature rand_DevSetMsftIDSignature() {
|
|
switch(rand_int(0,3)) {
|
|
case 0:
|
|
return icSigMsftResolution;
|
|
case 1:
|
|
return icSigMsftMedia;
|
|
case 2:
|
|
return icSigMsftHalftone;
|
|
case 3:
|
|
return icSigMsftHalftone;
|
|
}
|
|
return icMaxEnumDevSetMsftID;
|
|
}
|
|
|
|
icDevSetMsftMedia rand_DevSetMsftMedia() {
|
|
switch(rand_int(0,3)) {
|
|
case 0:
|
|
return icMsftMediaStandard;
|
|
case 1:
|
|
return icMsftMediaTrans;
|
|
case 2:
|
|
return icMsftMediaGloss;
|
|
case 3:
|
|
return icMsftMediaUser1 + rand_int(0, 255);
|
|
}
|
|
return icMaxEnumMsftMedia;
|
|
}
|
|
|
|
icDevSetMsftDither rand_DevSetMsftDither() {
|
|
switch(rand_int(0,10)) {
|
|
case 0:
|
|
return icMsftDitherNone;
|
|
case 1:
|
|
return icMsftDitherCoarse;
|
|
case 2:
|
|
return icMsftDitherFine;
|
|
case 3:
|
|
return icMsftDitherLineArt;
|
|
case 4:
|
|
return icMsftDitherErrorDiffusion;
|
|
case 5:
|
|
return icMsftDitherReserved6;
|
|
case 6:
|
|
return icMsftDitherReserved7;
|
|
case 7:
|
|
return icMsftDitherReserved8;
|
|
case 8:
|
|
return icMsftDitherReserved9;
|
|
case 9:
|
|
return icMsftDitherGrayScale;
|
|
case 10:
|
|
return icMsftDitherUser1 + rand_int(0, 255);
|
|
}
|
|
return icMsftMaxEnumMsftDither;
|
|
}
|
|
|
|
|
|
|
|
/* Malloc and initialize a random ascii string. */
|
|
/* Input is range of number of characters. */
|
|
/* Can free() buffer after use */
|
|
char *rand_ascii_string(int lenmin, int lenmax) {
|
|
int len; /* Length of output string */
|
|
int olen; /* Length of obuf allocation */
|
|
char *obuf, *ebuf, *out;
|
|
int i;
|
|
|
|
len = rand_int(lenmin, lenmax);
|
|
|
|
olen = len + 1;
|
|
if ((obuf = malloc(olen)) == NULL)
|
|
error("Malloc of rand_ascii_string len %d failed\n",olen);
|
|
out = obuf;
|
|
ebuf = obuf + olen; /* One past end */
|
|
|
|
for (i = 0; i < len; i++) {
|
|
char ch;
|
|
|
|
/* Create mostly printable ascii */
|
|
if (rand_int(0, 6) != 4) {
|
|
ch = rand_int(0x20, 0x7f);
|
|
|
|
/* And less often control characters */
|
|
} else {
|
|
ch = rand_int(1, 0x1f);
|
|
}
|
|
|
|
*out++ = ch;
|
|
}
|
|
|
|
*out++ = '\000';
|
|
|
|
return obuf;
|
|
}
|
|
|
|
/* Malloc and initialize a random utf-8 string */
|
|
/* Input is range of number of code points. */
|
|
/* Can free() buffer after use */
|
|
icmUTF8 *rand_utf8_string(int lenmin, int lenmax) {
|
|
int len; /* Length of output string */
|
|
int olen; /* Length of obuf allocation */
|
|
ORD8 *obuf, *ebuf, *out;
|
|
int i;
|
|
|
|
len = rand_int(lenmin, lenmax);
|
|
|
|
olen = len + len/2 + 1;
|
|
if ((obuf = malloc(olen)) == NULL)
|
|
error("Malloc of rand_utf8_string len %d failed\n",olen);
|
|
out = obuf;
|
|
ebuf = obuf + olen; /* One past end */
|
|
|
|
for (i = 0; i < len; i++) {
|
|
const icmUTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
|
const icmUTF32 byteMask = 0xBF;
|
|
const icmUTF32 byteMark = 0x80;
|
|
unsigned short btw = 0;
|
|
icmUTF32 ch;
|
|
|
|
/* Create mostly ascii code points */
|
|
if (rand_int(0, 6) != 4) {
|
|
ch = rand_int(0x20, 0x7f);
|
|
|
|
/* And less often contrl characters and non-ascii code points */
|
|
} else {
|
|
for (;;) {
|
|
ch = rand_int(0, 0x10fff); /* unicode range */
|
|
|
|
if ( ch == 0 /* nul */
|
|
|| ch == 0xfeff /* BOM */
|
|
|| (ch >= 0x20 && ch <= 0x7f) /* ascii */
|
|
|| (ch >= 0xd800 && ch <= 0xdfff)) /* surrogate */
|
|
continue; /* try again */
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* We have a UTF32 value. Convert to UTF8 */
|
|
|
|
/* Figure out how many bytes the result will require */
|
|
if (ch < (icmUTF32)0x80) { btw = 1;
|
|
} else if (ch < (icmUTF32)0x800) { btw = 2;
|
|
} else if (ch < (icmUTF32)0x10000) { btw = 3;
|
|
} else if (ch < (icmUTF32)0x110000) { btw = 4;
|
|
} else { btw = 3;
|
|
error("rand_utf8_string got out of range UTF32 0x%x\n",ch);
|
|
}
|
|
|
|
/* Do we need to re-allocate output buffer ? */
|
|
if ((out + btw + 1) >= ebuf) {
|
|
size_t off = out - obuf;
|
|
olen += btw + 1;
|
|
if ((obuf = realloc(obuf, olen)) == NULL)
|
|
error("Realloc of rand_utf8_string len %d failed\n",olen);
|
|
ebuf = obuf + olen; /* One past end */
|
|
out = obuf + off;
|
|
}
|
|
|
|
out += btw;
|
|
switch (btw) { /* note: everything falls through. */
|
|
case 4:
|
|
*--out = (icmUTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
|
case 3:
|
|
*--out = (icmUTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
|
case 2:
|
|
*--out = (icmUTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
|
case 1:
|
|
*--out = (icmUTF8)(ch | firstByteMark[btw]);
|
|
}
|
|
out += btw;
|
|
}
|
|
|
|
*out++ = '\000';
|
|
|
|
return obuf;
|
|
}
|
|
|
|
/* Malloc and initialize a random utf-16 string */
|
|
/* Input is range of number of code points. */
|
|
/* Can free() buffer after use */
|
|
icmUTF16 *rand_utf16_string(int lenmin, int lenmax) {
|
|
int len; /* Length of output string */
|
|
int olen; /* Length of obuf allocation */
|
|
icmUTF16 *obuf, *ebuf, *out;
|
|
int i;
|
|
|
|
len = rand_int(lenmin, lenmax);
|
|
|
|
olen = len + len/2 + 1;
|
|
if ((obuf = (icmUTF16 *)malloc(olen * 2)) == NULL)
|
|
error("Malloc of rand_utf8_string len %d failed\n",olen);
|
|
out = obuf;
|
|
ebuf = obuf + olen; /* One past end */
|
|
|
|
for (i = 0; i < len; i++) {
|
|
icmUTF32 ch;
|
|
|
|
/* Create mostly ascii code points */
|
|
if (rand_int(0, 6) != 4) {
|
|
ch = rand_int(0x20, 0x7f);
|
|
|
|
/* And less often control characters and non-ascii code points */
|
|
} else {
|
|
for (;;) {
|
|
ch = rand_int(0, 0x10fff); /* unicode range */
|
|
|
|
if ( ch == 0 /* nul */
|
|
|| ch == 0xfeff /* BOM */
|
|
|| (ch >= 0x20 && ch <= 0x7f) /* ascii */
|
|
|| (ch >= 0xd800 && ch <= 0xdfff)) /* surrogate */
|
|
continue; /* try again */
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* We have a UTF32 value. Convert to UTF16 */
|
|
|
|
/* Do we need to re-allocate output buffer ? */
|
|
if ((out + 2 + 1) >= ebuf) {
|
|
size_t off = out - obuf;
|
|
olen += 2 + 1;
|
|
if ((obuf = (icmUTF16 *)realloc(obuf, olen * 2)) == NULL)
|
|
error("Realloc of rand_utf16_string len %d failed\n",olen);
|
|
ebuf = obuf + olen; /* One past end */
|
|
out = obuf + off;
|
|
}
|
|
|
|
/* Is a character <= 0xFFFF */
|
|
if (ch <= 0x0000FFFF) {
|
|
|
|
*out++ = (icmUTF16)ch;
|
|
|
|
/* Output a surrogate pair */
|
|
} else {
|
|
ch -= 0x0010000;
|
|
out[0] = (icmUTF16)(((ch >> 10) & 0x3FF) + 0xD800);
|
|
out[1] = (icmUTF16)(( ch & 0x3FF) + 0xDC00);
|
|
out += 2;
|
|
}
|
|
}
|
|
*out++ = 0;
|
|
|
|
return obuf;
|
|
}
|
|
|
|
/* Return length of UTF-16 string */
|
|
size_t strlen_utf16(icmUTF16 *in) {
|
|
size_t len;
|
|
|
|
for (len = 0; *in != 0; in++, len++)
|
|
;
|
|
|
|
return len;
|
|
}
|
|
|
|
/* Compare two UTF-16 strings */
|
|
int strcmp_utf16(icmUTF16 *in1, icmUTF16 *in2) {
|
|
|
|
for (;; in1++, in2++) {
|
|
if (*in1 != *in2)
|
|
return 1;
|
|
if (*in1 == 0 || *in2 == 0)
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Compare doubles with a margine to allow */
|
|
/* for floating point handling funnies */
|
|
int dcomp(double a, double b) {
|
|
double dif = fabs(a - b);
|
|
double mag = fabs(a) + fabs(b);
|
|
|
|
return dif > (mag * 1e-10) ? 1 : 0;
|
|
}
|
|
|
|
|
|
/* Generate a random id */
|
|
void rand_id(unsigned char id[16]) {
|
|
int i;
|
|
|
|
for (i = 0; i < 16; i++)
|
|
id[i] = rand_o8();
|
|
}
|
|
|
|
/* Compare to id's */
|
|
int idcomp(unsigned char a[16], unsigned char b[16]) {
|
|
int i;
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
if (a[i] != b[i])
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* ------------------------------------------------ */
|
|
/* Basic printf type error() and warning() routines */
|
|
|
|
void
|
|
error(char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
fprintf(stderr,"icctest: 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,"icctest: Warning - ");
|
|
va_start(args, fmt);
|
|
vfprintf(stderr, fmt, args);
|
|
va_end(args);
|
|
fprintf(stderr, "\n");
|
|
}
|