Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#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 */