summaryrefslogtreecommitdiff
path: root/gs/icclib/icc.h
blob: 7631022b133b8f63d1603cd977361f6c9c7e8126 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
#ifndef ICC_H
#define ICC_H
/*
 * International Color Consortium Format Library (icclib)
 *
 * Author:  Graeme W. Gill
 * Date:    99/11/29
 * Version: 2.01
 *
 * Copyright 1997, 1998, 1999, 2000, 2001 Graeme W. Gill
 * Please refer to Licence.txt file for details.
 */

/* We can get some subtle errors if certain headers aren't included */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <math.h>
#include <time.h>
#include <sys/types.h>

/*
 *  Note XYZ scaling to 1.0, not 100.0
 */

/* Make allowance for shared library use */
#ifdef ICCLIB_SHARED		/* Compiling or Using shared library version */
# ifdef ICCLIB_EXPORTS		/* Compiling shared library */
#  ifdef NT
#   define ICCLIB_API __declspec(dllexport)
#  endif /* NT */
# else						/* Using shared library */
#  ifdef NT
#   define ICCLIB_API __declspec(dllimport)
#   ifdef ICCLIB_DEBUG
#    pragma comment (lib, "icclibd.lib")
#   else
#    pragma comment (lib, "icclib.lib")
#   endif	/* DEBUG */
#  endif /* NT */
# endif
#else						/* Using static library */
# define ICCLIB_API	/* empty */
#endif

