1
2 /*
3 * International Color Consortium Format Library (icclib)
4 * Library Read/Write test and example code.
5 *
6 * Author: Graeme W. Gill
7 * Date: 1999/11/29
8 * Version: 2.15
9 *
10 * Copyright 1997 - 2012 Graeme W. Gill
11 *
12 * This material is licensed with an "MIT" free use license:-
13 * see the License4.txt file in this directory for licensing details.
14 */
15
16 /* TTBD:
17 *
18 * Fix enums to be selected randomly (ie. header)
19 *
20 * Should add test of ->delete_tag()
21 * Should add test of ->rename_tag()
22 *
23 * Add many extra comments and explanations.
24 *
25 */
26
27 /*
28
29 This file is intended to serve two purposes. One
30 is to minimally test the ability of the icc library
31 to read and write all tag types. The other is as
32 a source code example of how to read and write
33 each tag type, since icc.h might otherwise take
34 some effort to understand.
35
36 Note XYZ scaling to 1.0, not 100.0
37
38 */
39
40 #define NTRIALS 100
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <stdarg.h>
45 #include <fcntl.h>
46 #include <string.h>
47 #ifdef __sun
48 #include <unistd.h>
49 #endif
50 #include "icc.h"
51
52 void error(char *fmt, ...), warning(char *fmt, ...);
53
54 /* Rounded floating test numbers */
55 int rand_int(int low, int high);
56 unsigned int rand_o8(void), rand_o16(void), rand_o32(void);
57 double rand_8f(void), rand_L8(void), rand_ab8(void);
58 double rand_16f(void), rand_XYZ16(void), rand_u8f8(void), rand_L16(void), rand_ab16(void);
59 double rand_u16f16(void), rand_s15f16(void);
60 int dcomp(double a, double b);
61
62 /* random ICC specific values */
63 unsigned int rand_ScreenEncodings(void);
64 unsigned int rand_DeviceAttributes(void);
65 unsigned int rand_ProfileHeaderFlags(void);
66 unsigned int rand_AsciiOrBinaryData(void);
67 icColorSpaceSignature rand_ColorSpaceSignature(void);
68 icColorSpaceSignature rand_PCS(void);
69 icTechnologySignature rand_TechnologySignature(void);
70 icProfileClassSignature rand_ProfileClassSignature(void);
71 icPlatformSignature rand_PlatformSignature(void);
72 icMeasurementFlare rand_MeasurementFlare(void);
73 icMeasurementGeometry rand_MeasurementGeometry(void);
74 icRenderingIntent rand_RenderingIntent(void);
75 icSpotShape rand_SpotShape(void);
76 icStandardObserver rand_StandardObserver(void);
77 icIlluminant rand_Illuminant(void);
78
79 /* declare some test functions */
80 int md5_test(void);
81
82 /*
83 I've split the functionality up into two pieces.
84 The main() code does the overall file write/read,
85 while the tag type code is all in the doit() function.
86 The write/read logic is all sandwiched together (distinguished
87 by the state of the mode flag), so that the code for each
88 tag type is kept adjacent.
89
90 In a real application, one wouldn't do it this way.
91 */
92
93 int doit(int mode, icc *wr_icco, icc *rd_icco);
94
95 int
main(int argc,char * argv[])96 main(
97 int argc,
98 char *argv[]
99 ) {
100 char *file_name = "xxxx.icm";
101 icmFile *wr_fp, *rd_fp;
102 icc *wr_icco, *rd_icco; /* Keep object separate */
103 int rv = 0;
104 int i;
105 unsigned int offset = 0; /* File write/read offset, 0 for standard icc */
106
107 printf("ICC library regression test, V%s\n",ICCLIB_VERSION_STR);
108
109 /* Do any internal code tests. */
110
111 if (md5_test() != 0)
112 error ("MD5 checksum routine is faulty");
113
114
115 /* Outer loop does a number of file write/reads, */
116 /* in order to exercise random tests, and to test file offsets. */
117
118 for (i = 0; i < NTRIALS; i++) {
119 unsigned int size; /* Expected write size */
120
121 printf(".");
122 fflush(stdout);
123
124 /* -------------------------- */
125 /* Deal with writing the file */
126
127 /* Open up the file for writing */
128 if ((wr_fp = new_icmFileStd_name(file_name,"w")) == NULL)
129 error ("Write: Can't open file '%s'",file_name);
130
131 if ((wr_icco = new_icc()) == NULL)
132 error ("Write: Creation of ICC object failed");
133
134 /* Add all the tags with their tag types */
135 if ((rv = doit(0, wr_icco, NULL)) != 0)
136 error ("Write tags: %d, %s",rv,wr_icco->err);
137
138 /* Write the file (including all tags) out */
139 /* The last parameter is the offset to write the */
140 /* ICC profile into the file. For a standard ICC profile, */
141 /* this needs to be 0, but it might be non-zero if you are writing */
142 /* an embedded profile. */
143
144 /* Check that get_size() is working too. */
145 if ((size = wr_icco->get_size(wr_icco)) == 0)
146 error ("Write size: %d, %s",wr_icco->errc,wr_icco->err);
147
148 if ((rv = wr_icco->write(wr_icco,wr_fp,offset)) != 0)
149 error ("Write file: %d, %s",rv,wr_icco->err);
150
151 /* To check that get_size() is correct: */
152 {
153 icmFileStd *pp = (icmFileStd *)wr_fp; /* Cheat - Look inside icmFile */
154
155 if (fseek(pp->fp, 0, SEEK_END))
156 error ("Write: seek to EOF failed");
157 if ((unsigned int)ftell(pp->fp) != offset + size)
158 error ("Write: get_size function didn't return correct value - got %d, expected %d",
159 ftell(pp->fp),offset+size);
160 }
161
162 /*
163 Would normally call wr_icco->del(wr_icco);
164 but leave it, so that we can verify the read.
165 */
166
167 wr_fp->del(wr_fp);
168
169 /* -------------------------- */
170 /* Deal with reading and verifying the file */
171
172 /* Open up the file for reading */
173 if ((rd_fp = new_icmFileStd_name(file_name,"r")) == NULL)
174 error ("Read: Can't open file '%s'",file_name);
175
176 if ((rd_icco = new_icc()) == NULL)
177 error ("Read: Creation of ICC object failed");
178
179 /* Read the header and tag list */
180 /* The last parameter is the offset to read the */
181 /* ICC profile from the file. For a standard ICC proifile, */
182 /* this needs to be 0, but it might be non-zero if you are writing */
183 /* an embedded profile this needs to be 0, but it might be non-zero */
184 /* if you are writing an embedded profile. */
185 if ((rv = rd_icco->read(rd_icco,rd_fp,offset)) != 0)
186 error ("Read: %d, %s",rv,rd_icco->err);
187
188 /* Read and verify all the tags and their tag types */
189 if ((rv = doit(1, wr_icco, rd_icco)) != 0)
190 error ("Read: %d, %s",rv,rd_icco->err);
191
192 /* -------- */
193 /* Clean up */
194 wr_icco->del(wr_icco);
195
196 rd_icco->del(rd_icco);
197 rd_fp->del(rd_fp);
198
199 /* choose another file offset to test */
200 offset = rand_int(0,72789);
201 }
202
203 return 0;
204 }
205
206 /* -------------------------------------------------------------- */
207 /* Internal routine checks. */
208
209 /* Test the MD5 function. Return nz if fail. */
md5_test()210 int md5_test() {
211 int rv = 0;
212 int i, j;
213 icc *icco;
214 icmMD5 *m;
215
216 unsigned char chs1[16];
217 unsigned char chs2[16];
218
219 /* Standard RFC 1321 test cases */
220 struct {
221 char *s;
222 ORD32 sum[4];
223 } tc[] = {
224 { "", { 0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e } },
225 { "a", { 0x0cc175b9, 0xc0f1b6a8, 0x31c399e2, 0x69772661 } },
226 { "abc", { 0x90015098, 0x3cd24fb0, 0xd6963f7d, 0x28e17f72 } },
227 { "message digest", { 0xf96b697d, 0x7cb7938d, 0x525a2f31, 0xaaf161d0 } },
228 { "abcdefghijklmnopqrstuvwxyz", { 0xc3fcd3d7, 0x6192e400, 0x7dfb496c, 0xca67e13b } },
229 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
230 { 0xd174ab98, 0xd277d9f5, 0xa5611c2c, 0x9f419d9f } },
231 { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
232 { 0x57edf4a2, 0x2be3c955, 0xac49da2e, 0x2107b67a } },
233 { NULL, { 0,0,0,0 } }
234 };
235
236 if ((icco = new_icc()) == NULL)
237 error ("Creation of ICC object failed");
238
239 m = new_icmMD5_a(icco->al);
240
241 for (i = 0; ; i++) {
242 if (tc[i].s == NULL)
243 break;
244
245 m->reset(m);
246
247 m->add(m, (unsigned char *)tc[i].s, strlen(tc[i].s));
248 m->get(m, chs2);
249
250 /* Convert reference to a byte stream */
251 chs1[0] = (tc[i].sum[0] >> 24) & 0xff,
252 chs1[1] = (tc[i].sum[0] >> 16) & 0xff,
253 chs1[2] = (tc[i].sum[0] >> 8) & 0xff,
254 chs1[3] = tc[i].sum[0] & 0xff,
255 chs1[4] = (tc[i].sum[1] >> 24) & 0xff,
256 chs1[5] = (tc[i].sum[1] >> 16) & 0xff,
257 chs1[6] = (tc[i].sum[1] >> 8) & 0xff,
258 chs1[7] = tc[i].sum[1] & 0xff,
259 chs1[8] = (tc[i].sum[2] >> 24) & 0xff,
260 chs1[9] = (tc[i].sum[2] >> 16) & 0xff,
261 chs1[10] = (tc[i].sum[2] >> 8) & 0xff,
262 chs1[11] = tc[i].sum[2] & 0xff,
263 chs1[12] = (tc[i].sum[3] >> 24) & 0xff,
264 chs1[13] = (tc[i].sum[3] >> 16) & 0xff,
265 chs1[14] = (tc[i].sum[3] >> 8) & 0xff,
266 chs1[15] = tc[i].sum[3] & 0xff;
267
268 for (j = 0; j < 16; j++) {
269 if (chs1[j] != chs2[j]) {
270 printf("MD5 check on '%s' fails at %d with:\n",tc[i].s,j);
271 printf("Sum is %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
272 chs2[0], chs2[1], chs2[2], chs2[3], chs2[4], chs2[5], chs2[6], chs2[7],
273 chs2[8], chs2[9], chs2[10], chs2[11], chs2[12], chs2[13], chs2[14], chs2[15]);
274 printf("Should be %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
275 chs1[0], chs1[1], chs1[2], chs1[3], chs1[4], chs1[5], chs1[6], chs1[7],
276 chs1[8], chs1[9], chs1[10], chs1[11], chs1[12], chs1[13], chs1[14], chs1[15]);
277 rv = 1;
278 break;
279 }
280 }
281
282 }
283 m->del(m);
284 icco->del(icco);
285
286 return rv;
287 }
288
289 /* -------------------------------------------------------------- */
290 /* This is the code that inits and checks the header and tag data. */
291 /* Note that to undestand this, you need a copy of the ICC profile */
292 /* spec., and a copy of the icc header file (icc34.h in this code) */
293 /* All items that begin "icXXX" are from the ICC generic icc34.h file, */
294 /* while the items that begin "icmXXX" are machine versions of structures */
295 /* that are specific to this library. */
296
doit(int mode,icc * wr_icco,icc * rd_icco)297 int doit(
298 int mode, /* 0 - write, 1 = read/verify */
299 icc *wr_icco, /* The write icc object */
300 icc *rd_icco /* The read icc object */
301 ) {
302 int rv = 0;
303
304 /* ----------- */
305 /* The header: */
306 if (mode == 0) {
307 icmHeader *wh = wr_icco->header;
308
309 /* Values that must be set before writing */
310 wh->deviceClass = icSigAbstractClass;
311 wh->colorSpace = rand_ColorSpaceSignature();
312 wh->pcs = rand_PCS();
313 wh->renderingIntent = rand_RenderingIntent();
314
315 /* Values that should be set before writing */
316 wh->manufacturer = str2tag("tst1");
317 wh->model = str2tag("1234");
318 wh->attributes.l = rand_DeviceAttributes();
319 wh->flags = rand_ProfileHeaderFlags();
320
321 /* Values that may optionally be set before writing */
322 wh->attributes.h = 0x12345678;
323 wh->creator = str2tag("tst2");
324
325 /* Values that are not normally set. Set them to non-defaults for testing */
326 wh->cmmId = str2tag("tst3");
327 wh->majv = 2; /* Default version 2.1.0 */
328 wh->minv = 1;
329 wh->bfv = 0;
330 wh->date.year = rand_int(1900,3000); /* Defaults to current date */
331 wh->date.month = rand_int(1,12);
332 wh->date.day = rand_int(1,31);
333 wh->date.hours = rand_int(0,23);
334 wh->date.minutes = rand_int(0,59);
335 wh->date.seconds = rand_int(0,59);
336 wh->platform = rand_PlatformSignature();
337 wh->illuminant.X = rand_XYZ16(); /* Defaults to D50 */
338 wh->illuminant.Y = rand_XYZ16();
339 wh->illuminant.Z = rand_XYZ16();
340 } else {
341 icmHeader *rh = rd_icco->header;
342 icmHeader *wh = wr_icco->header;
343
344 /* Check all the values */
345 rv |= (rh->deviceClass != wh->deviceClass);
346 rv |= (rh->colorSpace != wh->colorSpace);
347 rv |= (rh->pcs != wh->pcs);
348 rv |= (rh->renderingIntent != wh->renderingIntent);
349 rv |= (rh->manufacturer != wh->manufacturer);
350 rv |= (rh->model != wh->model);
351 rv |= (rh->attributes.l != wh->attributes.l);
352 rv |= (rh->attributes.h != wh->attributes.h);
353 rv |= (rh->flags != wh->flags);
354 rv |= (rh->creator != wh->creator);
355 rv |= (rh->cmmId != wh->cmmId);
356 rv |= (rh->majv != wh->majv);
357 rv |= (rh->minv != wh->minv);
358 rv |= (rh->bfv != wh->bfv);
359 rv |= (rh->date.year != wh->date.year);
360 rv |= (rh->date.month != wh->date.month);
361 rv |= (rh->date.day != wh->date.day);
362 rv |= (rh->date.hours != wh->date.hours);
363 rv |= (rh->date.minutes != wh->date.minutes);
364 rv |= (rh->date.seconds != wh->date.seconds);
365 rv |= (rh->platform != wh->platform);
366 rv |= dcomp(rh->illuminant.X, wh->illuminant.X);
367 rv |= dcomp(rh->illuminant.Y, wh->illuminant.Y);
368 rv |= dcomp(rh->illuminant.Z, wh->illuminant.Z);
369 if (rv)
370 error ("Header verify failed");
371 }
372 /* ------------- */
373 /* CrdInfo info: */
374 {
375 char *str1 = "Product Name";
376 char *str2[4] = { "Intent zero CRD Name",
377 "Intent one CRD Name",
378 "Intent two CRD Name",
379 "Intent three CRD Name" };
380 static icmCrdInfo *wo;
381 if (mode == 0) {
382 unsigned int i;
383 if ((wo = (icmCrdInfo *)wr_icco->add_tag(
384 wr_icco, icSigCrdInfoTag, icSigCrdInfoType)) == NULL)
385 return 1;
386
387 wo->ppsize = strlen(str1)+1; /* Allocated and used size of text, inc null */
388 for (i = 0; i < 4; i++)
389 wo->crdsize[i] = strlen(str2[i])+1; /* Allocated and used size of text, inc null */
390
391 wo->allocate((icmBase *)wo); /* Allocate space */
392 /* Note we could allocate and copy as we go, rather than doing them all at once. */
393
394 strcpy(wo->ppname, str1); /* Copy the text in */
395 for (i = 0; i < 4; i++)
396 strcpy(wo->crdname[i], str2[i]); /* Copy the text in */
397 } else {
398 icmCrdInfo *ro;
399 unsigned int i;
400
401 /* Try and read the tag from the file */
402 ro = (icmCrdInfo *)rd_icco->read_tag(rd_icco, icSigCrdInfoTag);
403 if (ro == NULL)
404 return 1;
405
406 /* Need to check that the cast is appropriate. */
407 if (ro->ttype != icSigCrdInfoType)
408 return 1;
409
410 /* Now check it out */
411 if (ro->ppsize != wo->ppsize)
412 for (i = 0; i < 4; i++) {
413 if (ro->crdsize[i] != wo->crdsize[i])
414 error ("CrdInfo crdsize[%d] doesn't match",i);
415 }
416
417 rv |= strcmp(ro->ppname, wo->ppname);
418 for (i = 0; i < 4; i++) {
419 rv |= strcmp(ro->crdname[i], wo->crdname[i]);
420 }
421
422 if (rv)
423 error ("CrdInfo verify failed");
424 }
425 }
426 /* ---------------------- */
427 /* Curve - Linear version */
428 {
429 static icmCurve *wo;
430 if (mode == 0) {
431 if ((wo = (icmCurve *)wr_icco->add_tag(
432 wr_icco, icSigRedTRCTag, icSigCurveType)) == NULL)
433 return 1;
434
435 wo->flag = icmCurveLin; /* Linear version */
436 wo->allocate((icmBase *)wo);/* Allocate space */
437 } else {
438 icmCurve *ro;
439
440 /* Try and read the tag from the file */
441 ro = (icmCurve *)rd_icco->read_tag(rd_icco, icSigRedTRCTag);
442 if (ro == NULL)
443 return 1;
444
445 /* Need to check that the cast is appropriate. */
446 if (ro->ttype != icSigCurveType)
447 return 1;
448
449 /* Now check it out */
450 if (ro->flag != wo->flag)
451 error ("Curve flag doesn't match for Linear");
452
453 if (ro->size != wo->size)
454 error ("Curve size doesn't match");
455
456 if (rv)
457 error ("Curve verify failed");
458 }
459 }
460 /* --------------------- */
461 /* Curve - Gamma version */
462 {
463 static icmCurve *wo;
464 if (mode == 0) {
465 if ((wo = (icmCurve *)wr_icco->add_tag(
466 wr_icco, icSigGreenTRCTag, icSigCurveType)) == NULL)
467 return 1;
468
469 wo->flag = icmCurveGamma; /* Gamma version */
470 wo->allocate((icmBase *)wo); /* Allocate space */
471 wo->data[0] = rand_u8f8(); /* Gamma value */
472 } else {
473 icmCurve *ro;
474
475 /* Try and read the tag from the file */
476 ro = (icmCurve *)rd_icco->read_tag(rd_icco, icSigGreenTRCTag);
477 if (ro == NULL)
478 return 1;
479
480 /* Need to check that the cast is appropriate. */
481 if (ro->ttype != icSigCurveType)
482 return 1;
483
484 /* Now check it out */
485 if (ro->flag != wo->flag)
486 error ("Curve flag doesn't match for Gamma");
487
488 if (ro->size != wo->size)
489 error ("Curve size doesn't match");
490
491 rv |= dcomp(ro->data[0], wo->data[0]);
492
493 if (rv)
494 error ("Curve verify failed");
495 }
496 }
497 /* ------------------------- */
498 /* Curve - Specified version */
499 {
500 static icmCurve *wo;
501 if (mode == 0) {
502 unsigned int i;
503 if ((wo = (icmCurve *)wr_icco->add_tag(
504 wr_icco, icSigBlueTRCTag, icSigCurveType)) == NULL)
505 return 1;
506
507 wo->flag = icmCurveSpec; /* Specified version */
508 wo->size = rand_int(2,23); /* Number of entries (min must be 2!) */
509 wo->allocate((icmBase *)wo);/* Allocate space */
510 for (i = 0; i < wo->size; i++)
511 wo->data[i] = rand_16f(); /* Curve values 0.0 - 1.0 */
512 } else {
513 icmCurve *ro;
514 unsigned int i;
515
516 /* Try and read the tag from the file */
517 ro = (icmCurve *)rd_icco->read_tag(rd_icco, icSigBlueTRCTag);
518 if (ro == NULL)
519 return 1;
520
521 /* Need to check that the cast is appropriate. */
522 if (ro->ttype != icSigCurveType)
523 return 1;
524
525 /* Now check it out */
526 if (ro->flag != wo->flag)
527 error ("Curve flag doesn't match for specified");
528
529 if (ro->size != wo->size)
530 error ("Curve size doesn't match");
531
532 for (i = 0; i < wo->size; i++)
533 rv |= dcomp(ro->data[i], wo->data[i]);
534
535 if (rv)
536 error ("Curve verify failed");
537 }
538 }
539 /* ------------------- */
540 /* Data - text version */
541 {
542 static icmData *wo;
543 char *ts1 = "This is a data string";
544 if (mode == 0) {
545 if ((wo = (icmData *)wr_icco->add_tag(
546 wr_icco, icSigPs2CRD0Tag, icSigDataType)) == NULL)
547 return 1;
548
549 wo->flag = icmDataASCII; /* Holding ASCII data */
550 wo->size = strlen(ts1)+1; /* Allocated and used size of text, inc null */
551 wo->allocate((icmBase *)wo);/* Allocate space */
552 strcpy((char *)wo->data, ts1); /* Copy the text in */
553 } else {
554 icmData *ro;
555
556 /* Try and read the tag from the file */
557 ro = (icmData *)rd_icco->read_tag(rd_icco, icSigPs2CRD0Tag);
558 if (ro == NULL)
559 return 1;
560
561 /* Need to check that the cast is appropriate. */
562 if (ro->ttype != icSigDataType)
563 return 1;
564
565 /* Now check it out */
566 if (ro->flag != wo->flag)
567 error ("Data size doesn't match");
568
569 if (ro->size != wo->size)
570 error ("Data size doesn't match");
571
572 rv |= strcmp((char *)ro->data, (char *)wo->data);
573
574 if (rv)
575 error ("Data verify failed");
576 }
577 }
578 /* --------------------- */
579 /* Data - Binary version */
580 {
581 static icmData *wo;
582 if (mode == 0) {
583 unsigned int i;
584 if ((wo = (icmData *)wr_icco->add_tag(
585 wr_icco, icSigPs2CRD1Tag, icSigDataType)) == NULL)
586 return 1;
587
588 wo->flag = icmDataBin; /* Holding binary data */
589 wo->size = rand_int(0,43); /* Space we need for data */
590 wo->allocate((icmBase *)wo);/* Allocate space */
591 for (i = 0; i < wo->size; i ++)
592 wo->data[i] = rand_o8();
593 } else {
594 icmData *ro;
595 unsigned int i;
596
597 /* Try and read the tag from the file */
598 ro = (icmData *)rd_icco->read_tag(rd_icco, icSigPs2CRD1Tag);
599 if (ro == NULL)
600 return 1;
601
602 /* Need to check that the cast is appropriate. */
603 if (ro->ttype != icSigDataType)
604 return 1;
605
606 /* Now check it out */
607 if (ro->flag != wo->flag)
608 error ("Data size doesn't match");
609
610 if (ro->size != wo->size)
611 error ("Data size doesn't match");
612
613 for (i = 0; i < wo->size; i++)
614 rv |= (ro->data[i] != wo->data[i]);
615
616 if (rv)
617 error ("Data verify failed");
618 }
619 }
620 /* --------- */
621 /* DateTime: */
622 {
623 static icmDateTimeNumber *wo;
624 if (mode == 0) {
625 if ((wo = (icmDateTimeNumber *)wr_icco->add_tag(
626 wr_icco, icSigCalibrationDateTimeTag, icSigDateTimeType)) == NULL)
627 return 1;
628
629 wo->year = rand_int(1900, 3000);
630 wo->month = rand_int(1, 12);
631 wo->day = rand_int(1, 31);
632 wo->hours = rand_int(0, 23);
633 wo->minutes = rand_int(0, 59);
634 wo->seconds = rand_int(0, 59);
635 } else {
636 icmDateTimeNumber *ro;
637
638 /* Try and read the tag from the file */
639 ro = (icmDateTimeNumber *)rd_icco->read_tag(rd_icco, icSigCalibrationDateTimeTag);
640 if (ro == NULL)
641 return 1;
642
643 /* Need to check that the cast is appropriate. */
644 if (ro->ttype != icSigDateTimeType)
645 return 1;
646
647 /* Now check it out */
648 rv |= (ro->year != wo->year);
649 rv |= (ro->month != wo->month);
650 rv |= (ro->day != wo->day);
651 rv |= (ro->hours != wo->hours);
652 rv |= (ro->minutes != wo->minutes);
653 rv |= (ro->seconds != wo->seconds);
654
655 if (rv)
656 error ("DateTime verify failed");
657 }
658 }
659 /* ----------- */
660 /* 16 bit lut: */
661 {
662 static icmLut *wo;
663 if (mode == 0) {
664 unsigned int i, j, k;
665 if ((wo = (icmLut *)wr_icco->add_tag(
666 wr_icco, icSigAToB0Tag, icSigLut16Type)) == NULL)
667 return 1;
668
669 wo->inputChan = 2;
670 wo->outputChan = 3;
671 wo->clutPoints = 5;
672 wo->inputEnt = 56;
673 wo->outputEnt = 73;
674 wo->allocate((icmBase *)wo);/* Allocate space */
675
676 /* The matrix is only applicable to XYZ input space */
677 for (i = 0; i < 3; i++) /* Matrix */
678 for (j = 0; j < 3; j++)
679 wo->e[i][j] = rand_s15f16();
680
681 /* See icc.getNormFuncs() for normalizing functions */
682 /* The input table index range is over the normalized range 0.0 - 1.0. */
683 /* The range in input color space can be determined by denormalizing */
684 /* the values 0.0 - 1.0. */
685 for (i = 0; i < wo->inputChan; i++) /* Input tables */
686 for (j = 0; j < wo->inputEnt; j++)
687 wo->inputTable[i * wo->inputEnt + j] = rand_16f();
688
689 /* Lut */
690 /* The multidimentional lut has a normalized index range */
691 /* of 0.0 - 1.0 in each dimension. Its entry values are also */
692 /* normalized values in the range 0.0 - 1.0. */
693 for (i = 0; i < wo->clutPoints; i++) /* Input chan 0 - slow changing */
694 for (j = 0; j < wo->clutPoints; j++) /* Input chan 1 - faster changing */
695 for (k = 0; k < wo->outputChan; k++) /* Output chans */
696 wo->clutTable[(i * wo->clutPoints + j) * wo->outputChan + k] = rand_16f();
697
698 /* The output color space values should be normalized to the */
699 /* range 0.0 - 1.0 for use as output table entry values. */
700 for (i = 0; i < wo->outputChan; i++) /* Output tables */
701 for (j = 0; j < wo->outputEnt; j++)
702 wo->outputTable[i * wo->outputEnt + j] = rand_16f();
703
704 } else {
705 icmLut *ro;
706 unsigned int size;
707 unsigned int i, j;
708
709 /* Try and read the tag from the file */
710 ro = (icmLut *)rd_icco->read_tag(rd_icco, icSigAToB0Tag);
711 if (ro == NULL)
712 return 1;
713
714 /* Need to check that the cast is appropriate. */
715 if (ro->ttype != icSigLut16Type)
716 return 1;
717
718 /* Now check it out */
719 rv |= (ro->inputChan != wo->inputChan);
720 rv |= (ro->outputChan != wo->outputChan);
721 rv |= (ro->clutPoints != wo->clutPoints);
722 rv |= (ro->inputEnt != wo->inputEnt);
723 rv |= (ro->outputEnt != wo->outputEnt);
724
725 for (i = 0; i < 3; i++)
726 for (j = 0; j < 3; j++)
727 rv |= dcomp(ro->e[i][j], wo->e[i][j]);
728
729 size = (wo->inputChan * wo->inputEnt);
730 for (i = 0; i < size; i++)
731 rv |= dcomp(ro->inputTable[i], wo->inputTable[i]);
732
733 size = wo->outputChan;
734 for (i = 0; i < wo->inputChan; i++)
735 size *= wo->clutPoints;
736 for (i = 0; i < size; i++)
737 rv |= dcomp(ro->clutTable[i], wo->clutTable[i]);
738
739 size = (wo->outputChan * wo->outputEnt);
740 for (i = 0; i < size; i++)
741 rv |= dcomp(ro->outputTable[i], wo->outputTable[i]);
742 if (rv)
743 error ("Lut16 verify failed");
744 }
745 }
746 /* ------------------ */
747 /* 16 bit lut - link: */
748 {
749 static icmLut *wo;
750 if (mode == 0) {
751 /* Just link to the existing LUT. This is often used when there */
752 /* is no distinction between intents, and saves file and memory space. */
753 if ((wo = (icmLut *)wr_icco->link_tag(
754 wr_icco, icSigAToB1Tag, icSigAToB0Tag)) == NULL)
755 return 1;
756 } else {
757 icmLut *ro;
758 unsigned int size;
759 unsigned int i;
760
761 /* Try and read the tag from the file */
762 ro = (icmLut *)rd_icco->read_tag(rd_icco, icSigAToB1Tag);
763 if (ro == NULL)
764 return 1;
765
766 /* Need to check that the cast is appropriate. */
767 if (ro->ttype != icSigLut16Type)
768 return 1;
769
770 /* Now check it out */
771 rv |= (ro->inputChan != wo->inputChan);
772 rv |= (ro->outputChan != wo->outputChan);
773 rv |= (ro->clutPoints != wo->clutPoints);
774 rv |= (ro->inputEnt != wo->inputEnt);
775 rv |= (ro->outputEnt != wo->outputEnt);
776
777 size = (wo->inputChan * wo->inputEnt);
778 for (i = 0; i < size; i++)
779 rv |= (ro->inputTable[i] != wo->inputTable[i]);
780
781 size = wo->outputChan;
782 for (i = 0; i < wo->inputChan; i++)
783 size *= wo->clutPoints;
784 for (i = 0; i < size; i++)
785 rv |= (ro->clutTable[i] != wo->clutTable[i]);
786
787 size = (wo->outputChan * wo->outputEnt);
788 for (i = 0; i < size; i++)
789 rv |= (ro->outputTable[i] != wo->outputTable[i]);
790 if (rv)
791 error ("Lut16 link verify failed");
792 }
793 }
794 /* ---------- */
795 /* 8 bit lut: */
796 {
797 static icmLut *wo;
798 if (mode == 0) {
799 unsigned int i, j, m, k;
800 if ((wo = (icmLut *)wr_icco->add_tag(
801 wr_icco, icSigAToB2Tag, icSigLut8Type)) == NULL)
802 return 1;
803
804 wo->inputChan = 3;
805 wo->outputChan = 2;
806 wo->clutPoints = 4;
807 wo->inputEnt = 256; /* Must be 256 for Lut8 */
808 wo->outputEnt = 256;
809 wo->allocate((icmBase *)wo);/* Allocate space */
810
811 for (i = 0; i < 3; i++) /* Matrix */
812 for (j = 0; j < 3; j++)
813 wo->e[i][j] = rand_s15f16();
814
815 for (i = 0; i < wo->inputChan; i++) /* Input tables */
816 for (j = 0; j < wo->inputEnt; j++)
817 wo->inputTable[i * wo->inputEnt + j] = rand_8f();
818
819 /* Lut */
820 for (i = 0; i < wo->clutPoints; i++) /* Input chan 0 */
821 for (j = 0; j < wo->clutPoints; j++) /* Input chan 1 */
822 for (m = 0; m < wo->clutPoints; m++) /* Input chan 2 */
823 for (k = 0; k < wo->outputChan; k++) { /* Output chans */
824 int idx = ((i * wo->clutPoints + j)
825 * wo->clutPoints + m)
826 * wo->outputChan + k;
827 wo->clutTable[idx] = rand_8f();
828 }
829
830 for (i = 0; i < wo->outputChan; i++) /* Output tables */
831 for (j = 0; j < wo->outputEnt; j++)
832 wo->outputTable[i * wo->outputEnt + j] = rand_8f();
833
834 } else {
835 icmLut *ro;
836 unsigned int size;
837 unsigned int i, j;
838
839 /* Try and read the tag from the file */
840 ro = (icmLut *)rd_icco->read_tag(rd_icco, icSigAToB2Tag);
841 if (ro == NULL)
842 return 1;
843
844 /* Need to check that the cast is appropriate. */
845 if (ro->ttype != icSigLut8Type)
846 return 1;
847
848 /* Now check it out */
849 rv |= (ro->inputChan != wo->inputChan);
850 rv |= (ro->outputChan != wo->outputChan);
851 rv |= (ro->clutPoints != wo->clutPoints);
852 rv |= (ro->inputEnt != wo->inputEnt);
853 rv |= (ro->outputEnt != wo->outputEnt);
854
855 for (i = 0; i < 3; i++)
856 for (j = 0; j < 3; j++)
857 rv |= dcomp(ro->e[i][j], wo->e[i][j]);
858
859 size = (wo->inputChan * wo->inputEnt);
860 for (i = 0; i < size; i++)
861 rv |= dcomp(ro->inputTable[i], wo->inputTable[i]);
862
863 size = wo->outputChan;
864 for (i = 0; i < wo->inputChan; i++)
865 size *= wo->clutPoints;
866 for (i = 0; i < size; i++)
867 rv |= dcomp(ro->clutTable[i], wo->clutTable[i]);
868
869 size = (wo->outputChan * wo->outputEnt);
870 for (i = 0; i < size; i++)
871 rv |= dcomp(ro->outputTable[i], wo->outputTable[i]);
872 if (rv)
873 error ("Lut8 verify failed");
874 }
875 }
876 /* ----------------- */
877 /* Measurement: */
878 {
879 static icmMeasurement *wo;
880 if (mode == 0) {
881 if ((wo = (icmMeasurement *)wr_icco->add_tag(
882 wr_icco, icSigMeasurementTag, icSigMeasurementType)) == NULL)
883 return 1;
884
885 /* Standard observer */
886 switch(rand_int(0,2)) {
887 case 0:
888 wo->observer = icStdObsUnknown;
889 break;
890 case 1:
891 wo->observer = icStdObs1931TwoDegrees;
892 break;
893 case 2:
894 wo->observer = icStdObs1964TenDegrees;
895 break;
896 }
897
898 /* XYZ for backing color */
899 wo->backing.X = rand_XYZ16();
900 wo->backing.Y = rand_XYZ16();
901 wo->backing.Z = rand_XYZ16();
902
903 /* Measurement geometry */
904 switch(rand_int(0,2)) {
905 case 0:
906 wo->geometry = icGeometryUnknown;
907 break;
908 case 1:
909 wo->geometry = icGeometry045or450;
910 break;
911 case 2:
912 wo->geometry = icGeometry0dord0;
913 break;
914 }
915
916 /* Measurement flare */
917 wo->flare = rand_u16f16();
918
919 /* Illuminant */
920 switch(rand_int(0,8)) {
921 case 0:
922 wo->illuminant = icIlluminantUnknown;
923 break;
924 case 1:
925 wo->illuminant = icIlluminantD50;
926 break;
927 case 2:
928 wo->illuminant = icIlluminantD65;
929 break;
930 case 3:
931 wo->illuminant = icIlluminantD93;
932 break;
933 case 4:
934 wo->illuminant = icIlluminantF2;
935 break;
936 case 5:
937 wo->illuminant = icIlluminantD55;
938 break;
939 case 6:
940 wo->illuminant = icIlluminantA;
941 break;
942 case 7:
943 wo->illuminant = icIlluminantEquiPowerE;
944 break;
945 case 8:
946 wo->illuminant = icIlluminantF8;
947 break;
948 }
949 } else {
950 icmMeasurement *ro;
951
952 /* Try and read the tag from the file */
953 ro = (icmMeasurement *)rd_icco->read_tag(rd_icco, icSigMeasurementTag);
954 if (ro == NULL)
955 return 1;
956
957 /* Need to check that the cast is appropriate. */
958 if (ro->ttype != icSigMeasurementType)
959 return 1;
960
961 /* Now check it out */
962 rv |= (ro->observer != wo->observer);
963 rv |= dcomp(ro->backing.X, wo->backing.X);
964 rv |= dcomp(ro->backing.Y, wo->backing.Y);
965 rv |= dcomp(ro->backing.Z, wo->backing.Z);
966 rv |= (ro->geometry != wo->geometry);
967 rv |= dcomp(ro->flare, wo->flare);
968 rv |= (ro->illuminant != wo->illuminant);
969
970 if (rv)
971 error ("Measurement verify failed");
972 }
973 }
974 /* ----------------- */
975 /* Old style NamedColor: */
976 {
977 static icmNamedColor *wo;
978 if (mode == 0) {
979 unsigned int i;
980 if ((wo = (icmNamedColor *)wr_icco->add_tag(
981 wr_icco, icSigNamedColorTag, icSigNamedColorType)) == NULL)
982 return 1;
983
984 wo->vendorFlag = rand_int(0,65535) << 16; /* Bottom 16 bits for IC use */
985 wo->count = 3; /* Count of named colors */
986 strcpy(wo->prefix,"Prefix"); /* Prefix for each color name, max 32, null terminated */
987 strcpy(wo->suffix,"Suffix"); /* Suffix for each color name, max 32, null terminated */
988
989 wo->allocate((icmBase *)wo); /* Allocate named color structures */
990
991 for (i = 0; i < wo->count; i++) {
992 unsigned int j;
993 sprintf(wo->data[i].root,"Color %d",i); /* Root name, max 32, null terminated */
994 for (j = 0; j < wo->nDeviceCoords; j++) /* nDeviceCoords defaults appropriately */
995 wo->data[i].deviceCoords[j] = rand_8f(); /* Device coords of color */
996 }
997 } else {
998 icmNamedColor *ro;
999 unsigned int i;
1000
1001 /* Try and read the tag from the file */
1002 ro = (icmNamedColor *)rd_icco->read_tag(rd_icco, icSigNamedColorTag);
1003 if (ro == NULL)
1004 return 1;
1005
1006 /* Need to check that the cast is appropriate. */
1007 if (ro->ttype != icSigNamedColorType)
1008 return 1;
1009
1010 /* Now check it out */
1011 rv |= (ro->vendorFlag != wo->vendorFlag);
1012 rv |= (ro->count != wo->count);
1013 rv |= (ro->nDeviceCoords != wo->nDeviceCoords);
1014 rv |= strcmp(ro->prefix, wo->prefix);
1015 rv |= strcmp(ro->suffix, wo->suffix);
1016
1017 if (rv)
1018 error ("NamedColor verify failed");
1019
1020 for (i = 0; i < wo->count; i++) {
1021 unsigned int j;
1022 rv |= strcmp(ro->data[i].root, wo->data[i].root);
1023 for (j = 0; j < wo->nDeviceCoords; j++)
1024 rv |= dcomp(ro->data[i].deviceCoords[j], wo->data[i].deviceCoords[j]);
1025 }
1026
1027 if (rv)
1028 error ("NamedColor verify failed");
1029 }
1030 }
1031 /* ----------------- */
1032 /* NamedColor2: */
1033 {
1034 static icmNamedColor *wo; /* Shares same machine specific structure */
1035 if (mode == 0) {
1036 unsigned int i;
1037 if ((wo = (icmNamedColor *)wr_icco->add_tag(
1038 wr_icco, icSigNamedColor2Tag, icSigNamedColor2Type)) == NULL)
1039 return 1;
1040
1041 wo->vendorFlag = rand_int(0,65535) << 16; /* Bottom 16 bits for ICC use */
1042 wo->count = 4; /* Count of named colors */
1043 wo->nDeviceCoords = 3; /* Num of device coordinates */
1044 /* Could set this different to that implied by wr_icco->header->colorSpace */
1045 strcpy(wo->prefix,"Prefix-ix"); /* Prefix for each color name, max 32, null terminated */
1046 strcpy(wo->suffix,"Suffix-ixix"); /* Suffix for each color name, max 32, null terminated */
1047
1048 wo->allocate((icmBase *)wo); /* Allocate named color structures */
1049
1050 for (i = 0; i < wo->count; i++) {
1051 unsigned int j;
1052 sprintf(wo->data[i].root,"Pigment %d",i); /* Root name, max 32, null terminated */
1053 for (j = 0; j < wo->nDeviceCoords; j++)
1054 wo->data[i].deviceCoords[j] = rand_8f(); /* Device coords of color */
1055 switch(wo->icp->header->pcs) {
1056 case icSigXYZData:
1057 wo->data[i].pcsCoords[0] = rand_XYZ16();
1058 wo->data[i].pcsCoords[1] = rand_XYZ16();
1059 wo->data[i].pcsCoords[2] = rand_XYZ16();
1060 break;
1061 case icSigLabData:
1062 wo->data[i].pcsCoords[0] = rand_L16();
1063 wo->data[i].pcsCoords[1] = rand_ab16();
1064 wo->data[i].pcsCoords[2] = rand_ab16();
1065 break;
1066 default:
1067 break;
1068 }
1069 }
1070 } else {
1071 icmNamedColor *ro;
1072 unsigned int i;
1073
1074 /* Try and read the tag from the file */
1075 ro = (icmNamedColor *)rd_icco->read_tag(rd_icco, icSigNamedColor2Tag);
1076 if (ro == NULL)
1077 return 1;
1078
1079 /* Need to check that the cast is appropriate. */
1080 if (ro->ttype != icSigNamedColor2Type)
1081 return 1;
1082
1083 /* Now check it out */
1084 rv |= (ro->vendorFlag != wo->vendorFlag);
1085 rv |= (ro->count != wo->count);
1086 rv |= (ro->nDeviceCoords != wo->nDeviceCoords);
1087 rv |= strcmp(ro->prefix, wo->prefix);
1088 rv |= strcmp(ro->suffix, wo->suffix);
1089
1090 if (rv)
1091 error ("NamedColor2 verify failed");
1092
1093 for (i = 0; i < wo->count; i++) {
1094 unsigned int j;
1095 rv |= strcmp(ro->data[i].root, wo->data[i].root);
1096 for (j = 0; j < wo->nDeviceCoords; j++)
1097 rv |= dcomp(ro->data[i].deviceCoords[j], wo->data[i].deviceCoords[j]);
1098 for (j = 0; j < 3; j++) {
1099 rv |= dcomp(ro->data[i].pcsCoords[j], wo->data[i].pcsCoords[j]);
1100 }
1101 }
1102
1103 if (rv)
1104 error ("NamedColor2 verify failed");
1105 }
1106 }
1107 /* ----------------- */
1108 /* ColorantTable: */
1109 {
1110 static icmColorantTable *wo;
1111 if (mode == 0) {
1112 unsigned int i;
1113 if ((wo = (icmColorantTable *)wr_icco->add_tag(
1114 wr_icco, icSigColorantTableTag, icSigColorantTableType)) == NULL)
1115 return 1;
1116
1117 wo->count = 4; /* Count of colorants - should be same as implied by device space */
1118 wo->allocate((icmBase *)wo); /* Allocate ColorantTable structures */
1119
1120 for (i = 0; i < wo->count; i++) {
1121 sprintf(wo->data[i].name,"Color %d",i); /* Colorant name, max 32, null terminated */
1122 switch(wo->icp->header->pcs) {
1123 case icSigXYZData:
1124 wo->data[i].pcsCoords[0] = rand_XYZ16();
1125 wo->data[i].pcsCoords[1] = rand_XYZ16();
1126 wo->data[i].pcsCoords[2] = rand_XYZ16();
1127 break;
1128 case icSigLabData:
1129 wo->data[i].pcsCoords[0] = rand_L16();
1130 wo->data[i].pcsCoords[1] = rand_ab16();
1131 wo->data[i].pcsCoords[2] = rand_ab16();
1132 break;
1133 default:
1134 break;
1135 }
1136 }
1137 } else {
1138 icmColorantTable *ro;
1139 unsigned int i;
1140
1141 /* Try and read the tag from the file */
1142 ro = (icmColorantTable *)rd_icco->read_tag(rd_icco, icSigColorantTableTag);
1143 if (ro == NULL)
1144 return 1;
1145
1146 /* Need to check that the cast is appropriate. */
1147 if (ro->ttype != icSigColorantTableType)
1148 return 1;
1149
1150 /* Now check it out */
1151 rv |= (ro->count != wo->count);
1152
1153 if (rv)
1154 error ("ColorantTable verify failed");
1155
1156 for (i = 0; i < wo->count; i++) {
1157 int j;
1158 rv |= strcmp(ro->data[i].name, wo->data[i].name);
1159 for (j = 0; j < 3; j++) {
1160 rv |= dcomp(ro->data[i].pcsCoords[j], wo->data[i].pcsCoords[j]);
1161 }
1162 }
1163
1164 if (rv)
1165 error ("ColorantTable verify failed");
1166 }
1167 }
1168 /* ----------------- */
1169 /* ProfileSequenceDescTag: */
1170 {
1171 unsigned short ts2a[29] = {'T','h','i','s',' ','i','s',' ','a',' ','d','e','v','i','c','e',
1172 ' ','d','e','s','c','r','i','p','t','i','o','n',0x0000};
1173 unsigned short ts2b[28] = {'T','h','i','s',' ','i','s',' ','a',' ','m','o','d','e','l',
1174 ' ','d','e','s','c','r','i','p','t','i','o','n',0x0000};
1175 char *ts3a = "This is a device description";
1176 char *ts3b = "This is a model description";
1177 static icmProfileSequenceDesc*wo;
1178 if (mode == 0) {
1179 unsigned int i;
1180 if ((wo = (icmProfileSequenceDesc *)wr_icco->add_tag(
1181 wr_icco, icSigProfileSequenceDescTag, icSigProfileSequenceDescType)) == NULL)
1182 return 1;
1183
1184 wo->count = 3; /* Number of descriptions in sequence */
1185 wo->allocate((icmBase *)wo); /* Allocate space for all the DescStructures */
1186
1187 /* Fill in each description structure in sequence */
1188 for (i = 0; i < wo->count; i++) {
1189 char ts1[100];
1190 wo->data[i].deviceMfg = str2tag("mfg7");
1191 wo->data[i].deviceModel = str2tag("2345");
1192 wo->data[i].attributes.l = icTransparency | icMatte;
1193 wo->data[i].attributes.h = 0x98765432;
1194 wo->data[i].technology = rand_TechnologySignature();
1195
1196 /* device Text description */
1197 sprintf(ts1,"This is device descrption %d",i);
1198 wo->data[i].device.size = strlen(ts1)+1;
1199 wo->data[i].allocate(&wo->data[i]); /* Allocate space */
1200 strcpy(wo->data[i].device.desc, ts1); /* Copy the string in */
1201
1202 /* We'll fudge up the Unicode string */
1203 wo->data[i].device.ucLangCode = 8765; /* UniCode language code */
1204 wo->data[i].device.ucSize = 29; /* Size in chars inc null */
1205 wo->data[i].allocate(&wo->data[i]); /* Allocate space */
1206 memmove(wo->data[i].device.ucDesc, ts2a, 2 * 29); /* Copy string in */
1207
1208 wo->data[i].device.scCode = 67; /* Fudge scriptCode code */
1209 wo->data[i].device.scSize = strlen(ts3a)+1; /* Used size of scDesc in bytes, inc null */
1210 if (wo->data[i].device.scSize > 67)
1211 error("ScriptCode string longer than 67");
1212 strcpy((char *)wo->data[i].device.scDesc, ts3a); /* Copy the string in */
1213
1214 /* model Text description */
1215 sprintf(ts1,"This is model descrption %d",i);
1216 wo->data[i].model.size = strlen(ts1)+1;
1217 wo->data[i].allocate(&wo->data[i]); /* Allocate space */
1218 strcpy(wo->data[i].model.desc, ts1); /* Copy the string in */
1219
1220 /* We'll fudge up the Unicode string */
1221 wo->data[i].model.ucLangCode = 7856; /* UniCode language code */
1222 wo->data[i].model.ucSize = 28; /* Size in chars inc null */
1223 wo->data[i].allocate(&wo->data[i]); /* Allocate space */
1224 memmove(wo->data[i].model.ucDesc, ts2b, 2 * 28); /* Copy string in */
1225
1226 wo->data[i].model.scCode = 67; /* Fudge scriptCode code */
1227 wo->data[i].model.scSize = strlen(ts3b)+1; /* Used size of scDesc in bytes, inc null */
1228 if (wo->data[i].model.scSize > 67)
1229 error("ScriptCode string longer than 67");
1230 strcpy((char *)wo->data[i].model.scDesc, ts3b); /* Copy the string in */
1231 }
1232 } else {
1233 icmProfileSequenceDesc *ro;
1234 unsigned int i;
1235
1236 /* Try and read the tag from the file */
1237 ro = (icmProfileSequenceDesc *)rd_icco->read_tag(rd_icco, icSigProfileSequenceDescTag);
1238 if (ro == NULL)
1239 return 1;
1240
1241 /* Need to check that the cast is appropriate. */
1242 if (ro->ttype != icSigProfileSequenceDescType)
1243 return 1;
1244
1245 /* Now check it out */
1246 if (ro->count != wo->count)
1247 error ("ProfileSequenceDesc count doesn't match");
1248
1249 for (i = 0; i < wo->count; i++) {
1250 rv |= (ro->data[i].deviceMfg != wo->data[i].deviceMfg);
1251 rv |= (ro->data[i].deviceModel != wo->data[i].deviceModel);
1252 rv |= (ro->data[i].attributes.l != wo->data[i].attributes.l);
1253 rv |= (ro->data[i].attributes.h != wo->data[i].attributes.h);
1254 rv |= (ro->data[i].technology != wo->data[i].technology);
1255
1256 /* device Text description */
1257 rv |= (ro->data[i].device.size != wo->data[i].device.size);
1258 rv |= strcmp(ro->data[i].device.desc, wo->data[i].device.desc);
1259
1260 rv |= (ro->data[i].device.ucLangCode != wo->data[i].device.ucLangCode);
1261 rv |= (ro->data[i].device.ucSize != wo->data[i].device.ucSize);
1262 rv |= memcmp(ro->data[i].device.ucDesc, wo->data[i].device.ucDesc, wo->data[i].device.ucSize * 2);
1263
1264 rv |= (ro->data[i].device.scCode != wo->data[i].device.scCode);
1265 rv |= (ro->data[i].device.scSize != wo->data[i].device.scSize);
1266 rv |= strcmp((char *)ro->data[i].device.scDesc, (char *)wo->data[i].device.scDesc);
1267
1268 /* model Text description */
1269 rv |= (ro->data[i].model.size != wo->data[i].model.size);
1270 rv |= strcmp(ro->data[i].model.desc, wo->data[i].model.desc);
1271
1272 rv |= (ro->data[i].model.ucLangCode != wo->data[i].model.ucLangCode);
1273 rv |= (ro->data[i].model.ucSize != wo->data[i].model.ucSize);
1274 rv |= memcmp(ro->data[i].model.ucDesc, wo->data[i].model.ucDesc, wo->data[i].model.ucSize * 2);
1275
1276 rv |= (ro->data[i].model.scCode != wo->data[i].model.scCode);
1277 rv |= (ro->data[i].model.scSize != wo->data[i].model.scSize);
1278 rv |= strcmp((char *)ro->data[i].model.scDesc, (char *)wo->data[i].model.scDesc);
1279 }
1280
1281 if (rv)
1282 error ("ProfileSequenceDesc verify failed");
1283 }
1284 }
1285 /* ----------------- */
1286 /* S15Fixed16Array: */
1287 {
1288 static icmS15Fixed16Array *wo;
1289 if (mode == 0) {
1290 unsigned int i;
1291 /* There is no standard Tag that uses icSigS15Fixed16ArrayType, so use a 'custom' tag */
1292 if ((wo = (icmS15Fixed16Array *)wr_icco->add_tag(
1293 wr_icco, str2tag("sf32"), icSigS15Fixed16ArrayType)) == NULL)
1294 return 1;
1295
1296 wo->size = rand_int(0,17); /* Number in array */
1297 wo->allocate((icmBase *)wo); /* Allocate space */
1298 for (i = 0; i < wo->size; i++) {
1299 wo->data[i] = rand_s15f16(); /* Set numbers value */
1300 }
1301 } else {
1302 icmS15Fixed16Array *ro;
1303 unsigned int i;
1304
1305 /* Try and read the tag from the file */
1306 ro = (icmS15Fixed16Array *)rd_icco->read_tag(rd_icco, str2tag("sf32"));
1307 if (ro == NULL)
1308 return 1;
1309
1310 /* Need to check that the cast is appropriate. */
1311 if (ro->ttype != icSigS15Fixed16ArrayType)
1312 return 1;
1313
1314 /* Now check it out */
1315 if (ro->size != wo->size)
1316 error ("S15Fixed16Array size doesn't match");
1317
1318 for (i = 0; i < wo->size; i++) {
1319 rv |= dcomp(ro->data[i], wo->data[i]);
1320 }
1321
1322 if (rv)
1323 error ("S15Fixed16Array verify failed");
1324 }
1325 }
1326 /* ----------------- */
1327 /* Screening: */
1328 {
1329 static icmScreening *wo;
1330 if (mode == 0) {
1331 unsigned int i;
1332 if ((wo = (icmScreening *)wr_icco->add_tag(
1333 wr_icco, icSigScreeningTag, icSigScreeningType)) == NULL)
1334 return 1;
1335
1336 wo->screeningFlag = rand_ScreenEncodings();
1337 wo->channels = rand_int(1,4); /* Number of channels */
1338 wo->allocate((icmBase *)wo); /* Allocate space */
1339 for (i = 0; i < wo->channels; i++) {
1340 wo->data[i].frequency = rand_s15f16(); /* Set screening frequency */
1341 wo->data[i].angle = rand_s15f16(); /* Set screening angle */
1342 wo->data[i].spotShape = rand_SpotShape(); /* Set spot shape */
1343 }
1344 } else {
1345 icmScreening *ro;
1346 unsigned int i;
1347
1348 /* Try and read the tag from the file */
1349 ro = (icmScreening *)rd_icco->read_tag(rd_icco, icSigScreeningTag);
1350 if (ro == NULL)
1351 return 1;
1352
1353 /* Need to check that the cast is appropriate. */
1354 if (ro->ttype != icSigScreeningType)
1355 return 1;
1356
1357 /* Now check it out */
1358 if (ro->channels != wo->channels)
1359 error ("Screening channels doesn't match");
1360
1361 rv |= (ro->screeningFlag != wo->screeningFlag);
1362
1363 for (i = 0; i < wo->channels; i++) {
1364 rv |= dcomp(ro->data[i].frequency, wo->data[i].frequency);
1365 rv |= dcomp(ro->data[i].angle, wo->data[i].angle);
1366 rv |= (ro->data[i].spotShape != wo->data[i].spotShape);
1367 }
1368
1369 if (rv)
1370 error ("Screening verify failed");
1371 }
1372 }
1373 /* ----------------- */
1374 /* Signature: */
1375 {
1376 static icmSignature *wo;
1377 if (mode == 0) {
1378 if ((wo = (icmSignature *)wr_icco->add_tag(
1379 wr_icco, icSigTechnologyTag, icSigSignatureType)) == NULL)
1380 return 1;
1381
1382 wo->sig = rand_TechnologySignature();
1383 } else {
1384 icmSignature *ro;
1385
1386 /* Try and read the tag from the file */
1387 ro = (icmSignature *)rd_icco->read_tag(rd_icco, icSigTechnologyTag);
1388 if (ro == NULL)
1389 return 1;
1390
1391 /* Need to check that the cast is appropriate. */
1392 if (ro->ttype != icSigSignatureType)
1393 return 1;
1394
1395 /* Now check it out */
1396 rv |= (ro->sig != wo->sig);
1397
1398 if (rv)
1399 error ("Signature verify failed");
1400 }
1401 }
1402 /* ----------------- */
1403 /* Text Description: */
1404 {
1405 static icmTextDescription *wo;
1406 char *ts1 = "This is a test description";
1407 unsigned short ts2[27] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',
1408 ' ','d','e','s','c','r','i','p','t','i','o','n',0x0000};
1409 char *ts3 = "This is a test3 description";
1410 if (mode == 0) {
1411 if ((wo = (icmTextDescription *)wr_icco->add_tag(
1412 wr_icco, icSigProfileDescriptionTag, icSigTextDescriptionType)) == NULL)
1413 return 1;
1414
1415 /* Data in tag type wojects is always allocated and freed by the woject */
1416 wo->size = strlen(ts1)+1; /* Allocated and used size of desc, inc null */
1417 wo->allocate((icmBase *)wo);/* Allocate space */
1418 strcpy(wo->desc, ts1); /* Copy the string in */
1419
1420 /* We'll fudge up the Unicode string */
1421 wo->ucLangCode = 1234; /* UniCode language code */
1422 wo->ucSize = 27; /* Allocated and used size of ucDesc in characters, inc null */
1423 wo->allocate((icmBase *)wo);/* Allocate space */
1424 memmove(wo->ucDesc, ts2, 2 * 27); /* Copy string in */
1425
1426 /* Don't really know anything about scriptCode, but fudge some values */
1427 wo->scCode = 23; /* ScriptCode code */
1428 wo->scSize = strlen(ts3)+1; /* Used size of scDesc in bytes, inc null */
1429 /* No allocations, since this has a fixed max of 67 bytes */
1430 if (wo->scSize > 67)
1431 error("ScriptCode string longer than 67");
1432 strcpy((char *)wo->scDesc, ts3); /* Copy the string in */
1433 } else {
1434 icmTextDescription *ro;
1435
1436 /* Try and read the tag from the file */
1437 ro = (icmTextDescription *)rd_icco->read_tag(rd_icco, icSigProfileDescriptionTag);
1438 if (ro == NULL)
1439 return 1;
1440
1441 /* Need to check that the cast is appropriate. */
1442 /* We could have left it icmBase, switched on ro->ttype, & then cast appropriately. */
1443 if (ro->ttype != icSigTextDescriptionType)
1444 return 1;
1445
1446 /* Now check it out */
1447 rv |= (ro->size != wo->size);
1448 rv |= strcmp(ro->desc, wo->desc);
1449
1450 rv |= (ro->ucLangCode != wo->ucLangCode);
1451 rv |= (ro->ucSize != wo->ucSize);
1452 rv |= memcmp(ro->ucDesc, wo->ucDesc, wo->ucSize * 2);
1453
1454 rv |= (ro->scCode != wo->scCode);
1455 rv |= (ro->scSize != wo->scSize);
1456 rv |= strcmp((char *)ro->scDesc, (char *)wo->scDesc);
1457 if (rv)
1458 error ("Text Description verify failed4");
1459 }
1460 }
1461 /* ----- */
1462 /* Text: */
1463 {
1464 static icmText *wo;
1465 char *ts1 = "This is Copyright by me!";
1466 if (mode == 0) {
1467 if ((wo = (icmText *)wr_icco->add_tag(
1468 wr_icco, icSigCopyrightTag, icSigTextType)) == NULL)
1469 return 1;
1470
1471 wo->size = strlen(ts1)+1; /* Allocated and used size of text, inc null */
1472 wo->allocate((icmBase *)wo);/* Allocate space */
1473 strcpy(wo->data, ts1); /* Copy the text in */
1474 } else {
1475 icmText *ro;
1476
1477 /* Try and read the tag from the file */
1478 ro = (icmText *)rd_icco->read_tag(rd_icco, icSigCopyrightTag);
1479 if (ro == NULL)
1480 return 1;
1481
1482 /* Need to check that the cast is appropriate. */
1483 if (ro->ttype != icSigTextType)
1484 return 1;
1485
1486 /* Now check it out */
1487 if (ro->size != wo->size)
1488 error ("Text size doesn't match");
1489
1490 rv |= strcmp(ro->data, wo->data);
1491
1492 if (rv)
1493 error ("Text verify failed");
1494 }
1495 }
1496 /* ---------------- */
1497 /* U16Fixed16Array: */
1498 {
1499 static icmU16Fixed16Array *wo;
1500 if (mode == 0) {
1501 unsigned int i;
1502 /* There is no standard Tag that uses icSigU16Fixed16ArrayType, so use a 'custom' tag */
1503 if ((wo = (icmU16Fixed16Array *)wr_icco->add_tag(
1504 wr_icco, str2tag("uf32"), icSigU16Fixed16ArrayType)) == NULL)
1505 return 1;
1506
1507 wo->size = rand_int(0,17); /* Number in array */
1508 wo->allocate((icmBase *)wo); /* Allocate space */
1509 for (i = 0; i < wo->size; i++) {
1510 wo->data[i] = rand_u16f16(); /* Set numbers value */
1511 }
1512 } else {
1513 icmU16Fixed16Array *ro;
1514 unsigned int i;
1515
1516 /* Try and read the tag from the file */
1517 ro = (icmU16Fixed16Array *)rd_icco->read_tag(rd_icco, str2tag("uf32"));
1518 if (ro == NULL)
1519 return 1;
1520
1521 /* Need to check that the cast is appropriate. */
1522 if (ro->ttype != icSigU16Fixed16ArrayType)
1523 return 1;
1524
1525 /* Now check it out */
1526 if (ro->size != wo->size)
1527 error ("U16Fixed16Array size doesn't match");
1528
1529 for (i = 0; i < wo->size; i++) {
1530 rv |= dcomp(ro->data[i], wo->data[i]);
1531 }
1532
1533 if (rv)
1534 error ("U16Fixed16Array verify failed");
1535 }
1536 }
1537 /* ------------------- */
1538 /* UcrBg - full curve: */
1539 {
1540 static icmUcrBg *wo;
1541 char *ts1 = "UcrBg - full curve info";
1542 if (mode == 0) {
1543 unsigned int i;
1544 if ((wo = (icmUcrBg *)wr_icco->add_tag(
1545 wr_icco, icSigUcrBgTag, icSigUcrBgType)) == NULL)
1546 return 1;
1547
1548 wo->UCRcount = rand_int(2,55); /* Number in UCR curve */
1549 wo->BGcount = rand_int(2,32); /* Number in BG array */
1550 wo->allocate((icmBase *)wo); /* Allocate space for both curves */
1551 for (i = 0; i < wo->UCRcount; i++)
1552 wo->UCRcurve[i] = rand_16f(); /* Set numbers value */
1553 for (i = 0; i < wo->BGcount; i++)
1554 wo->BGcurve[i] = rand_16f(); /* Set numbers value */
1555 wo->size = strlen(ts1)+1; /* Allocated and used size of text, inc null */
1556 wo->allocate((icmBase *)wo); /* Allocate space */
1557 strcpy(wo->string, ts1); /* Copy the text in */
1558 } else {
1559 icmUcrBg *ro;
1560 unsigned int i;
1561
1562 /* Try and read the tag from the file */
1563 ro = (icmUcrBg *)rd_icco->read_tag(rd_icco, icSigUcrBgTag);
1564 if (ro == NULL)
1565 return 1;
1566
1567 /* Need to check that the cast is appropriate. */
1568 if (ro->ttype != icSigUcrBgType)
1569 return 1;
1570
1571 /* Now check it out */
1572 if (ro->UCRcount != wo->UCRcount)
1573 error ("UcrBg UCRcount doesn't match");
1574
1575 if (ro->BGcount != wo->BGcount)
1576 error ("UcrBg BGcount doesn't match");
1577
1578 for (i = 0; i < wo->UCRcount; i++)
1579 rv |= dcomp(ro->UCRcurve[i], wo->UCRcurve[i]);
1580
1581 for (i = 0; i < wo->BGcount; i++)
1582 rv |= dcomp(ro->BGcurve[i], wo->BGcurve[i]);
1583
1584 if (ro->size != wo->size)
1585 error ("Text size doesn't match");
1586
1587 rv |= strcmp(ro->string, wo->string);
1588
1589 if (rv)
1590 error ("UcrBg verify failed");
1591 }
1592 }
1593 /* ------------------- */
1594 /* UcrBg - percentage: */
1595 {
1596 static icmUcrBg *wo;
1597 char *ts1 = "UcrBg - percentage info";
1598 if (mode == 0) {
1599 if ((wo = (icmUcrBg *)wr_icco->add_tag(
1600 wr_icco, str2tag("bfd%"), icSigUcrBgType)) == NULL)
1601 return 1;
1602
1603 wo->UCRcount = 1; /* 1 == UCR percentage */
1604 wo->BGcount = 1; /* 1 == BG percentage */
1605 wo->allocate((icmBase *)wo);/* Allocate space */
1606 wo->UCRcurve[0] = (double) rand_int(0,65535);
1607 wo->BGcurve[0] = (double) rand_int(0,65535);
1608 wo->size = strlen(ts1)+1; /* Allocated and used size of text, inc null */
1609 wo->allocate((icmBase *)wo);/* Allocate space */
1610 strcpy(wo->string, ts1); /* Copy the text in */
1611 } else {
1612 icmUcrBg *ro;
1613
1614 /* Try and read the tag from the file */
1615 ro = (icmUcrBg *)rd_icco->read_tag(rd_icco, str2tag("bfd%"));
1616 if (ro == NULL)
1617 return 1;
1618
1619 /* Need to check that the cast is appropriate. */
1620 if (ro->ttype != icSigUcrBgType)
1621 return 1;
1622
1623 /* Now check it out */
1624 if (ro->UCRcount != wo->UCRcount)
1625 error ("UcrBg UCRcount doesn't match");
1626
1627 if (ro->BGcount != wo->BGcount)
1628 error ("UcrBg BGcount doesn't match");
1629
1630 rv |= (ro->UCRcurve[0] != wo->UCRcurve[0]);
1631 rv |= (ro->BGcurve[0] != wo->BGcurve[0]);
1632
1633 if (ro->size != wo->size)
1634 error ("Text size doesn't match");
1635
1636 rv |= strcmp(ro->string, wo->string);
1637
1638 if (rv)
1639 error ("UcrBg verify failed");
1640 }
1641 }
1642 /* ------------ */
1643 /* UInt16Array: */
1644 {
1645 static icmUInt16Array *wo;
1646 if (mode == 0) {
1647 unsigned int i;
1648 /* There is no standard Tag that uses icSigUInt16ArrayType, so use a 'custom' tag */
1649 if ((wo = (icmUInt16Array *)wr_icco->add_tag(
1650 wr_icco, str2tag("ui16"), icSigUInt16ArrayType)) == NULL)
1651 return 1;
1652
1653 wo->size = rand_int(0,17); /* Number in array */
1654 wo->allocate((icmBase *)wo); /* Allocate space */
1655 for (i = 0; i < wo->size; i++) {
1656 wo->data[i] = rand_o16(); /* Set numbers value */
1657 }
1658 } else {
1659 icmUInt16Array *ro;
1660 unsigned int i;
1661
1662 /* Try and read the tag from the file */
1663 ro = (icmUInt16Array *)rd_icco->read_tag(rd_icco, str2tag("ui16"));
1664 if (ro == NULL)
1665 return 1;
1666
1667 /* Need to check that the cast is appropriate. */
1668 if (ro->ttype != icSigUInt16ArrayType)
1669 return 1;
1670
1671 /* Now check it out */
1672 if (ro->size != wo->size)
1673 error ("UInt16Array size doesn't match");
1674
1675 for (i = 0; i < wo->size; i++) {
1676 rv |= (ro->data[i] != wo->data[i]);
1677 }
1678
1679 if (rv)
1680 error ("UInt16Array verify failed");
1681 }
1682 }
1683 /* ------------ */
1684 /* UInt32Array: */
1685 {
1686 static icmUInt32Array *wo;
1687 if (mode == 0) {
1688 unsigned int i;
1689 /* There is no standard Tag that uses icSigUInt32ArrayType, so use a 'custom' tag */
1690 if ((wo = (icmUInt32Array *)wr_icco->add_tag(
1691 wr_icco, str2tag("ui32"), icSigUInt32ArrayType)) == NULL)
1692 return 1;
1693
1694 wo->size = rand_int(0,18); /* Number in array */
1695 wo->allocate((icmBase *)wo); /* Allocate space */
1696 for (i = 0; i < wo->size; i++) {
1697 wo->data[i] = rand_o32(); /* Set numbers value */
1698 }
1699 } else {
1700 icmUInt32Array *ro;
1701 unsigned int i;
1702
1703 /* Try and read the tag from the file */
1704 ro = (icmUInt32Array *)rd_icco->read_tag(rd_icco, str2tag("ui32"));
1705 if (ro == NULL)
1706 return 1;
1707
1708 /* Need to check that the cast is appropriate. */
1709 if (ro->ttype != icSigUInt32ArrayType)
1710 return 1;
1711
1712 /* Now check it out */
1713 if (ro->size != wo->size)
1714 error ("UInt32Array size doesn't match");
1715
1716 for (i = 0; i < wo->size; i++) {
1717 rv |= (ro->data[i] != wo->data[i]);
1718 }
1719
1720 if (rv)
1721 error ("UInt32Array verify failed");
1722 }
1723 }
1724 /* ------------ */
1725 /* UInt64Array: */
1726 {
1727 static icmUInt64Array *wo;
1728 if (mode == 0) {
1729 unsigned int i;
1730 /* There is no standard Tag that uses icSigUInt64ArrayType, so use a 'custom' tag */
1731 if ((wo = (icmUInt64Array *)wr_icco->add_tag(
1732 wr_icco, str2tag("ui64"), icSigUInt64ArrayType)) == NULL)
1733 return 1;
1734
1735 wo->size = rand_int(0,19); /* Number in array */
1736 wo->allocate((icmBase *)wo); /* Allocate space */
1737 for (i = 0; i < wo->size; i++) {
1738 wo->data[i].l = rand_o32(); /* Set numbers value - low 32 bits */
1739 wo->data[i].h = rand_o32(); /* Set numbers value - low 32 bits */
1740 }
1741 } else {
1742 icmUInt64Array *ro;
1743 unsigned int i;
1744
1745 /* Try and read the tag from the file */
1746 ro = (icmUInt64Array *)rd_icco->read_tag(rd_icco, str2tag("ui64"));
1747 if (ro == NULL)
1748 return 1;
1749
1750 /* Need to check that the cast is appropriate. */
1751 if (ro->ttype != icSigUInt64ArrayType)
1752 return 1;
1753
1754 /* Now check it out */
1755 if (ro->size != wo->size)
1756 error ("UInt64Array size doesn't match");
1757
1758 for (i = 0; i < wo->size; i++) {
1759 rv |= (ro->data[i].l != wo->data[i].l);
1760 rv |= (ro->data[i].h != wo->data[i].h);
1761 }
1762
1763 if (rv)
1764 error ("UInt64Array verify failed");
1765 }
1766 }
1767 /* ----------- */
1768 /* UInt8Array: */
1769 {
1770 static icmUInt8Array *wo;
1771 if (mode == 0) {
1772 unsigned int i;
1773 /* There is no standard Tag that uses icSigUInt8ArrayType, so use a 'custom' tag */
1774 if ((wo = (icmUInt8Array *)wr_icco->add_tag(
1775 wr_icco, str2tag("ui08"), icSigUInt8ArrayType)) == NULL)
1776 return 1;
1777
1778 wo->size = rand_int(0,18); /* Number in array */
1779 wo->allocate((icmBase *)wo); /* Allocate space */
1780 for (i = 0; i < wo->size; i++) {
1781 wo->data[i] = rand_o8(); /* Set numbers value */
1782 }
1783 } else {
1784 icmUInt8Array *ro;
1785 unsigned int i;
1786
1787 /* Try and read the tag from the file */
1788 ro = (icmUInt8Array *)rd_icco->read_tag(rd_icco, str2tag("ui08"));
1789 if (ro == NULL)
1790 return 1;
1791
1792 /* Need to check that the cast is appropriate. */
1793 if (ro->ttype != icSigUInt8ArrayType)
1794 return 1;
1795
1796 /* Now check it out */
1797 if (ro->size != wo->size)
1798 error ("UInt8Array size doesn't match");
1799
1800 for (i = 0; i < wo->size; i++) {
1801 rv |= (ro->data[i] != wo->data[i]);
1802 }
1803
1804 if (rv)
1805 error ("UInt8Array verify failed");
1806 }
1807 }
1808 /* --------------- */
1809 /* VideoCardGamma: (ColorSync specific) */
1810 {
1811 static icmVideoCardGamma *wo;
1812 if (mode == 0) {
1813 int i;
1814 if ((wo = (icmVideoCardGamma *)wr_icco->add_tag(
1815 wr_icco, icSigVideoCardGammaTag, icSigVideoCardGammaType)) == NULL)
1816 return 1;
1817
1818 wo->tagType = icmVideoCardGammaTableType;
1819 wo->u.table.channels = rand_int(1,3);
1820 wo->u.table.entryCount = rand_int(2,1024);
1821 wo->u.table.entrySize = rand_int(1,2);
1822 wo->allocate((icmBase *)wo);
1823 if (wo->u.table.entrySize == 1) {
1824 unsigned char *cp = wo->u.table.data;
1825 for (i=0; i<wo->u.table.channels*wo->u.table.entryCount;i++,cp++)
1826 *cp = (unsigned char)rand_int(0,255);
1827 } else {
1828 unsigned short *sp = wo->u.table.data;
1829 for (i=0; i<wo->u.table.channels*wo->u.table.entryCount;i++,sp++)
1830 *sp = (unsigned short)rand_int(0,65535);
1831 }
1832 } else {
1833 icmVideoCardGamma *ro;
1834 int i;
1835
1836 /* Try and read tag from the file */
1837 ro = (icmVideoCardGamma *)rd_icco->read_tag(rd_icco, icSigVideoCardGammaTag);
1838 if (ro == NULL)
1839 return 1;
1840
1841 /* Need to check that the cast is appropriate */
1842 if (ro->ttype != icSigVideoCardGammaType)
1843 return 1;
1844
1845 /* Now check it out */
1846 rv |= (ro->tagType != wo->tagType);
1847 rv |= (ro->u.table.channels != wo->u.table.channels);
1848 rv |= (ro->u.table.entryCount != wo->u.table.entryCount);
1849 rv |= (ro->u.table.entrySize != wo->u.table.entrySize);
1850 for (i=0; i<ro->u.table.channels*ro->u.table.entryCount*ro->u.table.entrySize; i++) {
1851 rv |= (((char*)ro->u.table.data)[i] != ((char*)wo->u.table.data)[i]);
1852 if (rv) break;
1853 }
1854 if (rv)
1855 error ("VideoCardGamma verify failed");
1856 }
1857 }
1858 /* ------------------ */
1859 /* ViewingConditions: */
1860 {
1861 static icmViewingConditions *wo;
1862 if (mode == 0) {
1863 if ((wo = (icmViewingConditions *)wr_icco->add_tag(
1864 wr_icco, icSigViewingConditionsTag, icSigViewingConditionsType)) == NULL)
1865 return 1;
1866
1867 wo->illuminant.X = rand_XYZ16(); /* XYZ of illuminant in cd/m^2 */
1868 wo->illuminant.Y = rand_XYZ16();
1869 wo->illuminant.Z = rand_XYZ16();
1870 wo->surround.X = rand_XYZ16(); /* XYZ of surround in cd/m^2 */
1871 wo->surround.Y = rand_XYZ16();
1872 wo->surround.Z = rand_XYZ16();
1873 wo->stdIlluminant = rand_Illuminant(); /* Standard illuminent type */
1874 } else {
1875 icmViewingConditions *ro;
1876
1877 /* Try and read the tag from the file */
1878 ro = (icmViewingConditions *)rd_icco->read_tag(rd_icco, icSigViewingConditionsTag);
1879 if (ro == NULL)
1880 return 1;
1881
1882 /* Need to check that the cast is appropriate. */
1883 if (ro->ttype != icSigViewingConditionsType)
1884 return 1;
1885
1886 /* Now check it out */
1887 rv |= dcomp(ro->illuminant.X, wo->illuminant.X);
1888 rv |= dcomp(ro->illuminant.Y, wo->illuminant.Y);
1889 rv |= dcomp(ro->illuminant.Z, wo->illuminant.Z);
1890 rv |= dcomp(ro->surround.X , wo->surround.X);
1891 rv |= dcomp(ro->surround.Y , wo->surround.Y);
1892 rv |= dcomp(ro->surround.Z , wo->surround.Z);
1893 rv |= (ro->stdIlluminant != wo->stdIlluminant);
1894
1895 if (rv)
1896 error ("ViewingConditions verify failed");
1897 }
1898 }
1899 /* ---------- */
1900 /* XYZ array: */
1901 {
1902 static icmXYZArray *wo;
1903 if (mode == 0) {
1904 unsigned int i;
1905 /* Note that tag types icSigXYZType and icSigXYZArrayType are identical */
1906 if ((wo = (icmXYZArray *)wr_icco->add_tag(
1907 wr_icco, icSigMediaWhitePointTag, icSigXYZArrayType)) == NULL)
1908 return 1;
1909
1910 wo->size = rand_int(1,7); /* Should be one XYZ number, but test more */
1911 wo->allocate((icmBase *)wo); /* Allocate space */
1912 for (i = 0; i < wo->size; i++) {
1913 wo->data[i].X = rand_XYZ16(); /* Set numbers value */
1914 wo->data[i].Y = rand_XYZ16();
1915 wo->data[i].Z = rand_XYZ16();
1916 }
1917 } else {
1918 icmXYZArray *ro;
1919 unsigned int i;
1920
1921 /* Try and read the tag from the file */
1922 ro = (icmXYZArray *)rd_icco->read_tag(rd_icco, icSigMediaWhitePointTag);
1923 if (ro == NULL)
1924 return 1;
1925
1926 /* Need to check that the cast is appropriate. */
1927 if (ro->ttype != icSigXYZArrayType)
1928 return 1;
1929
1930 /* Now check it out */
1931 if (ro->size != wo->size)
1932 error ("XYZArray size doesn't match");
1933
1934 for (i = 0; i < wo->size; i++) {
1935 rv |= dcomp(ro->data[i].X, wo->data[i].X);
1936 rv |= dcomp(ro->data[i].Y, wo->data[i].Y);
1937 rv |= dcomp(ro->data[i].Z, wo->data[i].Z);
1938 }
1939
1940 if (rv)
1941 error ("XYZArray verify failed");
1942 }
1943 }
1944
1945 return 0;
1946 }
1947
1948 /* ------------------------------------------------ */
1949 /* Floating point random number generators */
1950 /* These are appropriate for the underlying integer */
1951 /* representations in the icc format. */
1952 /* This is simply as a convenience so that we can */
1953 /* test the full range of representation, and */
1954 /* get away with exact verification. */
1955
1956 /* 32 bit pseudo random sequencer */
1957 static unsigned int seed = 0x12345678;
1958
1959 /* #define PSRAND(S) ((S) * 1103515245 + 12345) */
1960 #define PSRAND(S) (((S) & 0x80000000) ? (((S) << 1) ^ 0xa398655d) : ((S) << 1))
1961
rand_o8()1962 unsigned int rand_o8() {
1963 ORD32 o32;
1964 seed = PSRAND(seed);
1965 o32 = seed & 0xff;
1966 return o32;
1967 }
1968
rand_o16()1969 unsigned int rand_o16() {
1970 ORD32 o32;
1971 seed = PSRAND(seed);
1972 o32 = seed & 0xffff;
1973 return o32;
1974 }
1975
rand_o32()1976 unsigned int rand_o32() {
1977 ORD32 o32;
1978 o32 = seed = PSRAND(seed);
1979 return o32;
1980 }
1981
rand_int(int low,int high)1982 int rand_int(int low, int high) {
1983 int i;
1984 seed = PSRAND(seed);
1985 i = seed % (high - low + 1);
1986 return i + low;
1987 }
1988
rand_u8f8()1989 double rand_u8f8() {
1990 ORD32 o32;
1991 seed = PSRAND(seed);
1992 o32 = seed & 0xffff;
1993 return (double)o32/256.0;
1994 }
1995
rand_u16f16()1996 double rand_u16f16() {
1997 ORD32 o32;
1998 seed = PSRAND(seed);
1999 o32 = seed;
2000 return (double)o32/65536.0;
2001 }
2002
rand_s15f16()2003 double rand_s15f16() {
2004 INR32 i32;
2005 seed = PSRAND(seed);
2006 i32 = seed;
2007 return (double)i32/65536.0;
2008 }
2009
rand_XYZ16()2010 double rand_XYZ16() {
2011 ORD32 o32;
2012 seed = PSRAND(seed);
2013 o32 = seed & 0xffff;
2014 return (double)o32/32768.0;
2015 }
2016
rand_L8()2017 double rand_L8() {
2018 ORD32 o32;
2019 seed = PSRAND(seed);
2020 o32 = seed & 0xff;
2021 return (double)o32/2.550;
2022 }
2023
rand_ab8()2024 double rand_ab8() {
2025 ORD32 o32;
2026 seed = PSRAND(seed);
2027 o32 = seed & 0xff;
2028 return (double)o32-128.0;
2029 }
2030
rand_L16()2031 double rand_L16() {
2032 ORD32 o32;
2033 seed = PSRAND(seed);
2034 o32 = seed & 0xffff;
2035 return (double)o32/652.800; /* 0xff00/100.0 */
2036 }
2037
rand_ab16()2038 double rand_ab16() {
2039 ORD32 o32;
2040 seed = PSRAND(seed);
2041 o32 = seed & 0xffff;
2042 return ((double)o32/256.0)-128.0;
2043 }
2044
rand_8f()2045 double rand_8f() {
2046 unsigned int rv;
2047 seed = PSRAND(seed);
2048 rv = seed & 0xff;
2049 return (double)rv/255.0;
2050 }
2051
rand_16f()2052 double rand_16f() {
2053 unsigned int rv;
2054 seed = PSRAND(seed);
2055 rv = seed & 0xffff;
2056 return (double)rv/65535.0;
2057 }
2058
2059 /* Random selectors for ICC flags and enumerayions */
2060
rand_ScreenEncodings()2061 unsigned int rand_ScreenEncodings() {
2062 unsigned int flags = 0;
2063
2064 if (rand_int(0,1) == 0)
2065 flags |= icPrtrDefaultScreensTrue;
2066
2067 if (rand_int(0,1) == 0)
2068 flags |= icLinesPerInch;
2069
2070 return flags;
2071 }
2072
2073 /* Device attributes */
rand_DeviceAttributes()2074 unsigned int rand_DeviceAttributes() {
2075 unsigned int flags = 0;
2076
2077 if (rand_int(0,1) == 0)
2078 flags |= icTransparency;
2079
2080 if (rand_int(0,1) == 0)
2081 flags |= icMatte;
2082
2083 return flags;
2084 }
2085
2086 /* Profile header flags */
rand_ProfileHeaderFlags()2087 unsigned int rand_ProfileHeaderFlags() {
2088 unsigned int flags = 0;
2089
2090 if (rand_int(0,1) == 0)
2091 flags |= icEmbeddedProfileTrue;
2092
2093 if (rand_int(0,1) == 0)
2094 flags |= icUseWithEmbeddedDataOnly;
2095
2096 return flags;
2097 }
2098
2099
rand_AsciiOrBinaryData()2100 unsigned int rand_AsciiOrBinaryData() {
2101 unsigned int flags = 0;
2102
2103 if (rand_int(0,1) == 0)
2104 flags |= icBinaryData;
2105
2106 return flags;
2107 }
2108
rand_ColorSpaceSignature()2109 icColorSpaceSignature rand_ColorSpaceSignature() {
2110 switch(rand_int(0,25)) {
2111 case 0:
2112 return icSigXYZData;
2113 case 1:
2114 return icSigLabData;
2115 case 2:
2116 return icSigLuvData;
2117 case 3:
2118 return icSigYCbCrData;
2119 case 4:
2120 return icSigYxyData;
2121 case 5:
2122 return icSigRgbData;
2123 case 6:
2124 return icSigGrayData;
2125 case 7:
2126 return icSigHsvData;
2127 case 8:
2128 return icSigHlsData;
2129 case 9:
2130 return icSigCmykData;
2131 case 10:
2132 return icSigCmyData;
2133 case 11:
2134 return icSigMch6Data;
2135 case 12:
2136 return icSig2colorData;
2137 case 13:
2138 return icSig3colorData;
2139 case 14:
2140 return icSig4colorData;
2141 case 15:
2142 return icSig5colorData;
2143 case 16:
2144 return icSig6colorData;
2145 case 17:
2146 return icSig7colorData;
2147 case 18:
2148 return icSig8colorData;
2149 case 19:
2150 return icSig9colorData;
2151 case 20:
2152 return icSig10colorData;
2153 case 21:
2154 return icSig11colorData;
2155 case 22:
2156 return icSig12colorData;
2157 case 23:
2158 return icSig13colorData;
2159 case 24:
2160 return icSig14colorData;
2161 case 25:
2162 return icSig15colorData;
2163 }
2164 return icMaxEnumData;
2165 }
2166
rand_PCS()2167 icColorSpaceSignature rand_PCS() {
2168 switch(rand_int(0,1)) {
2169 case 0:
2170 return icSigXYZData;
2171 case 1:
2172 return icSigLabData;
2173 }
2174 return icMaxEnumData;
2175 }
2176
rand_TechnologySignature()2177 icTechnologySignature rand_TechnologySignature() {
2178 switch(rand_int(0,21)) {
2179 case 0:
2180 return icSigDigitalCamera;
2181 case 1:
2182 return icSigFilmScanner;
2183 case 2:
2184 return icSigReflectiveScanner;
2185 case 3:
2186 return icSigInkJetPrinter;
2187 case 4:
2188 return icSigThermalWaxPrinter;
2189 case 5:
2190 return icSigElectrophotographicPrinter;
2191 case 6:
2192 return icSigElectrostaticPrinter;
2193 case 7:
2194 return icSigDyeSublimationPrinter;
2195 case 8:
2196 return icSigPhotographicPaperPrinter;
2197 case 9:
2198 return icSigFilmWriter;
2199 case 10:
2200 return icSigVideoMonitor;
2201 case 11:
2202 return icSigVideoCamera;
2203 case 12:
2204 return icSigProjectionTelevision;
2205 case 13:
2206 return icSigCRTDisplay;
2207 case 14:
2208 return icSigPMDisplay;
2209 case 15:
2210 return icSigAMDisplay;
2211 case 16:
2212 return icSigPhotoCD;
2213 case 17:
2214 return icSigPhotoImageSetter;
2215 case 18:
2216 return icSigGravure;
2217 case 19:
2218 return icSigOffsetLithography;
2219 case 20:
2220 return icSigSilkscreen;
2221 case 21:
2222 return icSigFlexography;
2223 }
2224 return icMaxEnumTechnology;
2225 }
2226
rand_ProfileClassSignature()2227 icProfileClassSignature rand_ProfileClassSignature() {
2228 switch(rand_int(0,6)) {
2229 case 0:
2230 return icSigInputClass;
2231 case 1:
2232 return icSigDisplayClass;
2233 case 2:
2234 return icSigOutputClass;
2235 case 3:
2236 return icSigLinkClass;
2237 case 4:
2238 return icSigAbstractClass;
2239 case 5:
2240 return icSigColorSpaceClass;
2241 case 6:
2242 return icSigNamedColorClass;
2243 }
2244 return icMaxEnumClass;
2245 }
2246
rand_PlatformSignature()2247 icPlatformSignature rand_PlatformSignature() {
2248 switch(rand_int(0,4)) {
2249 case 0:
2250 return icSigMacintosh;
2251 case 1:
2252 return icSigMicrosoft;
2253 case 2:
2254 return icSigSolaris;
2255 case 3:
2256 return icSigSGI;
2257 case 4:
2258 return icSigTaligent;
2259 }
2260 return icMaxEnumPlatform;
2261 }
2262
rand_MeasurementFlare()2263 icMeasurementFlare rand_MeasurementFlare() {
2264 switch(rand_int(0,1)) {
2265 case 0:
2266 return icFlare0;
2267 case 1:
2268 return icFlare100;
2269 }
2270 return icMaxFlare;
2271 }
2272
rand_MeasurementGeometry()2273 icMeasurementGeometry rand_MeasurementGeometry() {
2274 switch(rand_int(0,2)) {
2275 case 0:
2276 return icGeometryUnknown;
2277 case 1:
2278 return icGeometry045or450;
2279 case 2:
2280 return icGeometry0dord0;
2281 }
2282 return icMaxGeometry;
2283 }
2284
rand_RenderingIntent()2285 icRenderingIntent rand_RenderingIntent() {
2286 switch(rand_int(0,3)) {
2287 case 0:
2288 return icPerceptual;
2289 case 1:
2290 return icRelativeColorimetric;
2291 case 2:
2292 return icSaturation;
2293 case 3:
2294 return icAbsoluteColorimetric;
2295 }
2296 return icMaxEnumIntent;
2297 }
2298
rand_SpotShape()2299 icSpotShape rand_SpotShape() {
2300 switch(rand_int(0,7)) {
2301 case 0:
2302 return icSpotShapeUnknown;
2303 case 1:
2304 return icSpotShapePrinterDefault;
2305 case 2:
2306 return icSpotShapeRound;
2307 case 3:
2308 return icSpotShapeDiamond;
2309 case 4:
2310 return icSpotShapeEllipse;
2311 case 5:
2312 return icSpotShapeLine;
2313 case 6:
2314 return icSpotShapeSquare;
2315 case 7:
2316 return icSpotShapeCross;
2317 }
2318 return icMaxEnumSpot;
2319 }
2320
rand_StandardObserver()2321 icStandardObserver rand_StandardObserver() {
2322 switch(rand_int(0,2)) {
2323 case 0:
2324 return icStdObsUnknown;
2325 case 1:
2326 return icStdObs1931TwoDegrees;
2327 case 2:
2328 return icStdObs1964TenDegrees;
2329 }
2330 return icMaxStdObs;
2331 }
2332
rand_Illuminant()2333 icIlluminant rand_Illuminant() {
2334 switch(rand_int(0,8)) {
2335 case 0:
2336 return icIlluminantUnknown;
2337 case 1:
2338 return icIlluminantD50;
2339 case 2:
2340 return icIlluminantD65;
2341 case 3:
2342 return icIlluminantD93;
2343 case 4:
2344 return icIlluminantF2;
2345 case 5:
2346 return icIlluminantD55;
2347 case 6:
2348 return icIlluminantA;
2349 case 7:
2350 return icIlluminantEquiPowerE;
2351 case 8:
2352 return icIlluminantF8;
2353 }
2354 return icMaxEnumIlluminant;
2355 }
2356
2357 /* Compare doubles with a margine to allow */
2358 /* for floating point handling funnies */
dcomp(double a,double b)2359 int dcomp(double a, double b) {
2360 double dif = fabs(a - b);
2361 double mag = fabs(a) + fabs(b);
2362
2363 return dif > (mag * 1e-10) ? 1 : 0;
2364 }
2365
2366 /* ------------------------------------------------ */
2367 /* Basic printf type error() and warning() routines */
2368
2369 void
error(char * fmt,...)2370 error(char *fmt, ...)
2371 {
2372 va_list args;
2373
2374 fprintf(stderr,"icctest: Error - ");
2375 va_start(args, fmt);
2376 vfprintf(stderr, fmt, args);
2377 va_end(args);
2378 fprintf(stderr, "\n");
2379 exit (-1);
2380 }
2381
2382 void
warning(char * fmt,...)2383 warning(char *fmt, ...)
2384 {
2385 va_list args;
2386
2387 fprintf(stderr,"icctest: Warning - ");
2388 va_start(args, fmt);
2389 vfprintf(stderr, fmt, args);
2390 va_end(args);
2391 fprintf(stderr, "\n");
2392 }
2393