#ifdef __cplusplus
        extern "C" {
#endif

/* ---------------------------------------------- */
/* Platform specific defines */
/* It is assumed that the native machine size is 32 bits */
#ifndef INR8
#define INR8   signed char		/* 8 bit signed */
#endif
#ifndef INR16
#define INR16  signed short		/* 16 bit signed */
#endif
#ifndef INR32
#define INR32  signed long		/* 32 bit signed */
#endif
#ifndef ORD8
#define ORD8   unsigned char	/* 8 bit unsigned */
#endif
#ifndef ORD16
#define ORD16  unsigned short	/* 16 bit unsigned */
#endif
#ifndef ORD32
#define ORD32  unsigned long	/* 32 bit unsigned */
#endif

#include "icc9809.h"	/* Standard ICC definitions, version ICC.1:1998-09 with mods noted. */

/* Note that the prefix icm is used for the native Machine */
/* equivalents of the file structures defined in icc34.h */

/* ---------------------------------------------- */
/* System interface objects. The defaults can be replaced */
/* for adaption to different system environments */

/* File access class interface definition */
#define ICM_FILE_BASE																		\
        /* Public: */																			\
                                                                                                                                                                                        \
        /* Set current position to offset. Return 0 on success, nz on failure. */				\
        int    (*seek) (struct _icmFile *p, long int offset);									\
                                                                                                                                                                                        \
        /* Read count items of size length. Return number of items successfully read. */ 		\
        size_t (*read) (struct _icmFile *p, void *buffer, size_t size, size_t count);			\
                                                                                                                                                                                        \
        /* write count items of size length. Return number of items successfully written. */ 	\
        size_t (*write)(struct _icmFile *p, void *buffer, size_t size, size_t count);			\
                                                                                                                                                                                        \
        /* flush all write data out to secondary storage. Return nz on failure. */				\
        int (*flush)(struct _icmFile *p);														\
                                                                                                                                                                                        \
        /* we're done with the file object, return nz on failure */								\
        int (*del)(struct _icmFile *p);															\

/* Common file interface class */
struct _icmFile {
        ICM_FILE_BASE
}; typedef struct _icmFile icmFile;

/* - - - - - - - - - - - - - - - - - - - - -  */

/* Implementation of file access class based on standard file I/O */
struct _icmFileStd {
        ICM_FILE_BASE

        /* Private: */
        FILE *fp;
        int   doclose;		/* nz if free should close */
}; typedef struct _icmFileStd icmFileStd;

/* Create given a file name */
icmFile *new_icmFileStd_name(char *name, char *mode);

/* Create given a (binary) FILE* */
icmFile *new_icmFileStd_fp(FILE *fp);

/* - - - - - - - - - - - - - - - - - - - - -  */
/* Implementation of file access class based on a memory image */
struct _icmFileMem {
        ICM_FILE_BASE

        /* Private: */
        unsigned char *start, *cur, *end;

}; typedef struct _icmFileMem icmFileMem;

/* Create a memory image file access class */
icmFile *new_icmFileMem(void *base, size_t length);

/* - - - - - - - - - - - - - - - - - - - - -  */
/* Heap allocator class interface definition */
#define ICM_ALLOC_BASE																		\
        /* Public: */																			\
                                                                                                                                                                                        \
        void *(*malloc) (struct _icmAlloc *p, size_t size);										\
        void *(*calloc) (struct _icmAlloc *p, size_t num, size_t size);							\
        void *(*realloc)(struct _icmAlloc *p, void *ptr, size_t size);							\
        void  (*free)   (struct _icmAlloc *p, void *ptr);										\
                                                                                                                                                                                        \
        /* we're done with the allocator object */												\
        void (*del)(struct _icmAlloc *p);														\

/* Common heap allocator interface class */
struct _icmAlloc {
        ICM_ALLOC_BASE
}; typedef struct _icmAlloc icmAlloc;

/* - - - - - - - - - - - - - - - - - - - - -  */

/* Implementation of heap class based on standard system malloc */
struct _icmAllocStd {
        ICM_ALLOC_BASE
}; typedef struct _icmAllocStd icmAllocStd;

/* Create a standard alloc object */
icmAlloc *new_icmAllocStd(void);

/* --------------------------------- */
/* Assumed constants                 */

#define MAX_CHAN 15		/* Maximum number of color channels */

/* --------------------------------- */
/* tag and other compound structures */

typedef int icmSig;	/* Otherwise un-enumerated 4 byte signature */

typedef struct {
        ORD32 l;			/* High and low components of signed 64 bit */
        INR32 h;
} icmInt64;

typedef struct {
        ORD32 l,h;			/* High and low components of unsigned 64 bit */
} icmUint64;

/* XYZ Number */
typedef struct {
    double  X;
    double  Y;
    double  Z;
} icmXYZNumber;

/* Response 16 number */
typedef struct {
        double	       deviceValue;	/* The device value in range 0.0 - 1.0 */
        double	       measurement;	/* The reading value */
} icmResponse16Number;

/*
 *  read and write method error codes:
 *  0 = sucess
 *  1 = file format/logistical error
 *  2 = system error
 */

#define ICM_BASE_MEMBERS																\
        /* Private: */																		\
        icTagTypeSignature  ttype;		/* The tag type signature */						\
        struct _icc    *icp;			/* Pointer to ICC we're a part of */				\
        int	           touched;			/* Flag for write bookeeping */						\
    int            refcount;		/* Reference count for sharing */					\
        unsigned int   (*get_size)(struct _icmBase *p);										\
        int            (*read)(struct _icmBase *p, unsigned long len, unsigned long of);	\
        int            (*write)(struct _icmBase *p, unsigned long of);						\
        void           (*del)(struct _icmBase *p);											\
                                                                                                                                                                                \
        /* Public: */																		\
        void           (*dump)(struct _icmBase *p, FILE *op, int verb);						\
        int            (*allocate)(struct _icmBase *p);

/* Base tag element data object */
struct _icmBase {
        ICM_BASE_MEMBERS
}; typedef struct _icmBase icmBase;

/* UInt8 Array */
struct _icmUInt8Array {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _size;		/* Size currently allocated */

        /* Public: */
        unsigned long	size;		/* Allocated and used size of the array */
    unsigned int   *data;		/* Pointer to array of data */
}; typedef struct _icmUInt8Array icmUInt8Array;

/* uInt16 Array */
struct _icmUInt16Array {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _size;		/* Size currently allocated */

        /* Public: */
        unsigned long	size;		/* Allocated and used size of the array */
    unsigned int	*data;		/* Pointer to array of data */
}; typedef struct _icmUInt16Array icmUInt16Array;

/* uInt32 Array */
struct _icmUInt32Array {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _size;		/* Size currently allocated */

        /* Public: */
        unsigned long	size;		/* Allocated and used size of the array */
    unsigned int	*data;		/* Pointer to array of data */
}; typedef struct _icmUInt32Array icmUInt32Array;

/* UInt64 Array */
struct _icmUInt64Array {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _size;		/* Size currently allocated */

        /* Public: */
        unsigned long	size;		/* Allocated and used size of the array */
    icmUint64		*data;		/* Pointer to array of hight data */
}; typedef struct _icmUInt64Array icmUInt64Array;

/* u16Fixed16 Array */
struct _icmU16Fixed16Array {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _size;		/* Size currently allocated */

        /* Public: */
        unsigned long	size;		/* Allocated and used size of the array */
    double			*data;		/* Pointer to array of hight data */
}; typedef struct _icmU16Fixed16Array icmU16Fixed16Array;

/* s15Fixed16 Array */
struct _icmS15Fixed16Array {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _size;		/* Size currently allocated */

        /* Public: */
        unsigned long	size;		/* Allocated and used size of the array */
    double			*data;		/* Pointer to array of hight data */
}; typedef struct _icmS15Fixed16Array icmS15Fixed16Array;

/* XYZ Array */
struct _icmXYZArray {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _size;		/* Size currently allocated */

        /* Public: */
        unsigned long	size;		/* Allocated and used size of the array */
    icmXYZNumber	*data;		/* Pointer to array of data */
}; typedef struct _icmXYZArray icmXYZArray;

/* Curve */
typedef enum {
    icmCurveUndef           = -1, /* Undefined curve */
    icmCurveLin             = 0,  /* Linear transfer curve */
    icmCurveGamma           = 1,  /* Gamma power transfer curve */
    icmCurveSpec            = 2   /* Specified curve */
} icmCurveStyle;

/* Curve reverse lookup information */
typedef struct {
        int inited;				/* Flag */
        double rmin, rmax;		/* Range of reverse grid */
        double qscale;			/* Quantising scale factor */
        long rsize;				/* Number of reverse lists */
        int **rlists;			/* Array of list of fwd values that may contain output value */
                                                        /* Offset 0 = allocated size */
                                                        /* Offset 1 = next free index */
                                                        /* Offset 2 = first fwd index */
        unsigned long size;		/* Copy of forward table size */
        double       *data;		/* Copy of forward table data */
} icmRevTable;

struct _icmCurve {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _size;		/* Size currently allocated */
        icmRevTable  rt;			/* Reverse table information */

        /* Public: */
    icmCurveStyle   flag;		/* Style of curve */
        unsigned long	size;		/* Allocated and used size of the array */
    double         *data;  		/* Curve data scaled to range 0.0 - 1.0 */
                                                                /* or data[0] = gamma value */
        /* Translate a value through the curve, return warning flags */
        int (*lookup_fwd) (struct _icmCurve *p, double *out, double *in);	/* Forwards */
        int (*lookup_bwd) (struct _icmCurve *p, double *out, double *in);	/* Backwards */

}; typedef struct _icmCurve icmCurve;

/* Data */
typedef enum {
    icmDataUndef           = -1, /* Undefined data curve */
    icmDataASCII           = 0,  /* ASCII data curve */
    icmDataBin             = 1   /* Binary data */
} icmDataStyle;

struct _icmData {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _size;		/* Size currently allocated */

        /* Public: */
    icmDataStyle	flag;		/* Style of data */
        unsigned long	size;		/* Allocated and used size of the array (inc ascii null) */
    unsigned char	*data;  	/* data or string, NULL if size == 0 */
}; typedef struct _icmData icmData;

/* text */
struct _icmText {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _size;		/* Size currently allocated */

        /* Public: */
        unsigned long	 size;		/* Allocated and used size of desc, inc null */
        char             *data;		/* ascii string (null terminated), NULL if size==0 */
}; typedef struct _icmText icmText;

/* The base date time number */
struct _icmDateTimeNumber {
        ICM_BASE_MEMBERS

        /* Public: */
    unsigned int      year;
    unsigned int      month;
    unsigned int      day;
    unsigned int      hours;
    unsigned int      minutes;
    unsigned int      seconds;
}; typedef struct _icmDateTimeNumber icmDateTimeNumber;

#ifdef NEW
/ * DeviceSettings */

/*
   I think this all works like this:

Valid setting = (   (platform == platform1 and platform1.valid)
                 or (platform == platform2 and platform2.valid)
                 or ...
                )

where
        platformN.valid = (   platformN.combination1.valid
                           or platformN.combination2.valid
                           or ...
                          )

where
        platformN.combinationM.valid = (    platformN.combinationM.settingstruct1.valid
                                        and platformN.combinationM.settingstruct2.valid
                                        and ...
                                       )

where
        platformN.combinationM.settingstructP.valid = (   platformN.combinationM.settingstructP.setting1.valid
                                                       or platformN.combinationM.settingstructP.setting2.valid
                                                       or ...
                                                      )

 */

/* The Settings Structure holds an array of settings of a particular type */
struct _icmSettingStruct {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _num;				/* Size currently allocated */

        /* Public: */
        icSettingsSig       settingSig;		/* Setting identification */
        unsigned long       numSettings; 	/* number of setting values */
        union {								/* Setting values - type depends on Sig */
                icUInt64Number      *resolution;
                icDeviceMedia       *media;
                icDeviceDither      *halftone;
        }
}; typedef struct _icmSettingStruct icmSettingStruct;

/* A Setting Combination holds all arrays of different setting types */
struct _icmSettingComb {
        /* Private: */
        unsigned int   _num;			/* number currently allocated */

        /* Public: */
        unsigned long       numStructs;   /* num of setting structures */
        icmSettingStruct    *data;
}; typedef struct _icmSettingComb icmSettingComb;

/* A Platform Entry holds all setting combinations */
struct _icmPlatformEntry {
        /* Private: */
        unsigned int   _num;			/* number currently allocated */

        /* Public: */
        icPlatformSignature platform;
        unsigned long       numCombinations;    /* num of settings and allocated array size */
        icmSettingComb      *data;
}; typedef struct _icmPlatformEntry icmPlatformEntry;

/* The Device Settings holds all platform settings */
struct _icmDeviceSettings {
        /* Private: */
        unsigned int   _num;			/* number currently allocated */

        /* Public: */
        unsigned long       numPlatforms;	/* num of platforms and allocated array size */
        icmPlatformEntry    *data;			/* Array of pointers to platform entry data */
}; typedef struct _icmDeviceSettings icmDeviceSettings;

#endif /* NEW */

/* lut */
struct _icmLut {
        ICM_BASE_MEMBERS

        /* Private: */
        /* Cache appropriate normalization routines */
        int dinc[MAX_CHAN];				/* Dimensional increment through clut */
        int dcube[1 << MAX_CHAN];		/* Hyper cube offsets */
        icmRevTable  rit;				/* Reverse input table information */
        icmRevTable  rot;				/* Reverse output table information */

        unsigned int inputTable_size;	/* size allocated to input table */
        unsigned int clutTable_size;	/* size allocated to clut table */
        unsigned int outputTable_size;	/* size allocated to output table */

        /* return the minimum and maximum values of the given channel in the clut */
        void (*min_max) (struct _icmLut *pp, double *minv, double *maxv, int chan);

        /* Translate color values through 3x3 matrix, input tables only, multi-dimensional lut, */
        /* or output tables, */
        int (*lookup_matrix)  (struct _icmLut *pp, double *out, double *in);
        int (*lookup_input)   (struct _icmLut *pp, double *out, double *in);
        int (*lookup_clut_nl) (struct _icmLut *pp, double *out, double *in);
        int (*lookup_clut_sx) (struct _icmLut *pp, double *out, double *in);
        int (*lookup_output)  (struct _icmLut *pp, double *out, double *in);

        /* Public: */

        /* return non zero if matrix is non-unity */
        int (*nu_matrix) (struct _icmLut *pp);

    unsigned int	inputChan;      /* Num of input channels */
    unsigned int	outputChan;     /* Num of output channels */
    unsigned int	clutPoints;     /* Num of grid points */
    unsigned int	inputEnt;       /* Num of in-table entries (must be 256 for Lut8) */
    unsigned int	outputEnt;      /* Num of out-table entries (must be 256 for Lut8) */
    double			e[3][3];		/* 3 * 3 array */
        double	        *inputTable;	/* The in-table: [inputChan * inputEnt] */
        double	        *clutTable;		/* The clut: [(clutPoints ^ inputChan) * outputChan] */
        double	        *outputTable;	/* The out-table: [outputChan * outputEnt] */
        /* inputTable  is organized [inputChan 0..ic-1][inputEnt 0..ie-1] */
        /* clutTable   is organized [inputChan 0, 0..cp-1]..[inputChan ic-1, 0..cp-1]
                                                                        [outputChan 0..oc-1] */
        /* outputTable is organized [outputChan 0..oc-1][outputEnt 0..oe-1] */

        /* Helper function to setup the three tables contents */
        int (*set_tables) (
                struct _icmLut *p,						/* Pointer to Lut object */
                void   *cbctx,							/* Opaque callback context pointer value */
                icColorSpaceSignature insig, 			/* Input color space */
                icColorSpaceSignature outsig, 			/* Output color space */
                void (*infunc)(void *cbctx, double *out, double *in),
                                                                /* Input transfer function, inspace->inspace' (NULL = default) */
                double *inmin, double *inmax,			/* Maximum range of inspace' values */
                                                                                                /* (NULL = default) */
                void (*clutfunc)(void *cbntx, double *out, double *in),
                                                                /* inspace' -> outspace' transfer function */
                double *clutmin, double *clutmax,		/* Maximum range of outspace' values */
                                                                                                /* (NULL = default) */
                void (*outfunc)(void *cbntx, double *out, double *in));
                                                                /* Output transfer function, outspace'->outspace (NULL = deflt) */

}; typedef struct _icmLut icmLut;

/* Measurement Data */
struct _icmMeasurement {
        ICM_BASE_MEMBERS

        /* Public: */
    icStandardObserver           observer;       /* Standard observer */
    icmXYZNumber                 backing;        /* XYZ for backing */
    icMeasurementGeometry        geometry;       /* Meas. geometry */
    double                       flare;          /* Measurement flare */
    icIlluminant                 illuminant;     /* Illuminant */
}; typedef struct _icmMeasurement icmMeasurement;

/* Named color */

/* Structure that holds each named color data */
typedef struct {
        struct _icc      *icp;				/* Pointer to ICC we're a part of */
        char              root[32];			/* Root name for color */
        double            pcsCoords[3];		/* icmNC2: PCS coords of color */
        double            deviceCoords[MAX_CHAN];	/* Dev coords of color */
} icmNamedColorVal;

struct _icmNamedColor {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int      _count;			/* Count currently allocated */

        /* Public: */
    unsigned int      vendorFlag;		/* Bottom 16 bits for IC use */
    unsigned int      count;			/* Count of named colors */
    unsigned int      nDeviceCoords;	/* Num of device coordinates */
    char              prefix[32];		/* Prefix for each color name (null terminated) */
    char              suffix[32];		/* Suffix for each color name (null terminated) */
    icmNamedColorVal  *data;			/* Array of [count] color values */
}; typedef struct _icmNamedColor icmNamedColor;

/* textDescription */
struct _icmTextDescription {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned long  _size;			/* Size currently allocated */
        unsigned long  uc_size;			/* uc Size currently allocated */
        int            (*core_read)(struct _icmTextDescription *p, char **bpp, char *end);
        int            (*core_write)(struct _icmTextDescription *p, char **bpp);

        /* Public: */
        unsigned long	  size;			/* Allocated and used size of desc, inc null */
        char              *desc;		/* ascii string (null terminated) */

        unsigned int      ucLangCode;	/* UniCode language code */
        unsigned long	  ucSize;		/* Allocated and used size of ucDesc in wchars, inc null */
        ORD16             *ucDesc;		/* The UniCode description (null terminated) */

        ORD16             scCode;		/* ScriptCode code */
        unsigned long	  scSize;		/* Used size of scDesc in bytes, inc null */
        ORD8              scDesc[67];	/* ScriptCode Description (null terminated, max 67) */
}; typedef struct _icmTextDescription icmTextDescription;

/* Profile sequence structure */
struct _icmDescStruct {
        /* Private: */
        struct _icc      *icp;				/* Pointer to ICC we're a part of */

        /* Public: */
        int             (*allocate)(struct _icmDescStruct *p);	/* Allocate method */
    icmSig            deviceMfg;		/* Dev Manufacturer */
    unsigned int      deviceModel;		/* Dev Model */
    icmUint64         attributes;		/* Dev attributes */
    icTechnologySignature technology;	/* Technology sig */
        icmTextDescription device;			/* Manufacturer text (sub structure) */
        icmTextDescription model;			/* Model text (sub structure) */
}; typedef struct _icmDescStruct icmDescStruct;

/* Profile sequence description */
struct _icmProfileSequenceDesc {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int	 _count;			/* number currently allocated */

        /* Public: */
    unsigned int      count;			/* Number of descriptions */
        icmDescStruct     *data;			/* array of [count] descriptions */
}; typedef struct _icmProfileSequenceDesc icmProfileSequenceDesc;

/* signature (only ever used for technology ??) */
struct _icmSignature {
        ICM_BASE_MEMBERS

        /* Public: */
    icTechnologySignature sig;	/* Signature */
}; typedef struct _icmSignature icmSignature;

/* Per channel Screening Data */
typedef struct {
        /* Public: */
    double            frequency;		/* Frequency */
    double            angle;			/* Screen angle */
    icSpotShape       spotShape;		/* Spot Shape encodings below */
} icmScreeningData;

struct _icmScreening {
        ICM_BASE_MEMBERS

        /* Private: */
        unsigned int   _channels;			/* number currently allocated */

        /* Public: */
    unsigned int      screeningFlag;	/* Screening flag */
    unsigned int      channels;			/* Number of channels */
    icmScreeningData  *data;			/* Array of screening data */
}; typedef struct _icmScreening icmScreening;

/* Under color removal, black generation */
struct _icmUcrBg {
        ICM_BASE_MEMBERS

        /* Private: */
    unsigned int      UCR_count;		/* Currently allocated UCR count */
    unsigned int      BG_count;			/* Currently allocated BG count */
        unsigned long	  _size;			/* Currently allocated string size */

        /* Public: */
    unsigned int      UCRcount;			/* Undercolor Removal Curve length */
    double           *UCRcurve;		    /* The array of UCR curve values, 0.0 - 1.0 */
                                                                                /* or 0.0 - 100 % if count = 1 */
    unsigned int      BGcount;			/* Black generation Curve length */
    double           *BGcurve;			/* The array of BG curve values, 0.0 - 1.0 */
                                                                                /* or 0.0 - 100 % if count = 1 */
        unsigned long	  size;				/* Allocated and used size of desc, inc null */
        char              *string;			/* UcrBg description (null terminated) */
}; typedef struct _icmUcrBg icmUcrBg;

/* viewingConditionsType */
struct _icmViewingConditions {
        ICM_BASE_MEMBERS

        /* Public: */
    icmXYZNumber    illuminant;		/* In candelas per sq. meter */
    icmXYZNumber    surround;		/* In candelas per sq. meter */
    icIlluminant    stdIlluminant;	/* See icIlluminant defines */
}; typedef struct _icmViewingConditions icmViewingConditions;

/* Postscript Color Rendering Dictionary names type */
struct _icmCrdInfo {
        ICM_BASE_MEMBERS
        /* Private: */
    unsigned long    _ppsize;		/* Currently allocated size */
        unsigned long    _crdsize[4];	/* Currently allocated sizes */

        /* Public: */
    unsigned long    ppsize;		/* Postscript product name size (including null) */
    char            *ppname;		/* Postscript product name (null terminated) */
        unsigned long    crdsize[4];	/* Rendering intent 0-3 CRD names sizes (icluding null) */
        char            *crdname[4];	/* Rendering intent 0-3 CRD names (null terminated) */
}; typedef struct _icmCrdInfo icmCrdInfo;

/* Apple ColorSync 2.5 video card gamma type */
struct _icmVideoCardGammaTable {
        unsigned short   channels;		/* # of gamma channels (1 or 3) */
        unsigned short   entryCount; 	/* 1-based number of entries per channel */
        unsigned short   entrySize;		/* size in bytes of each entry */
        void            *data;			/* variable size data */
}; typedef struct _icmVideoCardGammaTable icmVideoCardGammaTable;

struct _icmVideoCardGammaFormula {
        double           redGamma;		/* must be > 0.0 */
        double           redMin;		/* must be > 0.0 and < 1.0 */
        double           redMax;		/* must be > 0.0 and < 1.0 */
        double           greenGamma;   	/* must be > 0.0 */
        double           greenMin;		/* must be > 0.0 and < 1.0 */
        double           greenMax;		/* must be > 0.0 and < 1.0 */
        double           blueGamma;		/* must be > 0.0 */
        double           blueMin;		/* must be > 0.0 and < 1.0 */
        double           blueMax;		/* must be > 0.0 and < 1.0 */
}; typedef struct _icmVideoCardGammaFormula icmVideoCardGammaFormula;

enum {
        icmVideoCardGammaTableType = 0,
        icmVideoCardGammaFormulaType = 1
};

struct _icmVideoCardGamma {
        ICM_BASE_MEMBERS
        unsigned long                tagType;		/* eg. table or formula, use above enum */
        union {
                icmVideoCardGammaTable   table;
                icmVideoCardGammaFormula formula;
        } u;
}; typedef struct _icmVideoCardGamma icmVideoCardGamma;

/* ------------------------------------------------- */
/* The Profile header */
struct _icmHeader {
        /* Private: */
        unsigned int           (*get_size)(struct _icmHeader *p);
        int                    (*read)(struct _icmHeader *p, unsigned long len, unsigned long of);
        int                    (*write)(struct _icmHeader *p, unsigned long of);
        void                   (*del)(struct _icmHeader *p);
        struct _icc            *icp;			/* Pointer to ICC we're a part of */
    unsigned int            size;			/* Profile size in bytes */

        /* public: */
        void                   (*dump)(struct _icmHeader *p, FILE *op, int verb);

        /* Values that must be set before writing */
    icProfileClassSignature deviceClass;	/* Type of profile */
    icColorSpaceSignature   colorSpace;		/* Clr space of data */
    icColorSpaceSignature   pcs;			/* PCS: XYZ or Lab */
    icRenderingIntent       renderingIntent;/* Rendering intent */

        /* Values that should be set before writing */
    icmSig                  manufacturer;	/* Dev manufacturer */
    icmSig		            model;			/* Dev model */
    icmUint64               attributes;		/* Device attributes.l */
    unsigned int            flags;			/* Various bits */

        /* Values that may optionally be set before writing */
    /* icmUint64            attributes;		   Device attributes.h (see above) */
    icmSig                  creator;		/* Profile creator */

        /* Values that are not normally set, since they have defaults */
    icmSig                  cmmId;			/* CMM for profile */
    int            			majv, minv, bfv;/* Format version - major, minor, bug fix */
    icmDateTimeNumber       date;			/* Creation Date */
    icPlatformSignature     platform;		/* Primary Platform */
    icmXYZNumber            illuminant;		/* Profile illuminant */

}; typedef struct _icmHeader icmHeader;

/* ---------------------------------------------------------- */
/* Objects for accessing lookup functions */

/* Public: Parameter to get_luobj function */
typedef enum {
    icmFwd           = 0,  /* Device to PCS, or Device 1 to Last Device */
    icmBwd           = 1,  /* PCS to Device, or Last Device to Device */
    icmGamut         = 2,  /* PCS Gamut check */
    icmPreview       = 3   /* PCS to PCS preview */
} icmLookupFunc;

/* Public: Parameter to get_luobj function */
typedef enum {
    icmLuOrdNorm     = 0,  /* Normal profile preference: Lut, matrix, monochrome */
    icmLuOrdRev      = 1   /* Reverse profile preference: monochrome, matrix, monochrome */
} icmLookupOrder;

/* Public: Lookup algorithm object type */
typedef enum {
    icmMonoFwdType       = 0,	/* Monochrome, Forward */
    icmMonoBwdType       = 1,	/* Monochrome, Backward */
    icmMatrixFwdType     = 2,	/* Matrix, Forward */
    icmMatrixBwdType     = 3,	/* Matrix, Backward */
    icmLutType           = 4	/* Multi-dimensional Lookup Table */
} icmLuAlgType;

#define LU_ICM_BASE_MEMBERS																	\
        /* Private: */																		\
        icmLuAlgType   ttype;		    	/* The object tag */							\
        struct _icc    *icp;				/* Pointer to ICC we're a part of */			\
        icRenderingIntent intent;			/* Effective intent */							\
        icmLookupFunc function;				/* Functionality being used */					\
        icmXYZNumber pcswht, whitePoint, blackPoint;	/* White and black point info */	\
        double toAbs[3][3];					/* Matrix to convert from relative to absolute */ \
        double fromAbs[3][3];				/* Matrix to convert from absolute to relative */ \
    icColorSpaceSignature inSpace;		/* Native Clr space of input */					\
    icColorSpaceSignature outSpace;		/* Native Clr space of output */				\
        icColorSpaceSignature pcs;			/* Native PCS */								\
    icColorSpaceSignature e_inSpace;	/* Effective Clr space of input */				\
    icColorSpaceSignature e_outSpace;	/* Effective Clr space of output */				\
        icColorSpaceSignature e_pcs;		/* Effective PCS */								\
                                                                                                                                                                                \
        /* Public: */																		\
        void           (*del)(struct _icmLuBase *p);										\
                                    /* Internal native colorspaces */     							\
        void           (*lutspaces) (struct _icmLuBase *p, icColorSpaceSignature *ins, int *inn,	\
                                                           icColorSpaceSignature *outs, int *outn);	\
                                                                                                \
                                 /* External effecive colorspaces */							\
        void           (*spaces) (struct _icmLuBase *p, icColorSpaceSignature *ins, int *inn,	\
                                         icColorSpaceSignature *outs, int *outn,				\
                                         icmLuAlgType *alg, icRenderingIntent *intt, 			\
                                         icmLookupFunc *fnc, icColorSpaceSignature *pcs); 		\
                                                                                                                                                                                        \
        /* Get the effective input space and output space ranges */								\
        void (*get_ranges) (struct _icmLuBase *p,												\
                double *inmin, double *inmax,		/* Maximum range of inspace values */			\
                double *outmin, double *outmax);	/* Maximum range of outspace values */			\
                                                                                                                                                                                        \
        void           (*wh_bk_points)(struct _icmLuBase *p, icmXYZNumber *wht, icmXYZNumber *blk);	\
        int            (*lookup) (struct _icmLuBase *p, double *out, double *in);

        /* Translate color values through profile */
        /* 0 = success */
        /* 1 = warning: clipping occured */
        /* 2 = fatal: other error */

/* Base lookup object */
struct _icmLuBase {
        LU_ICM_BASE_MEMBERS
}; typedef struct _icmLuBase icmLuBase;

/* Monochrome  Fwd & Bwd type object */
struct _icmLuMono {
        LU_ICM_BASE_MEMBERS
        icmCurve    *grayCurve;

        /* Overall lookups */
        int (*fwd_lookup) (struct _icmLuBase *p, double *out, double *in);
        int (*bwd_lookup) (struct _icmLuBase *p, double *out, double *in);

        /* Components of lookup */
        int (*fwd_curve) (struct _icmLuMono *p, double *out, double *in);
        int (*fwd_map)   (struct _icmLuMono *p, double *out, double *in);
        int (*fwd_abs)   (struct _icmLuMono *p, double *out, double *in);
        int (*bwd_abs)   (struct _icmLuMono *p, double *out, double *in);
        int (*bwd_map)   (struct _icmLuMono *p, double *out, double *in);
        int (*bwd_curve) (struct _icmLuMono *p, double *out, double *in);

}; typedef struct _icmLuMono icmLuMono;

/* 3D Matrix Fwd & Bwd type object */
struct _icmLuMatrix {
        LU_ICM_BASE_MEMBERS
        icmCurve    *redCurve, *greenCurve, *blueCurve;
        icmXYZArray *redColrnt, *greenColrnt, *blueColrnt;
    double		mx[3][3];	/* 3 * 3 conversion matrix */
    double		bmx[3][3];	/* 3 * 3 backwards conversion matrix */

        /* Overall lookups */
        int (*fwd_lookup) (struct _icmLuBase *p, double *out, double *in);
        int (*bwd_lookup) (struct _icmLuBase *p, double *out, double *in);

        /* Components of lookup */
        int (*fwd_curve)  (struct _icmLuMatrix *p, double *out, double *in);
        int (*fwd_matrix) (struct _icmLuMatrix *p, double *out, double *in);
        int (*fwd_abs)    (struct _icmLuMatrix *p, double *out, double *in);
        int (*bwd_abs)    (struct _icmLuMatrix *p, double *out, double *in);
        int (*bwd_matrix) (struct _icmLuMatrix *p, double *out, double *in);
        int (*bwd_curve)  (struct _icmLuMatrix *p, double *out, double *in);

}; typedef struct _icmLuMatrix icmLuMatrix;

/* Multi-D. Lut type object */
struct _icmLuLut {
        LU_ICM_BASE_MEMBERS

        /* private: */
        icmLut *lut;								/* Lut to use */
        int    usematrix;							/* non-zero if matrix should be used */
    double imx[3][3];							/* 3 * 3 inverse conversion matrix */
        int    imx_valid;							/* Inverse matrix is valid */
        void (*in_normf)(double *out, double *in);	/* Lut input data normalizing function */
        void (*in_denormf)(double *out, double *in);/* Lut input data de-normalizing function */
        void (*out_normf)(double *out, double *in);	/* Lut output data normalizing function */
        void (*out_denormf)(double *out, double *in);/* Lut output de-normalizing function */
        void (*e_in_denormf)(double *out, double *in);/* Effective input de-normalizing function */
        void (*e_out_denormf)(double *out, double *in);/* Effecive output de-normalizing function */
        /* function chosen out of lut->lookup_clut_sx and lut->lookup_clut_nl to imp. clut() */
        int (*lookup_clut) (struct _icmLut *pp, double *out, double *in);	/* clut function */

        /* public: */

        /* Components of lookup */
        int (*in_abs)  (struct _icmLuLut *p, double *out, double *in);	/* Should be in icmLut ? */
        int (*matrix)  (struct _icmLuLut *p, double *out, double *in);
        int (*input)   (struct _icmLuLut *p, double *out, double *in);
        int (*clut)    (struct _icmLuLut *p, double *out, double *in);
        int (*output)  (struct _icmLuLut *p, double *out, double *in);
        int (*out_abs) (struct _icmLuLut *p, double *out, double *in);	/* Should be in icmLut ? */

        /* Some inverse components */
        /* Should be in icmLut ??? */
        int (*inv_out_abs) (struct _icmLuLut *p, double *out, double *in);
        int (*inv_output)  (struct _icmLuLut *p, double *out, double *in);
        /* inv_clut is beyond scope of icclib. See argyll for solution! */
        int (*inv_input)   (struct _icmLuLut *p, double *out, double *in);
        int (*inv_matrix)  (struct _icmLuLut *p, double *out, double *in);
        int (*inv_in_abs)  (struct _icmLuLut *p, double *out, double *in);

        /* Get various types of information about the LuLut */
        void (*get_info) (struct _icmLuLut *p, icmLut **lutp,
                         icmXYZNumber *pcswhtp, icmXYZNumber *whitep,
                         icmXYZNumber *blackp);

        /* Get the native input space and output space ranges */
        void (*get_lutranges) (struct _icmLuLut *p,
                double *inmin, double *inmax,		/* Maximum range of inspace values */
                double *outmin, double *outmax);	/* Maximum range of outspace values */

        /* Get the matrix contents */
        void (*get_matrix) (struct _icmLuLut *p, double m[3][3]);

}; typedef struct _icmLuLut icmLuLut;

/* ---------------------------------------------------------- */
/* A tag */
typedef struct {
    icTagSignature      sig;			/* The tag signature */
        icTagTypeSignature  ttype;			/* The tag type signature */
    unsigned int        offset;			/* File offset to start header */
    unsigned int        size;			/* Size in bytes */
        icmBase            *objp;			/* In memory data structure */
} icmTag;

/* Pseudo enumerations valid as parameter to get_luobj(): */

/* To be specified where an intent is not appropriate */
#define icmDefaultIntent ((icRenderingIntent)98)

/* Pseudo PCS colospace used to indicate the native PCS */
#define icmSigDefaultData ((icColorSpaceSignature) 0x0)

/* The ICC object */
struct _icc {
        /* Public: */
        unsigned int (*get_size)(struct _icc *p);				/* Return total size needed, 0 = err. */
        int          (*read)(struct _icc *p, icmFile *fp, unsigned long of);	/* Returns error code */
        int          (*write)(struct _icc *p, icmFile *fp, unsigned long of);/* Returns error code */
        void         (*dump)(struct _icc *p, FILE *op, int verb);	/* Dump whole icc */
        void         (*del)(struct _icc *p);						/* Free whole icc */
        int          (*find_tag)(struct _icc *p, icTagSignature sig);
                                                                                                                        /* Returns 1 if found, 2 readable */
        icmBase *    (*read_tag)(struct _icc *p, icTagSignature sig);
                                                                                                                        /* Returns pointer to object */
        icmBase *    (*add_tag)(struct _icc *p, icTagSignature sig, icTagTypeSignature ttype);
                                                                                                                        /* Returns pointer to object */
        int          (*rename_tag)(struct _icc *p, icTagSignature sig, icTagSignature sigNew);
                                                                                                                        /* Rename and existing tag */
        icmBase *    (*link_tag)(struct _icc *p, icTagSignature sig, icTagSignature ex_sig);
                                                                                                                        /* Returns pointer to object */
        int          (*unread_tag)(struct _icc *p, icTagSignature sig);
                                                                                                                /* Unread a tag (free on refcount == 0 */
        int          (*read_all_tags)(struct _icc *p); /* Read all the tags, non-zero on error. */

        int          (*delete_tag)(struct _icc *p, icTagSignature sig);
                                                                                                                        /* Returns 0 if deleted OK */
        icmLuBase *  (*get_luobj) (struct _icc *p,
                                     icmLookupFunc func,			/* Functionality */
                                         icRenderingIntent intent,		/* Intent */
                                         icColorSpaceSignature pcsor,	/* PCS overide (0 = def) */
                                         icmLookupOrder order);			/* Search Order */
                                         /* Return appropriate lookup object */
                                         /* NULL on error, check errc+err for reason */

    icmHeader       *header;			/* The header */
        char             err[512];			/* Error message */
        int              errc;				/* Error code */

        /* Private: ? */
        icmAlloc        *al;				/* Heap allocator */
        int              del_al;			/* NZ if heap allocator should be deleted */
        icmFile         *fp;				/* File associated with object */
        unsigned long    of;				/* Offset of the profile within the file */
    unsigned int     count;				/* Num tags in the profile */
    icmTag          *data;    			/* The tagTable and tagData */

        }; typedef struct _icc icc;

/* ========================================================== */
/* Utility structures and declarations */

/* Structure to hold pseudo-hilbert counter info */
struct _psh {
        int      di;	/* Dimensionality */
        unsigned res;	/* Resolution per coordinate */
        unsigned bits;	/* Bits per coordinate */
        unsigned ix;	/* Current binary index */
        unsigned tmask;	/* Total 2^n count mask */
        unsigned count;	/* Usable count */
}; typedef struct _psh psh;

/* Type of encoding to be returned as a string */
typedef enum {
    icmScreenEncodings,
    icmDeviceAttributes,
        icmProfileHeaderFlags,
        icmAsciiOrBinaryData,
        icmTagSignature,
        icmTechnologySignature,
        icmTypeSignature,
        icmColorSpaceSignature,
        icmProfileClassSignaure,
        icmPlatformSignature,
        icmMeasurementFlare,
        icmMeasurementGeometry,
        icmRenderingIntent,
        icmSpotShape,
        icmStandardObserver,
        icmIlluminant,
        icmLuAlg
} icmEnumType;

/* ========================================================== */
/* Public function declarations */
/* Create an empty object. Return null on error */
extern ICCLIB_API icc *new_icc(void);				/* Default allocator */
extern ICCLIB_API icc *new_icc_a(icmAlloc *al);		/* With allocator class */

/* - - - - - - - - - - - - - */
/* Some useful utilities: */

/* Return a string that represents a tag */
extern ICCLIB_API char *tag2str(int tag);

/* Return a tag created from a string */
extern ICCLIB_API int str2tag(const char *str);

/* Return a string description of the given enumeration value */
extern ICCLIB_API const char *icm2str(icmEnumType etype, int enumval);

/* CIE XYZ to perceptual Lab */
extern ICCLIB_API void icmXYZ2Lab(icmXYZNumber *w, double *out, double *in);

/* Perceptual Lab to CIE XYZ */
extern ICCLIB_API void icmLab2XYZ(icmXYZNumber *w, double *out, double *in);

/* The standard D50 illuminant value */
extern ICCLIB_API icmXYZNumber icmD50;

/* The standard D65 illuminant value */
extern ICCLIB_API icmXYZNumber icmD65;

/* The default black value */
extern ICCLIB_API icmXYZNumber icmBlack;

/* Initialise a pseudo-hilbert grid counter, return total usable count. */
extern ICCLIB_API unsigned psh_init(psh *p, int di, unsigned res, int co[]);

/* Reset the counter */
extern ICCLIB_API void psh_reset(psh *p);

/* Increment pseudo-hilbert coordinates */
/* Return non-zero if count rolls over to 0 */
extern ICCLIB_API int psh_inc(psh *p, int co[]);

/* Chromatic Adaption transform utility */
/* Return a 3x3 chromatic adaption matrix */
void icmChromAdaptMatrix(
        int flags,				/* Flags as defined below */
        icmXYZNumber d_wp,		/* Destination white point */
        icmXYZNumber s_wp,		/* Source white point */
        double mat[3][3]		/* Destination matrix */
);

#define ICM_CAM_BRADFORD	0x0001	/* Use Bradford sharpened response space */
#define ICM_CAM_MULMATRIX	0x0002	/* Transform the given matrix */

/* Return the normal Delta E given two Lab values */
extern ICCLIB_API double icmLabDE(double *in1, double *in2);

/* Return the normal Delta E squared, given two Lab values */
extern ICCLIB_API double icmLabDEsq(double *in1, double *in2);

/* Return the CIE94 Delta E color difference measure for two Lab values */
extern ICCLIB_API double icmCIE94(double *in1, double *in2);

/* Return the CIE94 Delta E color difference measure squared, for two Lab values */
extern ICCLIB_API double icmCIE94sq(double *in1, double *in2);

/* Simple macro to transfer an array to an XYZ number */
#define icmAry2XYZ(xyz, ary) ((xyz).X = (ary)[0], (xyz).Y = (ary)[1], (xyz).Z = (ary)[2])

/* And the reverse */
#define icmXYZ2Ary(ary, xyz) ((ary)[0] = (xyz).X, (ary)[1] = (xyz).Y, (ary)[2] = (xyz).Z)

/* ---------------------------------------------------------- */

#ifdef __cplusplus
        }
#endif

#endif /* ICC_H */