summaryrefslogtreecommitdiff
path: root/.pc/04_CVE-2012-4405.diff/icc/icc.c
diff options
context:
space:
mode:
Diffstat (limited to '.pc/04_CVE-2012-4405.diff/icc/icc.c')
-rw-r--r--.pc/04_CVE-2012-4405.diff/icc/icc.c17833
1 files changed, 0 insertions, 17833 deletions
diff --git a/.pc/04_CVE-2012-4405.diff/icc/icc.c b/.pc/04_CVE-2012-4405.diff/icc/icc.c
deleted file mode 100644
index 68668d0..0000000
--- a/.pc/04_CVE-2012-4405.diff/icc/icc.c
+++ /dev/null
@@ -1,17833 +0,0 @@
-
-/*
- * International Color Consortium Format Library (icclib)
- * For ICC profile version 3.4
- *
- * Author: Graeme W. Gill
- * Date: 2002/04/22
- * Version: 2.15
- *
- * Copyright 1997 - 2012 Graeme W. Gill
- *
- * This material is licensed with an "MIT" free use license:-
- * see the License.txt file in this directory for licensing details.
- */
-
-/*
- * TTBD:
- *
- * Add a "warning mode" to file reading, in which file format
- * errors are ignored where possible, rather than generating
- * a fatal error (see ICM_STRICT #define).
- *
- * NameColor Dump doesn't handle device space correctly -
- * should use appropriate interpretation in case device is Lab etc.
- *
- * Should recognise & honour unicode 0xFFFE endian marker.
- * Should generate it on writing too ?
- *
- * Add support for copying tags from one icc to another.
- *
- * Should fix all write_number failure errors to indicate failed value.
- * (Partially implemented - need to check all write_number functions)
- *
- * Make write fail error messages be specific on which element failed.
- *
- * Should add named color space lookup function support.
- *
- * Would be nice to add generic ability to add new tag type handling,
- * so that the base library doesn't need to be modified (ie. VideoCardGamma) ?
- *
- * Need to add DeviceSettings and OutputResponse tags to bring up to
- * ICC.1:1998-09 [started but not complete]
- *
- */
-
-#undef ICM_STRICT /* Not fully implimented - switch off strict checking of file format */
-
-/* Make the default grid points of the Lab clut be symetrical about */
-/* a/b 0.0, and also make L = 100.0 fall on a grid point. */
-#define SYMETRICAL_DEFAULT_LAB_RANGE
-
-#define _ICC_C_ /* Turn on implimentation code */
-
-#undef DEBUG_SETLUT /* Show each value being set in setting lut contents */
-#undef DEBUG_SETLUT_CLIP /* Show clipped values when setting LUT */
-#undef DEBUG_LULUT /* Show each value being looked up from lut contents */
-#undef DEBUG_LLULUT /* Debug individual lookup steps (not fully implemented) */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-#include <time.h>
-#ifdef __sun
-#include <unistd.h>
-#endif
-#if defined(__IBMC__) && defined(_M_IX86)
-#include <float.h>
-#endif
-#include "icc.h"
-
-#ifdef _MSC_VER
-#define vsnprintf _vsnprintf
-#define snprintf _snprintf
-#endif
-
-/* ========================================================== */
-/* Default system interface object implementations */
-
-#ifndef SEPARATE_STD
-#define COMBINED_STD
-
-#include "iccstd.c"
-
-#undef COMBINED_STD
-#endif /* SEPARATE_STD */
-
-/* Forced byte alignment for tag table and tags */
-#define ALIGN_SIZE 4
-
-/* =========================================================== */
-
-#ifdef DEBUG_SETLUT
-#undef DBGSL
-#define DBGSL(xxx) printf xxx ;
-#else
-#undef DBGSL
-#define DBGSL(xxx)
-#endif
-
-#if defined(DEBUG_SETLUT) || defined(DEBUG_SETLUT_CLIP)
-#undef DBGSLC
-#define DBGSLC(xxx) printf xxx ;
-#else
-#undef DBGSLC
-#define DBGSLC(xxx)
-#endif
-
-#ifdef DEBUG_LULUT
-#undef DBGLL
-#define DBGLL(xxx) printf xxx ;
-#else
-#undef DBGLL
-#define DBGLL(xxx)
-#endif
-
-#ifdef DEBUG_LLULUT
-#undef DBLLL
-#define DBLLL(xxx) printf xxx ;
-#else
-#undef DBLLL
-#define DBLLL(xxx)
-#endif
-
-/* =========================================================== */
-/* Overflow protected unsigned int arithmatic functions. */
-/* These functions saturate rather than wrapping around. */
-/* (Divide doesn't need protection) */
-/* They return UINT_MAX if there was an overflow */
-
-/* a + b */
-static unsigned int sat_add(unsigned int a, unsigned int b) {
- if (b > (UINT_MAX - a))
- return UINT_MAX;
- return a + b;
-}
-
-/* a - b */
-static unsigned int sat_sub(unsigned int a, unsigned int b) {
- if (a < b)
- return UINT_MAX;
- return a - b;
-}
-
-/* a * b */
-static unsigned int sat_mul(unsigned int a, unsigned int b) {
- unsigned int c;
-
- if (a == 0 || b == 0)
- return 0;
-
- if (a > (UINT_MAX/b))
- return UINT_MAX;
- else
- return a * b;
-}
-
-/* A + B + C */
-#define sat_addadd(A, B, C) sat_add(A, sat_add(B, C))
-
-/* A + B * C */
-#define sat_addmul(A, B, C) sat_add(A, sat_mul(B, C))
-
-/* A + B + C * D */
-#define sat_addaddmul(A, B, C, D) sat_add(A, sat_add(B, sat_mul(C, D)))
-
-/* A * B * C */
-#define sat_mul3(A, B, C) sat_mul(A, sat_mul(B, C))
-
-/* a ^ b */
-static unsigned int sat_pow(unsigned int a, unsigned int b) {
- unsigned int c = 1;
- for (; b > 0; b--) {
- c = sat_mul(c, a);
- if (c == UINT_MAX)
- break;
- }
- return c;
-}
-
-/* Alignment */
-static unsigned int sat_align(unsigned int align_size, unsigned int a) {
- align_size--;
-
- if (align_size > (UINT_MAX - a))
- return UINT_MAX;
-
- return (a + align_size) & ~align_size;
-}
-
-/* These test functions detect whether an overflow would occur */
-
-/* Return nz if add would overflow */
-static int ovr_add(unsigned int a, unsigned int b) {
-
- if (b > (UINT_MAX - a))
- return 1;
- return 0;
-}
-
-/* Return nz if sub would overflow */
-static int ovr_sub(unsigned int a, unsigned int b) {
- if (a < b)
- return 1;
- return 0;
-}
-
-/* Return nz if mult would overflow */
-static int ovr_mul(unsigned int a, unsigned int b) {
- if (a > (UINT_MAX/b))
- return 1;
- return 0;
-}
-
-
-/* size_t versions of saturating arithmatic */
-
-#ifndef SIZE_MAX
-# define SIZE_MAX ((size_t)(-1))
-#endif
-
-/* a + b */
-static size_t ssat_add(size_t a, size_t b) {
- if (b > (SIZE_MAX - a))
- return SIZE_MAX;
- return a + b;
-}
-
-/* a - b */
-static size_t ssat_sub(size_t a, size_t b) {
- if (a < b)
- return SIZE_MAX;
- return a - b;
-}
-
-/* a * b */
-static size_t ssat_mul(size_t a, size_t b) {
- size_t c;
-
- if (a == 0 || b == 0)
- return 0;
-
- if (a > (SIZE_MAX/b))
- return SIZE_MAX;
- else
- return a * b;
-}
-
-/* ------------------------------------------------- */
-/* Memory image icmFile compatible class */
-/* Buffer is assumed to have been allocated by the given allocator, */
-/* and will be expanded on write. */
-
-/* Get the size of the file */
-static size_t icmFileMem_get_size(icmFile *pp) {
- icmFileMem *p = (icmFileMem *)pp;
-
- return p->end - p->start;
-}
-
-/* Set current position to offset. Return 0 on success, nz on failure. */
-static int icmFileMem_seek(
-icmFile *pp,
-unsigned int offset
-) {
- icmFileMem *p = (icmFileMem *)pp;
- unsigned char *np;
-
- np = p->start + offset;
- if (np < p->start || np >= p->end)
- return 1;
- p->cur = np;
- return 0;
-}
-
-/* Read count items of size length. Return number of items successfully read. */
-static size_t icmFileMem_read(
-icmFile *pp,
-void *buffer,
-size_t size,
-size_t count
-) {
- icmFileMem *p = (icmFileMem *)pp;
- size_t len;
-
- len = ssat_mul(size, count);
- if (len > (p->end - p->cur)) { /* Too much */
- if (size > 0)
- count = (p->end - p->cur)/size;
- else
- count = 0;
- }
- len = size * count;
- if (len > 0)
- memmove(buffer, p->cur, len);
- p->cur += len;
- return count;
-}
-
-/* Expand the memory buffer file to hold up to pointer ep */
-/* Don't expand if realloc fails */
-static void icmFileMem_filemem_resize(icmFileMem *p, unsigned char *ep) {
- size_t na, co, ce;
- unsigned char *nstart;
-
- /* No need to realloc */
- if (ep <= p->aend) {
- return;
- }
-
- co = p->cur - p->start; /* Current offset */
- ce = p->end - p->start; /* Current end */
- na = ep - p->start; /* new allocated size */
-
- /* Round new allocation up */
- if (na <= 1024)
- na += 1024;
- else
- na += 4096;
-
- if ((nstart = p->al->realloc(p->al, p->start, na)) != NULL) {
- p->start = nstart;
- p->cur = nstart + co;
- p->end = nstart + ce;
- p->aend = nstart + na;
- }
-}
-
-/* write count items of size length. Return number of items successfully written. */
-static size_t icmFileMem_write(
-icmFile *pp,
-void *buffer,
-size_t size,
-size_t count
-) {
- icmFileMem *p = (icmFileMem *)pp;
- size_t len;
-
- len = ssat_mul(size, count);
- if (len > (size_t)(p->aend - p->cur)) /* Try and expand buffer */
- icmFileMem_filemem_resize(p, p->start + len);
-
- if (len > (size_t)(p->aend - p->cur)) {
- if (size > 0)
- count = (p->aend - p->cur)/size;
- else
- count = 0;
- }
- len = size * count;
- if (len > 0)
- memmove(p->cur, buffer, len);
- p->cur += len;
- if (p->end < p->cur)
- p->end = p->cur;
- return count;
-}
-
-/* do a printf */
-static int icmFileMem_printf(
-icmFile *pp,
-const char *format,
-...
-) {
- int rv;
- va_list args;
- icmFileMem *p = (icmFileMem *)pp;
- int len;
-
- va_start(args, format);
-
- rv = 1;
- len = 100; /* Initial allocation for printf */
- icmFileMem_filemem_resize(p, p->cur + len);
-
- /* We have to use the available printf functions to resize the buffer if needed. */
- for (;rv != 0;) {
- /* vsnprintf() either returns -1 if it doesn't fit, or */
- /* returns the size-1 needed in order to fit. */
- len = vsnprintf((char *)p->cur, (p->aend - p->cur), format, args);
-
- if (len > -1 && ((p->cur + len +1) <= p->aend)) /* Fitted in current allocation */
- break;
-
- if (len > -1) /* vsnprintf returned needed size-1 */
- len = len+2; /* (In case vsnprintf returned 1 less than it needs) */
- else
- len *= 2; /* We just have to guess */
-
- /* Attempt to resize */
- icmFileMem_filemem_resize(p, p->cur + len);
-
- /* If resize failed */
- if ((p->aend - p->cur) < len) {
- rv = 0;
- break;
- }
- }
- if (rv != 0) {
- /* Figure out where end of printf is */
- len = strlen((char *)p->cur); /* Length excluding nul */
- p->cur += len;
- if (p->cur > p->end)
- p->end = p->cur;
- rv = len;
- }
- va_end(args);
- return rv;
-}
-
-/* flush all write data out to secondary storage. Return nz on failure. */
-static int icmFileMem_flush(
-icmFile *pp
-) {
- return 0;
-}
-
-/* Return the memory buffer. Error if not icmFileMem */
-static int icmFileMem_get_buf(
-icmFile *pp,
-unsigned char **buf,
-size_t *len
-) {
- icmFileMem *p = (icmFileMem *)pp;
- if (buf != NULL)
- *buf = p->start;
- if (len != NULL)
- *len = p->end - p->start;
- return 0;
-}
-
-/* we're done with the file object, return nz on failure */
-static int icmFileMem_delete(
-icmFile *pp
-) {
- icmFileMem *p = (icmFileMem *)pp;
- icmAlloc *al = p->al;
- int del_al = p->del_al;
-
- if (p->del_buf) /* Free the memory buffer */
- al->free(al, p->start);
- al->free(al, p); /* Free object */
- if (del_al) /* We are responsible for deleting allocator */
- al->del(al);
- return 0;
-}
-
-/* Create a memory image file access class with allocator */
-/* Buffer is used as is. */
-icmFile *new_icmFileMem_a(
-void *base, /* Pointer to base of memory buffer */
-size_t length, /* Number of bytes in buffer */
-icmAlloc *al /* heap allocator */
-) {
- icmFileMem *p;
-
- if ((p = (icmFileMem *) al->calloc(al, 1, sizeof(icmFileMem))) == NULL) {
- return NULL;
- }
- p->al = al; /* Heap allocator */
- p->get_size = icmFileMem_get_size;
- p->seek = icmFileMem_seek;
- p->read = icmFileMem_read;
- p->write = icmFileMem_write;
- p->gprintf = icmFileMem_printf;
- p->flush = icmFileMem_flush;
- p->get_buf = icmFileMem_get_buf;
- p->del = icmFileMem_delete;
-
- p->start = (unsigned char *)base;
- p->cur = p->start;
- p->aend = p->end = p->start + length;
-
- return (icmFile *)p;
-}
-
-/* Create a memory image file access class with given allocator */
-/* and delete base when icmFile is deleted. */
-icmFile *new_icmFileMem_ad(void *base, size_t length, icmAlloc *al) {
- icmFile *fp;
-
- if ((fp = new_icmFileMem_a(base, length, al)) != NULL) {
- ((icmFileMem *)fp)->del_buf = 1;
- }
-
- return fp;
-}
-
-/* ========================================================== */
-/* Conversion support functions */
-/* Convert between ICC storage types and native C types */
-/* Write routine return non-zero if numbers can't be represented */
-
-/* Unsigned */
-static unsigned int read_UInt8Number(char *p) {
- unsigned int rv;
- rv = (unsigned int)((ORD8 *)p)[0];
- return rv;
-}
-
-static int write_UInt8Number(unsigned int d, char *p) {
- if (d > 255)
- return 1;
- ((ORD8 *)p)[0] = (ORD8)d;
- return 0;
-}
-
-static unsigned int read_UInt16Number(char *p) {
- unsigned int rv;
- rv = 256 * (unsigned int)((ORD8 *)p)[0]
- + (unsigned int)((ORD8 *)p)[1];
- return rv;
-}
-
-static int write_UInt16Number(unsigned int d, char *p) {
- if (d > 65535)
- return 1;
- ((ORD8 *)p)[0] = (ORD8)(d >> 8);
- ((ORD8 *)p)[1] = (ORD8)(d);
- return 0;
-}
-
-static unsigned int read_UInt32Number(char *p) {
- unsigned int rv;
- rv = 16777216 * (unsigned int)((ORD8 *)p)[0]
- + 65536 * (unsigned int)((ORD8 *)p)[1]
- + 256 * (unsigned int)((ORD8 *)p)[2]
- + (unsigned int)((ORD8 *)p)[3];
- return rv;
-}
-
-static int write_UInt32Number(unsigned int d, char *p) {
- ((ORD8 *)p)[0] = (ORD8)(d >> 24);
- ((ORD8 *)p)[1] = (ORD8)(d >> 16);
- ((ORD8 *)p)[2] = (ORD8)(d >> 8);
- ((ORD8 *)p)[3] = (ORD8)(d);
- return 0;
-}
-
-static void read_UInt64Number(icmUint64 *d, char *p) {
- d->h = 16777216 * (unsigned int)((ORD8 *)p)[0]
- + 65536 * (unsigned int)((ORD8 *)p)[1]
- + 256 * (unsigned int)((ORD8 *)p)[2]
- + (unsigned int)((ORD8 *)p)[3];
- d->l = 16777216 * (unsigned int)((ORD8 *)p)[4]
- + 65536 * (unsigned int)((ORD8 *)p)[5]
- + 256 * (unsigned int)((ORD8 *)p)[6]
- + (unsigned int)((ORD8 *)p)[7];
-}
-
-static int write_UInt64Number(icmUint64 *d, char *p) {
- ((ORD8 *)p)[0] = (ORD8)(d->h >> 24);
- ((ORD8 *)p)[1] = (ORD8)(d->h >> 16);
- ((ORD8 *)p)[2] = (ORD8)(d->h >> 8);
- ((ORD8 *)p)[3] = (ORD8)(d->h);
- ((ORD8 *)p)[4] = (ORD8)(d->l >> 24);
- ((ORD8 *)p)[5] = (ORD8)(d->l >> 16);
- ((ORD8 *)p)[6] = (ORD8)(d->l >> 8);
- ((ORD8 *)p)[7] = (ORD8)(d->l);
- return 0;
-}
-
-static double read_U8Fixed8Number(char *p) {
- ORD32 o32;
- o32 = 256 * (ORD32)((ORD8 *)p)[0] /* Read big endian 16 bit unsigned */
- + (ORD32)((ORD8 *)p)[1];
- return (double)o32/256.0;
-}
-
-static int write_U8Fixed8Number(double d, char *p) {
- ORD32 o32;
- d = d * 256.0 + 0.5;
- if (d >= 65536.0)
- return 1;
- if (d < 0.0)
- return 1;
- o32 = (ORD32)d;
- ((ORD8 *)p)[0] = (ORD8)((o32) >> 8);
- ((ORD8 *)p)[1] = (ORD8)((o32));
- return 0;
-}
-
-static double read_U16Fixed16Number(char *p) {
- ORD32 o32;
- o32 = 16777216 * (ORD32)((ORD8 *)p)[0] /* Read big endian 32 bit unsigned */
- + 65536 * (ORD32)((ORD8 *)p)[1]
- + 256 * (ORD32)((ORD8 *)p)[2]
- + (ORD32)((ORD8 *)p)[3];
- return (double)o32/65536.0;
-}
-
-static int write_U16Fixed16Number(double d, char *p) {
- ORD32 o32;
- d = d * 65536.0 + 0.5;
- if (d >= 4294967296.0)
- return 1;
- if (d < 0.0)
- return 1;
- o32 = (ORD32)d;
- ((ORD8 *)p)[0] = (ORD8)((o32) >> 24);
- ((ORD8 *)p)[1] = (ORD8)((o32) >> 16);
- ((ORD8 *)p)[2] = (ORD8)((o32) >> 8);
- ((ORD8 *)p)[3] = (ORD8)((o32));
- return 0;
-}
-
-
-/* Signed numbers */
-static int read_SInt8Number(char *p) {
- int rv;
- rv = (int)((INR8 *)p)[0];
- return rv;
-}
-
-static int write_SInt8Number(int d, char *p) {
- if (d > 127)
- return 1;
- else if (d < -128)
- return 1;
- ((INR8 *)p)[0] = (INR8)d;
- return 0;
-}
-
-static int read_SInt16Number(char *p) {
- int rv;
- rv = 256 * (int)((INR8 *)p)[0]
- + (int)((ORD8 *)p)[1];
- return rv;
-}
-
-static int write_SInt16Number(int d, char *p) {
- if (d > 32767)
- return 1;
- else if (d < -32768)
- return 1;
- ((INR8 *)p)[0] = (INR8)(d >> 8);
- ((ORD8 *)p)[1] = (ORD8)(d);
- return 0;
-}
-
-static int read_SInt32Number(char *p) {
- int rv;
- rv = 16777216 * (int)((INR8 *)p)[0]
- + 65536 * (int)((ORD8 *)p)[1]
- + 256 * (int)((ORD8 *)p)[2]
- + (int)((ORD8 *)p)[3];
- return rv;
-}
-
-static int write_SInt32Number(int d, char *p) {
- ((INR8 *)p)[0] = (INR8)(d >> 24);
- ((ORD8 *)p)[1] = (ORD8)(d >> 16);
- ((ORD8 *)p)[2] = (ORD8)(d >> 8);
- ((ORD8 *)p)[3] = (ORD8)(d);
- return 0;
-}
-
-static void read_SInt64Number(icmInt64 *d, char *p) {
- d->h = 16777216 * (int)((INR8 *)p)[0]
- + 65536 * (int)((ORD8 *)p)[1]
- + 256 * (int)((ORD8 *)p)[2]
- + (int)((ORD8 *)p)[3];
- d->l = 16777216 * (unsigned int)((ORD8 *)p)[4]
- + 65536 * (unsigned int)((ORD8 *)p)[5]
- + 256 * (unsigned int)((ORD8 *)p)[6]
- + (unsigned int)((ORD8 *)p)[7];
-}
-
-static int write_SInt64Number(icmInt64 *d, char *p) {
- ((INR8 *)p)[0] = (INR8)(d->h >> 24);
- ((ORD8 *)p)[1] = (ORD8)(d->h >> 16);
- ((ORD8 *)p)[2] = (ORD8)(d->h >> 8);
- ((ORD8 *)p)[3] = (ORD8)(d->h);
- ((ORD8 *)p)[4] = (ORD8)(d->l >> 24);
- ((ORD8 *)p)[5] = (ORD8)(d->l >> 16);
- ((ORD8 *)p)[6] = (ORD8)(d->l >> 8);
- ((ORD8 *)p)[7] = (ORD8)(d->l);
- return 0;
-}
-
-static double read_S15Fixed16Number(char *p) {
- INR32 i32;
- i32 = 16777216 * (INR32)((INR8 *)p)[0] /* Read big endian 32 bit signed */
- + 65536 * (INR32)((ORD8 *)p)[1]
- + 256 * (INR32)((ORD8 *)p)[2]
- + (INR32)((ORD8 *)p)[3];
- return (double)i32/65536.0;
-}
-
-static int write_S15Fixed16Number(double d, char *p) {
- INR32 i32;
- d = floor(d * 65536.0 + 0.5); /* Beware! (int)(d + 0.5) doesn't work! */
- if (d >= 2147483648.0)
- return 1;
- if (d < -2147483648.0)
- return 1;
- i32 = (INR32)d;
- ((INR8 *)p)[0] = (INR8)((i32) >> 24); /* Write big endian 32 bit signed */
- ((ORD8 *)p)[1] = (ORD8)((i32) >> 16);
- ((ORD8 *)p)[2] = (ORD8)((i32) >> 8);
- ((ORD8 *)p)[3] = (ORD8)((i32));
- return 0;
-}
-
-/* Device coordinate as 8 bit value range 0.0 - 1.0 */
-static double read_DCS8Number(char *p) {
- unsigned int rv;
- rv = (unsigned int)((ORD8 *)p)[0];
- return (double)rv/255.0;
-}
-
-static int write_DCS8Number(double d, char *p) {
- ORD32 o32;
- d = d * 255.0 + 0.5;
- if (d >= 256.0)
- return 1;
- if (d < 0.0)
- return 1;
- o32 = (ORD32)d;
- ((ORD8 *)p)[0] = (ORD8)(o32);
- return 0;
-}
-
-/* Device coordinate as 16 bit value range 0.0 - 1.0 */
-static double read_DCS16Number(char *p) {
- unsigned int rv;
- rv = 256 * (unsigned int)((ORD8 *)p)[0]
- + (unsigned int)((ORD8 *)p)[1];
- return (double)rv/65535.0;
-}
-
-static int write_DCS16Number(double d, char *p) {
- ORD32 o32;
- d = d * 65535.0 + 0.5;
- if (d >= 65536.0)
- return 1;
- if (d < 0.0)
- return 1;
- o32 = (ORD32)d;
- ((ORD8 *)p)[0] = (ORD8)(o32 >> 8);
- ((ORD8 *)p)[1] = (ORD8)(o32);
- return 0;
-}
-
-static void Lut_Lut2XYZ(double *out, double *in);
-static void Lut_XYZ2Lut(double *out, double *in);
-static void Lut_Lut2Lab_8(double *out, double *in);
-static void Lut_Lab2Lut_8(double *out, double *in);
-static void Lut_Lut2LabV2_16(double *out, double *in);
-static void Lut_Lab2LutV2_16(double *out, double *in);
-static void Lut_Lut2LabV4_16(double *out, double *in);
-static void Lut_Lab2LutV4_16(double *out, double *in);
-
-static void Lut_Lut2Y(double *out, double *in);
-static void Lut_Y2Lut(double *out, double *in);
-static void Lut_Lut2L_8(double *out, double *in);
-static void Lut_L2Lut_8(double *out, double *in);
-static void Lut_Lut2LV2_16(double *out, double *in);
-static void Lut_L2LutV2_16(double *out, double *in);
-static void Lut_Lut2LV4_16(double *out, double *in);
-static void Lut_L2LutV4_16(double *out, double *in);
-
-//~~~~888888
-/* read a PCS number. PCS can be profile PCS, profile version Lab, */
-/* or a specific type of Lab, depending on the value of csig: */
-/* icmSigPCSData, icSigXYZData, icmSigLab8Data, icSigLabData, */
-/* icmSigLabV2Data or icmSigLabV4Data */
-/* Do nothing if not one of the above. */
-static void read_PCSNumber(icc *icp, icColorSpaceSignature csig, double pcs[3], char *p) {
-
- if (csig == icmSigPCSData)
- csig = icp->header->pcs;
- if (csig == icSigLabData) {
- if (icp->ver != 0)
- csig = icmSigLabV4Data;
- else
- csig = icmSigLabV2Data;
- }
-
- if (csig == icmSigLab8Data) {
- pcs[0] = read_DCS8Number(p);
- pcs[1] = read_DCS8Number(p+1);
- pcs[2] = read_DCS8Number(p+2);
- } else {
- pcs[0] = read_DCS16Number(p);
- pcs[1] = read_DCS16Number(p+2);
- pcs[2] = read_DCS16Number(p+4);
- }
- switch (csig) {
- case icSigXYZData:
- Lut_Lut2XYZ(pcs, pcs);
- break;
- case icmSigLab8Data:
- Lut_Lut2Lab_8(pcs, pcs);
- break;
- case icmSigLabV2Data:
- Lut_Lut2LabV2_16(pcs, pcs);
- break;
- case icmSigLabV4Data:
- Lut_Lut2LabV4_16(pcs, pcs);
- break;
- default:
- break;
- }
-}
-
-/* write a PCS number. PCS can be profile PCS, profile version Lab, */
-/* or a specific type of Lab, depending on the value of csig: */
-/* icmSigPCSData, icSigXYZData, icmSigLab8Data, icSigLabData, */
-/* icmSigLabV2Data or icmSigLabV4Data */
-/* Return 1 if error */
-static int write_PCSNumber(icc *icp, icColorSpaceSignature csig, double pcs[3], char *p) {
- double v[3];
- int j;
-
- if (csig == icmSigPCSData)
- csig = icp->header->pcs;
- if (csig == icSigLabData) {
- if (icp->ver != 0)
- csig = icmSigLabV4Data;
- else
- csig = icmSigLabV2Data;
- }
-
- switch (csig) {
- case icSigXYZData:
- Lut_XYZ2Lut(v, pcs);
- break;
- case icmSigLab8Data:
- Lut_Lab2Lut_8(v, pcs);
- break;
- case icmSigLabV2Data:
- Lut_Lab2LutV2_16(v, pcs);
- break;
- case icmSigLabV4Data:
- Lut_Lab2LutV4_16(v, pcs);
- break;
- default:
- return 1;
- }
- if (csig == icmSigLab8Data) {
- for (j = 0; j < 3; j++) {
- if (write_DCS8Number(v[j], p+j))
- return 1;
- }
- } else {
- for (j = 0; j < 3; j++) {
- if (write_DCS16Number(v[j], p+(2 * j)))
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Read a given primitive type. Return non-zero on error */
-/* (Not currently used internaly ?) */
-/* Public: */
-int read_Primitive(icc *icp, icmPrimType ptype, void *prim, char *p) {
-
- switch(ptype) {
- case icmUInt8Number:
- *((unsigned int *)prim) = read_UInt8Number(p);
- return 0;
- case icmUInt16Number:
- *((unsigned int *)prim) = read_UInt16Number(p);
- return 0;
- case icmUInt32Number:
- *((unsigned int *)prim) = read_UInt32Number(p);
- return 0;
- case icmUInt64Number:
- read_UInt64Number((icmUint64 *)prim, p);
- return 0;
- case icmU8Fixed8Number:
- *((double *)prim) = read_U8Fixed8Number(p);
- return 0;
- case icmU16Fixed16Number:
- *((double *)prim) = read_U16Fixed16Number(p);
- return 0;
- case icmSInt8Number:
- *((int *)prim) = read_SInt8Number(p);
- return 0;
- case icmSInt16Number:
- *((int *)prim) = read_SInt16Number(p);
- return 0;
- case icmSInt32Number:
- *((int *)prim) = read_SInt32Number(p);
- return 0;
- case icmSInt64Number:
- read_SInt64Number((icmInt64 *)prim, p);
- return 0;
- case icmS15Fixed16Number:
- *((double *)prim) = read_S15Fixed16Number(p);
- return 0;
- case icmDCS8Number:
- *((double *)prim) = read_DCS8Number(p);
- return 0;
- case icmDCS16Number:
- *((double *)prim) = read_DCS16Number(p);
- return 0;
- case icmPCSNumber:
- read_PCSNumber(icp, icmSigPCSData, ((double *)prim), p);
- return 0;
- case icmPCSXYZNumber:
- read_PCSNumber(icp, icSigXYZData, ((double *)prim), p);
- return 0;
- case icmPCSLab8Number:
- read_PCSNumber(icp, icmSigLab8Data, ((double *)prim), p);
- return 0;
- case icmPCSLabNumber:
- read_PCSNumber(icp, icSigLabData, ((double *)prim), p);
- return 0;
- case icmPCSLabV2Number:
- read_PCSNumber(icp, icmSigLabV2Data, ((double *)prim), p);
- return 0;
- case icmPCSLabV4Number:
- read_PCSNumber(icp, icmSigLabV4Data, ((double *)prim), p);
- return 0;
- }
-
- return 2;
-}
-
-/* Write a given primitive type. Return non-zero on error */
-/* (Not currently used internaly ?) */
-/* Public: */
-int write_Primitive(icc *icp, icmPrimType ptype, char *p, void *prim) {
-
- switch(ptype) {
- case icmUInt8Number:
- return write_UInt8Number(*((unsigned int *)prim), p);
- case icmUInt16Number:
- return write_UInt16Number(*((unsigned int *)prim), p);
- case icmUInt32Number:
- return write_UInt32Number(*((unsigned int *)prim), p);
- case icmUInt64Number:
- return write_UInt64Number((icmUint64 *)prim, p);
- case icmU8Fixed8Number:
- return write_U8Fixed8Number(*((double *)prim), p);
- case icmU16Fixed16Number:
- return write_U16Fixed16Number(*((double *)prim), p);
- case icmSInt8Number:
- return write_SInt8Number(*((int *)prim), p);
- case icmSInt16Number:
- return write_SInt16Number(*((int *)prim), p);
- case icmSInt32Number:
- return write_SInt32Number(*((int *)prim), p);
- case icmSInt64Number:
- return write_SInt64Number((icmInt64 *)prim, p);
- case icmS15Fixed16Number:
- return write_S15Fixed16Number(*((double *)prim), p);
- case icmDCS8Number:
- return write_DCS8Number(*((double *)prim), p);
- case icmDCS16Number:
- return write_DCS16Number(*((double *)prim), p);
- case icmPCSNumber:
- return write_PCSNumber(icp, icmSigPCSData, ((double *)prim), p);
- case icmPCSXYZNumber:
- return write_PCSNumber(icp, icSigXYZData, ((double *)prim), p);
- case icmPCSLab8Number:
- return write_PCSNumber(icp, icmSigLab8Data, ((double *)prim), p);
- case icmPCSLabNumber:
- return write_PCSNumber(icp, icSigLabData, ((double *)prim), p);
- case icmPCSLabV2Number:
- return write_PCSNumber(icp, icmSigLabV2Data, ((double *)prim), p);
- case icmPCSLabV4Number:
- return write_PCSNumber(icp, icmSigLabV4Data, ((double *)prim), p);
- }
-
- return 2;
-}
-
-/* ---------------------------------------------------------- */
-/* Auiliary function - return a string that represents a tag */
-/* Note - returned buffers are static, can only be used 5 */
-/* times before buffers get reused. */
-char *tag2str(
- int tag
-) {
- int i;
- static int si = 0; /* String buffer index */
- static char buf[5][20]; /* String buffers */
- char *bp;
- unsigned char c[4];
-
- bp = buf[si++];
- si %= 5; /* Rotate through buffers */
-
- c[0] = 0xff & (tag >> 24);
- c[1] = 0xff & (tag >> 16);
- c[2] = 0xff & (tag >> 8);
- c[3] = 0xff & (tag >> 0);
- for (i = 0; i < 4; i++) { /* Can we represent it as a string ? */
- if (!isprint(c[i]))
- break;
- }
- if (i < 4) { /* Not printable - use hex */
- sprintf(bp,"0x%x",tag);
- } else { /* Printable */
- sprintf(bp,"'%c%c%c%c'",c[0],c[1],c[2],c[3]);
- }
- return bp;
-}
-
-/* Auiliary function - return a tag created from a string */
-/* Note there is also the icmMakeTag() macro */
-unsigned int str2tag(
- const char *str
-) {
- unsigned int tag;
- tag = (((unsigned int)str[0]) << 24)
- + (((unsigned int)str[1]) << 16)
- + (((unsigned int)str[2]) << 8)
- + (((unsigned int)str[3]));
- return tag;
-}
-
-/* helper - return 1 if the string doesn't have a */
-/* null terminator within len, return 0 has null at exactly len, */
-/* and 2 if it has null before len. */
-/* Note: will return 1 if len == 0 */
-static int check_null_string(char *cp, int len) {
- for (; len > 0; len--) {
- if (cp[0] == '\000')
- break;
- cp++;
- }
- if (len == 0)
- return 1;
- if (len > 1)
- return 2;
- return 0;
-}
-
-/* helper - return 1 if the string doesn't have a */
-/* null terminator within len, return 0 has null at exactly len, */
-/* and 2 if it has null before len. */
-/* Note: will return 1 if len == 0 */
-/* Unicode version */
-static int check_null_string16(char *cp, int len) {
- for (; len > 0; len--) { /* Length is in characters */
- if (cp[0] == 0 && cp[1] == 0)
- break;
- cp += 2;
- }
- if (len == 0)
- return 1;
- if (len > 1)
- return 2;
- return 0;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Color Space to number of component conversion */
-/* Return 0 on error */
-static unsigned int number_ColorSpaceSignature(icColorSpaceSignature sig) {
- switch(sig) {
- case icSigXYZData:
- return 3;
- case icSigLabData:
- return 3;
- case icSigLuvData:
- return 3;
- case icSigYCbCrData:
- return 3;
- case icSigYxyData:
- return 3;
- case icSigRgbData:
- return 3;
- case icSigGrayData:
- return 1;
- case icSigHsvData:
- return 3;
- case icSigHlsData:
- return 3;
- case icSigCmykData:
- return 4;
- case icSigCmyData:
- return 3;
- case icSig2colorData:
- return 2;
- case icSig3colorData:
- return 3;
- case icSig4colorData:
- return 4;
- case icSig5colorData:
- case icSigMch5Data:
- return 5;
- case icSig6colorData:
- case icSigMch6Data:
- return 6;
- case icSig7colorData:
- case icSigMch7Data:
- return 7;
- case icSig8colorData:
- case icSigMch8Data:
- return 8;
- case icSig9colorData:
- return 9;
- case icSig10colorData:
- return 10;
- case icSig11colorData:
- return 11;
- case icSig12colorData:
- return 12;
- case icSig13colorData:
- return 13;
- case icSig14colorData:
- return 14;
- case icSig15colorData:
- return 15;
-
- /* Non-standard and Pseudo spaces */
- case icmSigYData:
- return 1;
- case icmSigLData:
- return 1;
- case icmSigL8Data:
- return 1;
- case icmSigLV2Data:
- return 1;
- case icmSigLV4Data:
- return 1;
- case icmSigPCSData:
- return 3;
- case icmSigLab8Data:
- return 3;
- case icmSigLabV2Data:
- return 3;
- case icmSigLabV4Data:
- return 3;
-
- default:
- break;
- }
- return 0;
-}
-
-/* Public version of above */
-
-/* Return the number of channels for the given color space. Return 0 if unknown. */
-ICCLIB_API unsigned int icmCSSig2nchan(icColorSpaceSignature sig) {
- return number_ColorSpaceSignature(sig);
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Return the individual channel names and number of channels give a colorspace signature. */
-/* Return 0 if it is not a colorspace that itself defines particular channels, */
-/* 1 if it is a colorant based colorspace, and 2 if it is not a colorant based space */
-static int chnames_ColorSpaceSignature(
-icColorSpaceSignature sig,
-char *cvals[] /* Pointers to return for each channel */
-) {
- switch (sig) {
- case icSigXYZData:
- cvals[0] = "CIE X";
- cvals[1] = "CIE Y";
- cvals[2] = "CIE Z";
- return 2;
-
- case icSigLabData:
- cvals[0] = "CIE L*";
- cvals[1] = "CIE a*";
- cvals[2] = "CIE b*";
- return 2;
-
- case icSigLuvData:
- cvals[0] = "CIE L*";
- cvals[1] = "CIE u*";
- cvals[2] = "CIE v*";
- return 2;
-
- /* Usually ITU-R BT.601 (was CCIR 601) */
- case icSigYCbCrData:
- cvals[0] = "ITU Y";
- cvals[1] = "ITU Cb";
- cvals[2] = "ITU Cr";
- return 2;
-
- case icSigYxyData:
- cvals[0] = "CIE Y";
- cvals[1] = "CIE x";
- cvals[2] = "CIE y";
- return 2;
-
- /* Alvy Ray Smith ? */
- case icSigHsvData:
- cvals[0] = "RGB Hue";
- cvals[1] = "RGB Saturation";
- cvals[2] = "RGB Value";
- return 2;
-
- /* GSPC ? */
- case icSigHlsData:
- cvals[0] = "RGB Hue";
- cvals[1] = "RGB Lightness";
- cvals[2] = "RGB Saturation";
- return 2;
-
- case icSigCmyData:
- cvals[0] = "Cyan";
- cvals[1] = "Magenta";
- cvals[2] = "Yellow";
- return 1;
-
- case icSigRgbData:
- cvals[0] = "Red";
- cvals[1] = "Green";
- cvals[2] = "Blue";
- return 1;
-
- case icSigCmykData:
- cvals[0] = "Cyan";
- cvals[1] = "Magenta";
- cvals[2] = "Yellow";
- cvals[3] = "Black";
- return 1;
-
-
- /* Non-standard and Pseudo spaces */
- case icmSigYData:
- cvals[0] = "CIE Y";
- return 2;
-
- case icmSigLData:
- cvals[0] = "CIE L*";
- return 2;
-
- default:
- break;
-
- }
- return 0;
-}
-
-/* Public version of above */
-
-/* Return the individual channel names and number of channels give a colorspace signature. */
-/* Return 0 if it is not a colorspace that itself defines particular channels, */
-/* 1 if it is a colorant based colorspace, and 2 if it is not a colorant based space */
-ICCLIB_API unsigned int icmCSSig2chanNames(icColorSpaceSignature sig, char *cvals[]) {
-
- return chnames_ColorSpaceSignature(sig, cvals);
-}
-
-/* ------------------------------------------------------- */
-/* Flag dump functions */
-/* Note - returned buffers are static, can only be used 5 */
-/* times before buffers get reused. */
-
-/* Screening Encodings */
-static char *string_ScreenEncodings(unsigned int flags) {
- static int si = 0; /* String buffer index */
- static char buf[5][80]; /* String buffers */
- char *bp, *cp;
-
- cp = bp = buf[si++];
- si %= 5; /* Rotate through buffers */
-
- if (flags & icPrtrDefaultScreensTrue) {
- sprintf(cp,"Default Screen");
- } else {
- sprintf(cp,"No Default Screen");
- }
- cp = cp + strlen(cp);
- if (flags & icLinesPerInch) {
- sprintf(cp,", Lines Per Inch");
- } else {
- sprintf(cp,", Lines Per cm");
- }
- cp = cp + strlen(cp);
-
- return bp;
-}
-
-/* Device attributes */
-static char *string_DeviceAttributes(unsigned int flags) {
- static int si = 0; /* String buffer index */
- static char buf[5][80]; /* String buffers */
- char *bp, *cp;
-
- cp = bp = buf[si++];
- si %= 5; /* Rotate through buffers */
-
- if (flags & icTransparency) {
- sprintf(cp,"Transparency");
- } else {
- sprintf(cp,"Reflective");
- }
- cp = cp + strlen(cp);
- if (flags & icMatte) {
- sprintf(cp,", Matte");
- } else {
- sprintf(cp,", Glossy");
- }
- cp = cp + strlen(cp);
- if (flags & icNegative) {
- sprintf(cp,", Negative");
- } else {
- sprintf(cp,", Positive");
- }
- cp = cp + strlen(cp);
- if (flags & icBlackAndWhite) {
- sprintf(cp,", BlackAndWhite");
- } else {
- sprintf(cp,", Color");
- }
- cp = cp + strlen(cp);
-
- return bp;
-}
-
-/* Profile header flags */
-static char *string_ProfileHeaderFlags(unsigned int flags) {
- static int si = 0; /* String buffer index */
- static char buf[5][80]; /* String buffers */
- char *bp, *cp;
-
- cp = bp = buf[si++];
- si %= 5; /* Rotate through buffers */
-
- if (flags & icEmbeddedProfileTrue) {
- sprintf(cp,"Embedded Profile");
- } else {
- sprintf(cp,"Not Embedded Profile");
- }
- cp = cp + strlen(cp);
- if (flags & icUseWithEmbeddedDataOnly) {
- sprintf(cp,", Use with embedded data only");
- } else {
- sprintf(cp,", Use anywhere");
- }
- cp = cp + strlen(cp);
-
- return bp;
-}
-
-
-static char *string_AsciiOrBinaryData(unsigned int flags) {
- static int si = 0; /* String buffer index */
- static char buf[5][80]; /* String buffers */
- char *bp, *cp;
-
- cp = bp = buf[si++];
- si %= 5; /* Rotate through buffers */
-
- if (flags & icBinaryData) {
- sprintf(cp,"Binary");
- } else {
- sprintf(cp,"Ascii");
- }
- cp = cp + strlen(cp);
-
- return bp;
-}
-
-/* ------------------------------------------------------------ */
-/* Enumeration dump functions */
-/* Note - returned buffers are static, can only be used once */
-/* before buffers get reused if type is unknown. */
-
-/* public tags and sizes */
-static const char *string_TagSignature(icTagSignature sig) {
- static char buf[80];
- switch(sig) {
- case icSigAToB0Tag:
- return "AToB0 Multidimentional Transform";
- case icSigAToB1Tag:
- return "AToB1 Multidimentional Transform";
- case icSigAToB2Tag:
- return "AToB2 Multidimentional Transform";
- case icSigBlueColorantTag:
- return "Blue Colorant";
- case icSigBlueTRCTag:
- return "Blue Tone Reproduction Curve";
- case icSigBToA0Tag:
- return "BToA0 Multidimentional Transform";
- case icSigBToA1Tag:
- return "BToA1 Multidimentional Transform";
- case icSigBToA2Tag:
- return "BToA2 Multidimentional Transform";
- case icSigCalibrationDateTimeTag:
- return "Calibration Date & Time";
- case icSigCharTargetTag:
- return "Characterization Target";
- case icSigCopyrightTag:
- return "Copyright";
- case icSigCrdInfoTag:
- return "CRD Info";
- case icSigDeviceMfgDescTag:
- return "Device Manufacturer Description";
- case icSigDeviceModelDescTag:
- return "Device Model Description";
- case icSigGamutTag:
- return "Gamut";
- case icSigGrayTRCTag:
- return "Gray Tone Reproduction Curve";
- case icSigGreenColorantTag:
- return "Green Colorant";
- case icSigGreenTRCTag:
- return "Green Tone Reproduction Curve";
- case icSigLuminanceTag:
- return "Luminance";
- case icSigMeasurementTag:
- return "Measurement";
- case icSigMediaBlackPointTag:
- return "Media Black Point";
- case icSigMediaWhitePointTag:
- return "Media White Point";
- case icSigNamedColorTag:
- return "Named Color";
- case icSigNamedColor2Tag:
- return "Named Color 2";
- case icSigPreview0Tag:
- return "Preview0";
- case icSigPreview1Tag:
- return "Preview1";
- case icSigPreview2Tag:
- return "Preview2";
- case icSigProfileDescriptionTag:
- return "Profile Description";
- case icSigProfileSequenceDescTag:
- return "Profile Sequence";
- case icSigPs2CRD0Tag:
- return "PS Level 2 CRD perceptual";
- case icSigPs2CRD1Tag:
- return "PS Level 2 CRD colorimetric";
- case icSigPs2CRD2Tag:
- return "PS Level 2 CRD saturation";
- case icSigPs2CRD3Tag:
- return "PS Level 2 CRD absolute";
- case icSigPs2CSATag:
- return "PS Level 2 color space array";
- case icSigPs2RenderingIntentTag:
- return "PS Level 2 Rendering Intent";
- case icSigRedColorantTag:
- return "Red Colorant";
- case icSigRedTRCTag:
- return "Red Tone Reproduction Curve";
- case icSigScreeningDescTag:
- return "Screening Description";
- case icSigScreeningTag:
- return "Screening Attributes";
- case icSigTechnologyTag:
- return "Device Technology";
- case icSigUcrBgTag:
- return "Under Color Removal & Black Generation";
- case icSigVideoCardGammaTag:
- return "Video Card Gamma Curve";
- case icSigViewingCondDescTag:
- return "Viewing Condition Description";
- case icSigViewingConditionsTag:
- return "Viewing Condition Paramaters";
- default:
- sprintf(buf,"Unrecognized - %s",tag2str(sig));
- return buf;
- }
-}
-
-/* technology signature descriptions */
-static const char *string_TechnologySignature(icTechnologySignature sig) {
- static char buf[80];
- switch(sig) {
- case icSigDigitalCamera:
- return "Digital Camera";
- case icSigFilmScanner:
- return "Film Scanner";
- case icSigReflectiveScanner:
- return "Reflective Scanner";
- case icSigInkJetPrinter:
- return "InkJet Printer";
- case icSigThermalWaxPrinter:
- return "Thermal WaxPrinter";
- case icSigElectrophotographicPrinter:
- return "Electrophotographic Printer";
- case icSigElectrostaticPrinter:
- return "Electrostatic Printer";
- case icSigDyeSublimationPrinter:
- return "DyeSublimation Printer";
- case icSigPhotographicPaperPrinter:
- return "Photographic Paper Printer";
- case icSigFilmWriter:
- return "Film Writer";
- case icSigVideoMonitor:
- return "Video Monitor";
- case icSigVideoCamera:
- return "Video Camera";
- case icSigProjectionTelevision:
- return "Projection Television";
- case icSigCRTDisplay:
- return "Cathode Ray Tube Display";
- case icSigPMDisplay:
- return "Passive Matrix Display";
- case icSigAMDisplay:
- return "Active Matrix Display";
- case icSigPhotoCD:
- return "Photo CD";
- case icSigPhotoImageSetter:
- return "Photo ImageSetter";
- case icSigGravure:
- return "Gravure";
- case icSigOffsetLithography:
- return "Offset Lithography";
- case icSigSilkscreen:
- return "Silkscreen";
- case icSigFlexography:
- return "Flexography";
- default:
- sprintf(buf,"Unrecognized - %s",tag2str(sig));
- return buf;
- }
-}
-
-/* type signatures */
-static const char *string_TypeSignature(icTagTypeSignature sig) {
- static char buf[80];
- switch(sig) {
- case icSigCurveType:
- return "Curve";
- case icSigDataType:
- return "Data";
- case icSigDateTimeType:
- return "DateTime";
- case icSigLut16Type:
- return "Lut16";
- case icSigLut8Type:
- return "Lut8";
- case icSigMeasurementType:
- return "Measurement";
- case icSigNamedColorType:
- return "Named Color";
- case icSigProfileSequenceDescType:
- return "Profile Sequence Desc";
- case icSigS15Fixed16ArrayType:
- return "S15Fixed16 Array";
- case icSigScreeningType:
- return "Screening";
- case icSigSignatureType:
- return "Signature";
- case icSigTextType:
- return "Text";
- case icSigTextDescriptionType:
- return "Text Description";
- case icSigU16Fixed16ArrayType:
- return "U16Fixed16 Array";
- case icSigUcrBgType:
- return "Under Color Removal & Black Generation";
- case icSigUInt16ArrayType:
- return "UInt16 Array";
- case icSigUInt32ArrayType:
- return "UInt32 Array";
- case icSigUInt64ArrayType:
- return "UInt64 Array";
- case icSigUInt8ArrayType:
- return "UInt8 Array";
- case icSigVideoCardGammaType:
- return "Video Card Gamma";
- case icSigViewingConditionsType:
- return "Viewing Conditions";
- case icSigXYZType:
- return "XYZ (Array?)";
- case icSigNamedColor2Type:
- return "Named Color 2";
- case icSigCrdInfoType:
- return "CRD Info";
- default:
- sprintf(buf,"Unrecognized - %s",tag2str(sig));
- return buf;
- }
-}
-
-/* Color Space Signatures */
-static const char *string_ColorSpaceSignature(icColorSpaceSignature sig) {
- static char buf[80];
- switch(sig) {
- case icSigXYZData:
- return "XYZ";
- case icSigLabData:
- return "Lab";
- case icSigLuvData:
- return "Luv";
- case icSigYCbCrData:
- return "YCbCr";
- case icSigYxyData:
- return "Yxy";
- case icSigRgbData:
- return "RGB";
- case icSigGrayData:
- return "Gray";
- case icSigHsvData:
- return "HSV";
- case icSigHlsData:
- return "HLS";
- case icSigCmykData:
- return "CMYK";
- case icSigCmyData:
- return "CMY";
- case icSig2colorData:
- return "2 Color";
- case icSig3colorData:
- return "3 Color";
- case icSig4colorData:
- return "4 Color";
- case icSig5colorData:
- case icSigMch5Data:
- return "5 Color";
- case icSig6colorData:
- case icSigMch6Data:
- return "6 Color";
- case icSig7colorData:
- case icSigMch7Data:
- return "7 Color";
- case icSig8colorData:
- case icSigMch8Data:
- return "8 Color";
- case icSig9colorData:
- return "9 Color";
- case icSig10colorData:
- return "10 Color";
- case icSig11colorData:
- return "11 Color";
- case icSig12colorData:
- return "12 Color";
- case icSig13colorData:
- return "13 Color";
- case icSig14colorData:
- return "14 Color";
- case icSig15colorData:
- return "15 Color";
-
- /* Non-standard and Pseudo spaces */
- case icmSigYData:
- return "Y";
- case icmSigLData:
- return "L";
- case icmSigL8Data:
- return "L";
- case icmSigLV2Data:
- return "L";
- case icmSigLV4Data:
- return "L";
- case icmSigPCSData:
- return "PCS";
- case icmSigLab8Data:
- return "Lab";
- case icmSigLabV2Data:
- return "Lab";
- case icmSigLabV4Data:
- return "Lab";
-
- default:
- sprintf(buf,"Unrecognized - %s",tag2str(sig));
- return buf;
- }
-}
-
-#ifdef NEVER
-/* Public version of above */
-char *ColorSpaceSignature2str(icColorSpaceSignature sig) {
- return string_ColorSpaceSignature(sig);
-}
-#endif
-
-
-/* profileClass enumerations */
-static const char *string_ProfileClassSignature(icProfileClassSignature sig) {
- static char buf[80];
- switch(sig) {
- case icSigInputClass:
- return "Input";
- case icSigDisplayClass:
- return "Display";
- case icSigOutputClass:
- return "Output";
- case icSigLinkClass:
- return "Link";
- case icSigAbstractClass:
- return "Abstract";
- case icSigColorSpaceClass:
- return "Color Space";
- case icSigNamedColorClass:
- return "Named Color";
- default:
- sprintf(buf,"Unrecognized - %s",tag2str(sig));
- return buf;
- }
-}
-
-/* Platform Signatures */
-static const char *string_PlatformSignature(icPlatformSignature sig) {
- static char buf[80];
- switch(sig) {
- case icSigMacintosh:
- return "Macintosh";
- case icSigMicrosoft:
- return "Microsoft";
- case icSigSolaris:
- return "Solaris";
- case icSigSGI:
- return "SGI";
- case icSigTaligent:
- return "Taligent";
- case icmSig_nix:
- return "*nix";
- default:
- sprintf(buf,"Unrecognized - %s",tag2str(sig));
- return buf;
- }
-}
-
-/* Measurement Geometry, used in the measurmentType tag */
-static const char *string_MeasurementGeometry(icMeasurementGeometry sig) {
- static char buf[30];
- switch(sig) {
- case icGeometryUnknown:
- return "Unknown";
- case icGeometry045or450:
- return "0/45 or 45/0";
- case icGeometry0dord0:
- return "0/d or d/0";
- default:
- sprintf(buf,"Unrecognized - 0x%x",sig);
- return buf;
- }
-}
-
-/* Rendering Intents, used in the profile header */
-static const char *string_RenderingIntent(icRenderingIntent sig) {
- static char buf[30];
- switch(sig) {
- case icPerceptual:
- return "Perceptual";
- case icRelativeColorimetric:
- return "Relative Colorimetric";
- case icSaturation:
- return "Saturation";
- case icAbsoluteColorimetric:
- return "Absolute Colorimetric";
- case icmAbsolutePerceptual: /* icclib specials */
- return "Absolute Perceptual";
- case icmAbsoluteSaturation: /* icclib specials */
- return "Absolute Saturation";
- case icmDefaultIntent: /* icclib specials */
- return "Default Intent";
- default:
- sprintf(buf,"Unrecognized - 0x%x",sig);
- return buf;
- }
-}
-
-/* Transform Lookup function */
-static const char *string_LookupFunc(icmLookupFunc sig) {
- static char buf[30];
- switch(sig) {
- case icmFwd:
- return "Forward";
- case icmBwd:
- return "Backward";
- case icmGamut:
- return "Gamut";
- case icmPreview:
- return "Preview";
- default:
- sprintf(buf,"Unrecognized - 0x%x",sig);
- return buf;
- }
-}
-
-
-/* Different Spot Shapes currently defined, used for screeningType */
-static const char *string_SpotShape(icSpotShape sig) {
- static char buf[30];
- switch(sig) {
- case icSpotShapeUnknown:
- return "Unknown";
- case icSpotShapePrinterDefault:
- return "Printer Default";
- case icSpotShapeRound:
- return "Round";
- case icSpotShapeDiamond:
- return "Diamond";
- case icSpotShapeEllipse:
- return "Ellipse";
- case icSpotShapeLine:
- return "Line";
- case icSpotShapeSquare:
- return "Square";
- case icSpotShapeCross:
- return "Cross";
- default:
- sprintf(buf,"Unrecognized - 0x%x",sig);
- return buf;
- }
-}
-
-/* Standard Observer, used in the measurmentType tag */
-static const char *string_StandardObserver(icStandardObserver sig) {
- static char buf[30];
- switch(sig) {
- case icStdObsUnknown:
- return "Unknown";
- case icStdObs1931TwoDegrees:
- return "1931 Two Degrees";
- case icStdObs1964TenDegrees:
- return "1964 Ten Degrees";
- default:
- sprintf(buf,"Unrecognized - 0x%x",sig);
- return buf;
- }
-}
-
-/* Pre-defined illuminants, used in measurement and viewing conditions type */
-static const char *string_Illuminant(icIlluminant sig) {
- static char buf[30];
- switch(sig) {
- case icIlluminantUnknown:
- return "Unknown";
- case icIlluminantD50:
- return "D50";
- case icIlluminantD65:
- return "D65";
- case icIlluminantD93:
- return "D93";
- case icIlluminantF2:
- return "F2";
- case icIlluminantD55:
- return "D55";
- case icIlluminantA:
- return "A";
- case icIlluminantEquiPowerE:
- return "Equi-Power(E)";
- case icIlluminantF8:
- return "F8";
- default:
- sprintf(buf,"Unrecognized - 0x%x",sig);
- return buf;
- }
-}
-
-/* Return a text abreviation of a color lookup algorithm */
-static const char *string_LuAlg(icmLuAlgType alg) {
- static char buf[80];
-
- switch(alg) {
- case icmMonoFwdType:
- return "MonoFwd";
- case icmMonoBwdType:
- return "MonoBwd";
- case icmMatrixFwdType:
- return "MatrixFwd";
- case icmMatrixBwdType:
- return "MatrixBwd";
- case icmLutType:
- return "Lut";
- default:
- sprintf(buf,"Unrecognized - %d",alg);
- return buf;
- }
-}
-
-/* Return a string description of the given enumeration value */
-/* Public: */
-const char *icm2str(icmEnumType etype, int enumval) {
-
- switch(etype) {
- case icmScreenEncodings:
- return string_ScreenEncodings((unsigned int) enumval);
- case icmDeviceAttributes:
- return string_DeviceAttributes((unsigned int) enumval);
- case icmProfileHeaderFlags:
- return string_ProfileHeaderFlags((unsigned int) enumval);
- case icmAsciiOrBinaryData:
- return string_AsciiOrBinaryData((unsigned int) enumval);
- case icmTagSignature:
- return string_TagSignature((icTagSignature) enumval);
- case icmTechnologySignature:
- return string_TechnologySignature((icTechnologySignature) enumval);
- case icmTypeSignature:
- return string_TypeSignature((icTagTypeSignature) enumval);
- case icmColorSpaceSignature:
- return string_ColorSpaceSignature((icColorSpaceSignature) enumval);
- case icmProfileClassSignature:
- return string_ProfileClassSignature((icProfileClassSignature) enumval);
- case icmPlatformSignature:
- return string_PlatformSignature((icPlatformSignature) enumval);
- case icmMeasurementGeometry:
- return string_MeasurementGeometry((icMeasurementGeometry) enumval);
- case icmRenderingIntent:
- return string_RenderingIntent((icRenderingIntent) enumval);
- case icmTransformLookupFunc:
- return string_LookupFunc((icmLookupFunc) enumval);
- case icmSpotShape:
- return string_SpotShape((icSpotShape) enumval);
- case icmStandardObserver:
- return string_StandardObserver((icStandardObserver) enumval);
- case icmIlluminant:
- return string_Illuminant((icIlluminant) enumval);
- case icmLuAlg:
- return string_LuAlg((icmLuAlgType) enumval);
- default:
- return "enum2str got unknown type";
- }
-}
-
-/* ========================================================== */
-/* Object I/O routines */
-/* ========================================================== */
-/* icmUnknown object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmUnknown_get_size(
- icmBase *pp
-) {
- icmUnknown *p = (icmUnknown *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addmul(len, p->size, 1); /* 1 byte for each unknown data */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmUnknown_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmUnknown *p = (icmUnknown *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i, size;
- char *bp, *buf;
-
- if (len < 8) {
- sprintf(icp->err,"icmUnknown_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUnknown_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmUnknown_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = size = (len - 8)/1; /* Number of elements in the array */
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read type descriptor from the buffer */
- p->uttype = (icTagTypeSignature)read_SInt32Number(bp);
- bp += 8; /* Skip padding */
-
- /* Read all the data from the buffer */
- for (i = 0; i < size; i++, bp += 1) {
- p->data[i] = read_UInt8Number(bp);
- }
- icp->al->free(p->icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmUnknown_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmUnknown *p = (icmUnknown *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmUnknown_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUnknown_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->uttype,bp)) != 0) {
- sprintf(icp->err,"icmUnknown_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
- bp += 8; /* Skip padding */
-
- /* Write all the data to the buffer */
- for (i = 0; i < p->size; i++, bp += 1) {
- if ((rv = write_UInt8Number(p->data[i],bp)) != 0) {
- sprintf(icp->err,"icmUnknown_write: write_UInt8umber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmUnknown_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmUnknown_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmUnknown *p = (icmUnknown *)pp;
- unsigned int i, ii, r, ph;
-
- if (verb <= 1)
- return;
-
- op->gprintf(op,"Unknown:\n");
- op->gprintf(op," Payload size in bytes = %u\n",p->size);
-
- /* Print one row of binary and ASCII interpretation if verb == 2, All if == 3 */
- /* else print all of it. */
- ii = i = ph = 0;
- for (r = 1;; r++) { /* count rows */
- int c = 1; /* Character location */
-
- c = 1;
- if (ph != 0) { /* Print ASCII under binary */
- op->gprintf(op," ");
- i = ii; /* Swap */
- c += 12;
- } else {
- op->gprintf(op," 0x%04lx: ",i);
- ii = i; /* Swap */
- c += 12;
- }
- while (i < p->size && c < 60) {
- if (ph == 0)
- op->gprintf(op,"%02x ",p->data[i]);
- else {
- if (isprint(p->data[i]))
- op->gprintf(op,"%c ",p->data[i]);
- else
- op->gprintf(op," ",p->data[i]);
- }
- c += 3;
- i++;
- }
- if (ph == 0 || i < p->size)
- op->gprintf(op,"\n");
-
- if (ph == 1 && i >= p->size) {
- op->gprintf(op,"\n");
- break;
- }
- if (ph == 1 && r > 1 && verb < 3) {
- op->gprintf(op," ...\n");
- break; /* Print 1 row if not verbose */
- }
-
- if (ph == 0)
- ph = 1;
- else
- ph = 0;
-
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmUnknown_allocate(
- icmBase *pp
-) {
- icmUnknown *p = (icmUnknown *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(unsigned char))) {
- sprintf(icp->err,"icmUnknown_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (unsigned char *) icp->al->calloc(icp->al, p->size, sizeof(unsigned char)))
- == NULL) {
- sprintf(icp->err,"icmUnknown_alloc: malloc() of icmUnknown data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmUnknown_delete(
- icmBase *pp
-) {
- icmUnknown *p = (icmUnknown *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmUnknown(
- icc *icp
-) {
- icmUnknown *p;
- if ((p = (icmUnknown *) icp->al->calloc(icp->al,1,sizeof(icmUnknown))) == NULL)
- return NULL;
- p->ttype = icmSigUnknownType;
- p->uttype = icmSigUnknownType;
- p->refcount = 1;
- p->get_size = icmUnknown_get_size;
- p->read = icmUnknown_read;
- p->write = icmUnknown_write;
- p->dump = icmUnknown_dump;
- p->allocate = icmUnknown_allocate;
- p->del = icmUnknown_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmUInt8Array object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmUInt8Array_get_size(
- icmBase *pp
-) {
- icmUInt8Array *p = (icmUInt8Array *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addmul(len, p->size, 1); /* 1 byte for each UInt8 */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmUInt8Array_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmUInt8Array *p = (icmUInt8Array *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i, size;
- char *bp, *buf;
-
- if (len < 8) {
- sprintf(icp->err,"icmUInt8Array_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUInt8Array_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmUInt8Array_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = size = (len - 8)/1; /* Number of elements in the array */
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- icp->al->free(icp->al, buf);
- sprintf(icp->err,"icmUInt8Array_read: Wrong tag type for icmUInt8Array");
- return icp->errc = 1;
- }
- bp += 8; /* Skip padding */
-
- /* Read all the data from the buffer */
- for (i = 0; i < size; i++, bp += 1) {
- p->data[i] = read_UInt8Number(bp);
- }
- icp->al->free(p->icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmUInt8Array_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmUInt8Array *p = (icmUInt8Array *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmUInt8Array_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUInt8Array_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmUInt8Array_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
- bp += 8; /* Skip padding */
-
- /* Write all the data to the buffer */
- for (i = 0; i < p->size; i++, bp += 1) {
- if ((rv = write_UInt8Number(p->data[i],bp)) != 0) {
- sprintf(icp->err,"icmUInt8Array_write: write_UInt8umber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmUInt8Array_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmUInt8Array_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmUInt8Array *p = (icmUInt8Array *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"UInt8Array:\n");
- op->gprintf(op," No. elements = %lu\n",p->size);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->size; i++)
- op->gprintf(op," %lu: %u\n",i,p->data[i]);
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmUInt8Array_allocate(
- icmBase *pp
-) {
- icmUInt8Array *p = (icmUInt8Array *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(unsigned int))) {
- sprintf(icp->err,"icmUInt8Array_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (unsigned int *) icp->al->calloc(icp->al, p->size, sizeof(unsigned int)))
- == NULL) {
- sprintf(icp->err,"icmUInt8Array_alloc: malloc() of icmUInt8Array data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmUInt8Array_delete(
- icmBase *pp
-) {
- icmUInt8Array *p = (icmUInt8Array *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmUInt8Array(
- icc *icp
-) {
- icmUInt8Array *p;
- if ((p = (icmUInt8Array *) icp->al->calloc(icp->al,1,sizeof(icmUInt8Array))) == NULL)
- return NULL;
- p->ttype = icSigUInt8ArrayType;
- p->refcount = 1;
- p->get_size = icmUInt8Array_get_size;
- p->read = icmUInt8Array_read;
- p->write = icmUInt8Array_write;
- p->dump = icmUInt8Array_dump;
- p->allocate = icmUInt8Array_allocate;
- p->del = icmUInt8Array_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmUInt16Array object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmUInt16Array_get_size(
- icmBase *pp
-) {
- icmUInt16Array *p = (icmUInt16Array *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addmul(len, p->size, 2); /* 2 bytes for each UInt16 */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmUInt16Array_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmUInt16Array *p = (icmUInt16Array *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i, size;
- char *bp, *buf;
-
- if (len < 8) {
- sprintf(icp->err,"icmUInt16Array_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUInt16Array_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmUInt16Array_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = size = (len - 8)/2; /* Number of elements in the array */
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmUInt16Array_read: Wrong tag type for icmUInt16Array");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp += 8; /* Skip padding */
-
- /* Read all the data from the buffer */
- for (i = 0; i < size; i++, bp += 2) {
- p->data[i] = read_UInt16Number(bp);
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmUInt16Array_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmUInt16Array *p = (icmUInt16Array *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmUInt16Array_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUInt16Array_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmUInt16Array_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write all the data to the buffer */
- bp += 8; /* Skip padding */
- for (i = 0; i < p->size; i++, bp += 2) {
- if ((rv = write_UInt16Number(p->data[i],bp)) != 0) {
- sprintf(icp->err,"icmUInt16Array_write: write_UInt16umber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmUInt16Array_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmUInt16Array_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmUInt16Array *p = (icmUInt16Array *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"UInt16Array:\n");
- op->gprintf(op," No. elements = %lu\n",p->size);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->size; i++)
- op->gprintf(op," %lu: %u\n",i,p->data[i]);
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmUInt16Array_allocate(
- icmBase *pp
-) {
- icmUInt16Array *p = (icmUInt16Array *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(unsigned int))) {
- sprintf(icp->err,"icmUInt16Array_alloc:: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (unsigned int *) icp->al->calloc(icp->al, p->size, sizeof(unsigned int)))
- == NULL) {
- sprintf(icp->err,"icmUInt16Array_alloc: malloc() of icmUInt16Array data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmUInt16Array_delete(
- icmBase *pp
-) {
- icmUInt16Array *p = (icmUInt16Array *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmUInt16Array(
- icc *icp
-) {
- icmUInt16Array *p;
- if ((p = (icmUInt16Array *) icp->al->calloc(icp->al,1,sizeof(icmUInt16Array))) == NULL)
- return NULL;
- p->ttype = icSigUInt16ArrayType;
- p->refcount = 1;
- p->get_size = icmUInt16Array_get_size;
- p->read = icmUInt16Array_read;
- p->write = icmUInt16Array_write;
- p->dump = icmUInt16Array_dump;
- p->allocate = icmUInt16Array_allocate;
- p->del = icmUInt16Array_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmUInt32Array object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmUInt32Array_get_size(
- icmBase *pp
-) {
- icmUInt32Array *p = (icmUInt32Array *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addmul(len, p->size, 4); /* 4 bytes for each UInt32 */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmUInt32Array_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmUInt32Array *p = (icmUInt32Array *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i, size;
- char *bp, *buf;
-
- if (len < 8) {
- sprintf(icp->err,"icmUInt32Array_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUInt32Array_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmUInt32Array_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = size = (len - 8)/4; /* Number of elements in the array */
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmUInt32Array_read: Wrong tag type for icmUInt32Array");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp += 8; /* Skip padding */
-
- /* Read all the data from the buffer */
- for (i = 0; i < size; i++, bp += 4) {
- p->data[i] = read_UInt32Number(bp);
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmUInt32Array_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmUInt32Array *p = (icmUInt32Array *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmUInt32Array_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUInt32Array_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmUInt32Array_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write all the data to the buffer */
- bp += 8; /* Skip padding */
- for (i = 0; i < p->size; i++, bp += 4) {
- if ((rv = write_UInt32Number(p->data[i],bp)) != 0) {
- sprintf(icp->err,"icmUInt32Array_write: write_UInt32umber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmUInt32Array_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmUInt32Array_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmUInt32Array *p = (icmUInt32Array *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"UInt32Array:\n");
- op->gprintf(op," No. elements = %lu\n",p->size);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->size; i++)
- op->gprintf(op," %lu: %u\n",i,p->data[i]);
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmUInt32Array_allocate(
- icmBase *pp
-) {
- icmUInt32Array *p = (icmUInt32Array *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(unsigned int))) {
- sprintf(icp->err,"icmUInt32Array_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (unsigned int *) icp->al->calloc(icp->al, p->size, sizeof(unsigned int)))
- == NULL) {
- sprintf(icp->err,"icmUInt32Array_alloc: malloc() of icmUInt32Array data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmUInt32Array_delete(
- icmBase *pp
-) {
- icmUInt32Array *p = (icmUInt32Array *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmUInt32Array(
- icc *icp
-) {
- icmUInt32Array *p;
- if ((p = (icmUInt32Array *) icp->al->calloc(icp->al,1,sizeof(icmUInt32Array))) == NULL)
- return NULL;
- p->ttype = icSigUInt32ArrayType;
- p->refcount = 1;
- p->get_size = icmUInt32Array_get_size;
- p->read = icmUInt32Array_read;
- p->write = icmUInt32Array_write;
- p->dump = icmUInt32Array_dump;
- p->allocate = icmUInt32Array_allocate;
- p->del = icmUInt32Array_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmUInt64Array object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmUInt64Array_get_size(
- icmBase *pp
-) {
- icmUInt64Array *p = (icmUInt64Array *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addmul(len, p->size, 8); /* 8 bytes for each UInt64 */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmUInt64Array_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmUInt64Array *p = (icmUInt64Array *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i, size;
- char *bp, *buf;
-
- if (len < 8) {
- sprintf(icp->err,"icmUInt64Array_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUInt64Array_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmUInt64Array_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = size = (len - 8)/8; /* Number of elements in the array */
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmUInt64Array_read: Wrong tag type for icmUInt64Array");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp += 8; /* Skip padding */
-
- /* Read all the data from the buffer */
- for (i = 0; i < size; i++, bp += 8) {
- read_UInt64Number(&p->data[i], bp);
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmUInt64Array_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmUInt64Array *p = (icmUInt64Array *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmUInt64Array_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUInt64Array_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmUInt64Array_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write all the data to the buffer */
- bp += 8; /* Skip padding */
- for (i = 0; i < p->size; i++, bp += 8) {
- if ((rv = write_UInt64Number(&p->data[i],bp)) != 0) {
- sprintf(icp->err,"icmUInt64Array_write: write_UInt64umber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmUInt64Array_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmUInt64Array_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmUInt64Array *p = (icmUInt64Array *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"UInt64Array:\n");
- op->gprintf(op," No. elements = %lu\n",p->size);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->size; i++)
- op->gprintf(op," %lu: h=%lu, l=%lu\n",i,p->data[i].h,p->data[i].l);
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmUInt64Array_allocate(
- icmBase *pp
-) {
- icmUInt64Array *p = (icmUInt64Array *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(icmUint64))) {
- sprintf(icp->err,"icmUInt64Array_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (icmUint64 *) icp->al->calloc(icp->al, p->size, sizeof(icmUint64)))
- == NULL) {
- sprintf(icp->err,"icmUInt64Array_alloc: malloc() of icmUInt64Array data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmUInt64Array_delete(
- icmBase *pp
-) {
- icmUInt64Array *p = (icmUInt64Array *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmUInt64Array(
- icc *icp
-) {
- icmUInt64Array *p;
- if ((p = (icmUInt64Array *) icp->al->calloc(icp->al,1,sizeof(icmUInt64Array))) == NULL)
- return NULL;
- p->ttype = icSigUInt64ArrayType;
- p->refcount = 1;
- p->get_size = icmUInt64Array_get_size;
- p->read = icmUInt64Array_read;
- p->write = icmUInt64Array_write;
- p->dump = icmUInt64Array_dump;
- p->allocate = icmUInt64Array_allocate;
- p->del = icmUInt64Array_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmU16Fixed16Array object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmU16Fixed16Array_get_size(
- icmBase *pp
-) {
- icmU16Fixed16Array *p = (icmU16Fixed16Array *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addmul(len, p->size, 4); /* 4 byte for each U16Fixed16 */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmU16Fixed16Array_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmU16Fixed16Array *p = (icmU16Fixed16Array *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i, size;
- char *bp, *buf;
-
- if (len < 8) {
- sprintf(icp->err,"icmU16Fixed16Array_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmU16Fixed16Array_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmU16Fixed16Array_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = size = (len - 8)/4; /* Number of elements in the array */
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmU16Fixed16Array_read: Wrong tag type for icmU16Fixed16Array");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp += 8; /* Skip padding */
-
- /* Read all the data from the buffer */
- for (i = 0; i < size; i++, bp += 4) {
- p->data[i] = read_U16Fixed16Number(bp);
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmU16Fixed16Array_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmU16Fixed16Array *p = (icmU16Fixed16Array *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmU16Fixed16Array_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmU16Fixed16Array_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmU16Fixed16Array_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write all the data to the buffer */
- bp += 8; /* Skip padding */
- for (i = 0; i < p->size; i++, bp += 4) {
- if ((rv = write_U16Fixed16Number(p->data[i],bp)) != 0) {
- sprintf(icp->err,"icmU16Fixed16Array_write: write_U16Fixed16umber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmU16Fixed16Array_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmU16Fixed16Array_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmU16Fixed16Array *p = (icmU16Fixed16Array *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"U16Fixed16Array:\n");
- op->gprintf(op," No. elements = %lu\n",p->size);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->size; i++)
- op->gprintf(op," %lu: %f\n",i,p->data[i]);
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmU16Fixed16Array_allocate(
- icmBase *pp
-) {
- icmU16Fixed16Array *p = (icmU16Fixed16Array *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(double))) {
- sprintf(icp->err,"icmU16Fixed16Array_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (double *) icp->al->calloc(icp->al, p->size, sizeof(double))) == NULL) {
- sprintf(icp->err,"icmU16Fixed16Array_alloc: malloc() of icmU16Fixed16Array data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmU16Fixed16Array_delete(
- icmBase *pp
-) {
- icmU16Fixed16Array *p = (icmU16Fixed16Array *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmU16Fixed16Array(
- icc *icp
-) {
- icmU16Fixed16Array *p;
- if ((p = (icmU16Fixed16Array *) icp->al->calloc(icp->al,1,sizeof(icmU16Fixed16Array))) == NULL)
- return NULL;
- p->ttype = icSigU16Fixed16ArrayType;
- p->refcount = 1;
- p->get_size = icmU16Fixed16Array_get_size;
- p->read = icmU16Fixed16Array_read;
- p->write = icmU16Fixed16Array_write;
- p->dump = icmU16Fixed16Array_dump;
- p->allocate = icmU16Fixed16Array_allocate;
- p->del = icmU16Fixed16Array_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmS15Fixed16Array object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmS15Fixed16Array_get_size(
- icmBase *pp
-) {
- icmS15Fixed16Array *p = (icmS15Fixed16Array *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addmul(len, p->size, 4); /* 4 byte for each S15Fixed16 */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmS15Fixed16Array_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmS15Fixed16Array *p = (icmS15Fixed16Array *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i, size;
- char *bp, *buf;
-
- if (len < 8) {
- sprintf(icp->err,"icmS15Fixed16Array_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmS15Fixed16Array_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmS15Fixed16Array_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = size = (len - 8)/4; /* Number of elements in the array */
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmS15Fixed16Array_read: Wrong tag type for icmS15Fixed16Array");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp += 8; /* Skip padding */
-
- /* Read all the data from the buffer */
- for (i = 0; i < size; i++, bp += 4) {
- p->data[i] = read_S15Fixed16Number(bp);
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmS15Fixed16Array_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmS15Fixed16Array *p = (icmS15Fixed16Array *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmS15Fixed16Array_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmS15Fixed16Array_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmS15Fixed16Array_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write all the data to the buffer */
- bp += 8; /* Skip padding */
- for (i = 0; i < p->size; i++, bp += 4) {
- if ((rv = write_S15Fixed16Number(p->data[i],bp)) != 0) {
- sprintf(icp->err,"icmS15Fixed16Array_write: write_S15Fixed16umber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmS15Fixed16Array_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmS15Fixed16Array_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmS15Fixed16Array *p = (icmS15Fixed16Array *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"S15Fixed16Array:\n");
- op->gprintf(op," No. elements = %lu\n",p->size);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->size; i++)
- op->gprintf(op," %lu: %f\n",i,p->data[i]);
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmS15Fixed16Array_allocate(
- icmBase *pp
-) {
- icmS15Fixed16Array *p = (icmS15Fixed16Array *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(double))) {
- sprintf(icp->err,"icmS15Fixed16Array_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (double *) icp->al->calloc(icp->al, p->size, sizeof(double))) == NULL) {
- sprintf(icp->err,"icmS15Fixed16Array_alloc: malloc() of icmS15Fixed16Array data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmS15Fixed16Array_delete(
- icmBase *pp
-) {
- icmS15Fixed16Array *p = (icmS15Fixed16Array *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmS15Fixed16Array(
- icc *icp
-) {
- icmS15Fixed16Array *p;
- if ((p = (icmS15Fixed16Array *) icp->al->calloc(icp->al,1,sizeof(icmS15Fixed16Array))) == NULL)
- return NULL;
- p->ttype = icSigS15Fixed16ArrayType;
- p->refcount = 1;
- p->get_size = icmS15Fixed16Array_get_size;
- p->read = icmS15Fixed16Array_read;
- p->write = icmS15Fixed16Array_write;
- p->dump = icmS15Fixed16Array_dump;
- p->allocate = icmS15Fixed16Array_allocate;
- p->del = icmS15Fixed16Array_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-
-/* Data conversion support functions */
-static int write_XYZNumber(icmXYZNumber *p, char *d) {
- int rv;
- if ((rv = write_S15Fixed16Number(p->X, d + 0)) != 0)
- return rv;
- if ((rv = write_S15Fixed16Number(p->Y, d + 4)) != 0)
- return rv;
- if ((rv = write_S15Fixed16Number(p->Z, d + 8)) != 0)
- return rv;
- return 0;
-}
-
-static int read_XYZNumber(icmXYZNumber *p, char *d) {
- p->X = read_S15Fixed16Number(d + 0);
- p->Y = read_S15Fixed16Number(d + 4);
- p->Z = read_S15Fixed16Number(d + 8);
- return 0;
-}
-
-
-/* Helper: Return a string that shows the XYZ number value */
-static char *string_XYZNumber(icmXYZNumber *p) {
- static char buf[40];
-
- sprintf(buf,"%f, %f, %f", p->X, p->Y, p->Z);
- return buf;
-}
-
-/* Helper: Return a string that shows the XYZ number value, */
-/* and the Lab D50 number in paren. Note the buffer will be re-used on every call. */
-static char *string_XYZNumber_and_Lab(icmXYZNumber *p) {
- static char buf[100];
- double lab[3];
- lab[0] = p->X;
- lab[1] = p->Y;
- lab[2] = p->Z;
- icmXYZ2Lab(&icmD50, lab, lab);
- snprintf(buf,sizeof(buf),"%f, %f, %f [Lab %f, %f, %f]", p->X, p->Y, p->Z, lab[0], lab[1], lab[2]);
- return buf;
-}
-
-/* icmXYZArray object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmXYZArray_get_size(
- icmBase *pp
-) {
- icmXYZArray *p = (icmXYZArray *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addmul(len, p->size, 12); /* 12 bytes for each XYZ */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmXYZArray_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmXYZArray *p = (icmXYZArray *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i, size;
- char *bp, *buf;
-
- if (len < 8) {
- sprintf(icp->err,"icmXYZArray_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmXYZArray_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmXYZArray_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = size = (len - 8)/12; /* Number of elements in the array */
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmXYZArray_read: Wrong tag type for icmXYZArray");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp += 8; /* Skip padding */
-
- /* Read all the data from the buffer */
- for (i = 0; i < size; i++, bp += 12) {
- read_XYZNumber(&p->data[i], bp);
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmXYZArray_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmXYZArray *p = (icmXYZArray *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmXYZArray_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmXYZArray_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmXYZArray_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write all the data to the buffer */
- bp += 8; /* Skip padding */
- for (i = 0; i < p->size; i++, bp += 12) {
- if ((rv = write_XYZNumber(&p->data[i],bp)) != 0) {
- sprintf(icp->err,"icmXYZArray_write: write_XYZumber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmXYZArray_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmXYZArray_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmXYZArray *p = (icmXYZArray *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"XYZArray:\n");
- op->gprintf(op," No. elements = %lu\n",p->size);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->size; i++) {
- op->gprintf(op," %lu: %s\n",i,string_XYZNumber_and_Lab(&p->data[i]));
-
- }
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmXYZArray_allocate(
- icmBase *pp
-) {
- icmXYZArray *p = (icmXYZArray *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(icmXYZNumber))) {
- sprintf(icp->err,"icmXYZArray_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (icmXYZNumber *) icp->al->malloc(icp->al, sat_mul(p->size, sizeof(icmXYZNumber)))) == NULL) {
- sprintf(icp->err,"icmXYZArray_alloc: malloc() of icmXYZArray data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmXYZArray_delete(
- icmBase *pp
-) {
- icmXYZArray *p = (icmXYZArray *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmXYZArray(
- icc *icp
-) {
- icmXYZArray *p;
- if ((p = (icmXYZArray *) icp->al->calloc(icp->al,1,sizeof(icmXYZArray))) == NULL)
- return NULL;
- p->ttype = icSigXYZArrayType;
- p->refcount = 1;
- p->get_size = icmXYZArray_get_size;
- p->read = icmXYZArray_read;
- p->write = icmXYZArray_write;
- p->dump = icmXYZArray_dump;
- p->allocate = icmXYZArray_allocate;
- p->del = icmXYZArray_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmCurve object */
-
-/* Do a forward lookup through the curve */
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-static int icmCurve_lookup_fwd(
- icmCurve *p,
- double *out,
- double *in
-) {
- int rv = 0;
- if (p->flag == icmCurveLin) {
- *out = *in;
- } else if (p->flag == icmCurveGamma) {
- double val = *in;
- if (val <= 0.0)
- *out = 0.0;
- else
- *out = pow(val, p->data[0]);
- } else if (p->size == 0) { /* Table of 0 size */
- *out = *in;
- } else { /* Use linear interpolation */
- unsigned int ix;
- double val, w;
- double inputEnt_1 = (double)(p->size-1);
-
- val = *in * inputEnt_1;
- if (val < 0.0) {
- val = 0.0;
- rv |= 1;
- } else if (val > inputEnt_1) {
- val = inputEnt_1;
- rv |= 1;
- }
- ix = (unsigned int)floor(val); /* Coordinate */
- if (ix > (p->size-2))
- ix = (p->size-2);
- w = val - (double)ix; /* weight */
- val = p->data[ix];
- *out = val + w * (p->data[ix+1] - val);
- }
- return rv;
-}
-
-/* - - - - - - - - - - - - */
-/* Support for reverse interpolation of 1D lookup tables */
-
-/* Create a reverse curve lookup acceleration table */
-/* return non-zero on error, 2 = malloc error. */
-static int icmTable_setup_bwd(
- icc *icp, /* Base icc object */
- icmRevTable *rt, /* Reverse table data to setup */
- unsigned int size, /* Size of fwd table */
- double *data /* Table */
-) {
- unsigned int i;
-
- rt->size = size; /* Stash pointers to these away */
- rt->data = data;
-
- /* Find range of output values */
- rt->rmin = 1e300;
- rt->rmax = -1e300;
- for (i = 0; i < rt->size; i++) {
- if (rt->data[i] > rt->rmax)
- rt->rmax = rt->data[i];
- if (rt->data[i] < rt->rmin)
- rt->rmin = rt->data[i];
- }
-
- /* Decide on reverse granularity */
- rt->rsize = sat_add(rt->size,2)/2;
- rt->qscale = (double)rt->rsize/(rt->rmax - rt->rmin); /* Scale factor to quantize to */
-
- if (ovr_mul(rt->size, sizeof(unsigned int *))) {
- return 2;
- }
- /* Initialize the reverse lookup structures, and get overall min/max */
- if ((rt->rlists = (unsigned int **) icp->al->calloc(icp->al, rt->rsize, sizeof(unsigned int *))) == NULL) {
- return 2;
- }
-
- /* Assign each output value range bucket lists it intersects */
- for (i = 0; i < (rt->size-1); i++) {
- unsigned int s, e, j; /* Start and end indexes (inclusive) */
- s = (unsigned int)((rt->data[i] - rt->rmin) * rt->qscale);
- e = (unsigned int)((rt->data[i+1] - rt->rmin) * rt->qscale);
- if (s >= rt->rsize)
- s = rt->rsize-1;
- if (e >= rt->rsize)
- e = rt->rsize-1;
- if (s > e) { /* swap */
- unsigned int t;
- t = s; s = e; e = t;
- }
-
- /* For all buckets that may contain this output range, add index of this output */
- for (j = s; j <= e; j++) {
- unsigned int as; /* Allocation size */
- unsigned int nf; /* Next free slot */
- if (rt->rlists[j] == NULL) { /* No allocation */
- as = 5; /* Start with space for 5 */
- if ((rt->rlists[j] = (unsigned int *) icp->al->calloc(icp->al, as, sizeof(unsigned int))) == NULL) {
- return 2;
- }
- rt->rlists[j][0] = as;
- nf = rt->rlists[j][1] = 2;
- } else {
- as = rt->rlists[j][0]; /* Allocate space for this list */
- nf = rt->rlists[j][1]; /* Next free location in list */
- if (nf >= as) { /* need to expand space */
- if ((as = sat_mul(as, 2)) == UINT_MAX
- || ovr_mul(as, sizeof(unsigned int))) {
- return 2;
- }
- rt->rlists[j] = (unsigned int *) icp->al->realloc(icp->al,rt->rlists[j], as * sizeof(unsigned int));
- if (rt->rlists[j] == NULL) {
- return 2;
- }
- rt->rlists[j][0] = as;
- }
- }
- rt->rlists[j][nf++] = i;
- rt->rlists[j][1] = nf;
- }
- }
- rt->inited = 1;
- return 0;
-}
-
-/* Free up any data */
-static void icmTable_delete_bwd(
- icc *icp, /* Base icc */
- icmRevTable *rt /* Reverse table data to setup */
-) {
- if (rt->inited != 0) {
- while (rt->rsize > 0)
- icp->al->free(icp->al, rt->rlists[--rt->rsize]);
- icp->al->free(icp->al, rt->rlists);
- rt->size = 0; /* Don't keep these */
- rt->data = NULL;
- }
-}
-
-/* Do a reverse lookup through the curve */
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-static int icmTable_lookup_bwd(
- icmRevTable *rt,
- double *out,
- double *in
-) {
- int rv = 0;
- unsigned int ix, k, i;
- double oval, ival = *in, val;
- double rsize_1;
-
- /* Find appropriate reverse list */
- rsize_1 = (double)(rt->rsize-1);
- val = ((ival - rt->rmin) * rt->qscale);
- if (val < 0.0)
- val = 0.0;
- else if (val > rsize_1)
- val = rsize_1;
- ix = (unsigned int)floor(val); /* Coordinate */
-
- if (ix > (rt->size-2))
- ix = (rt->size-2);
- if (rt->rlists[ix] != NULL) { /* There is a list of fwd candidates */
- /* For each candidate forward range */
- for (i = 2; i < rt->rlists[ix][1]; i++) { /* For all fwd indexes */
- double lv,hv;
- k = rt->rlists[ix][i]; /* Base index */
- lv = rt->data[k];
- hv = rt->data[k+1];
- if ((ival >= lv && ival <= hv) /* If this slot contains output value */
- || (ival >= hv && ival <= lv)) {
- /* Reverse linear interpolation */
- if (hv == lv) { /* Technically non-monotonic - due to quantization ? */
- oval = (k + 0.5)/(rt->size-1.0);
- } else
- oval = (k + ((ival - lv)/(hv - lv)))/(rt->size-1.0);
- /* If we kept looking, we would find multiple */
- /* solution for non-monotonic curve */
- *out = oval;
- return rv;
- }
- }
- }
-
- /* We have failed to find an exact value, so return the nearest value */
- /* (This is slow !) */
- val = fabs(ival - rt->data[0]);
- for (k = 0, i = 1; i < rt->size; i++) {
- double er;
- er = fabs(ival - rt->data[i]);
- if (er < val) { /* new best */
- val = er;
- k = i;
- }
- }
- *out = k/(rt->size-1.0);
- rv |= 1;
- return rv;
-}
-
-
-/* - - - - - - - - - - - - */
-
-/* Do a reverse lookup through the curve */
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-static int icmCurve_lookup_bwd(
- icmCurve *p,
- double *out,
- double *in
-) {
- icc *icp = p->icp;
- int rv = 0;
- if (p->flag == icmCurveLin) {
- *out = *in;
- } else if (p->flag == icmCurveGamma) {
- double val = *in;
- if (val <= 0.0)
- *out = 0.0;
- else
- *out = pow(val, 1.0/p->data[0]);
- } else if (p->size == 0) { /* Table of 0 size */
- *out = *in;
- } else { /* Use linear interpolation */
- if (p->rt.inited == 0) {
- rv = icmTable_setup_bwd(icp, &p->rt, p->size, p->data);
- if (rv != 0) {
- sprintf(icp->err,"icmCurve_lookup: Malloc failure in reverse lookup init.");
- return icp->errc = rv;
- }
- }
- rv = icmTable_lookup_bwd(&p->rt, out, in);
- }
- return rv;
-}
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmCurve_get_size(
- icmBase *pp
-) {
- icmCurve *p = (icmCurve *)pp;
- unsigned int len = 0;
- len = sat_add(len, 12); /* 12 bytes for tag, padding and count */
- len = sat_addmul(len, p->size, 2); /* 2 bytes for each UInt16 */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmCurve_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmCurve *p = (icmCurve *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i;
- char *bp, *buf, *end;
-
- if (len < 12) {
- sprintf(icp->err,"icmCurve_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmCurve_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
- end = buf + len;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmCurve_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmCurve_read: Wrong tag type for icmCurve");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- p->size = read_UInt32Number(bp+8);
- bp = bp + 12;
-
- /* Set flag up before allocating */
- if (p->size == 0) { /* Linear curve */
- p->flag = icmCurveLin;
- } else if (p->size == 1) { /* Gamma curve */
- p->flag = icmCurveGamma;
- } else {
- p->flag = icmCurveSpec;
- if (p->size > (len - 12)/2) {
- sprintf(icp->err,"icmCurve_read: size overflow");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- }
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- if (p->flag == icmCurveGamma) { /* Gamma curve */
- if (bp > end || 1 > (end - bp)) {
- sprintf(icp->err,"icmCurve_read: Data too short for curve gamma");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->data[0] = read_U8Fixed8Number(bp);
- } else if (p->flag == icmCurveSpec) {
- /* Read all the data from the buffer */
- for (i = 0; i < p->size; i++, bp += 2) {
- if (bp > end || 2 > (end - bp)) {
- sprintf(icp->err,"icmCurve_read: Data too short for curve value");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->data[i] = read_DCS16Number(bp);
- }
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmCurve_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmCurve *p = (icmCurve *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmCurve_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmCurve_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmCurve_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write count */
- if ((rv = write_UInt32Number(p->size,bp+8)) != 0) {
- sprintf(icp->err,"icmCurve_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write all the data to the buffer */
- bp += 12; /* Skip padding */
- if (p->flag == icmCurveLin) {
- if (p->size != 0) {
- sprintf(icp->err,"icmCurve_write: Must be exactly 0 entry for Linear");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- } else if (p->flag == icmCurveGamma) {
- if (p->size != 1) {
- sprintf(icp->err,"icmCurve_write: Must be exactly 1 entry for Gamma");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- if ((rv = write_U8Fixed8Number(p->data[0],bp)) != 0) {
- sprintf(icp->err,"icmCurve_write: write_U8Fixed8umber(%f) failed",p->data[0]);
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- } else if (p->flag == icmCurveSpec) {
- if (p->size < 2) {
- sprintf(icp->err,"icmCurve_write: Must be 2 or more entries for Specified curve");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- for (i = 0; i < p->size; i++, bp += 2) {
- if ((rv = write_DCS16Number(p->data[i],bp)) != 0) {
- sprintf(icp->err,"icmCurve_write: write_UInt16umber(%f) failed",p->data[i]);
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmCurve_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmCurve_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmCurve *p = (icmCurve *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"Curve:\n");
-
- if (p->flag == icmCurveLin) {
- op->gprintf(op," Curve is linear\n");
- } else if (p->flag == icmCurveGamma) {
- op->gprintf(op," Curve is gamma of %f\n",p->data[0]);
- } else {
- op->gprintf(op," No. elements = %lu\n",p->size);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->size; i++)
- op->gprintf(op," %3lu: %f\n",i,p->data[i]);
- }
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmCurve_allocate(
- icmBase *pp
-) {
- icmCurve *p = (icmCurve *)pp;
- icc *icp = p->icp;
-
- if (p->flag == icmCurveUndef) {
- sprintf(icp->err,"icmCurve_alloc: flag not set");
- return icp->errc = 1;
- } else if (p->flag == icmCurveLin) {
- p->size = 0;
- } else if (p->flag == icmCurveGamma) {
- p->size = 1;
- }
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(double))) {
- sprintf(icp->err,"icmCurve_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (double *) icp->al->calloc(icp->al, p->size, sizeof(double))) == NULL) {
- sprintf(icp->err,"icmCurve_alloc: malloc() of icmCurve data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmCurve_delete(
- icmBase *pp
-) {
- icmCurve *p = (icmCurve *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icmTable_delete_bwd(icp, &p->rt); /* Free reverse table info */
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmCurve(
- icc *icp
-) {
- icmCurve *p;
- if ((p = (icmCurve *) icp->al->calloc(icp->al,1,sizeof(icmCurve))) == NULL)
- return NULL;
- p->ttype = icSigCurveType;
- p->refcount = 1;
- p->get_size = icmCurve_get_size;
- p->read = icmCurve_read;
- p->write = icmCurve_write;
- p->dump = icmCurve_dump;
- p->allocate = icmCurve_allocate;
- p->del = icmCurve_delete;
- p->icp = icp;
-
- p->lookup_fwd = icmCurve_lookup_fwd;
- p->lookup_bwd = icmCurve_lookup_bwd;
-
- p->rt.inited = 0;
-
- p->flag = icmCurveUndef;
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmData object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmData_get_size(
- icmBase *pp
-) {
- icmData *p = (icmData *)pp;
- unsigned int len = 0;
- len = sat_add(len, 12); /* 12 bytes for tag and padding */
- len = sat_addmul(len, p->size, 1); /* 1 byte for each data element */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmData_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmData *p = (icmData *)pp;
- icc *icp = p->icp;
- int rv;
- unsigned size, f;
- char *bp, *buf;
-
- if (len < 12) {
- sprintf(icp->err,"icmData_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmData_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmData_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = size = (len - 12)/1; /* Number of elements in the array */
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmData_read: Wrong tag type for icmData");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Read the data type flag */
- f = read_UInt32Number(bp+8);
- if (f == 0) {
- p->flag = icmDataASCII;
- } else if (f == 1) {
- p->flag = icmDataBin;
-#ifndef ICM_STRICT /* Profile maker sometimes has a problem */
- } else if (f == 0x01000000) {
- p->flag = icmDataBin;
-#endif
- } else {
- sprintf(icp->err,"icmData_read: Unknown flag value 0x%x",f);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp += 12; /* Skip padding and flag */
-
- if (p->size > 0) {
- if (p->flag == icmDataASCII) {
- if ((rv = check_null_string(bp,p->size)) == 1) {
- sprintf(icp->err,"icmData_read: ACSII is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
- }
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- memmove((void *)p->data, (void *)bp, p->size);
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmData_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmData *p = (icmData *)pp;
- icc *icp = p->icp;
- unsigned int len, f;
- char *bp, *buf; /* Buffer to write from */
- int rv;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmData_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmData_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmData_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
- switch(p->flag) {
- case icmDataASCII:
- f = 0;
- break;
- case icmDataBin:
- f = 1;
- break;
- default:
- sprintf(icp->err,"icmData_write: Unknown Data Flag value");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Write data flag descriptor to the buffer */
- if ((rv = write_UInt32Number(f,bp+8)) != 0) {
- sprintf(icp->err,"icmData_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- bp += 12; /* Skip padding */
-
- if (p->data != NULL) {
- if (p->flag == icmDataASCII) {
- if ((rv = check_null_string((char *)p->data, p->size)) == 1) {
- sprintf(icp->err,"icmData_write: ASCII is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
- }
- memmove((void *)bp, (void *)p->data, p->size);
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmData_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmData_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmData *p = (icmData *)pp;
- unsigned int i, r, c, ii, size = 0;
- int ph = 0; /* Phase */
-
- if (verb <= 0)
- return;
-
- op->gprintf(op,"Data:\n");
- switch(p->flag) {
- case icmDataASCII:
- op->gprintf(op," ASCII data\n");
- size = p->size > 0 ? p->size-1 : 0;
- break;
- case icmDataBin:
- op->gprintf(op," Binary data\n");
- size = p->size;
- break;
- case icmDataUndef:
- op->gprintf(op," Undefined data\n");
- size = p->size;
- break;
- }
- op->gprintf(op," No. elements = %lu\n",p->size);
-
- ii = i = 0;
- for (r = 1;; r++) { /* count rows */
- if (i >= size) {
- op->gprintf(op,"\n");
- break;
- }
- if (r > 1 && verb < 2) {
- op->gprintf(op,"...\n");
- break; /* Print 1 row if not verbose */
- }
-
- c = 1;
- if (ph != 0) { /* Print ASCII under binary */
- op->gprintf(op," ");
- i = ii;
- c += 11;
- } else {
- op->gprintf(op," 0x%04lx: ",i);
- ii = i;
- c += 10;
- }
- while (i < size && c < 75) {
- if (p->flag == icmDataASCII) {
- if (isprint(p->data[i])) {
- op->gprintf(op,"%c",p->data[i]);
- c++;
- } else {
- op->gprintf(op,"\\%03o",p->data[i]);
- c += 4;
- }
- } else {
- if (ph == 0)
- op->gprintf(op,"%02x ",p->data[i]);
- else {
- if (isprint(p->data[i]))
- op->gprintf(op," %c ",p->data[i]);
- else
- op->gprintf(op," ",p->data[i]);
- }
- c += 3;
- }
- i++;
- }
- if (i < size)
- op->gprintf(op,"\n");
- if (verb > 2 && p->flag != icmDataASCII && ph == 0)
- ph = 1;
- else
- ph = 0;
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmData_allocate(
- icmBase *pp
-) {
- icmData *p = (icmData *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(unsigned char))) {
- sprintf(icp->err,"icmData_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (unsigned char *) icp->al->calloc(icp->al, p->size, sizeof(unsigned char))) == NULL) {
- sprintf(icp->err,"icmData_alloc: malloc() of icmData data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmData_delete(
- icmBase *pp
-) {
- icmData *p = (icmData *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmData(
- icc *icp
-) {
- icmData *p;
- if ((p = (icmData *) icp->al->calloc(icp->al,1,sizeof(icmData))) == NULL)
- return NULL;
- p->ttype = icSigDataType;
- p->refcount = 1;
- p->get_size = icmData_get_size;
- p->read = icmData_read;
- p->write = icmData_write;
- p->dump = icmData_dump;
- p->allocate = icmData_allocate;
- p->del = icmData_delete;
- p->icp = icp;
-
- p->flag = icmDataUndef;
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmText object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmText_get_size(
- icmBase *pp
-) {
- icmText *p = (icmText *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addmul(len, p->size, 1); /* 1 byte for each character element (inc. null) */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmText_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmText *p = (icmText *)pp;
- icc *icp = p->icp;
- int rv;
- char *bp, *buf;
-
- if (len < 8) {
- sprintf(icp->err,"icmText_read: Tag too short to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmText_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmText_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = (len - 8)/1; /* Number of elements in the array */
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmText_read: Wrong tag type for icmText");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp = bp + 8;
-
- if (p->size > 0) {
- if ((rv = check_null_string(bp,p->size)) == 1) {
- sprintf(icp->err,"icmText_read: text is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- memmove((void *)p->data, (void *)bp, p->size);
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmText_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmText *p = (icmText *)pp;
- icc *icp = p->icp;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmText_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmText_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmText_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
- bp = bp + 8;
-
- if (p->data != NULL) {
- if ((rv = check_null_string(p->data, p->size)) == 1) {
- sprintf(icp->err,"icmText_write: text is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
- memmove((void *)bp, (void *)p->data, p->size);
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmText_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmText_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmText *p = (icmText *)pp;
- unsigned int i, r, c, size;
-
- if (verb <= 0)
- return;
-
- op->gprintf(op,"Text:\n");
- op->gprintf(op," No. chars = %lu\n",p->size);
-
- size = p->size > 0 ? p->size-1 : 0;
- i = 0;
- for (r = 1;; r++) { /* count rows */
- if (i >= size) {
- op->gprintf(op,"\n");
- break;
- }
- if (r > 1 && verb < 2) {
- op->gprintf(op,"...\n");
- break; /* Print 1 row if not verbose */
- }
- c = 1;
- op->gprintf(op," 0x%04lx: ",i);
- c += 10;
- while (i < size && c < 75) {
- if (isprint(p->data[i])) {
- op->gprintf(op,"%c",p->data[i]);
- c++;
- } else {
- op->gprintf(op,"\\%03o",p->data[i]);
- c += 4;
- }
- i++;
- }
- if (i < size)
- op->gprintf(op,"\n");
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmText_allocate(
- icmBase *pp
-) {
- icmText *p = (icmText *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(char))) {
- sprintf(icp->err,"icmText_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (char *) icp->al->calloc(icp->al, p->size, sizeof(char))) == NULL) {
- sprintf(icp->err,"icmText_alloc: malloc() of icmText data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmText_delete(
- icmBase *pp
-) {
- icmText *p = (icmText *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmText(
- icc *icp
-) {
- icmText *p;
- if ((p = (icmText *) icp->al->calloc(icp->al,1,sizeof(icmText))) == NULL)
- return NULL;
- p->ttype = icSigTextType;
- p->refcount = 1;
- p->get_size = icmText_get_size;
- p->read = icmText_read;
- p->write = icmText_write;
- p->dump = icmText_dump;
- p->allocate = icmText_allocate;
- p->del = icmText_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-
-/* Data conversion support functions */
-static int write_DateTimeNumber(icmDateTimeNumber *p, char *d) {
- int rv;
- if (p->year < 1900 || p->year > 3000
- || p->month == 0 || p->month > 12
- || p->day == 0 || p->day > 31
- || p->hours > 23
- || p->minutes > 59
- || p->seconds > 59)
- return 1;
-
- if ((rv = write_UInt16Number(p->year, d + 0)) != 0)
- return rv;
- if ((rv = write_UInt16Number(p->month, d + 2)) != 0)
- return rv;
- if ((rv = write_UInt16Number(p->day, d + 4)) != 0)
- return rv;
- if ((rv = write_UInt16Number(p->hours, d + 6)) != 0)
- return rv;
- if ((rv = write_UInt16Number(p->minutes, d + 8)) != 0)
- return rv;
- if ((rv = write_UInt16Number(p->seconds, d + 10)) != 0)
- return rv;
- return 0;
-}
-
-static int read_DateTimeNumber(icmDateTimeNumber *p, char *d) {
-
- p->year = read_UInt16Number(d + 0);
- p->month = read_UInt16Number(d + 2);
- p->day = read_UInt16Number(d + 4);
- p->hours = read_UInt16Number(d + 6);
- p->minutes = read_UInt16Number(d + 8);
- p->seconds = read_UInt16Number(d + 10);
-
- /* Sanity check the date and time */
- if (p->year >= 1900 && p->year <= 3000
- && p->month != 0 && p->month <= 12
- && p->day != 0 && p->day <= 31
- && p->hours <= 23
- && p->minutes <= 59
- && p->seconds <= 59)
- return 0;
-
-#ifdef NEVER
- printf("Raw year = %d, month = %d, day = %d\n",p->year, p->month, p->day);
- printf("Raw hour = %d, minutes = %d, seconds = %d\n", p->hours, p->minutes, p->seconds);
-#endif /* NEVER */
-
-#ifdef ICM_STRICT
- return 1; /* Not legal */
-
-#else
- /* Be more forgiving */
-
- /* Check for Adobe problem */
- if (p->month >= 1900 && p->month <= 3000
- && p->year != 0 && p->year <= 12
- && p->hours != 0 && p->hours <= 31
- && p->day <= 23
- && p->seconds <= 59
- && p->minutes <= 59) {
- unsigned int tt;
-
- /* Correct Adobe's faulty profile */
- tt = p->month; p->month = p->year; p->year = tt;
- tt = p->hours; p->hours = p->day; p->day = tt;
- tt = p->seconds; p->seconds = p->minutes; p->minutes = tt;
-
- return 0;
- }
-
- /* Hmm. some other sort of corruption. Limit values to sane */
- if (p->year < 1900) {
- if (p->year < 100) /* Hmm. didn't use 4 digit year, guess it's 19xx ? */
- p->year += 1900;
- else
- p->year = 1900;
- } else if (p->year > 3000)
- p->year = 3000;
-
- if (p->month == 0)
- p->month = 1;
- else if (p->month > 12)
- p->month = 12;
-
- if (p->day == 0)
- p->day = 1;
- else if (p->day > 31)
- p->day = 31;
-
- if (p->hours > 23)
- p->hours = 23;
-
- if (p->minutes > 59)
- p->minutes = 59;
-
- if (p->seconds > 59)
- p->seconds = 59;
-
- return 0;
-#endif
-}
-
-/* Return a string that shows the given date and time */
-static char *string_DateTimeNumber(icmDateTimeNumber *p) {
- static const char *mstring[13] = {"Bad", "Jan","Feb","Mar","Apr","May","Jun",
- "Jul","Aug","Sep","Oct","Nov","Dec"};
- static char buf[80];
-
- sprintf(buf,"%d %s %4d, %d:%02d:%02d",
- p->day, mstring[p->month > 12 ? 0 : p->month], p->year,
- p->hours, p->minutes, p->seconds);
- return buf;
-}
-
-/* Set the DateTime structure to the current date and time */
-static void setcur_DateTimeNumber(icmDateTimeNumber *p) {
- time_t cclk;
- struct tm *ctm;
-
- cclk = time(NULL);
- ctm = localtime(&cclk);
-
- p->year = ctm->tm_year + 1900;
- p->month = ctm->tm_mon + 1;
- p->day = ctm->tm_mday;
- p->hours = ctm->tm_hour;
- p->minutes = ctm->tm_min;
- p->seconds = ctm->tm_sec;
-}
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmDateTimeNumber_get_size(
- icmBase *pp
-) {
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_add(len, 12); /* 12 bytes for Date & Time */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmDateTimeNumber_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmDateTimeNumber *p = (icmDateTimeNumber *)pp;
- icc *icp = p->icp;
- int rv;
- char *bp, *buf;
-
- if (len < 20) {
- sprintf(icp->err,"icmDateTimeNumber_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmDateTimeNumber_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmDateTimeNumber_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmDateTimeNumber_read: Wrong tag type for icmDateTimeNumber");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp += 8; /* Skip padding */
-
- /* Read the time and date from buffer */
- if((rv = read_DateTimeNumber(p, bp)) != 0) {
- sprintf(icp->err,"icmDateTimeNumber_read: Corrupted DateTime");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmDateTimeNumber_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmDateTimeNumber *p = (icmDateTimeNumber *)pp;
- icc *icp = p->icp;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmDateTimeNumber_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmDateTimeNumber_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmDateTimeNumber_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write all the data to the buffer */
- bp += 8; /* Skip padding */
- if ((rv = write_DateTimeNumber(p, bp)) != 0) {
- sprintf(icp->err,"icmDateTimeNumber_write: write_DateTimeNumber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmDateTimeNumber_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmDateTimeNumber_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmDateTimeNumber *p = (icmDateTimeNumber *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"DateTimeNumber:\n");
- op->gprintf(op," Date = %s\n", string_DateTimeNumber(p));
-}
-
-/* Allocate variable sized data elements */
-static int icmDateTimeNumber_allocate(
- icmBase *pp
-) {
- /* Nothing to do */
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmDateTimeNumber_delete(
- icmBase *pp
-) {
- icmDateTimeNumber *p = (icmDateTimeNumber *)pp;
- icc *icp = p->icp;
-
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmDateTimeNumber(
- icc *icp
-) {
- icmDateTimeNumber *p;
- if ((p = (icmDateTimeNumber *) icp->al->calloc(icp->al,1,sizeof(icmDateTimeNumber))) == NULL)
- return NULL;
- p->ttype = icSigDateTimeType;
- p->refcount = 1;
- p->get_size = icmDateTimeNumber_get_size;
- p->read = icmDateTimeNumber_read;
- p->write = icmDateTimeNumber_write;
- p->dump = icmDateTimeNumber_dump;
- p->allocate = icmDateTimeNumber_allocate;
- p->del = icmDateTimeNumber_delete;
- p->icp = icp;
-
- setcur_DateTimeNumber(p); /* Default to current date and time */
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmLut object */
-
-/* Check if the matrix is non-zero */
-static int icmLut_nu_matrix(
- icmLut *p /* Pointer to Lut object */
-) {
- int i, j;
-
- for (j = 0; j < 3; j++) { /* Rows */
- for (i = 0; i < 3; i++) { /* Columns */
- if ( (i == j && p->e[j][i] != 1.0)
- || (i != j && p->e[j][i] != 0.0))
- return 1;
- }
- }
- return 0;
-}
-
-/* return the locations of the minimum and */
-/* maximum values of the given channel, in the clut */
-static void icmLut_min_max(
- icmLut *p, /* Pointer to Lut object */
- double *minp, /* Return position of min/max */
- double *maxp,
- int chan /* Channel, -1 for average of all */
-) {
- double *tp;
- double minv, maxv; /* Values */
- unsigned int e, ee, f;
- int gc[MAX_CHAN]; /* Grid coordinate */
-
- minv = 1e6;
- maxv = -1e6;
-
- for (e = 0; e < p->inputChan; e++)
- gc[e] = 0; /* init coords */
-
- /* Search the whole table */
- for (tp = p->clutTable, e = 0; e < p->inputChan; tp += p->outputChan) {
- double v;
- if (chan == -1) {
- for (v = 0.0, f = 0; f < p->outputChan; f++)
- v += tp[f];
- } else {
- v = tp[chan];
- }
- if (v < minv) {
- minv = v;
- for (ee = 0; ee < p->inputChan; ee++)
- minp[ee] = gc[ee]/(p->clutPoints-1.0);
- }
- if (v > maxv) {
- maxv = v;
- for (ee = 0; ee < p->inputChan; ee++)
- maxp[ee] = gc[ee]/(p->clutPoints-1.0);
- }
-
- /* Increment coord */
- for (e = 0; e < p->inputChan; e++) {
- if (++gc[e] < p->clutPoints)
- break; /* No carry */
- gc[e] = 0;
- }
- }
-}
-
-/* Convert XYZ throught Luts matrix */
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-static int icmLut_lookup_matrix(
-icmLut *p, /* Pointer to Lut object */
-double *out, /* Output array[outputChan] in ICC order - see Table 39 in 6.5.5 */
-double *in /* Input array[inputChan] */
-) {
- double t0,t1; /* Take care if out == in */
- t0 = p->e[0][0] * in[0] + p->e[0][1] * in[1] + p->e[0][2] * in[2];
- t1 = p->e[1][0] * in[0] + p->e[1][1] * in[1] + p->e[1][2] * in[2];
- out[2] = p->e[2][0] * in[0] + p->e[2][1] * in[1] + p->e[2][2] * in[2];
- out[0] = t0;
- out[1] = t1;
-
- return 0;
-}
-
-/* Convert normalized numbers though this Luts input tables. */
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-static int icmLut_lookup_input(
-icmLut *p, /* Pointer to Lut object */
-double *out, /* Output array[inputChan] */
-double *in /* Input array[inputChan] */
-) {
- int rv = 0;
- unsigned int ix, n;
- double inputEnt_1 = (double)(p->inputEnt-1);
- double *table = p->inputTable;
-
- if (p->inputEnt == 0) { /* Hmm. */
- for (n = 0; n < p->inputChan; n++)
- out[n] = in[n];
- } else {
- /* Use linear interpolation */
- for (n = 0; n < p->inputChan; n++, table += p->inputEnt) {
- double val, w;
- val = in[n] * inputEnt_1;
- if (val < 0.0) {
- val = 0.0;
- rv |= 1;
- } else if (val > inputEnt_1) {
- val = inputEnt_1;
- rv |= 1;
- }
- ix = (unsigned int)floor(val); /* Grid coordinate */
- if (ix > (p->inputEnt-2))
- ix = (p->inputEnt-2);
- w = val - (double)ix; /* weight */
- val = table[ix];
- out[n] = val + w * (table[ix+1] - val);
- }
- }
- return rv;
-}
-
-/* Convert normalized numbers though this Luts multi-dimensional table. */
-/* using multi-linear interpolation. */
-static int icmLut_lookup_clut_nl(
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-icmLut *p, /* Pointer to Lut object */
-double *out, /* Output array[inputChan] */
-double *in /* Input array[outputChan] */
-) {
- icc *icp = p->icp;
- int rv = 0;
- double *gp; /* Pointer to grid cube base */
- double co[MAX_CHAN]; /* Coordinate offset with the grid cell */
- double *gw, GW[1 << 8]; /* weight for each grid cube corner */
-
- if (p->inputChan <= 8) {
- gw = GW; /* Use stack allocation */
- } else {
- if ((gw = (double *) icp->al->malloc(icp->al, sat_mul((1 << p->inputChan), sizeof(double)))) == NULL) {
- sprintf(icp->err,"icmLut_lookup_clut: malloc() failed");
- return icp->errc = 2;
- }
- }
-
- /* We are using an multi-linear (ie. Trilinear for 3D input) interpolation. */
- /* The implementation here uses more multiplies that some other schemes, */
- /* (for instance, see "Tri-Linear Interpolation" by Steve Hill, */
- /* Graphics Gems IV, page 521), but has less involved bookeeping, */
- /* needs less local storage for intermediate output values, does fewer */
- /* output and intermediate value reads, and fp multiplies are fast on */
- /* todays processors! */
-
- /* Compute base index into grid and coordinate offsets */
- {
- unsigned int e;
- double clutPoints_1 = (double)(p->clutPoints-1);
- int clutPoints_2 = p->clutPoints-2;
- gp = p->clutTable; /* Base of grid array */
-
- for (e = 0; e < p->inputChan; e++) {
- unsigned int x;
- double val;
- val = in[e] * clutPoints_1;
- if (val < 0.0) {
- val = 0.0;
- rv |= 1;
- } else if (val > clutPoints_1) {
- val = clutPoints_1;
- rv |= 1;
- }
- x = (unsigned int)floor(val); /* Grid coordinate */
- if (x > clutPoints_2)
- x = clutPoints_2;
- co[e] = val - (double)x; /* 1.0 - weight */
- gp += x * p->dinc[e]; /* Add index offset for base of cube */
- }
- }
- /* Compute corner weights needed for interpolation */
- {
- unsigned int e;
- int i, g = 1;
- gw[0] = 1.0;
- for (e = 0; e < p->inputChan; e++) {
- for (i = 0; i < g; i++) {
- gw[g+i] = gw[i] * co[e];
- gw[i] *= (1.0 - co[e]);
- }
- g *= 2;
- }
- }
- /* Now compute the output values */
- {
- int i;
- unsigned int f;
- double w = gw[0];
- double *d = gp + p->dcube[0];
- for (f = 0; f < p->outputChan; f++) /* Base of cube */
- out[f] = w * d[f];
- for (i = 1; i < (1 << p->inputChan); i++) { /* For all other corners of cube */
- w = gw[i]; /* Strength reduce */
- d = gp + p->dcube[i];
- for (f = 0; f < p->outputChan; f++)
- out[f] += w * d[f];
- }
- }
- if (gw != GW)
- icp->al->free(icp->al, (void *)gw);
- return rv;
-}
-
-/* Convert normalized numbers though this Luts multi-dimensional table */
-/* using simplex interpolation. */
-static int icmLut_lookup_clut_sx(
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-icmLut *p, /* Pointer to Lut object */
-double *out, /* Output array[inputChan] */
-double *in /* Input array[outputChan] */
-) {
- int rv = 0;
- double *gp; /* Pointer to grid cube base */
- double co[MAX_CHAN]; /* Coordinate offset with the grid cell */
- int si[MAX_CHAN]; /* co[] Sort index, [0] = smalest */
-
- /* We are using a simplex (ie. tetrahedral for 3D input) interpolation. */
- /* This method is more appropriate for XYZ/RGB/CMYK input spaces, */
-
- /* Compute base index into grid and coordinate offsets */
- {
- unsigned int e;
- double clutPoints_1 = (double)(p->clutPoints-1);
- int clutPoints_2 = p->clutPoints-2;
- gp = p->clutTable; /* Base of grid array */
-
- for (e = 0; e < p->inputChan; e++) {
- unsigned int x;
- double val;
- val = in[e] * clutPoints_1;
- if (val < 0.0) {
- val = 0.0;
- rv |= 1;
- } else if (val > clutPoints_1) {
- val = clutPoints_1;
- rv |= 1;
- }
- x = (unsigned int)floor(val); /* Grid coordinate */
- if (x > clutPoints_2)
- x = clutPoints_2;
- co[e] = val - (double)x; /* 1.0 - weight */
- gp += x * p->dinc[e]; /* Add index offset for base of cube */
- }
- }
-#ifdef NEVER
- /* Do selection sort on coordinates, smallest to largest. */
- {
- int e, f;
- for (e = 0; e < p->inputChan; e++)
- si[e] = e; /* Initial unsorted indexes */
- for (e = 0; e < (p->inputChan-1); e++) {
- double cosn;
- cosn = co[si[e]]; /* Current smallest value */
- for (f = e+1; f < p->inputChan; f++) { /* Check against rest */
- int tt;
- tt = si[f];
- if (cosn > co[tt]) {
- si[f] = si[e]; /* Exchange */
- si[e] = tt;
- cosn = co[tt];
- }
- }
- }
- }
-#else
- /* Do insertion sort on coordinates, smallest to largest. */
- {
- int f, vf;
- unsigned int e;
- double v;
- for (e = 0; e < p->inputChan; e++)
- si[e] = e; /* Initial unsorted indexes */
-
- for (e = 1; e < p->inputChan; e++) {
- f = e;
- v = co[si[f]];
- vf = f;
- while (f > 0 && co[si[f-1]] > v) {
- si[f] = si[f-1];
- f--;
- }
- si[f] = vf;
- }
- }
-#endif
- /* Now compute the weightings, simplex vertices and output values */
- {
- unsigned int e, f;
- double w; /* Current vertex weight */
-
- w = 1.0 - co[si[p->inputChan-1]]; /* Vertex at base of cell */
- for (f = 0; f < p->outputChan; f++)
- out[f] = w * gp[f];
-
- for (e = p->inputChan-1; e > 0; e--) { /* Middle verticies */
- w = co[si[e]] - co[si[e-1]];
- gp += p->dinc[si[e]]; /* Move to top of cell in next largest dimension */
- for (f = 0; f < p->outputChan; f++)
- out[f] += w * gp[f];
- }
-
- w = co[si[0]];
- gp += p->dinc[si[0]]; /* Far corner from base of cell */
- for (f = 0; f < p->outputChan; f++)
- out[f] += w * gp[f];
- }
- return rv;
-}
-
-#ifdef NEVER // ~~~99 development code
-
-/* Convert normalized numbers though this Luts multi-dimensional table */
-/* using optimised simplex interpolation. */
-/* This version optimses the simplex split axis depending on the input */
-/* colorspace. */
-static int icmLut_lookup_clut_osx(
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-icmLut *p, /* Pointer to Lut object */
-double *out, /* Output array[inputChan] */
-double *in /* Input array[outputChan] */
-) {
- int rv = 0;
- double *gp; /* Pointer to grid cube base */
- double co[MAX_CHAN]; /* Coordinate offset with the grid cell */
- int si[MAX_CHAN]; /* co[] Sort index, [0] = smalest */
- char xflip[MAX_CHAN]; /* Optimised simplex axis flip flags */
-
- /* Compute base index into grid and coordinate offsets */
- {
- unsigned int e;
- double clutPoints_1 = (double)(p->clutPoints-1);
- int clutPoints_2 = p->clutPoints-2;
- gp = p->clutTable; /* Base of grid array */
-
- for (e = 0; e < p->inputChan; e++) {
- unsigned int x;
- double val;
-// ~~~999
-#ifdef NEVER
- xflip[e] = p->finfo[e].bthff;
- if (in[e] >= p->finfo[e].fth)
- xflip[e] = p->finfo[e].athff;
-#else
-
- xflip[e] = 0;
- if (e == 0)
- xflip[e] = 1;
-#endif
- val = in[e] * clutPoints_1;
- if (val < 0.0) {
- val = 0.0;
- rv |= 1;
- } else if (val > clutPoints_1) {
- val = clutPoints_1;
- rv |= 1;
- }
- x = (unsigned int)floor(val); /* Grid coordinate */
- if (x > clutPoints_2)
- x = clutPoints_2;
- co[e] = val - (double)x; /* 1.0 - weight */
- gp += x * p->dinc[e]; /* Add index offset for base of cube */
- if (xflip[e]) { /* Reverse sense of direction for this axis */
- co[e] = 1.0 - co[e];
- gp += p->dinc[e];
- }
- }
- }
-//printf("*");fflush(stdout);
-#ifdef NEVER
- /* Do selection sort on coordinates, smallest to largest. */
- {
- int e, f;
- for (e = 0; e < p->inputChan; e++)
- si[e] = e; /* Initial unsorted indexes */
- for (e = 0; e < (p->inputChan-1); e++) {
- double cosn;
- cosn = co[si[e]]; /* Current smallest value */
- for (f = e+1; f < p->inputChan; f++) { /* Check against rest */
- int tt;
- tt = si[f];
- if (cosn > co[tt]) {
- si[f] = si[e]; /* Exchange */
- si[e] = tt;
- cosn = co[tt];
- }
- }
- }
- }
-#else
- /* Do insertion sort on coordinates, smallest to largest. */
- {
- int f, vf;
- unsigned int e;
- double v;
- for (e = 0; e < p->inputChan; e++)
- si[e] = e; /* Initial unsorted indexes */
-
- for (e = 1; e < p->inputChan; e++) {
- f = e;
- v = co[si[f]];
- vf = f;
- while (f > 0 && co[si[f-1]] > v) {
- si[f] = si[f-1];
- f--;
- }
- si[f] = vf;
- }
- }
-#endif
- /* Now compute the weightings, simplex vertices and output values */
- {
- unsigned int e, f;
- double w; /* Current vertex weight */
-
- w = 1.0 - co[si[p->inputChan-1]]; /* Vertex at base of cell */
- for (f = 0; f < p->outputChan; f++)
- out[f] = w * gp[f];
-
- for (e = p->inputChan-1; e > 0; e--) { /* Middle verticies */
- w = co[si[e]] - co[si[e-1]];
- if (xflip[e])
- gp -= p->dinc[si[e]]; /* Move to top of cell in next largest dimension */
- else
- gp += p->dinc[si[e]]; /* Move to top of cell in next largest dimension */
- for (f = 0; f < p->outputChan; f++)
- out[f] += w * gp[f];
- }
-
- w = co[si[0]];
- if (xflip[0])
- gp -= p->dinc[si[0]]; /* Far corner from base of cell */
- else
- gp += p->dinc[si[0]]; /* Far corner from base of cell */
- for (f = 0; f < p->outputChan; f++)
- out[f] += w * gp[f];
- }
- return rv;
-}
-
-#endif /* NEVER */ // ~~~99 development code
-
-
-/* Convert normalized numbers though this Luts output tables. */
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-static int icmLut_lookup_output(
-icmLut *p, /* Pointer to Lut object */
-double *out, /* Output array[outputChan] */
-double *in /* Input array[outputChan] */
-) {
- int rv = 0;
- unsigned int ix, n;
- double outputEnt_1 = (double)(p->outputEnt-1);
- double *table = p->outputTable;
-
- if (p->outputEnt == 0) { /* Hmm. */
- for (n = 0; n < p->outputChan; n++)
- out[n] = in[n];
- } else {
- /* Use linear interpolation */
- for (n = 0; n < p->outputChan; n++, table += p->outputEnt) {
- double val, w;
- val = in[n] * outputEnt_1;
- if (val < 0.0) {
- val = 0.0;
- rv |= 1;
- } else if (val > outputEnt_1) {
- val = outputEnt_1;
- rv |= 1;
- }
- ix = (unsigned int)floor(val); /* Grid coordinate */
- if (ix > (p->outputEnt-2))
- ix = (p->outputEnt-2);
- w = val - (double)ix; /* weight */
- val = table[ix];
- out[n] = val + w * (table[ix+1] - val);
- }
- }
- return rv;
-}
-
-/* ----------------------------------------------- */
-/* Pseudo - Hilbert count sequencer */
-
-/* This multi-dimensional count sequence is a distributed */
-/* Gray code sequence, with direction reversal on every */
-/* alternate power of 2 scale. */
-/* It is intended to aid cache coherence in multi-dimensional */
-/* regular sampling. It approximates the Hilbert curve sequence. */
-
-/* Initialise, returns total usable count */
-unsigned
-psh_init(
-psh *p, /* Pointer to structure to initialise */
-int di, /* Dimensionality */
-unsigned int res, /* Size per coordinate */
-int co[] /* Coordinates to initialise (May be NULL) */
-) {
- int e;
-
- p->di = di;
- p->res = res;
-
- /* Compute bits */
- for (p->bits = 0; (1u << p->bits) < res; p->bits++)
- ;
-
- /* Compute the total count mask */
- p->tmask = ((((unsigned)1) << (p->bits * di))-1);
-
- /* Compute usable count */
- p->count = 1;
- for (e = 0; e < di; e++)
- p->count *= res;
-
- p->ix = 0;
-
- if (co != NULL) {
- for (e = 0; e < di; e++)
- co[e] = 0;
- }
-
- return p->count;
-}
-
-/* Reset the counter */
-void
-psh_reset(
-psh *p /* Pointer to structure */
-) {
- p->ix = 0;
-}
-
-/* Increment pseudo-hilbert coordinates */
-/* Return non-zero if count rolls over to 0 */
-int
-psh_inc(
-psh *p, /* Pointer to structure */
-int co[] /* Coordinates to return */
-) {
- int di = p->di;
- unsigned int res = p->res;
- unsigned int bits = p->bits;
- int e;
-
- do {
- unsigned int b;
- int gix; /* Gray code index */
-
- p->ix = (p->ix + 1) & p->tmask;
-
- gix = p->ix ^ (p->ix >> 1); /* Convert to gray code index */
-
- for (e = 0; e < di; e++)
- co[e] = 0;
-
- for (b = 0; b < bits; b++) { /* Distribute bits */
- if (b & 1) {
- for (e = di-1; e >= 0; e--) { /* In reverse order */
- co[e] |= (gix & 1) << b;
- gix >>= 1;
- }
- } else {
- for (e = 0; e < di; e++) { /* In normal order */
- co[e] |= (gix & 1) << b;
- gix >>= 1;
- }
- }
- }
-
- /* Convert from Gray to binary coordinates */
- for (e = 0; e < di; e++) {
- unsigned int sh, tv;
-
- for(sh = 1, tv = co[e];; sh <<= 1) {
- unsigned ptv = tv;
- tv ^= (tv >> sh);
- if (ptv <= 1 || sh == 16)
- break;
- }
- if (tv >= res) /* Dumbo filter - increment again if outside cube range */
- break;
- co[e] = tv;
- }
-
- } while (e < di);
-
- return (p->ix == 0);
-}
-
-/* ------------------------------------------------------- */
-
-#ifndef COUNTERS_H
-
-/* Macros for a multi-dimensional counter. */
-
-/* Declare the counter name nn, maximum di mxdi, dimensions di, & count */
-/* This counter can have each dimension range clipped */
-
-#define FCOUNT(nn, mxdi, di) \
- int nn[mxdi]; /* counter value */ \
- int nn##_di = (di); /* Number of dimensions */ \
- int nn##_stt[mxdi]; /* start count value */ \
- int nn##_res[mxdi]; /* last count +1 */ \
- int nn##_e /* dimension index */
-
-#define FRECONF(nn, start, endp1) \
- for (nn##_e = 0; nn##_e < nn##_di; nn##_e++) { \
- nn##_stt[nn##_e] = (start); /* start count value */ \
- nn##_res[nn##_e] = (endp1); /* last count +1 */ \
- }
-
-/* Set the counter value to 0 */
-#define FC_INIT(nn) \
-{ \
- for (nn##_e = 0; nn##_e < nn##_di; nn##_e++) \
- nn[nn##_e] = nn##_stt[nn##_e]; \
- nn##_e = 0; \
-}
-
-/* Increment the counter value */
-#define FC_INC(nn) \
-{ \
- for (nn##_e = 0; nn##_e < nn##_di; nn##_e++) { \
- nn[nn##_e]++; \
- if (nn[nn##_e] < nn##_res[nn##_e]) \
- break; /* No carry */ \
- nn[nn##_e] = nn##_stt[nn##_e]; \
- } \
-}
-
-/* After increment, expression is TRUE if counter is done */
-#define FC_DONE(nn) \
- (nn##_e >= nn##_di)
-
-#endif /* COUNTERS_H */
-
-/* Parameter to getNormFunc function */
-typedef enum {
- icmFromLuti = 0, /* return "fromo Lut normalized index" conversion function */
- icmToLuti = 1, /* return "to Lut normalized index" conversion function */
- icmFromLutv = 2, /* return "from Lut normalized value" conversion function */
- icmToLutv = 3 /* return "to Lut normalized value" conversion function */
-} icmNormFlag;
-
-/* Return an appropriate color space normalization function, */
-/* given the color space and Lut type */
-/* Return 0 on success, 1 on match failure */
-static int getNormFunc(
- icc *icp,
- icColorSpaceSignature csig,
- icTagTypeSignature tagSig,
- icmNormFlag flag,
- void (**nfunc)(double *out, double *in)
-);
-
-#define CLIP_MARGIN 0.005 /* Margine to allow before reporting clipping = 0.5% */
-
-/* Helper function to set multiple Lut tables simultaneously. */
-/* Note that these tables all have to be compatible in */
-/* having the same configuration and resolution. */
-/* Set errc and return error number in underlying icc */
-/* Set warnc if there is clipping in the output values */
-/* 1 = input table, 2 = main clut, 3 = clut midpoin, 4 = midpoint interp, 5 = output table */
-int icmSetMultiLutTables(
- int ntables, /* Number of tables to be set, 1..n */
- icmLut **pp, /* Pointer to array of Lut objects */
- int flags, /* Setting flags */
- 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) */
- /* Will be called ntables times for each input grid value */
- double *inmin, double *inmax, /* Maximum range of inspace' values */
- /* (NULL = default) */
- void (*clutfunc)(void *cbntx, double *out, double *in),
- /* inspace' -> outspace[ntables]' transfer function */
- /* will be called once for each input' grid value, and */
- /* ntables output values should be written consecutively */
- /* to out[]. */
- 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) */
- /* Will be called ntables times on each output value */
-{
- icmLut *p, *pn; /* Pointer to 0'th nd tn'th Lut object */
- icc *icp; /* Pointer to common icc */
- int tn;
- unsigned int e, f, i, n;
- double **clutTable2 = NULL; /* Cell center values for ICM_CLUT_SET_APXLS */
- double *clutTable3 = NULL; /* Vertex smoothing radius values [ntables] per entry */
- int dinc3[MAX_CHAN]; /* Dimensional increment through clut3 (in doubles) */
- int dcube3[1 << MAX_CHAN]; /* Hyper cube offsets throught clut3 (in doubles) */
- int ii[MAX_CHAN]; /* Index value */
- psh counter; /* Pseudo-Hilbert counter */
-// double _iv[4 * MAX_CHAN], *iv = &_iv[MAX_CHAN], *ivn; /* Real index value/table value */
- int maxchan; /* Actual max of input and output */
- double *_iv, *iv, *ivn; /* Real index value/table value */
- double imin[MAX_CHAN], imax[MAX_CHAN];
- double omin[MAX_CHAN], omax[MAX_CHAN];
- void (*ifromindex)(double *out, double *in); /* Index to input color space function */
- void (*itoentry)(double *out, double *in); /* Input color space to entry function */
- void (*ifromentry)(double *out, double *in); /* Entry to input color space function */
- void (*otoentry)(double *out, double *in); /* Output colorspace to table value function */
- void (*ofromentry)(double *out, double *in); /* Table value to output color space function */
- int clip = 0;
-
- /* Check that everything is OK to proceed */
- if (ntables < 1 || ntables > MAX_CHAN) {
- if (ntables >= 1) {
- icp = pp[0]->icp;
- sprintf(icp->err,"icmSetMultiLutTables has illegal number of tables %d",ntables);
- return icp->errc = 1;
- } else {
- /* Can't write error message anywhere */
- return 1;
- }
- }
-
- p = pp[0];
- icp = p->icp;
-
- for (tn = 1; tn < ntables; tn++) {
- if (pp[tn]->icp != icp) {
- sprintf(icp->err,"icmSetMultiLutTables Tables base icc is different");
- return icp->errc = 1;
- }
- if (pp[tn]->ttype != p->ttype) {
- sprintf(icp->err,"icmSetMultiLutTables Tables have different Tage Type");
- return icp->errc = 1;
- }
-
- if (pp[tn]->inputChan != p->inputChan) {
- sprintf(icp->err,"icmSetMultiLutTables Tables have different inputChan");
- return icp->errc = 1;
- }
- if (pp[tn]->outputChan != p->outputChan) {
- sprintf(icp->err,"icmSetMultiLutTables Tables have different outputChan");
- return icp->errc = 1;
- }
- if (pp[tn]->clutPoints != p->clutPoints) {
- sprintf(icp->err,"icmSetMultiLutTables Tables have different clutPoints");
- return icp->errc = 1;
- }
- }
-
- if (getNormFunc(icp, insig, p->ttype, icmFromLuti, &ifromindex) != 0) {
- sprintf(icp->err,"icmLut_set_tables index to input colorspace function lookup failed");
- return icp->errc = 1;
- }
- if (getNormFunc(icp, insig, p->ttype, icmToLutv, &itoentry) != 0) {
- sprintf(icp->err,"icmLut_set_tables input colorspace to table entry function lookup failed");
- return icp->errc = 1;
- }
- if (getNormFunc(icp, insig, p->ttype, icmFromLutv, &ifromentry) != 0) {
- sprintf(icp->err,"icmLut_set_tables table entry to input colorspace function lookup failed");
- return icp->errc = 1;
- }
-
- if (getNormFunc(icp, outsig, p->ttype, icmToLutv, &otoentry) != 0) {
- sprintf(icp->err,"icmLut_set_tables output colorspace to table entry function lookup failed");
- return icp->errc = 1;
- }
- if (getNormFunc(icp, outsig, p->ttype, icmFromLutv, &ofromentry) != 0) {
- sprintf(icp->err,"icmLut_set_tables table entry to output colorspace function lookup failed");
- return icp->errc = 1;
- }
-
- /* Allocate an array to hold the input and output values. */
- /* It needs to be able to hold di "index under valus as in[], */
- /* and ntables ICM_CLUT_SET_FILTER values as out[], so we assume maxchan >= di */
- maxchan = p->inputChan > p->outputChan ? p->inputChan : p->outputChan;
- if ((_iv = (double *) icp->al->malloc(icp->al, sizeof(double) * maxchan * (ntables+1)))
- == NULL) {
- sprintf(icp->err,"icmLut_read: malloc() failed");
- return icp->errc = 2;
- }
- iv = _iv + maxchan; /* Allow for "index under" and smoothing radius values */
-
- /* Setup input table value min-max */
- if (inmin == NULL || imax == NULL) {
-#ifdef SYMETRICAL_DEFAULT_LAB_RANGE /* Symetrical default range. */
- /* We are assuming V2 Lab16 encoding, since this is a lut16type that always uses */
- /* this encoding */
- if (insig == icSigLabData) { /* Special case Lab */
- double mn[3], mx[3];
- /* This is to ensure that Lab 100,0,0 maps exactly to a clut grid point. */
- /* This should work well if there is an odd grid resolution, */
- /* and icclib is being used, as input lookup will */
- /* be computed using floating point, so that the CLUT input value */
- /* 0.5 can be represented exactly. */
- /* Because the symetric range will cause slight clipping, */
- /* only do it if the input table has sufficient resolution */
- /* to represent the clipping faithfuly. */
- if (p->inputEnt >= 64) {
- if (p->ttype == icSigLut8Type) {
- mn[0] = 0.0, mn[1] = mn[2] = -127.0;
- mx[0] = 100.0, mx[1] = mx[2] = 127.0;
- } else {
- mn[0] = 0.0, mn[1] = mn[2] = -127.0 - 255.0/256.0;
- mx[0] = 100.0, mx[1] = mx[2] = 127.0 + 255.0/256.0;
- }
- itoentry(imin, mn); /* Convert from input color space to table representation */
- itoentry(imax, mx);
- } else {
- for (e = 0; e < p->inputChan; e++) {
- imin[e] = 0.0;
- imax[e] = 1.0;
- }
- }
- } else
-#endif
- {
- for (e = 0; e < p->inputChan; e++) {
- imin[e] = 0.0; /* We are assuming this is true for all other color spaces. */
- imax[e] = 1.0;
- }
- }
- } else {
- itoentry(imin, inmin); /* Convert from input color space to table representation */
- itoentry(imax, inmax);
- }
-
- /* Setup output table value min-max */
- if (clutmin == NULL || clutmax == NULL) {
-#ifdef SYMETRICAL_DEFAULT_LAB_RANGE
- /* This really isn't doing much, since the full range encoding doesn't need */
- /* any adjustment to map a*b* 0 to an integer value. */
- /* We are tweaking the 16 bit L* = 100 to the last index into */
- /* the output table, which may help its accuracy slightly. */
- /* We are assuming V2 Lab16 encoding, since this is a lut16type that always uses */
- /* this encoding */
- if (outsig == icSigLabData) { /* Special case Lab */
- double mn[3], mx[3];
- /* The output of the CLUT will be an 8 or 16 bit value, and we want to */
- /* adjust the range so that the input grid point holding the white */
- /* point can encode 0.0 exactly. */
- /* Note that in the case of the a & b values, the range equates to */
- /* normalised 0.0 .. 1.0, since 0 can be represented exactly in it. */
- if (p->outputEnt >= 64) {
- if (p->ttype == icSigLut8Type) {
- mn[0] = 0.0, mn[1] = mn[2] = -128.0;
- mx[0] = 100.0, mx[1] = mx[2] = 127.0;
- } else {
- mn[0] = 0.0, mn[1] = mn[2] = -128.0;
- mx[0] = 100.0, mx[1] = mx[2] = (65535.0 * 255.0)/65280.0 - 128.0;
- }
- otoentry(omin, mn);/* Convert from output color space to table representation */
- otoentry(omax, mx);
- } else {
- for (e = 0; e < p->inputChan; e++) {
- omin[e] = 0.0;
- omax[e] = 1.0;
- }
- }
- } else
-#endif
- {
- for (f = 0; f < p->outputChan; f++) {
- omin[f] = 0.0; /* We are assuming this is true for all other color spaces. */
- omax[f] = 1.0;
- }
- }
- } else {
- otoentry(omin, clutmin);/* Convert from output color space to table representation */
- otoentry(omax, clutmax);
- }
-
- /* Create the input table entry values */
- for (tn = 0; tn < ntables; tn++) {
- pn = pp[tn];
- for (n = 0; n < pn->inputEnt; n++) {
- double fv;
- fv = n/(pn->inputEnt-1.0);
- for (e = 0; e < pn->inputChan; e++)
- iv[e] = fv;
-
- ifromindex(iv,iv); /* Convert from index value to input color space value */
-
- if (infunc != NULL)
- infunc(cbctx, iv, iv); /* In colorspace -> input table -> In colorspace. */
-
- itoentry(iv,iv); /* Convert from input color space value to table value */
-
- /* Expand used range to 0.0 - 1.0, and clip to legal values */
- /* Note that if the range is reduced, and clipping occurs, */
- /* then there should be enough resolution within the input */
- /* table, to represent the sharp edges of the clipping. */
- for (e = 0; e < pn->inputChan; e++) {
- double tt;
- tt = (iv[e] - imin[e])/(imax[e] - imin[e]);
- if (tt < 0.0) {
- DBGSLC(("iclip: tt = %f, iv = %f, omin = %f, omax = %f\n",tt,iv[e],omin[e],omax[e]));
- if (tt < -CLIP_MARGIN)
- clip = 1;
- tt = 0.0;
- } else if (tt > 1.0) {
- DBGSLC(("iclip: tt = %f, iv = %f, omin = %f, omax = %f\n",tt,iv[e],omin[e],omax[e]));
- if (tt > (1.0 + CLIP_MARGIN))
- clip = 1;
- tt = 1.0;
- }
- iv[e] = tt;
- }
-
- for (e = 0; e < pn->inputChan; e++) /* Input tables */
- pn->inputTable[e * pn->inputEnt + n] = iv[e];
- }
- }
-
- /* Allocate space for cell center value lookup */
- if (flags & ICM_CLUT_SET_APXLS) {
- if ((clutTable2 = (double **) icp->al->calloc(icp->al,sizeof(double *), ntables)) == NULL) {
- sprintf(icp->err,"icmLut_set_tables malloc of cube center array failed");
- icp->al->free(icp->al, _iv);
- return icp->errc = 1;
- }
- for (tn = 0; tn < ntables; tn++) {
- if ((clutTable2[tn] = (double *) icp->al->calloc(icp->al,sizeof(double),
- p->clutTable_size)) == NULL) {
- for (--tn; tn >= 0; tn--)
- icp->al->free(icp->al, clutTable2[tn]);
- icp->al->free(icp->al, _iv);
- icp->al->free(icp->al, clutTable2);
- sprintf(icp->err,"icmLut_set_tables malloc of cube center array failed");
- return icp->errc = 1;
- }
- }
- }
-
- /* Allocate space for smoothing radius values */
- if (flags & ICM_CLUT_SET_FILTER) {
- unsigned int j, g, size;
-
- /* Private: compute dimensional increment though clut3 */
- i = p->inputChan-1;
- dinc3[i--] = ntables;
- for (; i < p->inputChan; i--)
- dinc3[i] = dinc3[i+1] * p->clutPoints;
-
- /* Private: compute offsets from base of cube to other corners */
- for (dcube3[0] = 0, g = 1, j = 0; j < p->inputChan; j++) {
- for (i = 0; i < g; i++)
- dcube3[g+i] = dcube3[i] + dinc3[j];
- g *= 2;
- }
-
- if ((size = sat_mul(ntables, sat_pow(p->clutPoints,p->inputChan))) == UINT_MAX) {
- sprintf(icp->err,"icmLut_alloc size overflow");
- if (flags & ICM_CLUT_SET_APXLS) {
- for (tn = 0; tn < ntables; tn++)
- icp->al->free(icp->al, clutTable2[tn]);
- }
- icp->al->free(icp->al, clutTable2);
- icp->al->free(icp->al, _iv);
- return icp->errc = 1;
- }
-
- if ((clutTable3 = (double *) icp->al->calloc(icp->al,sizeof(double),
- size)) == NULL) {
- if (flags & ICM_CLUT_SET_APXLS) {
- for (tn = 0; tn < ntables; tn++)
- icp->al->free(icp->al, clutTable2[tn]);
- }
- icp->al->free(icp->al, clutTable2);
- icp->al->free(icp->al, _iv);
- sprintf(icp->err,"icmLut_set_tables malloc of vertex smoothing value array failed");
- return icp->errc = 1;
- }
- }
-
- /* Create the multi-dimensional lookup table values */
-
- /* To make this clut function cache friendly, we use the pseudo-hilbert */
- /* count sequence. This keeps each point close to the last in the */
- /* multi-dimensional space. This is the point of setting multiple Luts at */
- /* once too - the assumption is that these tables are all related (different */
- /* gamut compressions for instance), and hence calling the clutfunc() with */
- /* close values will maximise reverse lookup cache hit rate. */
-
- psh_init(&counter, p->inputChan, p->clutPoints, ii); /* Initialise counter */
-
- /* Itterate through all verticies in the grid */
- for (;;) {
- int ti, ti3; /* Table indexes */
-
- for (ti = e = 0; e < p->inputChan; e++) { /* Input tables */
- ti += ii[e] * p->dinc[e]; /* Clut index */
- iv[e] = ii[e]/(p->clutPoints-1.0); /* Vertex coordinates */
- iv[e] = iv[e] * (imax[e] - imin[e]) + imin[e]; /* Undo expansion to 0.0 - 1.0 */
- *((int *)&iv[-((int)e)-1]) = ii[e]; /* Trick to supply grid index in iv[] */
- }
-
- if (flags & ICM_CLUT_SET_FILTER) {
- for (ti3 = e = 0; e < p->inputChan; e++) /* Input tables */
- ti3 += ii[e] * dinc3[e]; /* Clut3 index */
- }
-
- DBGSL(("\nix %s\n",icmPiv(p->inputChan, ii)));
- DBGSL(("raw itv %s to iv'",icmPdv(p->inputChan, iv)));
- ifromentry(iv,iv); /* Convert from table value to input color space */
- DBGSL((" %s\n",icmPdv(p->inputChan, iv)));
-
- /* Apply incolor -> outcolor function we want to represent for all tables */
- DBGSL(("iv: %s to ov'",icmPdv(p->inputChan, iv)));
- clutfunc(cbctx, iv, iv);
- DBGSL((" %s\n",icmPdv(p->outputChan, iv)));
-
- /* Save the results to the output tables */
- for (tn = 0, ivn = iv; tn < ntables; ivn += p->outputChan, tn++) {
- pn = pp[tn];
-
- DBGSL(("tn %d, ov' %s -> otv",tn,icmPdv(p->outputChan, ivn)));
- otoentry(ivn,ivn); /* Convert from output color space value to table value */
- DBGSL((" %s\n -> oval",icmPdv(p->outputChan, ivn)));
-
- /* Expand used range to 0.0 - 1.0, and clip to legal values */
- for (f = 0; f < pn->outputChan; f++) {
- double tt;
- tt = (ivn[f] - omin[f])/(omax[f] - omin[f]);
- if (tt < 0.0) {
- DBGSLC(("lclip: tt = %f, ivn= %f, omin = %f, omax = %f\n",tt,ivn[f],omin[f],omax[f]));
- if (tt < -CLIP_MARGIN)
- clip = 2;
- tt = 0.0;
- } else if (tt > 1.0) {
- DBGSLC(("lclip: tt = %f, ivn= %f, omin = %f, omax = %f\n",tt,ivn[f],omin[f],omax[f]));
- if (tt > (1.0 + CLIP_MARGIN))
- clip = 2;
- tt = 1.0;
- }
- ivn[f] = tt;
- }
-
- for (f = 0; f < pn->outputChan; f++) /* Output chans */
- pn->clutTable[ti + f] = ivn[f];
- DBGSL((" %s\n",icmPdv(pn->outputChan, ivn)));
-
- if (flags & ICM_CLUT_SET_FILTER) {
- clutTable3[ti3 + tn] = iv[-1 -tn]; /* Filter radiuses */
- }
- }
-
- /* Lookup cell center value if ICM_CLUT_SET_APXLS */
- if (clutTable2 != NULL) {
-
- for (e = 0; e < p->inputChan; e++) {
- if (ii[e] >= (p->clutPoints-1))
- break; /* Don't lookup beyond last */
- iv[e] = (ii[e] + 0.5)/(p->clutPoints-1.0); /* Vertex coordinates + 0.5 */
- iv[e] = iv[e] * (imax[e] - imin[e]) + imin[e]; /* Undo expansion to 0.0 - 1.0 */
- *((int *)&iv[-((int)e)-1]) = ii[e]; /* Trick to supply grid index in iv[] */
- /* (Not this is only the base for +0.5) */
- }
-
- if (e >= p->inputChan) { /* We're not on the last row */
-
- ifromentry(iv,iv); /* Convert from table value to input color space */
-
- /* Apply incolor -> outcolor function we want to represent */
- clutfunc(cbctx, iv, iv);
-
- /* Save the results to the output tables */
- for (tn = 0, ivn = iv; tn < ntables; ivn += p->outputChan, tn++) {
- pn = pp[tn];
-
- otoentry(ivn,ivn); /* Convert from output color space value to table value */
-
- /* Expand used range to 0.0 - 1.0, and clip to legal values */
- for (f = 0; f < pn->outputChan; f++) {
- double tt;
- tt = (ivn[f] - omin[f])/(omax[f] - omin[f]);
- if (tt < 0.0) {
- DBGSLC(("lclip: tt = %f, ivn= %f, omin = %f, omax = %f\n",tt,ivn[f],omin[f],omax[f]));
- if (tt < -CLIP_MARGIN)
- clip = 3;
- tt = 0.0;
- } else if (tt > 1.0) {
- DBGSLC(("lclip: tt = %f, ivn= %f, omin = %f, omax = %f\n",tt,ivn[f],omin[f],omax[f]));
- if (tt > (1.0 + CLIP_MARGIN))
- clip = 3;
- tt = 1.0;
- }
- ivn[f] = tt;
- }
-
- for (f = 0; f < pn->outputChan; f++) /* Output chans */
- clutTable2[tn][ti + f] = ivn[f];
- }
- }
- }
-
- /* Increment index within block (Reverse index significancd) */
- if (psh_inc(&counter, ii))
- break;
- }
-
-#define APXLS_WHT 0.5
-#define APXLS_DIFF_THRHESH 0.2
- /* Deal with cell center value, aproximate least squares adjustment. */
- /* Subtract some of the mean of the surrounding center values from each grid value. */
- /* Skip the edges so that things like the white point are not changed. */
- /* Avoid modifying the value if the difference between the */
- /* interpolated value and the current value is too great, */
- /* and there is the possibility of different color aliases. */
- if (clutTable2 != NULL) {
- int ti; /* cube vertex table index */
- int ti2; /* cube center table2 index */
- int ee;
- double cw = 1.0/(double)(1 << p->inputChan); /* Weight for each cube corner */
-
- /* For each cell center point except last row */
- for (e = 0; e < p->inputChan; e++)
- ii[e] = 0; /* init coords */
-
- /* Compute linear interpolated value from center values */
- for (ee = 0; ee < p->inputChan;) {
-
- /* Compute base index for table2 */
- for (ti2 = e = 0; e < p->inputChan; e++) /* Input tables */
- ti2 += ii[e] * p->dinc[e]; /* Clut index */
-
- ti = ti2 + p->dcube[(1 << p->inputChan)-1]; /* +1 to each coord for vertex index */
-
- for (tn = 0; tn < ntables; tn++) {
- double mval[MAX_CHAN], vv;
- double maxd = 0.0;
-
- pn = pp[tn];
-
- /* Compute mean of center values */
- for (f = 0; f < pn->outputChan; f++) { /* Output chans */
-
- mval[f] = 0.0;
- for (i = 0; i < (1 << p->inputChan); i++) { /* For surrounding center values */
- mval[f] += clutTable2[tn][ti2 + p->dcube[i] + f];
- }
- mval[f] = pn->clutTable[ti + f] - mval[f] * cw; /* Diff to mean */
- vv = fabs(mval[f]);
- if (vv > maxd)
- maxd = vv;
- }
-
- if (pn->outputChan <= 3 || maxd < APXLS_DIFF_THRHESH) {
- for (f = 0; f < pn->outputChan; f++) { /* Output chans */
-
- vv = pn->clutTable[ti + f] + APXLS_WHT * mval[f];
-
- /* Hmm. This is a bit crude. How do we know valid range is 0-1 ? */
- /* What about an ink limit ? */
- if (vv < 0.0) {
- vv = 0.0;
- } else if (vv > 1.0) {
- vv = 1.0;
- }
- pn->clutTable[ti + f] = vv;
- }
- }
- }
-
- /* Increment coord */
- for (ee = 0; ee < p->inputChan; ee++) {
- if (++ii[ee] < (p->clutPoints-2)) /* Don't go through upper edge */
- break; /* No carry */
- ii[ee] = 0;
- }
- }
-
- /* Done with center values */
- for (tn = 0; tn < ntables; tn++)
- icp->al->free(icp->al, clutTable2[tn]);
- icp->al->free(icp->al, clutTable2);
- }
-
- /* Apply any smoothing in the clipped region to the resulting clutTable */
- if (clutTable3 != NULL) {
- double *clutTable1; /* Copy of current unfilted values */
- FCOUNT(cc, MAX_CHAN, p->inputChan); /* Surrounding counter */
-
- if ((clutTable1 = (double *) icp->al->calloc(icp->al,sizeof(double),
- p->clutTable_size)) == NULL) {
- icp->al->free(icp->al, clutTable3);
- icp->al->free(icp->al, _iv);
- sprintf(icp->err,"icmLut_set_tables malloc of grid copy failed");
- return icp->errc = 1;
- }
-
- for (tn = 0; tn < ntables; tn++) {
- int aa;
- int ee;
- int ti, ti3; /* Table indexes */
-
- pn = pp[tn];
-
- /* For each pass */
- for (aa = 0; aa < 2; aa++) {
-
- /* Copy current values */
- memcpy(clutTable1, pn->clutTable, sizeof(double) * pn->clutTable_size);
-
- /* Filter each point */
- for (e = 0; e < pn->inputChan; e++)
- ii[e] = 0; /* init coords */
-
- /* Compute linear interpolated error to actual cell center value */
- for (ee = 0; ee < pn->inputChan;) {
- double rr; /* Filter radius */
- int ir; /* Integer radius */
- double tw; /* Total weight */
-
- /* Compute base index for this cell */
- for (ti3 = ti = e = 0; e < pn->inputChan; e++) { /* Input tables */
- ti += ii[e] * pn->dinc[e]; /* Clut index */
- ti3 += ii[e] * dinc3[e]; /* Clut3 index */
- }
- rr = clutTable3[ti3 + tn] * (pn->clutPoints-1.0);
- ir = (int)floor(rr + 0.5); /* Don't bother unless 1/2 over vertex */
-
- if (ir < 1)
- goto next_vert;
-
- //FRECONF(cc, -ir, ir + 1); /* Set size of surroundign grid */
-
- /* Clip scanning cube to be within grid */
- for (e = 0; e < pn->inputChan; e++) {
- int cr = ir;
- if ((ii[e] - ir) < 0)
- cr = ii[e];
- if ((ii[e] + ir) >= pn->clutPoints)
- cr = pn->clutPoints -1 -ii[e];
-
- cc_stt[e] = -cr;
- cc_res[e] = cr + 1;
- }
-
- for (f = 0; f < pn->outputChan; f++)
- pn->clutTable[ti + f] = 0.0;
- tw = 0.0;
-
- FC_INIT(cc)
- for (tw = 0.0; !FC_DONE(cc);) {
- double r;
- int tti;
-
- /* Radius of this cell */
- for (r = 0.0, tti = e = 0; e < pn->inputChan; e++) {
- int ix;
- r += cc[e] * cc[e];
- tti += (ii[e] + cc[e]) * p->dinc[e];
- }
- r = sqrt(r);
-
- if (r <= rr && e >= pn->inputChan) {
- double w = (rr - r)/rr; /* Triangle weighting */
- w = sqrt(w);
- for (f = 0; f < pn->outputChan; f++)
- pn->clutTable[ti+f] += w * clutTable1[tti + f];
- tw += w;
- }
- FC_INC(cc);
- }
- for (f = 0; f < pn->outputChan; f++) {
- double vv = pn->clutTable[ti+f] / tw;
- if (vv < 0.0) {
- vv = 0.0;
- } else if (vv > 1.0) {
- vv = 1.0;
- }
- pn->clutTable[ti+f] = vv;
- }
-
- /* Increment coord */
- next_vert:;
- for (ee = 0; ee < pn->inputChan; ee++) {
- if (++ii[ee] < (pn->clutPoints-1)) /* Don't go through upper edge */
- break; /* No carry */
- ii[ee] = 0;
- }
- } /* Next grid point to filter */
- } /* Next pass */
- } /* Next table */
-
- free(clutTable1);
- free(clutTable3);
- }
-
- /* Create the output table entry values */
- for (tn = 0; tn < ntables; tn++) {
- pn = pp[tn];
- for (n = 0; n < pn->outputEnt; n++) {
- double fv;
- fv = n/(pn->outputEnt-1.0);
- for (f = 0; f < pn->outputChan; f++)
- iv[f] = fv;
-
- /* Undo expansion to 0.0 - 1.0 */
- for (f = 0; f < pn->outputChan; f++) /* Output tables */
- iv[f] = iv[f] * (omax[f] - omin[f]) + omin[f];
-
- ofromentry(iv,iv); /* Convert from table value to output color space value */
-
- if (outfunc != NULL)
- outfunc(cbctx, iv, iv); /* Out colorspace -> output table -> out colorspace. */
-
- otoentry(iv,iv); /* Convert from output color space value to table value */
-
- /* Clip to legal values */
- for (f = 0; f < pn->outputChan; f++) {
- double tt;
- tt = iv[f];
- if (tt < 0.0) {
- DBGSLC(("oclip: tt = %f\n",tt));
- if (tt < -CLIP_MARGIN)
- clip = 5;
- tt = 0.0;
- } else if (tt > 1.0) {
- DBGSLC(("oclip: tt = %f\n",tt));
- if (tt > (1.0 + CLIP_MARGIN))
- clip = 5;
- tt = 1.0;
- }
- iv[f] = tt;
- }
-
- for (f = 0; f < pn->outputChan; f++) /* Input tables */
- pn->outputTable[f * pn->outputEnt + n] = iv[f];
- }
- }
-
- icp->al->free(icp->al, _iv);
-
- icp->warnc = 0;
- if (clip) {
- DBGSLC(("Returning clip status = %d\n",clip));
- icp->warnc = clip;
- }
-
- return 0;
-}
-
-/* Helper function to initialize a Lut tables contents */
-/* from supplied transfer functions. */
-/* Set errc and return error number */
-/* Set warnc if there is clipping in the output values */
-static int icmLut_set_tables (
-icmLut *p, /* Pointer to Lut object */
-int flags, /* Setting flags */
-void *cbctx, /* Opaque callback context pointer value */
-icColorSpaceSignature insig, /* Input color space */
-icColorSpaceSignature outsig, /* Output color space */
-void (*infunc)(void *cbcntx, 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 *cbctx, double *out, double *in),
- /* inspace' -> outspace' transfer function */
-double *clutmin, double *clutmax, /* Maximum range of outspace' values (NULL = default) */
-void (*outfunc)(void *cbctx, double *out, double *in)
- /* Output transfer function, outspace'->outspace (NULL = deflt) */
-) {
- struct _icmLut *pp[3];
-
- /* Simply call the multiple table function with one table */
- pp[0] = p;
- return icmSetMultiLutTables(1, pp, flags,
- cbctx, insig, outsig,
- infunc,
- inmin, inmax,
- clutfunc,
- clutmin, clutmax,
- outfunc);
-}
-
-/* - - - - - - - - - - - - - - - - */
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmLut_get_size(
- icmBase *pp
-) {
- icmLut *p = (icmLut *)pp;
- unsigned int len = 0;
-
- if (p->ttype == icSigLut8Type) {
- len = sat_add(len, 48); /* tag and header */
- len = sat_add(len, sat_mul3(1, p->inputChan, p->inputEnt));
- len = sat_add(len, sat_mul3(1, p->outputChan, sat_pow(p->clutPoints,p->inputChan)));
- len = sat_add(len, sat_mul3(1, p->outputChan, p->outputEnt));
- } else {
- len = sat_add(len, 52); /* tag and header */
- len = sat_add(len, sat_mul3(2, p->inputChan, p->inputEnt));
- len = sat_add(len, sat_mul3(2, p->outputChan, sat_pow(p->clutPoints,p->inputChan)));
- len = sat_add(len, sat_mul3(2, p->outputChan, p->outputEnt));
- }
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmLut_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmLut *p = (icmLut *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i, j, g, size;
- char *bp, *buf;
-
- if (len < 4) {
- sprintf(icp->err,"icmLut_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmLut_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmLut_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- p->ttype = (icTagTypeSignature)read_SInt32Number(bp);
- if (p->ttype != icSigLut8Type && p->ttype != icSigLut16Type) {
- sprintf(icp->err,"icmLut_read: Wrong tag type for icmLut");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- if (p->ttype == icSigLut8Type) {
- if (len < 48) {
- sprintf(icp->err,"icmLut_read: Tag too small to be legal");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- } else {
- if (len < 52) {
- sprintf(icp->err,"icmLut_read: Tag too small to be legal");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- }
-
- /* Read in the info common to 8 and 16 bit Lut */
- p->inputChan = read_UInt8Number(bp+8);
- p->outputChan = read_UInt8Number(bp+9);
- p->clutPoints = read_UInt8Number(bp+10);
-
- /* Sanity check */
- if (p->inputChan > MAX_CHAN) {
- sprintf(icp->err,"icmLut_read: Can't handle > %d input channels\n",MAX_CHAN);
- return icp->errc = 1;
- }
-
- if (p->outputChan > MAX_CHAN) {
- sprintf(icp->err,"icmLut_read: Can't handle > %d output channels\n",MAX_CHAN);
- return icp->errc = 1;
- }
-
- /* Read 3x3 transform matrix */
- for (j = 0; j < 3; j++) { /* Rows */
- for (i = 0; i < 3; i++) { /* Columns */
- p->e[j][i] = read_S15Fixed16Number(bp + 12 + ((j * 3 + i) * 4));
- }
- }
- /* Read 16 bit specific stuff */
- if (p->ttype == icSigLut8Type) {
- p->inputEnt = 256; /* By definition */
- p->outputEnt = 256; /* By definition */
- bp = buf+48;
- } else {
- p->inputEnt = read_UInt16Number(bp+48);
- p->outputEnt = read_UInt16Number(bp+50);
- bp = buf+52;
- }
-
- /* Sanity check dimensions. This protects against */
- /* subsequent integer overflows involving the dimensions. */
- if ((size = icmLut_get_size((icmBase *)p)) == UINT_MAX
- || size > len) {
- sprintf(icp->err,"icmLut_read: Tag wrong size for contents");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read the input tables */
- size = (p->inputChan * p->inputEnt);
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- if (p->ttype == icSigLut8Type) {
- for (i = 0; i < size; i++, bp += 1)
- p->inputTable[i] = read_DCS8Number(bp);
- } else {
- for (i = 0; i < size; i++, bp += 2)
- p->inputTable[i] = read_DCS16Number(bp);
- }
-
- /* Read the clut table */
- size = (p->outputChan * sat_pow(p->clutPoints,p->inputChan));
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- if (p->ttype == icSigLut8Type) {
- for (i = 0; i < size; i++, bp += 1)
- p->clutTable[i] = read_DCS8Number(bp);
- } else {
- for (i = 0; i < size; i++, bp += 2)
- p->clutTable[i] = read_DCS16Number(bp);
- }
-
- /* Read the output tables */
- size = (p->outputChan * p->outputEnt);
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- if (p->ttype == icSigLut8Type) {
- for (i = 0; i < size; i++, bp += 1)
- p->outputTable[i] = read_DCS8Number(bp);
- } else {
- for (i = 0; i < size; i++, bp += 2)
- p->outputTable[i] = read_DCS16Number(bp);
- }
-
- /* Private: compute dimensional increment though clut */
- /* Note that first channel varies least rapidly. */
- i = p->inputChan-1;
- p->dinc[i--] = p->outputChan;
- for (; i < p->inputChan; i--)
- p->dinc[i] = p->dinc[i+1] * p->clutPoints;
-
- /* Private: compute offsets from base of cube to other corners */
- for (p->dcube[0] = 0, g = 1, j = 0; j < p->inputChan; j++) {
- for (i = 0; i < g; i++)
- p->dcube[g+i] = p->dcube[i] + p->dinc[j];
- g *= 2;
- }
-
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmLut_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmLut *p = (icmLut *)pp;
- icc *icp = p->icp;
- unsigned int i,j;
- unsigned int len, size;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmLut_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmLut_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmLut_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write the info common to 8 and 16 bit Lut */
- if ((rv = write_UInt8Number(p->inputChan, bp+8)) != 0) {
- sprintf(icp->err,"icmLut_write: write_UInt8Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_UInt8Number(p->outputChan, bp+9)) != 0) {
- sprintf(icp->err,"icmLut_write: write_UInt8Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_UInt8Number(p->clutPoints, bp+10)) != 0) {
- sprintf(icp->err,"icmLut_write: write_UInt8Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- write_UInt8Number(0, bp+11); /* Set padding to 0 */
-
- /* Write 3x3 transform matrix */
- for (j = 0; j < 3; j++) { /* Rows */
- for (i = 0; i < 3; i++) { /* Columns */
- if ((rv = write_S15Fixed16Number(p->e[j][i],bp + 12 + ((j * 3 + i) * 4))) != 0) {
- sprintf(icp->err,"icmLut_write: write_S15Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- }
-
- /* Write 16 bit specific stuff */
- if (p->ttype == icSigLut8Type) {
- if (p->inputEnt != 256 || p->outputEnt != 256) {
- sprintf(icp->err,"icmLut_write: 8 bit Input and Output tables must be 256 entries");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp = buf+48;
- } else {
- if (p->inputEnt > 4096 || p->outputEnt > 4096) {
- sprintf(icp->err,"icmLut_write: 16 bit Input and Output tables must each be less than 4096 entries");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- if ((rv = write_UInt16Number(p->inputEnt, bp+48)) != 0) {
- sprintf(icp->err,"icmLut_write: write_UInt16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_UInt16Number(p->outputEnt, bp+50)) != 0) {
- sprintf(icp->err,"icmLut_write: write_UInt16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- bp = buf+52;
- }
-
- /* Write the input tables */
- size = (p->inputChan * p->inputEnt);
- if (p->ttype == icSigLut8Type) {
- for (i = 0; i < size; i++, bp += 1) {
- if ((rv = write_DCS8Number(p->inputTable[i], bp)) != 0) {
- sprintf(icp->err,"icmLut_write: inputTable write_DCS8Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- } else {
- for (i = 0; i < size; i++, bp += 2) {
- if ((rv = write_DCS16Number(p->inputTable[i], bp)) != 0) {
- sprintf(icp->err,"icmLut_write: inputTable write_DCS16Number(%f) failed",p->inputTable[i]);
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- }
-
- /* Write the clut table */
- size = (p->outputChan * sat_pow(p->clutPoints,p->inputChan));
- if (p->ttype == icSigLut8Type) {
- for (i = 0; i < size; i++, bp += 1) {
- if ((rv = write_DCS8Number(p->clutTable[i], bp)) != 0) {
- sprintf(icp->err,"icmLut_write: clutTable write_DCS8Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- } else {
- for (i = 0; i < size; i++, bp += 2) {
- if ((rv = write_DCS16Number(p->clutTable[i], bp)) != 0) {
- sprintf(icp->err,"icmLut_write: clutTable write_DCS16Number(%f) failed",p->clutTable[i]);
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- }
-
- /* Write the output tables */
- size = (p->outputChan * p->outputEnt);
- if (p->ttype == icSigLut8Type) {
- for (i = 0; i < size; i++, bp += 1) {
- if ((rv = write_DCS8Number(p->outputTable[i], bp)) != 0) {
- sprintf(icp->err,"icmLut_write: outputTable write_DCS8Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- } else {
- for (i = 0; i < size; i++, bp += 2) {
- if ((rv = write_DCS16Number(p->outputTable[i], bp)) != 0) {
- sprintf(icp->err,"icmLut_write: outputTable write_DCS16Number(%f) failed",p->outputTable[i]);
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- }
-
- /* Write buffer to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmLut_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmLut_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmLut *p = (icmLut *)pp;
- if (verb <= 0)
- return;
-
- if (p->ttype == icSigLut8Type) {
- op->gprintf(op,"Lut8:\n");
- } else {
- op->gprintf(op,"Lut16:\n");
- }
- op->gprintf(op," Input Channels = %u\n",p->inputChan);
- op->gprintf(op," Output Channels = %u\n",p->outputChan);
- op->gprintf(op," CLUT resolution = %u\n",p->clutPoints);
- op->gprintf(op," Input Table entries = %u\n",p->inputEnt);
- op->gprintf(op," Output Table entries = %u\n",p->outputEnt);
- op->gprintf(op," XYZ matrix = %f, %f, %f\n",p->e[0][0],p->e[0][1],p->e[0][2]);
- op->gprintf(op," %f, %f, %f\n",p->e[1][0],p->e[1][1],p->e[1][2]);
- op->gprintf(op," %f, %f, %f\n",p->e[2][0],p->e[2][1],p->e[2][2]);
-
- if (verb >= 2) {
- unsigned int i, j, size;
- unsigned int ii[MAX_CHAN]; /* maximum no of input channels */
-
- op->gprintf(op," Input table:\n");
- for (i = 0; i < p->inputEnt; i++) {
- op->gprintf(op," %3u: ",i);
- for (j = 0; j < p->inputChan; j++)
- op->gprintf(op," %1.10f",p->inputTable[j * p->inputEnt + i]);
- op->gprintf(op,"\n");
- }
-
- op->gprintf(op,"\n CLUT table:\n");
- if (p->inputChan > MAX_CHAN) {
- op->gprintf(op," !!Can't dump > %d input channel CLUT table!!\n",MAX_CHAN);
- } else {
- size = (p->outputChan * sat_pow(p->clutPoints,p->inputChan));
- for (j = 0; j < p->inputChan; j++)
- ii[j] = 0;
- for (i = 0; i < size;) {
- unsigned int k;
- /* Print table entry index */
- op->gprintf(op," ");
- for (j = p->inputChan-1; j < p->inputChan; j--)
- op->gprintf(op," %2u",ii[j]);
- op->gprintf(op,":");
- /* Print table entry contents */
- for (k = 0; k < p->outputChan; k++, i++)
- op->gprintf(op," %1.10f",p->clutTable[i]);
- op->gprintf(op,"\n");
-
- for (j = 0; j < p->inputChan; j++) { /* Increment index */
- ii[j]++;
- if (ii[j] < p->clutPoints)
- break; /* No carry */
- ii[j] = 0;
- }
- }
- }
-
- op->gprintf(op,"\n Output table:\n");
- for (i = 0; i < p->outputEnt; i++) {
- op->gprintf(op," %3u: ",i);
- for (j = 0; j < p->outputChan; j++)
- op->gprintf(op," %1.10f",p->outputTable[j * p->outputEnt + i]);
- op->gprintf(op,"\n");
- }
-
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmLut_allocate(
- icmBase *pp
-) {
- unsigned int i, j, g, size;
- icmLut *p = (icmLut *)pp;
- icc *icp = p->icp;
-
- /* Sanity check */
- if (p->inputChan < 1) {
- sprintf(icp->err,"icmLut_alloc: Can't handle %d input channels\n",p->inputChan);
- return icp->errc = 1;
- }
-
- if (p->inputChan > MAX_CHAN) {
- sprintf(icp->err,"icmLut_alloc: Can't handle > %d input channels\n",MAX_CHAN);
- return icp->errc = 1;
- }
-
- if (p->outputChan > MAX_CHAN) {
- sprintf(icp->err,"icmLut_alloc: Can't handle > %d output channels\n",MAX_CHAN);
- return icp->errc = 1;
- }
-
- if ((size = sat_mul(p->inputChan, p->inputEnt)) == UINT_MAX) {
- sprintf(icp->err,"icmLut_alloc size overflow");
- return icp->errc = 1;
- }
- if (size != p->inputTable_size) {
- if (ovr_mul(size, sizeof(double))) {
- sprintf(icp->err,"icmLut_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->inputTable != NULL)
- icp->al->free(icp->al, p->inputTable);
- if ((p->inputTable = (double *) icp->al->calloc(icp->al,size, sizeof(double))) == NULL) {
- sprintf(icp->err,"icmLut_alloc: calloc() of Lut inputTable data failed");
- return icp->errc = 2;
- }
- p->inputTable_size = size;
- }
- if ((size = sat_mul(p->outputChan, sat_pow(p->clutPoints,p->inputChan))) == UINT_MAX) {
- sprintf(icp->err,"icmLut_alloc size overflow");
- return icp->errc = 1;
- }
- if (size != p->clutTable_size) {
- if (ovr_mul(size, sizeof(double))) {
- sprintf(icp->err,"icmLut_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->clutTable != NULL)
- icp->al->free(icp->al, p->clutTable);
- if ((p->clutTable = (double *) icp->al->calloc(icp->al,size, sizeof(double))) == NULL) {
- sprintf(icp->err,"icmLut_alloc: calloc() of Lut clutTable data failed");
- return icp->errc = 2;
- }
- p->clutTable_size = size;
- }
- if ((size = sat_mul(p->outputChan, p->outputEnt)) == UINT_MAX) {
- sprintf(icp->err,"icmLut_alloc size overflow");
- return icp->errc = 1;
- }
- if (size != p->outputTable_size) {
- if (ovr_mul(size, sizeof(double))) {
- sprintf(icp->err,"icmLut_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->outputTable != NULL)
- icp->al->free(icp->al, p->outputTable);
- if ((p->outputTable = (double *) icp->al->calloc(icp->al,size, sizeof(double))) == NULL) {
- sprintf(icp->err,"icmLut_alloc: calloc() of Lut outputTable data failed");
- return icp->errc = 2;
- }
- p->outputTable_size = size;
- }
-
- /* Private: compute dimensional increment though clut */
- /* Note that first channel varies least rapidly. */
- i = p->inputChan-1;
- p->dinc[i--] = p->outputChan;
- for (; i < p->inputChan; i--)
- p->dinc[i] = p->dinc[i+1] * p->clutPoints;
-
- /* Private: compute offsets from base of cube to other corners */
- for (p->dcube[0] = 0, g = 1, j = 0; j < p->inputChan; j++) {
- for (i = 0; i < g; i++)
- p->dcube[g+i] = p->dcube[i] + p->dinc[j];
- g *= 2;
- }
-
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmLut_delete(
- icmBase *pp
-) {
- icmLut *p = (icmLut *)pp;
- icc *icp = p->icp;
- int i;
-
- if (p->inputTable != NULL)
- icp->al->free(icp->al, p->inputTable);
- if (p->clutTable != NULL)
- icp->al->free(icp->al, p->clutTable);
- if (p->outputTable != NULL)
- icp->al->free(icp->al, p->outputTable);
- for (i = 0; i < p->inputChan; i++)
- icmTable_delete_bwd(icp, &p->rit[i]);
- for (i = 0; i < p->outputChan; i++)
- icmTable_delete_bwd(icp, &p->rot[i]);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmLut(
- icc *icp
-) {
- int i,j;
- icmLut *p;
- if ((p = (icmLut *) icp->al->calloc(icp->al,1,sizeof(icmLut))) == NULL)
- return NULL;
- p->ttype = icSigLut16Type;
- p->refcount = 1;
- p->get_size = icmLut_get_size;
- p->read = icmLut_read;
- p->write = icmLut_write;
- p->dump = icmLut_dump;
- p->allocate = icmLut_allocate;
- p->del = icmLut_delete;
-
- /* Lookup methods */
- p->nu_matrix = icmLut_nu_matrix;
- p->min_max = icmLut_min_max;
- p->lookup_matrix = icmLut_lookup_matrix;
- p->lookup_input = icmLut_lookup_input;
- p->lookup_clut_nl = icmLut_lookup_clut_nl;
- p->lookup_clut_sx = icmLut_lookup_clut_sx;
- p->lookup_output = icmLut_lookup_output;
-
- /* Set method */
- p->set_tables = icmLut_set_tables;
-
- p->icp = icp;
-
- /* Set matrix to reasonable default */
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++) {
- if (i == j)
- p->e[i][j] = 1.0;
- else
- p->e[i][j] = 0.0;
- }
-
- /* Init lookups to non-dangerous values */
- for (i = 0; i < MAX_CHAN; i++)
- p->dinc[i] = 0;
-
- for (i = 0; i < (1 << MAX_CHAN); i++)
- p->dcube[i] = 0;
-
- for (i = 0; i < MAX_CHAN; i++) {
- p->rit[i].inited = 0;
- p->rot[i].inited = 0;
- }
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* Measurement */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmMeasurement_get_size(
- icmBase *pp
-) {
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_add(len, 4); /* 4 for standard observer */
- len = sat_add(len, 12); /* 12 for XYZ of measurement backing */
- len = sat_add(len, 4); /* 4 for measurement geometry */
- len = sat_add(len, 4); /* 4 for measurement flare */
- len = sat_add(len, 4); /* 4 for standard illuminant */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmMeasurement_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmMeasurement *p = (icmMeasurement *)pp;
- icc *icp = p->icp;
- int rv;
- char *bp, *buf;
-
- if (len < 36) {
- sprintf(icp->err,"icmMeasurement_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmMeasurement_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmMeasurement_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmMeasurement_read: Wrong tag type for icmMeasurement");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read the encoded standard observer */
- p->observer = (icStandardObserver)read_SInt32Number(bp + 8);
-
- /* Read the XYZ values for measurement backing */
- if ((rv = read_XYZNumber(&p->backing, bp+12)) != 0) {
- sprintf(icp->err,"icmMeasurement: read_XYZNumber error");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Read the encoded measurement geometry */
- p->geometry = (icMeasurementGeometry)read_SInt32Number(bp + 24);
-
- /* Read the proportion of flare */
- p->flare = read_U16Fixed16Number(bp + 28);
-
- /* Read the encoded standard illuminant */
- p->illuminant = (icIlluminant)read_SInt32Number(bp + 32);
-
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmMeasurement_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmMeasurement *p = (icmMeasurement *)pp;
- icc *icp = p->icp;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmMeasurement_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmMeasurement_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmMeasurement_write, type: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write the encoded standard observer */
- if ((rv = write_SInt32Number((int)p->observer, bp + 8)) != 0) {
- sprintf(icp->err,"icmMeasurementa_write, observer: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write the XYZ values for measurement backing */
- if ((rv = write_XYZNumber(&p->backing, bp+12)) != 0) {
- sprintf(icp->err,"icmMeasurement, backing: write_XYZNumber error");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write the encoded measurement geometry */
- if ((rv = write_SInt32Number((int)p->geometry, bp + 24)) != 0) {
- sprintf(icp->err,"icmMeasurementa_write, geometry: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write the proportion of flare */
- if ((rv = write_U16Fixed16Number(p->flare, bp + 28)) != 0) {
- sprintf(icp->err,"icmMeasurementa_write, flare: write_U16Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write the encoded standard illuminant */
- if ((rv = write_SInt32Number((int)p->illuminant, bp + 32)) != 0) {
- sprintf(icp->err,"icmMeasurementa_write, illuminant: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmMeasurement_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmMeasurement_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmMeasurement *p = (icmMeasurement *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"Measurement:\n");
- op->gprintf(op," Standard Observer = %s\n", string_StandardObserver(p->observer));
- op->gprintf(op," XYZ for Measurement Backing = %s\n", string_XYZNumber_and_Lab(&p->backing));
- op->gprintf(op," Measurement Geometry = %s\n", string_MeasurementGeometry(p->geometry));
- op->gprintf(op," Measurement Flare = %5.1f%%\n", p->flare * 100.0);
- op->gprintf(op," Standard Illuminant = %s\n", string_Illuminant(p->illuminant));
-}
-
-/* Allocate variable sized data elements */
-static int icmMeasurement_allocate(
- icmBase *pp
-) {
- /* Nothing to do */
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmMeasurement_delete(
- icmBase *pp
-) {
- icmMeasurement *p = (icmMeasurement *)pp;
- icc *icp = p->icp;
-
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmMeasurement(
- icc *icp
-) {
- icmMeasurement *p;
- if ((p = (icmMeasurement *) icp->al->calloc(icp->al,1,sizeof(icmMeasurement))) == NULL)
- return NULL;
- p->ttype = icSigMeasurementType;
- p->refcount = 1;
- p->get_size = icmMeasurement_get_size;
- p->read = icmMeasurement_read;
- p->write = icmMeasurement_write;
- p->dump = icmMeasurement_dump;
- p->allocate = icmMeasurement_allocate;
- p->del = icmMeasurement_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-
-/* Named color structure read/write support */
-static int read_NamedColorVal(
- icmNamedColorVal *p,
- char *bp,
- char *end,
- icColorSpaceSignature pcs, /* Header Profile Connection Space */
- unsigned int ndc /* Number of device corrds */
-) {
- icc *icp = p->icp;
- unsigned int i;
- unsigned int mxl; /* Max possible string length */
- int rv;
-
- if (bp > end) {
- sprintf(icp->err,"icmNamedColorVal_read: Data too short to read");
- return icp->errc = 1;
- }
- mxl = (end - bp) < 32 ? (end - bp) : 32;
- if ((rv = check_null_string(bp,mxl)) == 1) {
- sprintf(icp->err,"icmNamedColorVal_read: Root name string not terminated");
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
- strcpy(p->root, bp);
- bp += strlen(p->root) + 1;
- if (bp > end || ndc > (end - bp)) {
- sprintf(icp->err,"icmNamedColorVal_read: Data too short to read device coords");
- return icp->errc = 1;
- }
- for (i = 0; i < ndc; i++) {
- p->deviceCoords[i] = read_DCS8Number(bp);
- bp += 1;
- }
- return 0;
-}
-
-static int read_NamedColorVal2(
- icmNamedColorVal *p,
- char *bp,
- char *end,
- icColorSpaceSignature pcs, /* Header Profile Connection Space */
- unsigned int ndc /* Number of device coords */
-) {
- int rv;
- icc *icp = p->icp;
- unsigned int i;
-
- if (bp > end
- || (32 + 6) > (end - bp)
- || ndc > (end - bp - 32 - 6)/2) {
- sprintf(icp->err,"icmNamedColorVal2_read: Data too short to read");
- return icp->errc = 1;
- }
- if ((rv = check_null_string(bp,32)) == 1) {
- sprintf(icp->err,"icmNamedColorVal2_read: Root name string not terminated");
- return icp->errc = 1;
- }
- memmove((void *)p->root,(void *)(bp + 0),32);
- switch(pcs) {
- case icSigXYZData:
- read_PCSNumber(icp, icSigXYZData, p->pcsCoords, bp+32);
- break;
- case icSigLabData:
- /* namedColor2Type retains legacy Lab encoding */
- read_PCSNumber(icp, icmSigLabV2Data, p->pcsCoords, bp+32);
- break;
- default:
- return 1; /* Unknown PCS */
- }
- for (i = 0; i < ndc; i++)
- p->deviceCoords[i] = read_DCS16Number(bp + 32 + 6 + 2 * i);
- return 0;
-}
-
-static int write_NamedColorVal(
- icmNamedColorVal *p,
- char *d,
- icColorSpaceSignature pcs, /* Header Profile Connection Space */
- unsigned int ndc /* Number of device corrds */
-) {
- icc *icp = p->icp;
- unsigned int i;
- int rv;
-
- if ((rv = check_null_string(p->root,32)) == 1) {
- sprintf(icp->err,"icmNamedColorVal_write: Root string names is unterminated");
- return icp->errc = 1;
- }
- strcpy(d, p->root);
- d += strlen(p->root) + 1;
- for (i = 0; i < ndc; i++) {
- if ((rv = write_DCS8Number(p->deviceCoords[i], d)) != 0) {
- sprintf(icp->err,"icmNamedColorVal_write: write of device coord failed");
- return icp->errc = 1;
- }
- d += 1;
- }
- return 0;
-}
-
-static int write_NamedColorVal2(
- icmNamedColorVal *p,
- char *bp,
- icColorSpaceSignature pcs, /* Header Profile Connection Space */
- unsigned int ndc /* Number of device coords */
-) {
- icc *icp = p->icp;
- unsigned int i;
- int rv;
-
- if ((rv = check_null_string(p->root,32)) == 1) {
- sprintf(icp->err,"icmNamedColorVal2_write: Root string names is unterminated");
- return icp->errc = 1;
- }
- rv = 0;
- memmove((void *)(bp + 0),(void *)p->root,32);
- switch(pcs) {
- case icSigXYZData:
- rv |= write_PCSNumber(icp, icSigXYZData, p->pcsCoords, bp+32);
- break;
- case icSigLabData:
- /* namedColor2Type retains legacy Lab encoding */
- rv |= write_PCSNumber(icp, icmSigLabV2Data, p->pcsCoords, bp+32);
- break;
- default:
- sprintf(icp->err,"icmNamedColorVal2_write: Unknown PCS");
- return icp->errc = 1;
- }
- if (rv) {
- sprintf(icp->err,"icmNamedColorVal2_write: write of PCS coord failed");
- return icp->errc = 1;
- }
- for (i = 0; i < ndc; i++) {
- if ((rv = write_DCS16Number(p->deviceCoords[i], bp + 32 + 6 + 2 * i)) != 0) {
- sprintf(icp->err,"icmNamedColorVal2_write: write of device coord failed");
- return icp->errc = 1;
- }
- }
- return 0;
-}
-
-/* - - - - - - - - - - - */
-/* icmNamedColor object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmNamedColor_get_size(
- icmBase *pp
-) {
- icmNamedColor *p = (icmNamedColor *)pp;
- unsigned int len = 0;
- if (p->ttype == icSigNamedColorType) {
- unsigned int i;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_add(len, 4); /* 4 for vendor specific flags */
- len = sat_add(len, 4); /* 4 for count of named colors */
- len = sat_add(len, strlen(p->prefix) + 1); /* prefix of color names */
- len = sat_add(len, strlen(p->suffix) + 1); /* suffix of color names */
- for (i = 0; i < p->count; i++) {
- len = sat_add(len, strlen(p->data[i].root) + 1); /* color names */
- len = sat_add(len, p->nDeviceCoords * 1); /* bytes for each named color */
- }
- } else { /* Named Color 2 */
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_add(len, 4); /* 4 for vendor specific flags */
- len = sat_add(len, 4); /* 4 for count of named colors */
- len = sat_add(len, 4); /* 4 for number of device coords */
- len = sat_add(len, 32); /* 32 for prefix of color names */
- len = sat_add(len, 32); /* 32 for suffix of color names */
- len = sat_add(len, sat_mul(p->count, (32 + 6 + p->nDeviceCoords * 2)));
- /* bytes for each named color */
- }
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmNamedColor_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmNamedColor *p = (icmNamedColor *)pp;
- icc *icp = p->icp;
- unsigned int i;
- char *bp, *buf, *end;
- int rv;
-
- if (len < 4) {
- sprintf(icp->err,"icmNamedColor_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmNamedColor_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
- end = buf + len;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmNamedColor_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- p->ttype = (icTagTypeSignature)read_SInt32Number(bp);
- if (p->ttype != icSigNamedColorType && p->ttype != icSigNamedColor2Type) {
- sprintf(icp->err,"icmNamedColor_read: Wrong tag type for icmNamedColor");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- if (p->ttype == icSigNamedColorType) {
- if (len < 16) {
- sprintf(icp->err,"icmNamedColor_read: Tag too small to be legal");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Make sure that the number of device coords in known */
- p->nDeviceCoords = number_ColorSpaceSignature(icp->header->colorSpace);
- if (p->nDeviceCoords > MAX_CHAN) {
- sprintf(icp->err,"icmNamedColor_read: Can't handle more than %d device channels",MAX_CHAN);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- } else { /* icmNC2 */
- if (len < 84) {
- sprintf(icp->err,"icmNamedColor_read: Tag too small to be legal");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- }
-
- /* Read vendor specific flag */
- p->vendorFlag = read_UInt32Number(bp+8);
-
- /* Read count of named colors */
- p->count = read_UInt32Number(bp+12);
-
- if (p->ttype == icSigNamedColorType) {
- unsigned int mxl; /* Max possible string length */
- bp = bp + 16;
-
- /* Prefix for each color name */
- if (bp > end) {
- sprintf(icp->err,"icmNamedColor_read: Data too short to read");
- return icp->errc = 1;
- }
- mxl = (end - bp) < 32 ? (end - bp) : 32;
- if ((rv = check_null_string(bp,mxl)) == 1) {
- sprintf(icp->err,"icmNamedColor_read: Color prefix is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
- strcpy(p->prefix, bp);
- bp += strlen(p->prefix) + 1;
-
- /* Suffix for each color name */
- if (bp > end) {
- sprintf(icp->err,"icmNamedColor_read: Data too short to read");
- return icp->errc = 1;
- }
- mxl = (end - bp) < 32 ? (end - bp) : 32;
- if ((rv = check_null_string(bp,mxl)) == 1) {
- sprintf(icp->err,"icmNamedColor_read: Color suffix is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
- strcpy(p->suffix, bp);
- bp += strlen(p->suffix) + 1;
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read all the data from the buffer */
- for (i = 0; i < p->count; i++) {
- if ((rv = read_NamedColorVal(p->data+i, bp, end, icp->header->pcs, p->nDeviceCoords)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- bp += strlen(p->data[i].root) + 1;
- bp += p->nDeviceCoords * 1;
- }
- } else { /* icmNC2 */
- /* Number of device coords per color */
- p->nDeviceCoords = read_UInt32Number(bp+16);
- if (p->nDeviceCoords > MAX_CHAN) {
- sprintf(icp->err,"icmNamedColor_read: Can't handle more than %d device channels",MAX_CHAN);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Prefix for each color name */
- memmove((void *)p->prefix, (void *)(bp + 20), 32);
- if ((rv = check_null_string(p->prefix,32)) == 1) {
- sprintf(icp->err,"icmNamedColor_read: Color prefix is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Suffix for each color name */
- memmove((void *)p->suffix, (void *)(bp + 52), 32);
- if ((rv = check_null_string(p->suffix,32)) == 1) {
- sprintf(icp->err,"icmNamedColor_read: Color suffix is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read all the data from the buffer */
- bp = bp + 84;
- for (i = 0; i < p->count; i++) {
- if ((rv = read_NamedColorVal2(p->data+i, bp, end, icp->header->pcs, p->nDeviceCoords)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- bp += 32 + 6 + p->nDeviceCoords * 2;
- }
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmNamedColor_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmNamedColor *p = (icmNamedColor *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmNamedColor_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmNamedColor_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmNamedColor_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write vendor specific flag */
- if ((rv = write_UInt32Number(p->vendorFlag, bp+8)) != 0) {
- sprintf(icp->err,"icmNamedColor_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write count of named colors */
- if ((rv = write_UInt32Number(p->count, bp+12)) != 0) {
- sprintf(icp->err,"icmNamedColor_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- if (p->ttype == icSigNamedColorType) {
- bp = bp + 16;
-
- /* Prefix for each color name */
- if ((rv = check_null_string(p->prefix,32)) == 1) {
- sprintf(icp->err,"icmNamedColor_write: Color prefix is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- strcpy(bp, p->prefix);
- bp += strlen(p->prefix) + 1;
-
- /* Suffix for each color name */
- if ((rv = check_null_string(p->suffix,32)) == 1) {
- sprintf(icp->err,"icmNamedColor_write: Color sufix is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- strcpy(bp, p->suffix);
- bp += strlen(p->suffix) + 1;
-
- /* Write all the data to the buffer */
-
- for (i = 0; i < p->count; i++) {
- if ((rv = write_NamedColorVal(p->data+i, bp, icp->header->pcs, p->nDeviceCoords)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- bp += strlen(p->data[i].root) + 1;
- bp += p->nDeviceCoords * 1;
- }
- } else { /* icmNC2 */
- /* Number of device coords per color */
- if ((rv = write_UInt32Number(p->nDeviceCoords, bp+16)) != 0) {
- sprintf(icp->err,"icmNamedColor_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Prefix for each color name */
- if ((rv = check_null_string(p->prefix,32)) == 1) {
- sprintf(icp->err,"icmNamedColor_write: Color prefix is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- memmove((void *)(bp + 20), (void *)p->prefix, 32);
-
- /* Suffix for each color name */
- if ((rv = check_null_string(p->suffix,32)) == 1) {
- sprintf(icp->err,"icmNamedColor_write: Color sufix is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- memmove((void *)(bp + 52), (void *)p->suffix, 32);
-
- /* Write all the data to the buffer */
- bp = bp + 84;
- for (i = 0; i < p->count; i++, bp += (32 + 6 + p->nDeviceCoords * 2)) {
- if ((rv = write_NamedColorVal2(p->data+i, bp, icp->header->pcs, p->nDeviceCoords)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmNamedColor_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmNamedColor_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmNamedColor *p = (icmNamedColor *)pp;
- icc *icp = p->icp;
- if (verb <= 0)
- return;
-
- if (p->ttype == icSigNamedColorType)
- op->gprintf(op,"NamedColor:\n");
- else
- op->gprintf(op,"NamedColor2:\n");
- op->gprintf(op," Vendor Flag = 0x%x\n",p->vendorFlag);
- op->gprintf(op," No. colors = %u\n",p->count);
- op->gprintf(op," No. dev. coords = %u\n",p->nDeviceCoords);
- op->gprintf(op," Name prefix = '%s'\n",p->prefix);
- op->gprintf(op," Name suffix = '%s'\n",p->suffix);
- if (verb >= 2) {
- unsigned int i, n;
- icmNamedColorVal *vp;
- for (i = 0; i < p->count; i++) {
- vp = p->data + i;
- op->gprintf(op," Color %lu:\n",i);
- op->gprintf(op," Name root = '%s'\n",vp->root);
-
- if (p->ttype == icSigNamedColor2Type) {
- switch(icp->header->pcs) {
- case icSigXYZData:
- op->gprintf(op," XYZ = %f, %f, %f\n",
- vp->pcsCoords[0],vp->pcsCoords[1],vp->pcsCoords[2]);
- break;
- case icSigLabData:
- op->gprintf(op," Lab = %f, %f, %f\n",
- vp->pcsCoords[0],vp->pcsCoords[1],vp->pcsCoords[2]);
- break;
- default:
- op->gprintf(op," Unexpected PCS\n");
- break;
- }
- }
- if (p->nDeviceCoords > 0) {
- op->gprintf(op," Device Coords = ");
- for (n = 0; n < p->nDeviceCoords; n++) {
- if (n > 0)
- op->gprintf(op,", ");
- op->gprintf(op,"%f",vp->deviceCoords[n]);
- }
- op->gprintf(op,"\n");
- }
- }
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmNamedColor_allocate(
- icmBase *pp
-) {
- icmNamedColor *p = (icmNamedColor *)pp;
- icc *icp = p->icp;
-
- if (p->count != p->_count) {
- unsigned int i;
- if (ovr_mul(p->count, sizeof(icmNamedColorVal))) {
- sprintf(icp->err,"icmNamedColor_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (icmNamedColorVal *) icp->al->calloc(icp->al,p->count, sizeof(icmNamedColorVal))) == NULL) {
- sprintf(icp->err,"icmNamedColor_alloc: malloc() of icmNamedColor data failed");
- return icp->errc = 2;
- }
- for (i = 0; i < p->count; i++) {
- p->data[i].icp = icp; /* Do init */
- }
- p->_count = p->count;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmNamedColor_delete(
- icmBase *pp
-) {
- icmNamedColor *p = (icmNamedColor *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmNamedColor(
- icc *icp
-) {
- icmNamedColor *p;
- if ((p = (icmNamedColor *) icp->al->calloc(icp->al,1,sizeof(icmNamedColor))) == NULL)
- return NULL;
- p->ttype = icSigNamedColor2Type;
- p->refcount = 1;
- p->get_size = icmNamedColor_get_size;
- p->read = icmNamedColor_read;
- p->write = icmNamedColor_write;
- p->dump = icmNamedColor_dump;
- p->allocate = icmNamedColor_allocate;
- p->del = icmNamedColor_delete;
- p->icp = icp;
-
- /* Default the the number of device coords appropriately for NamedColorType */
- p->nDeviceCoords = number_ColorSpaceSignature(icp->header->colorSpace);
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* Colorant table structure read/write support */
-/* (Contribution from Piet Vandenborre) */
-
-static int read_ColorantTableVal(
- icmColorantTableVal *p,
- char *bp,
- char *end,
- icColorSpaceSignature pcs /* Header Profile Connection Space */
-) {
- int rv;
- icc *icp = p->icp;
- if (bp > end || (32 + 6) > (end - bp)) {
- sprintf(icp->err,"icmColorantTableVal_read: Data too short to read");
- return icp->errc = 1;
- }
- if ((rv = check_null_string(bp,32)) == 1) {
- sprintf(icp->err,"icmColorantTableVal_read: Name string not terminated");
- return icp->errc = 1;
- }
- memmove((void *)p->name,(void *)(bp + 0),32);
- switch(pcs) {
- case icSigXYZData:
- case icSigLabData:
- read_PCSNumber(icp, pcs, p->pcsCoords, bp+32);
- break;
- default:
- return 1; /* Unknown PCS */
- }
- return 0;
-}
-
-static int write_ColorantTableVal(
- icmColorantTableVal *p,
- char *bp,
- icColorSpaceSignature pcs /* Header Profile Connection Space */
-) {
- int rv;
- icc *icp = p->icp;
-
- if ((rv = check_null_string(p->name,32)) == 1) {
- sprintf(icp->err,"icmColorantTableVal_write: Name string is unterminated");
- return icp->errc = 1;
- }
- memmove((void *)(bp + 0),(void *)p->name,32);
- rv = 0;
- switch(pcs) {
- case icSigXYZData:
- case icSigLabData:
- rv |= write_PCSNumber(icp, pcs, p->pcsCoords, bp+32);
- break;
- default:
- sprintf(icp->err,"icmColorantTableVal_write: Unknown PCS");
- return icp->errc = 1;
- }
- if (rv) {
- sprintf(icp->err,"icmColorantTableVal_write: write of PCS coord failed");
- return icp->errc = 1;
- }
- return 0;
-}
-
-/* - - - - - - - - - - - */
-/* icmColorantTable object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmColorantTable_get_size(
- icmBase *pp
-) {
- icmColorantTable *p = (icmColorantTable *)pp;
- unsigned int len = 0;
- if (p->ttype == icSigColorantTableType
- || p->ttype == icmSigAltColorantTableType) {
- unsigned int i;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_add(len, 4); /* 4 for count of colorants */
- for (i = 0; i < p->count; i++) {
- len = sat_add(len, 32); /* colorant names - 32 bytes*/
- len = sat_add(len, 6); /* colorant pcs value - 3 x 16bit number*/
- }
- }
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmColorantTable_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmColorantTable *p = (icmColorantTable *)pp;
- icc *icp = p->icp;
- icColorSpaceSignature pcs;
- unsigned int i;
- char *bp, *buf, *end;
- int rv = 0;
-
- if (icp->header->deviceClass != icSigLinkClass)
- pcs = icp->header->pcs;
- else
- pcs = icSigLabData;
-
- if (len < 4) {
- sprintf(icp->err,"icmColorantTable_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmColorantTable_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
- end = buf + len;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmColorantTable_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- p->ttype = (icTagTypeSignature)read_SInt32Number(bp);
- if (p->ttype != icSigColorantTableType
- && p->ttype != icmSigAltColorantTableType) {
- sprintf(icp->err,"icmColorantTable_read: Wrong tag type for icmColorantTable");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- if (len < 12) {
- sprintf(icp->err,"icmColorantTable_read: Tag too small to be legal");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read count of colorants */
- if (p->ttype == icmSigAltColorantTableType)
- p->count = read_UInt8Number(bp+8); /* Hmm. This is Little Endian */
- else
- p->count = read_UInt32Number(bp+8);
-
- if (p->count > ((len - 12) / (32 + 6))) {
- sprintf(icp->err,"icmColorantTable_read count overflow, count %x, len %d",p->count,len);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- bp = bp + 12;
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read all the data from the buffer */
- for (i = 0; i < p->count; i++, bp += (32 + 6)) {
- if (p->ttype == icmSigAltColorantTableType /* Hack to reverse little endian */
- && (end - bp) >= 38) {
- int tt;
- tt = *(bp + 32);
- *(bp+32) = *(bp+33);
- *(bp+33) = tt;
- tt = *(bp + 34);
- *(bp+34) = *(bp+35);
- *(bp+35) = tt;
- tt = *(bp + 36);
- *(bp+36) = *(bp+37);
- *(bp+37) = tt;
- }
- if ((rv = read_ColorantTableVal(p->data+i, bp, end, pcs)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- }
-
- icp->al->free(icp->al, buf);
- return rv;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmColorantTable_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmColorantTable *p = (icmColorantTable *)pp;
- icc *icp = p->icp;
- icColorSpaceSignature pcs;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- if (icp->header->deviceClass != icSigLinkClass)
- pcs = icp->header->pcs;
- else
- pcs = icSigLabData;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmColorantTable_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmColorantTable_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmColorantTable_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write count of colorants */
- if ((rv = write_UInt32Number(p->count, bp+8)) != 0) {
- sprintf(icp->err,"icmColorantTable_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- bp = bp + 12;
-
- /* Write all the data to the buffer */
- for (i = 0; i < p->count; i++, bp += (32 + 6)) {
- if ((rv = write_ColorantTableVal(p->data+i, bp, pcs)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmColorantTable_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmColorantTable_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmColorantTable *p = (icmColorantTable *)pp;
- icc *icp = p->icp;
- icColorSpaceSignature pcs;
-
- if (icp->header->deviceClass != icSigLinkClass)
- pcs = icp->header->pcs;
- else
- pcs = icSigLabData;
-
- if (verb <= 0)
- return;
-
- if (p->ttype == icSigColorantTableType
- || p->ttype == icmSigAltColorantTableType)
- op->gprintf(op,"ColorantTable:\n");
- op->gprintf(op," No. colorants = %u\n",p->count);
- if (verb >= 2) {
- unsigned int i;
- icmColorantTableVal *vp;
- for (i = 0; i < p->count; i++) {
- vp = p->data + i;
- op->gprintf(op," Colorant %lu:\n",i);
- op->gprintf(op," Name = '%s'\n",vp->name);
-
- if (p->ttype == icSigColorantTableType
- || p->ttype == icmSigAltColorantTableType) {
-
- switch(pcs) {
- case icSigXYZData:
- op->gprintf(op," XYZ = %f, %f, %f\n",
- vp->pcsCoords[0],vp->pcsCoords[1],vp->pcsCoords[2]);
- break;
- case icSigLabData:
- op->gprintf(op," Lab = %f, %f, %f\n",
- vp->pcsCoords[0],vp->pcsCoords[1],vp->pcsCoords[2]);
- break;
- default:
- op->gprintf(op," Unexpected PCS\n");
- break;
- }
- }
- }
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmColorantTable_allocate(
- icmBase *pp
-) {
- icmColorantTable *p = (icmColorantTable *)pp;
- icc *icp = p->icp;
-
- if (p->count != p->_count) {
- unsigned int i;
- if (ovr_mul(p->count, sizeof(icmColorantTableVal))) {
- sprintf(icp->err,"icmColorantTable_alloc: count overflow (%d of %ld bytes)",p->count,sizeof(icmColorantTableVal));
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (icmColorantTableVal *) icp->al->calloc(icp->al,p->count, sizeof(icmColorantTableVal))) == NULL) {
- sprintf(icp->err,"icmColorantTable_alloc: malloc() of icmColorantTable data failed");
- return icp->errc = 2;
- }
- for (i = 0; i < p->count; i++) {
- p->data[i].icp = icp; /* Do init */
- }
- p->_count = p->count;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmColorantTable_delete(
- icmBase *pp
-) {
- icmColorantTable *p = (icmColorantTable *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmColorantTable(
- icc *icp
-) {
- icmColorantTable *p;
- if ((p = (icmColorantTable *) icp->al->calloc(icp->al,1,sizeof(icmColorantTable))) == NULL)
- return NULL;
- p->ttype = icSigColorantTableType;
- p->refcount = 1;
- p->get_size = icmColorantTable_get_size;
- p->read = icmColorantTable_read;
- p->write = icmColorantTable_write;
- p->dump = icmColorantTable_dump;
- p->allocate = icmColorantTable_allocate;
- p->del = icmColorantTable_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* textDescription */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmTextDescription_get_size(
- icmBase *pp
-) {
- icmTextDescription *p = (icmTextDescription *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addadd(len, 4, p->size); /* Ascii string length + ascii string */
- len = sat_addaddmul(len, 8, 2, p->ucSize); /* Unicode language code + length + string */
- len = sat_addadd(len, 3, 67); /* ScriptCode code, length string */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmTextDescription_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmTextDescription *p = (icmTextDescription *)pp;
- icc *icp = p->icp;
- int rv;
- char *bp, *buf, *end;
-
-#ifdef ICM_STRICT
- if (len < (8 + 4 + 8 + 3 /* + 67 */)) {
-#else
- if (len < (8 + 4 + 8 + 3)) {
-#endif
- sprintf(icp->err,"icmTextDescription_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmTextDescription_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
- end = buf + len;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmTextDescription_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read from the buffer into the structure */
- if ((rv = p->core_read(p, &bp, end)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* core read the object, return 0 on success, error code on fail */
-static int icmTextDescription_core_read(
- icmTextDescription *p,
- char **bpp, /* Pointer to buffer pointer, returns next after read */
- char *end /* Pointer to past end of read buffer */
-) {
- icc *icp = p->icp;
- int rv;
- char *bp = *bpp;
-
- if (bp > end || 8 > (end - bp)) {
- sprintf(icp->err,"icmTextDescription_read: Data too short to type descriptor");
- *bpp = bp;
- return icp->errc = 1;
- }
-
- p->size = read_UInt32Number(bp);
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: Wrong tag type ('%s') for icmTextDescription",
- tag2str((icTagTypeSignature)read_SInt32Number(bp)));
- return icp->errc = 1;
- }
- bp = bp + 8;
-
- /* Read the Ascii string */
- if (bp > end || 4 > (end - bp)) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: Data too short to read Ascii header");
- return icp->errc = 1;
- }
- p->size = read_UInt32Number(bp);
- bp += 4;
- if (p->size > 0) {
- if (bp > end || p->size > (end - bp)) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: Data too short to read Ascii string");
- return icp->errc = 1;
- }
- if ((rv = check_null_string(bp,p->size)) == 1) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: ascii string is not terminated");
- return icp->errc = 1;
- }
-#ifdef ICM_STRICT
- if (rv == 2) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: ascii string is shorter than count");
- return icp->errc = 1;
- }
-#endif
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- return rv;
- }
- strcpy(p->desc, bp);
- bp += p->size;
- }
-
- /* Read the Unicode string */
- if (bp > end || 8 > (end - bp)) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: Data too short to read Unicode string");
- return icp->errc = 1;
- }
- p->ucLangCode = read_UInt32Number(bp);
- bp += 4;
- p->ucSize = read_UInt32Number(bp);
- bp += 4;
- if (p->ucSize > 0) {
- ORD16 *up;
- char *tbp;
- if (bp > end || p->ucSize > (end - bp)/2) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: Data too short to read Unicode string");
- return icp->errc = 1;
- }
- if ((rv = check_null_string16(bp,p->ucSize)) == 1) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: Unicode string is not terminated");
- return icp->errc = 1;
- }
-#ifdef ICM_STRICT
- if (rv == 2) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: Unicode string is shorter than count");
- return icp->errc = 1;
- }
-#endif
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- return rv;
- }
- for (up = p->ucDesc, tbp = bp; tbp[0] != 0 || tbp[1] != 0; up++, tbp += 2)
- *up = read_UInt16Number(tbp);
- *up = 0; /* Unicode null */
- bp += p->ucSize * 2;
- }
-
- /* Read the ScriptCode string */
- if (bp > end || 3 > (end - bp)) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: Data too short to read ScriptCode header");
- return icp->errc = 1;
- }
- p->scCode = read_UInt16Number(bp);
- bp += 2;
- p->scSize = read_UInt8Number(bp);
- bp += 1;
- if (p->scSize > 0) {
- if (p->scSize > 67) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: ScriptCode string too long");
- return icp->errc = 1;
- }
- if (bp > end || p->scSize > (end - bp)) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: Data too short to read ScriptCode string");
- return icp->errc = 1;
- }
- if ((rv = check_null_string(bp,p->scSize)) == 1) {
-#ifdef ICM_STRICT
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_read: ScriptCode string is not terminated");
- return icp->errc = 1;
-#else
- /* Patch it up */
- bp[p->scSize-1] = '\000';
-#endif
- }
- memmove((void *)p->scDesc, (void *)bp, p->scSize);
- } else {
- memset((void *)p->scDesc, 0, 67);
- }
- bp += 67;
-
- *bpp = bp;
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmTextDescription_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmTextDescription *p = (icmTextDescription *)pp;
- icc *icp = p->icp;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmTextDescription_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmTextDescription_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write to the buffer from the structure */
- if ((rv = p->core_write(p, &bp)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmTextDescription_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Core write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmTextDescription_core_write(
- icmTextDescription *p,
- char **bpp /* Pointer to buffer pointer, returns next after read */
-) {
- icc *icp = p->icp;
- char *bp = *bpp;
- int rv;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmTextDescription_write: write_SInt32Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
- bp = bp + 8;
-
- /* Write the Ascii string */
- if ((rv = write_UInt32Number(p->size,bp)) != 0) {
- sprintf(icp->err,"icmTextDescription_write: write_UInt32Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- bp += 4;
- if (p->size > 0) {
- if ((rv = check_null_string(p->desc,p->size)) == 1) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_write: ascii string is not terminated");
- return icp->errc = 1;
- }
- if (rv == 2) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_write: ascii string is shorter than length");
- return icp->errc = 1;
- }
- strcpy(bp, p->desc);
- bp += strlen(p->desc) + 1;
- }
-
- /* Write the Unicode string */
- if ((rv = write_UInt32Number(p->ucLangCode, bp)) != 0) {
- sprintf(icp->err,"icmTextDescription_write: write_UInt32Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- bp += 4;
- if ((rv = write_UInt32Number(p->ucSize, bp)) != 0) {
- sprintf(icp->err,"icmTextDescription_write: write_UInt32Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- bp += 4;
- if (p->ucSize > 0) {
- ORD16 *up;
- if ((rv = check_null_string16((char *)p->ucDesc,p->ucSize)) == 1) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_write: Unicode string is not terminated");
- return icp->errc = 1;
- }
- if (rv == 2) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_write: Unicode string is shorter than length");
- return icp->errc = 1;
- }
- for(up = p->ucDesc; *up != 0; up++, bp += 2) {
- if ((rv = write_UInt16Number(((unsigned int)*up), bp)) != 0) {
- sprintf(icp->err,"icmTextDescription_write: write_UInt16Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- }
- bp[0] = 0; /* null */
- bp[1] = 0;
- bp += 2;
- }
-
- /* Write the ScriptCode string */
- if ((rv = write_UInt16Number(p->scCode, bp)) != 0) {
- sprintf(icp->err,"icmTextDescription_write: write_UInt16Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- bp += 2;
- if ((rv = write_UInt8Number(p->scSize, bp)) != 0) {
- sprintf(icp->err,"icmTextDescription_write: write_UInt8Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- bp += 1;
- if (p->scSize > 0) {
- if (p->scSize > 67) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_write: ScriptCode string too long");
- return icp->errc = 1;
- }
- if ((rv = check_null_string((char *)p->scDesc,p->scSize)) == 1) {
- *bpp = bp;
- sprintf(icp->err,"icmTextDescription_write: ScriptCode string is not terminated");
- return icp->errc = 1;
- }
- memmove((void *)bp, (void *)p->scDesc, 67);
- } else {
- memset((void *)bp, 0, 67);
- }
- bp += 67;
-
- *bpp = bp;
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmTextDescription_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmTextDescription *p = (icmTextDescription *)pp;
- unsigned int i, r, c;
-
- if (verb <= 0)
- return;
-
- op->gprintf(op,"TextDescription:\n");
-
- if (p->size > 0) {
- unsigned int size = p->size > 0 ? p->size-1 : 0;
- op->gprintf(op," ASCII data, length %lu chars:\n",p->size);
-
- i = 0;
- for (r = 1;; r++) { /* count rows */
- if (i >= size) {
- op->gprintf(op,"\n");
- break;
- }
- if (r > 1 && verb < 2) {
- op->gprintf(op,"...\n");
- break; /* Print 1 row if not verbose */
- }
- c = 1;
- op->gprintf(op," 0x%04lx: ",i);
- c += 10;
- while (i < size && c < 75) {
- if (isprint(p->desc[i])) {
- op->gprintf(op,"%c",p->desc[i]);
- c++;
- } else {
- op->gprintf(op,"\\%03o",p->desc[i]);
- c += 4;
- }
- i++;
- }
- if (i < size)
- op->gprintf(op,"\n");
- }
- } else {
- op->gprintf(op," No ASCII data\n");
- }
-
- /* Can't dump Unicode or ScriptCode as text with portable code */
- if (p->ucSize > 0) {
- unsigned int size = p->ucSize;
- op->gprintf(op," Unicode Data, Language code 0x%x, length %lu chars\n",
- p->ucLangCode, p->ucSize);
- i = 0;
- for (r = 1;; r++) { /* count rows */
- if (i >= size) {
- op->gprintf(op,"\n");
- break;
- }
- if (r > 1 && verb < 2) {
- op->gprintf(op,"...\n");
- break; /* Print 1 row if not verbose */
- }
- c = 1;
- op->gprintf(op," 0x%04lx: ",i);
- c += 10;
- while (i < size && c < 75) {
- op->gprintf(op,"%04x ",p->ucDesc[i]);
- c += 5;
- i++;
- }
- if (i < size)
- op->gprintf(op,"\n");
- }
- } else {
- op->gprintf(op," No Unicode data\n");
- }
- if (p->scSize > 0) {
- unsigned int size = p->scSize;
- op->gprintf(op," ScriptCode Data, Code 0x%x, length %lu chars\n",
- p->scCode, p->scSize);
- i = 0;
- for (r = 1;; r++) { /* count rows */
- if (i >= size) {
- op->gprintf(op,"\n");
- break;
- }
- if (r > 1 && verb < 2) {
- op->gprintf(op,"...\n");
- break; /* Print 1 row if not verbose */
- }
- c = 1;
- op->gprintf(op," 0x%04lx: ",i);
- c += 10;
- while (i < size && c < 75) {
- op->gprintf(op,"%02x ",p->scDesc[i]);
- c += 3;
- i++;
- }
- if (i < size)
- op->gprintf(op,"\n");
- }
- } else {
- op->gprintf(op," No ScriptCode data\n");
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmTextDescription_allocate(
- icmBase *pp
-) {
- icmTextDescription *p = (icmTextDescription *)pp;
- icc *icp = p->icp;
-
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(char))) {
- sprintf(icp->err,"icmTextDescription_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->desc != NULL)
- icp->al->free(icp->al, p->desc);
- if ((p->desc = (char *) icp->al->calloc(icp->al, p->size, sizeof(char))) == NULL) {
- sprintf(icp->err,"icmTextDescription_alloc: malloc() of Ascii description failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- if (p->ucSize != p->uc_size) {
- if (ovr_mul(p->ucSize, sizeof(ORD16))) {
- sprintf(icp->err,"icmTextDescription_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->ucDesc != NULL)
- icp->al->free(icp->al, p->ucDesc);
- if ((p->ucDesc = (ORD16 *) icp->al->calloc(icp->al, p->ucSize, sizeof(ORD16))) == NULL) {
- sprintf(icp->err,"icmTextDescription_alloc: malloc() of Unicode description failed");
- return icp->errc = 2;
- }
- p->uc_size = p->ucSize;
- }
- return 0;
-}
-
-/* Free all variable sized elements */
-static void icmTextDescription_unallocate(
- icmTextDescription *p
-) {
- icc *icp = p->icp;
-
- if (p->desc != NULL)
- icp->al->free(icp->al, p->desc);
- if (p->ucDesc != NULL)
- icp->al->free(icp->al, p->ucDesc);
-}
-
-/* Free all storage in the object */
-static void icmTextDescription_delete(
- icmBase *pp
-) {
- icmTextDescription *p = (icmTextDescription *)pp;
- icc *icp = p->icp;
-
- icmTextDescription_unallocate(p);
- icp->al->free(icp->al, p);
-}
-
-/* Initialze a named object */
-static void icmTextDescription_init(
- icmTextDescription *p,
- icc *icp
-) {
- memset((void *)p, 0, sizeof(icmTextDescription)); /* Imitate calloc */
-
- p->ttype = icSigTextDescriptionType;
- p->refcount = 1;
- p->get_size = icmTextDescription_get_size;
- p->read = icmTextDescription_read;
- p->write = icmTextDescription_write;
- p->dump = icmTextDescription_dump;
- p->allocate = icmTextDescription_allocate;
- p->del = icmTextDescription_delete;
- p->icp = icp;
-
- p->core_read = icmTextDescription_core_read;
- p->core_write = icmTextDescription_core_write;
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmTextDescription(
- icc *icp
-) {
- icmTextDescription *p;
- if ((p = (icmTextDescription *) icp->al->calloc(icp->al,1,sizeof(icmTextDescription))) == NULL)
- return NULL;
-
- icmTextDescription_init(p,icp);
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-
-/* Support for icmDescStruct */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmDescStruct_get_size(
- icmDescStruct *p
-) {
- unsigned int len = 0;
- len = sat_add(len, 20); /* 20 bytes for header info */
- len = sat_add(len, p->device.get_size((icmBase *)&p->device));
- if (p->device.size == 0)
- len = sat_add(len, 1); /* Extra 1 because of zero length desciption */
- len = sat_add(len, p->model.get_size((icmBase *)&p->model));
- if (p->model.size == 0)
- len = sat_add(len, 1); /* Extra 1 because of zero length desciption */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmDescStruct_read(
- icmDescStruct *p,
- char **bpp, /* Pointer to buffer pointer, returns next after read */
- char *end /* Pointer to past end of read buffer */
-) {
- icc *icp = p->icp;
- char *bp = *bpp;
- int rv = 0;
-
- if (bp > end || 20 > (end - bp)) {
- sprintf(icp->err,"icmDescStruct_read: Data too short read header");
- *bpp = bp;
- return icp->errc = 1;
- }
-
- p->deviceMfg = read_SInt32Number(bp + 0);
- p->deviceModel = read_UInt32Number(bp + 4);
- read_UInt64Number(&p->attributes, bp + 8);
- p->technology = (icTechnologySignature) read_UInt32Number(bp + 16);
- *bpp = bp += 20;
-
- /* Read the device text description */
- if ((rv = p->device.core_read(&p->device, bpp, end)) != 0) {
- return rv;
- }
-
- /* Read the model text description */
- if ((rv = p->model.core_read(&p->model, bpp, end)) != 0) {
- return rv;
- }
-
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmDescStruct_write(
- icmDescStruct *p,
- char **bpp /* Pointer to buffer pointer, returns next after read */
-) {
- icc *icp = p->icp;
- char *bp = *bpp;
- int rv = 0;
- char *ttd = NULL;
- unsigned int tts = 0;
-
- if ((rv = write_SInt32Number(p->deviceMfg, bp + 0)) != 0) {
- sprintf(icp->err,"icmDescStruct_write: write_SInt32Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- if ((rv = write_UInt32Number(p->deviceModel, bp + 4)) != 0) {
- sprintf(icp->err,"icmDescStruct_write: write_UInt32Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- if ((rv = write_UInt64Number(&p->attributes, bp + 8)) != 0) {
- sprintf(icp->err,"icmDescStruct_write: write_UInt64Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- if ((rv = write_UInt32Number(p->technology, bp + 16)) != 0) {
- sprintf(icp->err,"icmDescStruct_write: write_UInt32Number() failed");
- *bpp = bp;
- return icp->errc = rv;
- }
- *bpp = bp += 20;
-
- /* Make sure the ASCII device text is a minimum size of 1, as per the spec. */
- ttd = p->device.desc;
- tts = p->device.size;
-
- if (p->device.size == 0) {
- p->device.desc = "";
- p->device.size = 1;
- }
-
- /* Write the device text description */
- if ((rv = p->device.core_write(&p->device, bpp)) != 0) {
- return rv;
- }
-
- p->device.desc = ttd;
- p->device.size = tts;
-
- /* Make sure the ASCII model text is a minimum size of 1, as per the spec. */
- ttd = p->model.desc;
- tts = p->model.size;
-
- if (p->model.size == 0) {
- p->model.desc = "";
- p->model.size = 1;
- }
-
- /* Write the model text description */
- if ((rv = p->model.core_write(&p->model, bpp)) != 0) {
- return rv;
- }
-
- p->model.desc = ttd;
- p->model.size = tts;
-
- /* Make sure the ASCII model text is a minimum size of 1, as per the spec. */
- ttd = p->device.desc;
- tts = p->device.size;
-
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmDescStruct_dump(
- icmDescStruct *p,
- icmFile *op, /* Output to dump to */
- int verb, /* Verbosity level */
- int index /* Description index */
-) {
- if (verb <= 0)
- return;
-
- op->gprintf(op,"DescStruct %u:\n",index);
- if (verb >= 1) {
- op->gprintf(op," Dev. Mnfctr. = %s\n",tag2str(p->deviceMfg)); /* ~~~ */
- op->gprintf(op," Dev. Model = %s\n",tag2str(p->deviceModel)); /* ~~~ */
- op->gprintf(op," Dev. Attrbts = %s\n", string_DeviceAttributes(p->attributes.l));
- op->gprintf(op," Dev. Technology = %s\n", string_TechnologySignature(p->technology));
- p->device.dump((icmBase *)&p->device, op,verb);
- p->model.dump((icmBase *)&p->model, op,verb);
- op->gprintf(op,"\n");
- }
-}
-
-/* Allocate variable sized data elements (ie. descriptions) */
-static int icmDescStruct_allocate(
- icmDescStruct *p
-) {
- int rv;
-
- if ((rv = p->device.allocate((icmBase *)&p->device)) != 0) {
- return rv;
- }
- if ((rv = p->model.allocate((icmBase *)&p->model)) != 0) {
- return rv;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmDescStruct_delete(
- icmDescStruct *p
-) {
- icmTextDescription_unallocate(&p->device);
- icmTextDescription_unallocate(&p->model);
-}
-
-/* Init a DescStruct object */
-static void icmDescStruct_init(
- icmDescStruct *p,
- icc *icp
-) {
-
- p->allocate = icmDescStruct_allocate;
- p->icp = icp;
-
- icmTextDescription_init(&p->device, icp);
- icmTextDescription_init(&p->model, icp);
-}
-
-/* - - - - - - - - - - - - - - - */
-/* icmProfileSequenceDesc object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmProfileSequenceDesc_get_size(
- icmBase *pp
-) {
- icmProfileSequenceDesc *p = (icmProfileSequenceDesc *)pp;
- unsigned int len = 0;
- unsigned int i;
- len = sat_add(len, 12); /* 12 bytes for tag, padding and count */
- for (i = 0; i < p->count; i++) { /* All the description structures */
- len = sat_add(len, icmDescStruct_get_size(&p->data[i]));
- }
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmProfileSequenceDesc_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmProfileSequenceDesc *p = (icmProfileSequenceDesc *)pp;
- icc *icp = p->icp;
- unsigned int i;
- char *bp, *buf, *end;
- int rv = 0;
-
- if (len < 12) {
- sprintf(icp->err,"icmProfileSequenceDesc_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmProfileSequenceDesc_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
- end = buf + len;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmProfileSequenceDesc_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmProfileSequenceDesc_read: Wrong tag type for icmProfileSequenceDesc");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp += 8; /* Skip padding */
-
- p->count = read_UInt32Number(bp); /* Number of sequence descriptions */
- bp += 4;
-
- /* Read all the sequence descriptions */
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- for (i = 0; i < p->count; i++) {
- if ((rv = icmDescStruct_read(&p->data[i], &bp, end)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- }
-
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmProfileSequenceDesc_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmProfileSequenceDesc *p = (icmProfileSequenceDesc *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmProfileSequenceDesc_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmProfileSequenceDesc_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmProfileSequenceDesc_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- if ((rv = write_UInt32Number(p->count,bp+8)) != 0) {
- sprintf(icp->err,"icmProfileSequenceDesc_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- bp = bp + 12;
-
- /* Write all the description structures */
- for (i = 0; i < p->count; i++) {
- if ((rv = icmDescStruct_write(&p->data[i], &bp)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmProfileSequenceDesc_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmProfileSequenceDesc_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmProfileSequenceDesc *p = (icmProfileSequenceDesc *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"ProfileSequenceDesc:\n");
- op->gprintf(op," No. elements = %u\n",p->count);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->count; i++)
- icmDescStruct_dump(&p->data[i], op, verb-1, i);
- }
-}
-
-/* Allocate variable sized data elements (ie. count of profile descriptions) */
-static int icmProfileSequenceDesc_allocate(
- icmBase *pp
-) {
- icmProfileSequenceDesc *p = (icmProfileSequenceDesc *)pp;
- icc *icp = p->icp;
- unsigned int i;
-
- if (p->count != p->_count) {
- if (ovr_mul(p->count, sizeof(icmDescStruct))) {
- sprintf(icp->err,"icmProfileSequenceDesc_allocate: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (icmDescStruct *) icp->al->calloc(icp->al, p->count, sizeof(icmDescStruct))) == NULL) {
- sprintf(icp->err,"icmProfileSequenceDesc_allocate Allocation of DescStruct array failed");
- return icp->errc = 2;
- }
- /* Now init the DescStructs */
- for (i = 0; i < p->count; i++) {
- icmDescStruct_init(&p->data[i], icp);
- }
- p->_count = p->count;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmProfileSequenceDesc_delete(
- icmBase *pp
-) {
- icmProfileSequenceDesc *p = (icmProfileSequenceDesc *)pp;
- icc *icp = p->icp;
- unsigned int i;
-
- for (i = 0; i < p->count; i++) {
- icmDescStruct_delete(&p->data[i]); /* Free allocated contents */
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmProfileSequenceDesc(
- icc *icp
-) {
- icmProfileSequenceDesc *p;
- if ((p = (icmProfileSequenceDesc *) icp->al->calloc(icp->al,1,sizeof(icmProfileSequenceDesc))) == NULL)
- return NULL;
- p->ttype = icSigProfileSequenceDescType;
- p->refcount = 1;
- p->get_size = icmProfileSequenceDesc_get_size;
- p->read = icmProfileSequenceDesc_read;
- p->write = icmProfileSequenceDesc_write;
- p->dump = icmProfileSequenceDesc_dump;
- p->allocate = icmProfileSequenceDesc_allocate;
- p->del = icmProfileSequenceDesc_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* Signature */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmSignature_get_size(
- icmBase *pp
-) {
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_add(len, 4); /* 4 for signature */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmSignature_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmSignature *p = (icmSignature *)pp;
- icc *icp = p->icp;
- char *bp, *buf;
-
- if (len < 12) {
- sprintf(icp->err,"icmSignature_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmSignature_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmSignature_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmSignaturSignatureng tag type for icmSignature");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read the encoded measurement geometry */
- p->sig = (icTechnologySignature)read_SInt32Number(bp + 8);
-
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmSignature_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmSignature *p = (icmSignature *)pp;
- icc *icp = p->icp;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmSignature_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmSignature_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmSignature_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write the signature */
- if ((rv = write_SInt32Number((int)p->sig, bp + 8)) != 0) {
- sprintf(icp->err,"icmSignaturea_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmSignature_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmSignature_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmSignature *p = (icmSignature *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"Signature\n");
- op->gprintf(op," Technology = %s\n", string_TechnologySignature(p->sig));
-}
-
-/* Allocate variable sized data elements */
-static int icmSignature_allocate(
- icmBase *pp
-) {
- /* Nothing to do */
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmSignature_delete(
- icmBase *pp
-) {
- icmSignature *p = (icmSignature *)pp;
- icc *icp = p->icp;
-
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmSignature(
- icc *icp
-) {
- icmSignature *p;
- if ((p = (icmSignature *) icp->al->calloc(icp->al,1,sizeof(icmSignature))) == NULL)
- return NULL;
- p->ttype = icSigSignatureType;
- p->refcount = 1;
- p->get_size = icmSignature_get_size;
- p->read = icmSignature_read;
- p->write = icmSignature_write;
- p->dump = icmSignature_dump;
- p->allocate = icmSignature_allocate;
- p->del = icmSignature_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-
-/* Data conversion support functions */
-static int read_ScreeningData(icmScreeningData *p, char *d) {
- p->frequency = read_S15Fixed16Number(d + 0);
- p->angle = read_S15Fixed16Number(d + 4);
- p->spotShape = (icSpotShape)read_SInt32Number(d + 8);
- return 0;
-}
-
-static int write_ScreeningData(icmScreeningData *p, char *d) {
- int rv;
- if ((rv = write_S15Fixed16Number(p->frequency, d + 0)) != 0)
- return rv;
- if ((rv = write_S15Fixed16Number(p->angle, d + 4)) != 0)
- return rv;
- if ((rv = write_SInt32Number((int)p->spotShape, d + 8)) != 0)
- return rv;
- return 0;
-}
-
-
-/* icmScreening object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmScreening_get_size(
- icmBase *pp
-) {
- icmScreening *p = (icmScreening *)pp;
- unsigned int len = 0;
- len = sat_add(len, 16); /* 16 bytes for tag, padding, flag & channeles */
- len = sat_addmul(len, p->channels, 12); /* 12 bytes for each channel */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmScreening_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmScreening *p = (icmScreening *)pp;
- icc *icp = p->icp;
- int rv = 0;
- unsigned int i;
- char *bp, *buf, *end;
-
- if (len < 12) {
- sprintf(icp->err,"icmScreening_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmScreening_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
- end = buf + len;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmScreening_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmScreening_read: Wrong tag type for icmScreening");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->screeningFlag = read_UInt32Number(bp+8); /* Flags */
- p->channels = read_UInt32Number(bp+12); /* Number of channels */
- bp = bp + 16;
-
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
-
- /* Read all the data from the buffer */
- for (i = 0; i < p->channels; i++, bp += 12) {
- if (bp > end || 12 > (end - bp)) {
- sprintf(icp->err,"icmScreening_read: Data too short to read Screening Data");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- read_ScreeningData(&p->data[i], bp);
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmScreening_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmScreening *p = (icmScreening *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmScreening_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmScreening_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmScreening_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- if ((rv = write_UInt32Number(p->screeningFlag,bp+8)) != 0) {
- sprintf(icp->err,"icmScreening_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_UInt32Number(p->channels,bp+12)) != 0) {
- sprintf(icp->err,"icmScreening_write: write_UInt32NumberXYZumber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- bp = bp + 16;
-
- /* Write all the data to the buffer */
- for (i = 0; i < p->channels; i++, bp += 12) {
- if ((rv = write_ScreeningData(&p->data[i],bp)) != 0) {
- sprintf(icp->err,"icmScreening_write: write_ScreeningData() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmScreening_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmScreening_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmScreening *p = (icmScreening *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"Screening:\n");
- op->gprintf(op," Flags = %s\n", string_ScreenEncodings(p->screeningFlag));
- op->gprintf(op," No. channels = %u\n",p->channels);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->channels; i++) {
- op->gprintf(op," %lu:\n",i);
- op->gprintf(op," Frequency: %f\n",p->data[i].frequency);
- op->gprintf(op," Angle: %f\n",p->data[i].angle);
- op->gprintf(op," Spot shape: %s\n", string_SpotShape(p->data[i].spotShape));
- }
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmScreening_allocate(
- icmBase *pp
-) {
- icmScreening *p = (icmScreening *)pp;
- icc *icp = p->icp;
-
- if (p->channels != p->_channels) {
- if (ovr_mul(p->channels, sizeof(icmScreeningData))) {
- sprintf(icp->err,"icmScreening_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- if ((p->data = (icmScreeningData *) icp->al->malloc(icp->al, p->channels * sizeof(icmScreeningData))) == NULL) {
- sprintf(icp->err,"icmScreening_alloc: malloc() of icmScreening data failed");
- return icp->errc = 2;
- }
- p->_channels = p->channels;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmScreening_delete(
- icmBase *pp
-) {
- icmScreening *p = (icmScreening *)pp;
- icc *icp = p->icp;
-
- if (p->data != NULL)
- icp->al->free(icp->al, p->data);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmScreening(
- icc *icp
-) {
- icmScreening *p;
- if ((p = (icmScreening *) icp->al->calloc(icp->al,1,sizeof(icmScreening))) == NULL)
- return NULL;
- p->ttype = icSigScreeningType;
- p->refcount = 1;
- p->get_size = icmScreening_get_size;
- p->read = icmScreening_read;
- p->write = icmScreening_write;
- p->dump = icmScreening_dump;
- p->allocate = icmScreening_allocate;
- p->del = icmScreening_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmUcrBg object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmUcrBg_get_size(
- icmBase *pp
-) {
- icmUcrBg *p = (icmUcrBg *)pp;
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addaddmul(len, 4, p->UCRcount, 2); /* Undercolor Removal */
- len = sat_addaddmul(len, 4, p->BGcount, 2); /* Black Generation */
- len = sat_add(len, p->size); /* Description string */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmUcrBg_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmUcrBg *p = (icmUcrBg *)pp;
- icc *icp = p->icp;
- unsigned int i;
- int rv;
- char *bp, *buf, *end;
-
- if (len < 16) {
- sprintf(icp->err,"icmUcrBg_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUcrBg_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
- end = buf + len;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmUcrBg_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmUcrBg_read: Wrong tag type for icmUcrBg");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->UCRcount = read_UInt32Number(bp+8); /* First curve count */
- bp = bp + 12;
-
- if (p->UCRcount > 0) {
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- for (i = 0; i < p->UCRcount; i++, bp += 2) {
- if (bp > end || 2 > (end - bp)) {
- sprintf(icp->err,"icmUcrBg_read: Data too short to read UCR Data");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- if (p->UCRcount == 1) /* % */
- p->UCRcurve[i] = (double)read_UInt16Number(bp);
- else /* 0.0 - 1.0 */
- p->UCRcurve[i] = read_DCS16Number(bp);
- }
- } else {
- p->UCRcurve = NULL;
- }
-
- if (bp > end || 4 > (end - bp)) {
- sprintf(icp->err,"icmData_read: Data too short to read Black Gen count");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->BGcount = read_UInt32Number(bp); /* First curve count */
- bp += 4;
-
- if (p->BGcount > 0) {
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- for (i = 0; i < p->BGcount; i++, bp += 2) {
- if (bp > end || 2 > (end - bp)) {
- sprintf(icp->err,"icmUcrBg_read: Data too short to read BG Data");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- if (p->BGcount == 1) /* % */
- p->BGcurve[i] = (double)read_UInt16Number(bp);
- else /* 0.0 - 1.0 */
- p->BGcurve[i] = read_DCS16Number(bp);
- }
- } else {
- p->BGcurve = NULL;
- }
-
- p->size = end - bp; /* Nominal string length */
- if (p->size > 0) {
- if ((rv = check_null_string(bp, p->size)) == 1) {
- sprintf(icp->err,"icmUcrBg_read: string is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->size = strlen(bp) + 1;
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- memmove((void *)p->string, (void *)bp, p->size);
- bp += p->size;
- } else {
- p->string = NULL;
- }
-
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmUcrBg_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmUcrBg *p = (icmUcrBg *)pp;
- icc *icp = p->icp;
- unsigned int i;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmUcrBg_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmUcrBg_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmUcrBg_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
- bp = bp + 8;
-
- /* Write UCR curve */
- if ((rv = write_UInt32Number(p->UCRcount,bp)) != 0) {
- sprintf(icp->err,"icmUcrBg_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- bp += 4;
-
- for (i = 0; i < p->UCRcount; i++, bp += 2) {
- if (p->UCRcount == 1) { /* % */
- if ((rv = write_UInt16Number((unsigned int)(p->UCRcurve[i]+0.5),bp)) != 0) {
- sprintf(icp->err,"icmUcrBg_write: write_UInt16umber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- } else {
- if ((rv = write_DCS16Number(p->UCRcurve[i],bp)) != 0) {
- sprintf(icp->err,"icmUcrBg_write: write_DCS16umber(%f) failed",p->UCRcurve[i]);
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- }
-
- /* Write BG curve */
- if ((rv = write_UInt32Number(p->BGcount,bp)) != 0) {
- sprintf(icp->err,"icmUcrBg_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- bp += 4;
-
- for (i = 0; i < p->BGcount; i++, bp += 2) {
- if (p->BGcount == 1) { /* % */
- if ((rv = write_UInt16Number((unsigned int)(p->BGcurve[i]+0.5),bp)) != 0) {
- sprintf(icp->err,"icmUcrBg_write: write_UInt16umber() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- } else {
- if ((rv = write_DCS16Number(p->BGcurve[i],bp)) != 0) {
- sprintf(icp->err,"icmUcrBg_write: write_DCS16umber(%f) failed",p->BGcurve[i]);
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- }
-
- if (p->string != NULL) {
- if ((rv = check_null_string(p->string,p->size)) == 1) {
- sprintf(icp->err,"icmUcrBg_write: text is not null terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- if (rv == 2) {
- sprintf(icp->err,"icmUcrBg_write: text is shorter than length");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- memmove((void *)bp, (void *)p->string, p->size);
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmUcrBg_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmUcrBg_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmUcrBg *p = (icmUcrBg *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"Undercolor Removal Curve & Black Generation:\n");
-
- if (p->UCRcount == 0) {
- op->gprintf(op," UCR: Not specified\n");
- } else if (p->UCRcount == 1) {
- op->gprintf(op," UCR: %f%%\n",p->UCRcurve[0]);
- } else {
- op->gprintf(op," UCR curve no. elements = %u\n",p->UCRcount);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->UCRcount; i++)
- op->gprintf(op," %3lu: %f\n",i,p->UCRcurve[i]);
- }
- }
- if (p->BGcount == 0) {
- op->gprintf(op," BG: Not specified\n");
- } else if (p->BGcount == 1) {
- op->gprintf(op," BG: %f%%\n",p->BGcurve[0]);
- } else {
- op->gprintf(op," BG curve no. elements = %u\n",p->BGcount);
- if (verb >= 2) {
- unsigned int i;
- for (i = 0; i < p->BGcount; i++)
- op->gprintf(op," %3lu: %f\n",i,p->BGcurve[i]);
- }
- }
-
- {
- unsigned int i, r, c, size;
- op->gprintf(op," Description:\n");
- op->gprintf(op," No. chars = %lu\n",p->size);
-
- size = p->size > 0 ? p->size-1 : 0;
- i = 0;
- for (r = 1;; r++) { /* count rows */
- if (i >= size) {
- op->gprintf(op,"\n");
- break;
- }
- if (r > 1 && verb < 2) {
- op->gprintf(op,"...\n");
- break; /* Print 1 row if not verbose */
- }
- c = 1;
- op->gprintf(op," 0x%04lx: ",i);
- c += 10;
- while (i < size && c < 73) {
- if (isprint(p->string[i])) {
- op->gprintf(op,"%c",p->string[i]);
- c++;
- } else {
- op->gprintf(op,"\\%03o",p->string[i]);
- c += 4;
- }
- i++;
- }
- if (i < size)
- op->gprintf(op,"\n");
- }
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmUcrBg_allocate(
- icmBase *pp
-) {
- icmUcrBg *p = (icmUcrBg *)pp;
- icc *icp = p->icp;
-
- if (p->UCRcount != p->UCR_count) {
- if (ovr_mul(p->UCRcount, sizeof(double))) {
- sprintf(icp->err,"icmUcrBg_allocate: size overflow");
- return icp->errc = 1;
- }
- if (p->UCRcurve != NULL)
- icp->al->free(icp->al, p->UCRcurve);
- if ((p->UCRcurve = (double *) icp->al->calloc(icp->al, p->UCRcount, sizeof(double))) == NULL) {
- sprintf(icp->err,"icmUcrBg_allocate: malloc() of UCR curve data failed");
- return icp->errc = 2;
- }
- p->UCR_count = p->UCRcount;
- }
- if (p->BGcount != p->BG_count) {
- if (ovr_mul(p->BGcount, sizeof(double))) {
- sprintf(icp->err,"icmUcrBg_allocate: size overflow");
- return icp->errc = 1;
- }
- if (p->BGcurve != NULL)
- icp->al->free(icp->al, p->BGcurve);
- if ((p->BGcurve = (double *) icp->al->calloc(icp->al, p->BGcount, sizeof(double))) == NULL) {
- sprintf(icp->err,"icmUcrBg_allocate: malloc() of BG curve data failed");
- return icp->errc = 2;
- }
- p->BG_count = p->BGcount;
- }
- if (p->size != p->_size) {
- if (ovr_mul(p->size, sizeof(char))) {
- sprintf(icp->err,"icmUcrBg_allocate: size overflow");
- return icp->errc = 1;
- }
- if (p->string != NULL)
- icp->al->free(icp->al, p->string);
- if ((p->string = (char *) icp->al->calloc(icp->al, p->size, sizeof(char))) == NULL) {
- sprintf(icp->err,"icmUcrBg_allocate: malloc() of string data failed");
- return icp->errc = 2;
- }
- p->_size = p->size;
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmUcrBg_delete(
- icmBase *pp
-) {
- icmUcrBg *p = (icmUcrBg *)pp;
- icc *icp = p->icp;
-
- if (p->UCRcurve != NULL)
- icp->al->free(icp->al, p->UCRcurve);
- if (p->BGcurve != NULL)
- icp->al->free(icp->al, p->BGcurve);
- if (p->string != NULL)
- icp->al->free(icp->al, p->string);
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmUcrBg(
- icc *icp
-) {
- icmUcrBg *p;
- if ((p = (icmUcrBg *) icp->al->calloc(icp->al,1,sizeof(icmUcrBg))) == NULL)
- return NULL;
- p->ttype = icSigUcrBgType;
- p->refcount = 1;
- p->get_size = icmUcrBg_get_size;
- p->read = icmUcrBg_read;
- p->write = icmUcrBg_write;
- p->dump = icmUcrBg_dump;
- p->allocate = icmUcrBg_allocate;
- p->del = icmUcrBg_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* VideoCardGamma (ColorSync 2.5 specific - c/o Neil Okamoto) */
-/* 'vcgt' */
-
-static unsigned int icmVideoCardGamma_get_size(
- icmBase *pp
-) {
- icmVideoCardGamma *p = (icmVideoCardGamma *)pp;
- unsigned int len = 0;
-
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_add(len, 4); /* 4 for gamma type */
-
- /* compute size of remainder */
- if (p->tagType == icmVideoCardGammaTableType) {
- len = sat_add(len, 2); /* 2 bytes for channels */
- len = sat_add(len, 2); /* 2 for entry count */
- len = sat_add(len, 2); /* 2 for entry size */
- len = sat_add(len, sat_mul3(p->u.table.channels, /* compute table size */
- p->u.table.entryCount, p->u.table.entrySize));
- }
- else if (p->tagType == icmVideoCardGammaFormulaType) {
- len = sat_add(len, 12); /* 4 bytes each for red gamma, min, & max */
- len = sat_add(len, 12); /* 4 bytes each for green gamma, min & max */
- len = sat_add(len, 12); /* 4 bytes each for blue gamma, min & max */
- }
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmVideoCardGamma_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmVideoCardGamma *p = (icmVideoCardGamma *)pp;
- icc *icp = p->icp;
- int rv, c;
- char *bp, *buf;
- ORD8 *pchar;
- ORD16 *pshort;
-
- if (len < 18) {
- sprintf(icp->err,"icmVideoCardGamma_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmVideoCardGamma_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmVideoCardGamma_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmVideoCardGamma_read: Wrong tag type for icmVideoCardGamma");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read gamma format (eg. table or formula) from the buffer */
- p->tagType = (icmVideoCardGammaTagType)read_UInt32Number(bp+8);
-
- /* Read remaining gamma data based on format */
- if (p->tagType == icmVideoCardGammaTableType) {
- p->u.table.channels = read_UInt16Number(bp+12);
- p->u.table.entryCount = read_UInt16Number(bp+14);
- p->u.table.entrySize = read_UInt16Number(bp+16);
- if ((len-18) < sat_mul3(p->u.table.channels, p->u.table.entryCount,
- p->u.table.entrySize)) {
- sprintf(icp->err,"icmVideoCardGamma_read: Tag too small to be legal");
- return icp->errc = 1;
- }
- if ((rv = pp->allocate(pp)) != 0) { /* make space for table */
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- /* ~~~~ This should be a table of doubles like the rest of icclib ! ~~~~ */
- pchar = (ORD8 *)p->u.table.data;
- pshort = (ORD16 *)p->u.table.data;
- for (c=0, bp=bp+18; c<p->u.table.channels*p->u.table.entryCount; c++) {
- switch (p->u.table.entrySize) {
- case 1:
- *pchar++ = read_UInt8Number(bp);
- bp++;
- break;
- case 2:
- *pshort++ = read_UInt16Number(bp);
- bp+=2;
- break;
- default:
- sprintf(icp->err,"icmVideoCardGamma_read: unsupported table entry size");
- pp->del(pp);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- }
- } else if (p->tagType == icmVideoCardGammaFormulaType) {
- if (len < 48) {
- sprintf(icp->err,"icmVideoCardGamma_read: Tag too small to be legal");
- return icp->errc = 1;
- }
- p->u.table.channels = 3; /* Always 3 for formula */
- p->u.formula.redGamma = read_S15Fixed16Number(bp+12);
- p->u.formula.redMin = read_S15Fixed16Number(bp+16);
- p->u.formula.redMax = read_S15Fixed16Number(bp+20);
- p->u.formula.greenGamma = read_S15Fixed16Number(bp+24);
- p->u.formula.greenMin = read_S15Fixed16Number(bp+28);
- p->u.formula.greenMax = read_S15Fixed16Number(bp+32);
- p->u.formula.blueGamma = read_S15Fixed16Number(bp+36);
- p->u.formula.blueMin = read_S15Fixed16Number(bp+40);
- p->u.formula.blueMax = read_S15Fixed16Number(bp+44);
- } else {
- sprintf(icp->err,"icmVideoCardGammaTable_read: Unknown gamma format for icmVideoCardGamma");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmVideoCardGamma_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmVideoCardGamma *p = (icmVideoCardGamma *)pp;
- icc *icp = p->icp;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0, c;
- ORD8 *pchar;
- ORD16 *pshort;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmViewingConditions_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmViewingConditions_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write gamma format (eg. table of formula) */
- if ((rv = write_UInt32Number(p->tagType,bp+8)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write remaining gamma data based on format */
- if (p->tagType == icmVideoCardGammaTableType) {
- if ((rv = write_UInt16Number(p->u.table.channels,bp+12)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_UInt16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_UInt16Number(p->u.table.entryCount,bp+14)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_UInt16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_UInt16Number(p->u.table.entrySize,bp+16)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_UInt16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- pchar = (ORD8 *)p->u.table.data;
- pshort = (ORD16 *)p->u.table.data;
- for (c=0, bp=bp+18; c<p->u.table.channels*p->u.table.entryCount; c++) {
- switch (p->u.table.entrySize) {
- case 1:
- write_UInt8Number(*pchar++,bp);
- bp++;
- break;
- case 2:
- write_UInt16Number(*pshort++,bp);
- bp+=2;
- break;
- default:
- sprintf(icp->err,"icmVideoCardGamma_write: unsupported table entry size");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- }
- } else if (p->tagType == icmVideoCardGammaFormulaType) {
- if ((rv = write_S15Fixed16Number(p->u.formula.redGamma,bp+12)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_S15Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_S15Fixed16Number(p->u.formula.redMin,bp+16)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_S15Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_S15Fixed16Number(p->u.formula.redMax,bp+20)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_S15Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_S15Fixed16Number(p->u.formula.greenGamma,bp+24)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_S15Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_S15Fixed16Number(p->u.formula.greenMin,bp+28)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_S15Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_S15Fixed16Number(p->u.formula.greenMax,bp+32)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_S15Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_S15Fixed16Number(p->u.formula.blueGamma,bp+36)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_S15Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_S15Fixed16Number(p->u.formula.blueMin,bp+40)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_S15Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_S15Fixed16Number(p->u.formula.blueMax,bp+44)) != 0) {
- sprintf(icp->err,"icmVideoCardGamma_write: write_S15Fixed16Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- } else {
- sprintf(icp->err,"icmVideoCardGammaTable_write: Unknown gamma format for icmVideoCardGamma");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmViewingConditions_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmVideoCardGamma_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmVideoCardGamma *p = (icmVideoCardGamma *)pp;
- int c,i;
-
- if (verb <= 0)
- return;
-
- if (p->tagType == icmVideoCardGammaTableType) {
- op->gprintf(op,"VideoCardGammaTable:\n");
- op->gprintf(op," channels = %d\n", p->u.table.channels);
- op->gprintf(op," entries = %d\n", p->u.table.entryCount);
- op->gprintf(op," entrysize = %d\n", p->u.table.entrySize);
- if (verb >= 2) {
- /* dump array contents also */
- for (c=0; c<p->u.table.channels; c++) {
- op->gprintf(op," channel #%d\n",c);
- for (i=0; i<p->u.table.entryCount; i++) {
- if (p->u.table.entrySize == 1) {
- op->gprintf(op," %d: %d\n",i,((ORD8 *)p->u.table.data)[c*p->u.table.entryCount+i]);
- }
- else if (p->u.table.entrySize == 2) {
- op->gprintf(op," %d: %d\n",i,((ORD16 *)p->u.table.data)[c*p->u.table.entryCount+i]);
- }
- }
- }
- }
- } else if (p->tagType == icmVideoCardGammaFormulaType) {
- op->gprintf(op,"VideoCardGammaFormula:\n");
- op->gprintf(op," red gamma = %f\n", p->u.formula.redGamma);
- op->gprintf(op," red min = %f\n", p->u.formula.redMin);
- op->gprintf(op," red max = %f\n", p->u.formula.redMax);
- op->gprintf(op," green gamma = %f\n", p->u.formula.greenGamma);
- op->gprintf(op," green min = %f\n", p->u.formula.greenMin);
- op->gprintf(op," green max = %f\n", p->u.formula.greenMax);
- op->gprintf(op," blue gamma = %f\n", p->u.formula.blueGamma);
- op->gprintf(op," blue min = %f\n", p->u.formula.blueMin);
- op->gprintf(op," blue max = %f\n", p->u.formula.blueMax);
- } else {
- op->gprintf(op," Unknown tag format\n");
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmVideoCardGamma_allocate(
- icmBase *pp
-) {
- icmVideoCardGamma *p = (icmVideoCardGamma *)pp;
- icc *icp = p->icp;
- unsigned int size;
-
- /* note: allocation is only relevant for table type
- * and in that case the channels, entryCount, and entrySize
- * fields must all be set prior to getting here
- */
-
- if (p->tagType == icmVideoCardGammaTableType) {
- size = sat_mul(p->u.table.channels, p->u.table.entryCount);
- switch (p->u.table.entrySize) {
- case 1:
- size = sat_mul(size, sizeof(ORD8));
- break;
- case 2:
- size = sat_mul(size, sizeof(unsigned short));
- break;
- default:
- sprintf(icp->err,"icmVideoCardGamma_alloc: unsupported table entry size");
- return icp->errc = 1;
- }
- if (size == UINT_MAX) {
- sprintf(icp->err,"icmVideoCardGamma_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->u.table.data != NULL)
- icp->al->free(icp->al, p->u.table.data);
- if ((p->u.table.data = (void*) icp->al->malloc(icp->al, size)) == NULL) {
- sprintf(icp->err,"icmVideoCardGamma_alloc: malloc() of table data failed");
- return icp->errc = 2;
- }
- }
-
- return 0;
-}
-
-/* Read a value */
-static double icmVideoCardGamma_lookup(
- icmVideoCardGamma *p,
- int chan, /* Channel, 0, 1 or 2 */
- double iv /* Input value 0.0 - 1.0 */
-) {
- double ov = 0.0;
-
- if (chan < 0 || chan > (p->u.table.channels-1)
- || iv < 0.0 || iv > 1.0)
- return iv;
-
- if (p->tagType == icmVideoCardGammaTableType && p->u.table.entryCount == 0) {
- /* Deal with siliness */
- ov = iv;
- } else if (p->tagType == icmVideoCardGammaTableType) {
- /* Use linear interpolation */
- unsigned int ix;
- double val0, val1, w;
- double inputEnt_1 = (double)(p->u.table.entryCount-1);
-
- val0 = iv * inputEnt_1;
- if (val0 < 0.0)
- val0 = 0.0;
- else if (val0 > inputEnt_1)
- val0 = inputEnt_1;
- ix = (unsigned int)floor(val0); /* Coordinate */
- if (ix > (p->u.table.entryCount-2))
- ix = (p->u.table.entryCount-2);
- w = val0 - (double)ix; /* weight */
- if (p->u.table.entrySize == 1) {
- val0 = ((ORD8 *)p->u.table.data)[chan * p->u.table.entryCount + ix]/255.0;
- val1 = ((ORD8 *)p->u.table.data)[chan * p->u.table.entryCount + ix + 1]/255.0;
- } else if (p->u.table.entrySize == 2) {
- val0 = ((ORD16 *)p->u.table.data)[chan * p->u.table.entryCount + ix]/65535.0;
- val1 = ((ORD16 *)p->u.table.data)[chan * p->u.table.entryCount + ix + 1]/65535.0;
- } else {
- val0 = val1 = iv;
- }
- ov = val0 + w * (val1 - val0);
-
- } else if (p->tagType == icmVideoCardGammaFormulaType) {
- double min, max, gam;
-
- if (iv == 0) {
- min = p->u.formula.redMin;
- max = p->u.formula.redMax;
- gam = p->u.formula.redGamma;
- } else if (iv == 1) {
- min = p->u.formula.greenMin;
- max = p->u.formula.greenMax;
- gam = p->u.formula.greenGamma;
- } else {
- min = p->u.formula.blueMin;
- max = p->u.formula.blueMax;
- gam = p->u.formula.blueGamma;
- }
-
- /* The Apple OSX doco confirms this is the formula */
- ov = min + (max - min) * pow(iv, gam);
- }
- return ov;
-}
-
-/* Free all storage in the object */
-static void icmVideoCardGamma_delete(
- icmBase *pp
-) {
- icmVideoCardGamma *p = (icmVideoCardGamma *)pp;
- icc *icp = p->icp;
-
- if (p->tagType == icmVideoCardGammaTableType && p->u.table.data != NULL)
- icp->al->free(icp->al, p->u.table.data);
-
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmVideoCardGamma(
- icc *icp
-) {
- icmVideoCardGamma *p;
- if ((p = (icmVideoCardGamma *) icp->al->calloc(icp->al,1,sizeof(icmVideoCardGamma))) == NULL)
- return NULL;
- p->ttype = icSigVideoCardGammaType;
- p->refcount = 1;
- p->get_size = icmVideoCardGamma_get_size;
- p->read = icmVideoCardGamma_read;
- p->write = icmVideoCardGamma_write;
- p->lookup = icmVideoCardGamma_lookup;
- p->dump = icmVideoCardGamma_dump;
- p->allocate = icmVideoCardGamma_allocate;
- p->del = icmVideoCardGamma_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* ViewingConditions */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmViewingConditions_get_size(
- icmBase *pp
-) {
- unsigned int len = 0;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_add(len, 12); /* 12 for XYZ of illuminant */
- len = sat_add(len, 12); /* 12 for XYZ of surround */
- len = sat_add(len, 4); /* 4 for illuminant type */
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmViewingConditions_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmViewingConditions *p = (icmViewingConditions *)pp;
- icc *icp = p->icp;
- int rv;
- char *bp, *buf;
-
- if (len < 36) {
- sprintf(icp->err,"icmViewingConditions_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmViewingConditions_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmViewingConditions_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmViewingConditions_read: Wrong tag type for icmViewingConditions");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read the XYZ values for the illuminant */
- if ((rv = read_XYZNumber(&p->illuminant, bp+8)) != 0) {
- sprintf(icp->err,"icmViewingConditions: read_XYZNumber error");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Read the XYZ values for the surround */
- if ((rv = read_XYZNumber(&p->surround, bp+20)) != 0) {
- sprintf(icp->err,"icmViewingConditions: read_XYZNumber error");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Read the encoded standard illuminant */
- p->stdIlluminant = (icIlluminant)read_SInt32Number(bp + 32);
-
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmViewingConditions_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmViewingConditions *p = (icmViewingConditions *)pp;
- icc *icp = p->icp;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmViewingConditions_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmViewingConditions_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmViewingConditions_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
-
- /* Write the XYZ values for the illuminant */
- if ((rv = write_XYZNumber(&p->illuminant, bp+8)) != 0) {
- sprintf(icp->err,"icmViewingConditions: write_XYZNumber error");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write the XYZ values for the surround */
- if ((rv = write_XYZNumber(&p->surround, bp+20)) != 0) {
- sprintf(icp->err,"icmViewingConditions: write_XYZNumber error");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write the encoded standard illuminant */
- if ((rv = write_SInt32Number((int)p->stdIlluminant, bp + 32)) != 0) {
- sprintf(icp->err,"icmViewingConditionsa_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmViewingConditions_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmViewingConditions_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmViewingConditions *p = (icmViewingConditions *)pp;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"Viewing Conditions:\n");
- op->gprintf(op," XYZ value of illuminant in cd/m^2 = %s\n", string_XYZNumber(&p->illuminant));
- op->gprintf(op," XYZ value of surround in cd/m^2 = %s\n", string_XYZNumber(&p->surround));
- op->gprintf(op," Illuminant type = %s\n", string_Illuminant(p->stdIlluminant));
-}
-
-/* Allocate variable sized data elements */
-static int icmViewingConditions_allocate(
- icmBase *pp
-) {
- /* Nothing to do */
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmViewingConditions_delete(
- icmBase *pp
-) {
- icmViewingConditions *p = (icmViewingConditions *)pp;
- icc *icp = p->icp;
-
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmViewingConditions(
- icc *icp
-) {
- icmViewingConditions *p;
- if ((p = (icmViewingConditions *) icp->al->calloc(icp->al,1,sizeof(icmViewingConditions))) == NULL)
- return NULL;
- p->ttype = icSigViewingConditionsType;
- p->refcount = 1;
- p->get_size = icmViewingConditions_get_size;
- p->read = icmViewingConditions_read;
- p->write = icmViewingConditions_write;
- p->dump = icmViewingConditions_dump;
- p->allocate = icmViewingConditions_allocate;
- p->del = icmViewingConditions_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ---------------------------------------------------------- */
-/* icmCrdInfo object */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmCrdInfo_get_size(
- icmBase *pp
-) {
- icmCrdInfo *p = (icmCrdInfo *)pp;
- unsigned int len = 0, t;
- len = sat_add(len, 8); /* 8 bytes for tag and padding */
- len = sat_addadd(len, 4, p->ppsize); /* Postscript product name */
- for (t = 0; t < 4; t++) { /* For all 4 intents */
- len = sat_addadd(len, 4, p->crdsize[t]); /* crd names */
- }
- return len;
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmCrdInfo_read(
- icmBase *pp,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icmCrdInfo *p = (icmCrdInfo *)pp;
- icc *icp = p->icp;
- unsigned int t;
- int rv;
- char *bp, *buf, *end;
-
- if (len < 28) {
- sprintf(icp->err,"icmCrdInfo_read: Tag too small to be legal");
- return icp->errc = 1;
- }
-
- /* Allocate a file read buffer */
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmCrdInfo_read: malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
- end = buf + len;
-
- /* Read portion of file into buffer */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, bp, 1, len) != len) {
- sprintf(icp->err,"icmCrdInfo_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Read type descriptor from the buffer */
- if (((icTagTypeSignature)read_SInt32Number(bp)) != p->ttype) {
- sprintf(icp->err,"icmCrdInfo_read: Wrong tag type for icmCrdInfo");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- bp = bp + 8;
-
- /* Postscript product name */
- if (bp > end || 4 > (end - bp)) {
- sprintf(icp->err,"icmCrdInfo_read: Data too short to read Postscript product name");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->ppsize = read_UInt32Number(bp);
- bp += 4;
- if (p->ppsize > 0) {
- if (p->ppsize > (end - bp)) {
- sprintf(icp->err,"icmCrdInfo_read: Data to short to read Postscript product string");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- if ((rv = check_null_string(bp,p->ppsize)) == 1) {
- sprintf(icp->err,"icmCrdInfo_read: Postscript product name is not terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- memmove((void *)p->ppname, (void *)bp, p->ppsize);
- bp += p->ppsize;
- }
-
- /* CRD names for the four rendering intents */
- for (t = 0; t < 4; t++) { /* For all 4 intents */
- if (bp > end || 4 > (end - bp)) {
- sprintf(icp->err,"icmCrdInfo_read: Data too short to read CRD%d name",t);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->crdsize[t] = read_UInt32Number(bp);
- bp += 4;
- if (p->crdsize[t] > 0) {
- if (p->crdsize[t] > (end - bp)) {
- sprintf(icp->err,"icmCrdInfo_read: Data to short to read CRD%d string",t);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- if ((rv = check_null_string(bp,p->crdsize[t])) == 1) {
- sprintf(icp->err,"icmCrdInfo_read: CRD%d name is not terminated",t);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
- memmove((void *)p->crdname[t], (void *)bp, p->crdsize[t]);
- bp += p->crdsize[t];
- }
- }
-
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmCrdInfo_write(
- icmBase *pp,
- unsigned int of /* File offset to write from */
-) {
- icmCrdInfo *p = (icmCrdInfo *)pp;
- icc *icp = p->icp;
- unsigned int t;
- unsigned int len;
- char *bp, *buf; /* Buffer to write from */
- int rv;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size((icmBase *)p)) == UINT_MAX) {
- sprintf(icp->err,"icmCrdInfo_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmCrdInfo_write malloc() failed");
- return icp->errc = 2;
- }
- bp = buf;
-
- /* Write type descriptor to the buffer */
- if ((rv = write_SInt32Number((int)p->ttype,bp)) != 0) {
- sprintf(icp->err,"icmCrdInfo_write: write_SInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- write_SInt32Number(0,bp+4); /* Set padding to 0 */
- bp = bp + 8;
-
- /* Postscript product name */
- if ((rv = write_UInt32Number(p->ppsize,bp)) != 0) {
- sprintf(icp->err,"icmCrdInfo_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- bp += 4;
- if (p->ppsize > 0) {
- if ((rv = check_null_string(p->ppname,p->ppsize)) == 1) {
- sprintf(icp->err,"icmCrdInfo_write: Postscript product name is not terminated");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
- memmove((void *)bp, (void *)p->ppname, p->ppsize);
- bp += p->ppsize;
- }
-
- /* CRD names for the four rendering intents */
- for (t = 0; t < 4; t++) { /* For all 4 intents */
- if ((rv = write_UInt32Number(p->crdsize[t],bp)) != 0) {
- sprintf(icp->err,"icmCrdInfo_write: write_UInt32Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- bp += 4;
- if (p->ppsize > 0) {
- if ((rv = check_null_string(p->crdname[t],p->crdsize[t])) == 1) {
- sprintf(icp->err,"icmCrdInfo_write: CRD%d name is not terminated",t);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- /* Haven't checked if rv == 2 is legal or not */
- memmove((void *)bp, (void *)p->crdname[t], p->crdsize[t]);
- bp += p->crdsize[t];
- }
- }
-
- /* Write to the file */
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmCrdInfo_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
- icp->al->free(icp->al, buf);
- return 0;
-}
-
-/* Dump a text description of the object */
-static void icmCrdInfo_dump(
- icmBase *pp,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- icmCrdInfo *p = (icmCrdInfo *)pp;
- unsigned int i, r, c, size, t;
-
- if (verb <= 0)
- return;
-
- op->gprintf(op,"PostScript Product name and CRD names:\n");
-
- op->gprintf(op," Product name:\n");
- op->gprintf(op," No. chars = %lu\n",p->ppsize);
-
- size = p->ppsize > 0 ? p->ppsize-1 : 0;
- i = 0;
- for (r = 1;; r++) { /* count rows */
- if (i >= size) {
- op->gprintf(op,"\n");
- break;
- }
- if (r > 1 && verb < 2) {
- op->gprintf(op,"...\n");
- break; /* Print 1 row if not verbose */
- }
- c = 1;
- op->gprintf(op," 0x%04lx: ",i);
- c += 10;
- while (i < size && c < 73) {
- if (isprint(p->ppname[i])) {
- op->gprintf(op,"%c",p->ppname[i]);
- c++;
- } else {
- op->gprintf(op,"\\%03o",p->ppname[i]);
- c += 4;
- }
- i++;
- }
- if (i < size)
- op->gprintf(op,"\n");
- }
-
- for (t = 0; t < 4; t++) { /* For all 4 intents */
- op->gprintf(op," CRD%ld name:\n",t);
- op->gprintf(op," No. chars = %lu\n",p->crdsize[t]);
-
- size = p->crdsize[t] > 0 ? p->crdsize[t]-1 : 0;
- i = 0;
- for (r = 1;; r++) { /* count rows */
- if (i >= size) {
- op->gprintf(op,"\n");
- break;
- }
- if (r > 1 && verb < 2) {
- op->gprintf(op,"...\n");
- break; /* Print 1 row if not verbose */
- }
- c = 1;
- op->gprintf(op," 0x%04lx: ",i);
- c += 10;
- while (i < size && c < 73) {
- if (isprint(p->crdname[t][i])) {
- op->gprintf(op,"%c",p->crdname[t][i]);
- c++;
- } else {
- op->gprintf(op,"\\%03o",p->crdname[t][i]);
- c += 4;
- }
- i++;
- }
- if (i < size)
- op->gprintf(op,"\n");
- }
- }
-}
-
-/* Allocate variable sized data elements */
-static int icmCrdInfo_allocate(
- icmBase *pp
-) {
- icmCrdInfo *p = (icmCrdInfo *)pp;
- icc *icp = p->icp;
- unsigned int t;
-
- if (p->ppsize != p->_ppsize) {
- if (ovr_mul(p->ppsize, sizeof(char))) {
- sprintf(icp->err,"icmCrdInfo_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->ppname != NULL)
- icp->al->free(icp->al, p->ppname);
- if ((p->ppname = (char *) icp->al->calloc(icp->al, p->ppsize, sizeof(char))) == NULL) {
- sprintf(icp->err,"icmCrdInfo_alloc: malloc() of string data failed");
- return icp->errc = 2;
- }
- p->_ppsize = p->ppsize;
- }
- for (t = 0; t < 4; t++) { /* For all 4 intents */
- if (p->crdsize[t] != p->_crdsize[t]) {
- if (ovr_mul(p->crdsize[t], sizeof(char))) {
- sprintf(icp->err,"icmCrdInfo_alloc: size overflow");
- return icp->errc = 1;
- }
- if (p->crdname[t] != NULL)
- icp->al->free(icp->al, p->crdname[t]);
- if ((p->crdname[t] = (char *) icp->al->calloc(icp->al, p->crdsize[t], sizeof(char))) == NULL) {
- sprintf(icp->err,"icmCrdInfo_alloc: malloc() of CRD%d name string failed",t);
- return icp->errc = 2;
- }
- p->_crdsize[t] = p->crdsize[t];
- }
- }
- return 0;
-}
-
-/* Free all storage in the object */
-static void icmCrdInfo_delete(
- icmBase *pp
-) {
- icmCrdInfo *p = (icmCrdInfo *)pp;
- icc *icp = p->icp;
- unsigned int t;
-
- if (p->ppname != NULL)
- icp->al->free(icp->al, p->ppname);
- for (t = 0; t < 4; t++) { /* For all 4 intents */
- if (p->crdname[t] != NULL)
- icp->al->free(icp->al, p->crdname[t]);
- }
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmBase *new_icmCrdInfo(
- icc *icp
-) {
- icmCrdInfo *p;
- if ((p = (icmCrdInfo *) icp->al->calloc(icp->al,1,sizeof(icmCrdInfo))) == NULL)
- return NULL;
- p->ttype = icSigCrdInfoType;
- p->refcount = 1;
- p->get_size = icmCrdInfo_get_size;
- p->read = icmCrdInfo_read;
- p->write = icmCrdInfo_write;
- p->dump = icmCrdInfo_dump;
- p->allocate = icmCrdInfo_allocate;
- p->del = icmCrdInfo_delete;
- p->icp = icp;
-
- return (icmBase *)p;
-}
-
-/* ========================================================== */
-/* icmHeader object */
-/* ========================================================== */
-
-/* Return the number of bytes needed to write this tag */
-static unsigned int icmHeader_get_size(
- icmHeader *p
-) {
- return 128; /* By definition */
-}
-
-/* read the object, return 0 on success, error code on fail */
-static int icmHeader_read(
- icmHeader *p,
- unsigned int len, /* tag length */
- unsigned int of /* start offset within file */
-) {
- icc *icp = p->icp;
- char *buf;
- unsigned int tt;
- int rv = 0;
-
- if (len != 128) {
- sprintf(icp->err,"icmHeader_read: Length expected to be 128");
- return icp->errc = 1;
- }
-
- if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) {
- sprintf(icp->err,"icmHeader_read: malloc() failed");
- return icp->errc = 2;
- }
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->read(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmHeader_read: fseek() or fread() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Check that the magic number is right */
- tt = read_SInt32Number(buf+36);
- if (tt != icMagicNumber) { /* Check magic number */
- sprintf(icp->err,"icmHeader_read: wrong magic number 0x%x",tt);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
-
- /* Fill in the in-memory structure */
- p->size = read_UInt32Number(buf + 0); /* Profile size in bytes */
- if (p->size < (128 + 4)) {
- sprintf(icp->err,"icmHeader_read: file size %d too small to be legal",p->size);
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- p->cmmId = read_SInt32Number(buf + 4); /* CMM for profile */
- tt = read_UInt8Number(buf + 8); /* Raw major version number */
- p->majv = (tt >> 4) * 10 + (tt & 0xf); /* Integer major version number */
- icp->ver = p->majv > 3 ? 1 : 0; /* Set major version flag in icc */
- tt = read_UInt8Number(buf + 9); /* Raw minor/bug fix version numbers */
- p->minv = (tt >> 4); /* Integer minor version number */
- p->bfv = (tt & 0xf); /* Integer bug fix version number */
- p->deviceClass = (icProfileClassSignature)
- read_SInt32Number(buf + 12); /* Type of profile */
- p->colorSpace = (icColorSpaceSignature)
- read_SInt32Number(buf + 16); /* Color space of data */
- p->pcs = (icColorSpaceSignature)
- read_SInt32Number(buf + 20); /* PCS: XYZ or Lab */
- if ((rv = read_DateTimeNumber(&p->date, buf + 24)) != 0) { /* Creation Date */
- sprintf(icp->err,"icmHeader_read: read_DateTimeNumber corrupted");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- p->platform = (icPlatformSignature)
- read_SInt32Number(buf + 40); /* Primary platform */
- p->flags = read_UInt32Number(buf + 44); /* Various bits */
- p->manufacturer = read_SInt32Number(buf + 48); /* Dev manufacturer */
- p->model = read_SInt32Number(buf + 52); /* Dev model */
- read_UInt64Number(&p->attributes, buf + 56); /* Device attributes */
- p->renderingIntent = (icRenderingIntent)
- read_SInt32Number(buf + 64); /* Rendering intent */
- if ((rv = read_XYZNumber(&p->illuminant, buf + 68)) != 0) { /* Profile illuminant */
- sprintf(icp->err,"icmHeader_read: read_XYZNumber error");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- p->creator = read_SInt32Number(buf + 80); /* Profile creator */
-
- for (tt = 0; tt < 16; tt++)
- p->id[tt] = icp->ver ? read_UInt8Number(buf + 84 + tt) : 0; /* Profile ID */
-
- icp->al->free(icp->al, buf);
-
-#ifndef ENABLE_V4
- if (icp->ver) {
- sprintf(icp->err,"icmHeader_read: ICC V4 not supported!");
- return icp->errc = 1;
- }
-#endif
- return 0;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-static int icmHeader_write(
- icmHeader *p,
- unsigned int of, /* File offset to write from */
- int doid /* Flag, nz = writing to compute ID */
-) {
- icc *icp = p->icp;
- char *buf; /* Buffer to write from */
- unsigned int len;
- unsigned int tt;
- int rv = 0;
-
- /* Allocate a file write buffer */
- if ((len = p->get_size(p)) == UINT_MAX) {
- sprintf(icp->err,"icmHeader_write get_size overflow");
- return icp->errc = 1;
- }
- if ((buf = (char *) icp->al->calloc(icp->al,1,len)) == NULL) { /* Zero it - some CMS are fussy */
- sprintf(icp->err,"icmHeader_write calloc() failed");
- return icp->errc = 2;
- }
-
- /* Fill in the write buffer */
- if ((rv = write_UInt32Number(p->size, buf + 0)) != 0) { /* Profile size in bytes */
- sprintf(icp->err,"icmHeader_write: profile size");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
-
- if ((rv = write_SInt32Number(p->cmmId, buf + 4)) != 0) { /* CMM for profile */
- sprintf(icp->err,"icmHeader_write: cmmId");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if (p->majv < 0 || p->majv > 99 /* Sanity check version numbers */
- || p->minv < 0 || p->minv > 9
- || p->bfv < 0 || p->bfv > 9) {
- sprintf(icp->err,"icmHeader_write: version number");
- icp->al->free(icp->al, buf);
- return icp->errc = 1;
- }
- tt = ((p->majv/10) << 4) + (p->majv % 10);
- if ((rv = write_UInt8Number(tt, buf + 8)) != 0) { /* Raw major version number */
- sprintf(icp->err,"icmHeader_write: Uint8Number major version");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- tt = (p->minv << 4) + p->bfv;
- if ((rv = write_UInt8Number(tt, buf + 9)) != 0) { /* Raw minor/bug fix version numbers */
- sprintf(icp->err,"icmHeader_write: Uint8Number minor/bug fix");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_SInt32Number((int)p->deviceClass, buf + 12)) != 0) { /* Type of profile */
- sprintf(icp->err,"icmHeader_write: SInt32Number deviceClass");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_SInt32Number((int)p->colorSpace, buf + 16)) != 0) { /* Color space of data */
- sprintf(icp->err,"icmHeader_write: SInt32Number data color space");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_SInt32Number((int)p->pcs, buf + 20)) != 0) { /* PCS: XYZ or Lab */
- sprintf(icp->err,"icmHeader_write: SInt32Number PCS");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_DateTimeNumber(&p->date, buf + 24)) != 0) { /* Creation Date */
- sprintf(icp->err,"icmHeader_write: DateTimeNumber creation");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_SInt32Number(icMagicNumber, buf+36)) != 0) { /* Magic number */
- sprintf(icp->err,"icmHeader_write: SInt32Number magic");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_SInt32Number((int)p->platform, buf + 40)) != 0) { /* Primary platform */
- sprintf(icp->err,"icmHeader_write: SInt32Number platform");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_UInt32Number(doid ? 0 : p->flags, buf + 44)) != 0) { /* Various flag bits */
- sprintf(icp->err,"icmHeader_write: UInt32Number flags");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_SInt32Number(p->manufacturer, buf + 48)) != 0) { /* Dev manufacturer */
- sprintf(icp->err,"icmHeader_write: SInt32Number manufaturer");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((write_SInt32Number(p->model, buf + 52)) != 0) { /* Dev model */
- sprintf(icp->err,"icmHeader_write: SInt32Number model");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_UInt64Number(&p->attributes, buf + 56)) != 0) { /* Device attributes */
- sprintf(icp->err,"icmHeader_write: UInt64Number attributes");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_SInt32Number(doid ? 0 : (int)p->renderingIntent, buf + 64)) != 0) { /* Rendering intent */
- sprintf(icp->err,"icmHeader_write: SInt32Number rendering intent");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_XYZNumber(&p->illuminant, buf + 68)) != 0) { /* Profile illuminant */
- sprintf(icp->err,"icmHeader_write: XYZNumber illuminant");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if ((rv = write_SInt32Number(p->creator, buf + 80)) != 0) { /* Profile creator */
- sprintf(icp->err,"icmHeader_write: SInt32Number creator");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- if (doid == 0 && icp->ver) { /* ID is V4.0+ feature */
- for (tt = 0; tt < 16; tt++) {
- if ((rv = write_UInt8Number(p->id[tt], buf + 84 + tt)) != 0) { /* Profile ID */
- sprintf(icp->err,"icmHeader_write: UInt8Number creator");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
- }
- }
- }
-
- if ( icp->fp->seek(icp->fp, of) != 0
- || icp->fp->write(icp->fp, buf, 1, len) != len) {
- sprintf(icp->err,"icmHeader_write fseek() or fwrite() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = 2;
- }
-
- icp->al->free(icp->al, buf);
- return rv;
-}
-
-static void icmHeader_dump(
- icmHeader *p,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- int i;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"Header:\n");
- op->gprintf(op," size = %d bytes\n",p->size);
- op->gprintf(op," CMM = %s\n",tag2str(p->cmmId));
- op->gprintf(op," Version = %d.%d.%d\n",p->majv, p->minv, p->bfv);
- op->gprintf(op," Device Class = %s\n", string_ProfileClassSignature(p->deviceClass));
- op->gprintf(op," Color Space = %s\n", string_ColorSpaceSignature(p->colorSpace));
- op->gprintf(op," Conn. Space = %s\n", string_ColorSpaceSignature(p->pcs));
- op->gprintf(op," Date, Time = %s\n", string_DateTimeNumber(&p->date));
- op->gprintf(op," Platform = %s\n", string_PlatformSignature(p->platform));
- op->gprintf(op," Flags = %s\n", string_ProfileHeaderFlags(p->flags));
- op->gprintf(op," Dev. Mnfctr. = %s\n", tag2str(p->manufacturer)); /* ~~~ */
- op->gprintf(op," Dev. Model = %s\n", tag2str(p->model)); /* ~~~ */
- op->gprintf(op," Dev. Attrbts = %s\n", string_DeviceAttributes(p->attributes.l));
- op->gprintf(op," Rndrng Intnt = %s\n", string_RenderingIntent(p->renderingIntent));
- op->gprintf(op," Illuminant = %s\n", string_XYZNumber_and_Lab(&p->illuminant));
- op->gprintf(op," Creator = %s\n", tag2str(p->creator)); /* ~~~ */
- if (p->icp->ver) { /* V4.0+ feature */
- for (i = 0; i < 16; i++) { /* Check if ID has been set */
- if (p->id[i] != 0)
- break;
- }
- if (i < 16)
- op->gprintf(op," ID = %02X%02X%02X%02X%02X%02X%02X%02X"
- "%02X%02X%02X%02X%02X%02X%02X%02X\n",
- p->id[0], p->id[1], p->id[2], p->id[3], p->id[4], p->id[5], p->id[6], p->id[7],
- p->id[8], p->id[9], p->id[10], p->id[11], p->id[12], p->id[13], p->id[14], p->id[15]);
- else
- op->gprintf(op," ID = <Not set>\n");
- }
- op->gprintf(op,"\n");
-}
-
-static void icmHeader_delete(
- icmHeader *p
-) {
- icc *icp = p->icp;
-
- icp->al->free(icp->al, p);
-}
-
-/* Create an empty object. Return null on error */
-static icmHeader *new_icmHeader(
- icc *icp
-) {
- icmHeader *p;
- if ((p = (icmHeader *) icp->al->calloc(icp->al,1,sizeof(icmHeader))) == NULL)
- return NULL;
- p->icp = icp;
- p->get_size = icmHeader_get_size;
- p->read = icmHeader_read;
- p->write = icmHeader_write;
- p->dump = icmHeader_dump;
- p->del = icmHeader_delete;
-
- return p;
-}
-
-/* ---------------------------------------------------------- */
-/* Type vector table. Match the Tag type against the object creator */
-static struct {
- icTagTypeSignature ttype; /* The tag type signature */
- icmBase * (*new_obj)(icc *icp);
-} typetable[] = {
- {icSigColorantTableType, new_icmColorantTable},
- {icmSigAltColorantTableType, new_icmColorantTable},
- {icSigCrdInfoType, new_icmCrdInfo},
- {icSigCurveType, new_icmCurve},
- {icSigDataType, new_icmData},
- {icSigDateTimeType, new_icmDateTimeNumber},
- {icSigLut16Type, new_icmLut},
- {icSigLut8Type, new_icmLut},
- {icSigMeasurementType, new_icmMeasurement},
- {icSigNamedColorType, new_icmNamedColor},
- {icSigNamedColor2Type, new_icmNamedColor},
- {icSigProfileSequenceDescType, new_icmProfileSequenceDesc},
- {icSigS15Fixed16ArrayType, new_icmS15Fixed16Array},
- {icSigScreeningType, new_icmScreening},
- {icSigSignatureType, new_icmSignature},
- {icSigTextDescriptionType, new_icmTextDescription},
- {icSigTextType, new_icmText},
- {icSigU16Fixed16ArrayType, new_icmU16Fixed16Array},
- {icSigUcrBgType, new_icmUcrBg},
- {icSigVideoCardGammaType, new_icmVideoCardGamma},
- {icSigUInt16ArrayType, new_icmUInt16Array},
- {icSigUInt32ArrayType, new_icmUInt32Array},
- {icSigUInt64ArrayType, new_icmUInt64Array},
- {icSigUInt8ArrayType, new_icmUInt8Array},
- {icSigViewingConditionsType, new_icmViewingConditions},
- {icSigXYZArrayType, new_icmXYZArray},
- {icMaxEnumType, NULL}
-};
-
-/* Table that lists the legal Types for each Tag Signature */
-static struct {
- icTagSignature sig;
- icTagTypeSignature ttypes[4]; /* Arbitrary max of 4 */
-} sigtypetable[] = {
- {icSigAToB0Tag, {icSigLut8Type,icSigLut16Type,icMaxEnumType}},
- {icSigAToB1Tag, {icSigLut8Type,icSigLut16Type,icMaxEnumType}},
- {icSigAToB2Tag, {icSigLut8Type,icSigLut16Type,icMaxEnumType}},
- {icSigBlueColorantTag, {icSigXYZType,icMaxEnumType}},
- {icSigBlueTRCTag, {icSigCurveType,icMaxEnumType}},
- {icSigBToA0Tag, {icSigLut8Type,icSigLut16Type,icMaxEnumType}},
- {icSigBToA1Tag, {icSigLut8Type,icSigLut16Type,icMaxEnumType}},
- {icSigBToA2Tag, {icSigLut8Type,icSigLut16Type,icMaxEnumType}},
- {icSigCalibrationDateTimeTag, {icSigDateTimeType,icMaxEnumType}},
- {icSigCharTargetTag, {icSigTextType,icMaxEnumType}},
- {icSigColorantTableTag, {icSigColorantTableType,icmSigAltColorantTableType,
- icMaxEnumType}},
- {icSigColorantTableOutTag, {icSigColorantTableType,icmSigAltColorantTableType,
- icMaxEnumType}},
- {icSigCopyrightTag, {icSigTextType,icMaxEnumType}},
- {icSigCrdInfoTag, {icSigCrdInfoType,icMaxEnumType}},
- {icSigDeviceMfgDescTag, {icSigTextDescriptionType,icMaxEnumType}},
- {icSigDeviceModelDescTag, {icSigTextDescriptionType,icMaxEnumType}},
- {icSigGamutTag, {icSigLut8Type,icSigLut16Type,icMaxEnumType}},
- {icSigGrayTRCTag, {icSigCurveType,icMaxEnumType}},
- {icSigGreenColorantTag, {icSigXYZType,icMaxEnumType}},
- {icSigGreenTRCTag, {icSigCurveType,icMaxEnumType}},
- {icSigLuminanceTag, {icSigXYZType,icMaxEnumType}},
- {icSigMeasurementTag, {icSigMeasurementType,icMaxEnumType}},
- {icSigMediaBlackPointTag, {icSigXYZType,icMaxEnumType}},
- {icSigMediaWhitePointTag, {icSigXYZType,icMaxEnumType}},
- {icSigNamedColorTag, {icSigNamedColorType,icMaxEnumType}},
- {icSigNamedColor2Tag, {icSigNamedColor2Type,icMaxEnumType}},
- {icSigPreview0Tag, {icSigLut8Type,icSigLut16Type,icMaxEnumType}},
- {icSigPreview1Tag, {icSigLut8Type,icSigLut16Type,icMaxEnumType}},
- {icSigPreview2Tag, {icSigLut8Type,icSigLut16Type,icMaxEnumType}},
- {icSigProfileDescriptionTag, {icSigTextDescriptionType,icMaxEnumType}},
- {icSigProfileSequenceDescTag, {icSigProfileSequenceDescType,icMaxEnumType}},
- {icSigPs2CRD0Tag, {icSigDataType,icMaxEnumType}},
- {icSigPs2CRD1Tag, {icSigDataType,icMaxEnumType}},
- {icSigPs2CRD2Tag, {icSigDataType,icMaxEnumType}},
- {icSigPs2CRD3Tag, {icSigDataType,icMaxEnumType}},
- {icSigPs2CSATag, {icSigDataType,icMaxEnumType}},
- {icSigPs2RenderingIntentTag, {icSigDataType,icMaxEnumType}},
- {icSigRedColorantTag, {icSigXYZType,icMaxEnumType}},
- {icSigRedTRCTag, {icSigCurveType,icMaxEnumType}},
- {icSigScreeningDescTag, {icSigTextDescriptionType,icMaxEnumType}},
- {icSigScreeningTag, {icSigScreeningType,icMaxEnumType}},
- {icSigTechnologyTag, {icSigSignatureType,icMaxEnumType}},
- {icSigUcrBgTag, {icSigUcrBgType,icMaxEnumType}},
- {icSigVideoCardGammaTag, {icSigVideoCardGammaType,icMaxEnumType}},
- {icSigViewingCondDescTag, {icSigTextDescriptionType,icMaxEnumType}},
- {icSigViewingConditionsTag, {icSigViewingConditionsType,icMaxEnumType}},
- {icMaxEnumTag, {icMaxEnumType}}
-};
-
-/* Fake color tag for specifying PCS */
-#define icSigPCSData ((icColorSpaceSignature) 0x50435320L)
-
-/* Table that lists the required tags for various profiles */
-static struct {
- icProfileClassSignature sig; /* Profile signature */
- int chans; /* Data Color channels, -ve for match but try next, */
- /* -100 for ignore, -200 for ignore and try next */
- icColorSpaceSignature colsig; /* Data Color space signature, icMaxEnumData for ignore, */
- /* icSigPCSData for XYZ of Lab */
- icColorSpaceSignature pcssig; /* PCS Color space signature, icMaxEnumData for ignore, */
- /* icSigPCSData for XYZ or Lab */
- icTagSignature tags[12]; /* Arbitrary max of 12 */
-} tagchecktable[] = {
- {icSigInputClass, -1, icMaxEnumData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigGrayTRCTag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigInputClass, -3, icMaxEnumData, icSigXYZData,
- {icSigProfileDescriptionTag,
- icSigRedColorantTag,
- icSigGreenColorantTag,
- icSigBlueColorantTag,
- icSigRedTRCTag,
- icSigGreenTRCTag,
- icSigBlueTRCTag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigInputClass, -100, icMaxEnumData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigAToB0Tag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigDisplayClass, -1, icMaxEnumData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigGrayTRCTag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigDisplayClass, -3, icSigRgbData, icSigXYZData, /* Rgb or any 3 component space ?? */
- {icSigProfileDescriptionTag,
- icSigRedColorantTag,
- icSigGreenColorantTag,
- icSigBlueColorantTag,
- icSigRedTRCTag,
- icSigGreenTRCTag,
- icSigBlueTRCTag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- /* Non-3 component Display device */
- {icSigDisplayClass, -100, icMaxEnumData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigAToB0Tag, /* BToA doesn't seem to be required, which is strange... */
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigOutputClass, -1, icMaxEnumData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigGrayTRCTag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigOutputClass, -1, icMaxEnumData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigAToB0Tag,
- icSigBToA0Tag,
- icSigGamutTag,
- icSigAToB1Tag,
- icSigBToA1Tag,
- icSigAToB2Tag,
- icSigBToA2Tag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigOutputClass, -2, icMaxEnumData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigAToB0Tag,
- icSigBToA0Tag,
- icSigGamutTag,
- icSigAToB1Tag,
- icSigBToA1Tag,
- icSigAToB2Tag,
- icSigBToA2Tag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigOutputClass, -3, icMaxEnumData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigAToB0Tag,
- icSigBToA0Tag,
- icSigGamutTag,
- icSigAToB1Tag,
- icSigBToA1Tag,
- icSigAToB2Tag,
- icSigBToA2Tag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigOutputClass, -4, icMaxEnumData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigAToB0Tag,
- icSigBToA0Tag,
- icSigGamutTag,
- icSigAToB1Tag,
- icSigBToA1Tag,
- icSigAToB2Tag,
- icSigBToA2Tag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigOutputClass, -100, icMaxEnumData, icSigPCSData, /* Assumed from Hexachrome examples */
- {icSigProfileDescriptionTag,
- icSigBToA0Tag,
- icSigBToA1Tag,
- icSigBToA2Tag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigLinkClass, -100, icMaxEnumData, icMaxEnumData,
- {icSigProfileDescriptionTag,
- icSigAToB0Tag,
- icSigProfileSequenceDescTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigColorSpaceClass, -100, icMaxEnumData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigBToA0Tag,
- icSigAToB0Tag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigAbstractClass, -100, icSigPCSData, icSigPCSData,
- {icSigProfileDescriptionTag,
- icSigAToB0Tag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigNamedColorClass, -200, icMaxEnumData, icMaxEnumData,
- {icSigProfileDescriptionTag,
- icSigNamedColor2Tag,
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icSigNamedColorClass, -100, icMaxEnumData, icMaxEnumData,
- {icSigProfileDescriptionTag,
- icSigNamedColorTag, /* Not strictly V3.4 */
- icSigMediaWhitePointTag,
- icSigCopyrightTag, icMaxEnumTag}},
-
- {icMaxEnumClass,-1,icMaxEnumData, icMaxEnumData, {icMaxEnumTag}}
-};
-
-/* ------------------------------------------------------------- */
-
-/* Return the current read fp (if any) */
-static icmFile *icc_get_rfp(icc *p) {
- return p->fp;
-}
-
-/* Change the version to be non-default (ie. not 2.2.0), */
-/* e.g. ICC V4 (used for creation) */
-/* Return 0 if OK */
-/* Return 1 on error */
-static int icc_set_version(icc *p, icmICCVersion ver) {
-
- if (p->header == NULL) {
- sprintf(p->err,"icc_set_version: Header is missing");
- return p->errc = 1;
- }
-
- switch (ver) {
- case icmVersionDefault:
- p->header->majv = 2;
- p->header->minv = 2;
- p->header->bfv = 0;
- break;
- case icmVersion2_3:
- p->header->majv = 2;
- p->header->minv = 3;
- p->header->bfv = 0;
- break;
- case icmVersion2_4:
- p->header->majv = 2;
- p->header->minv = 4;
- p->header->bfv = 0;
- break;
-#ifdef ENABLE_V4
- case icmVersion4_1:
- p->header->majv = 4;
- p->header->minv = 1;
- p->header->bfv = 0;
- break;
-#endif
- default:
- sprintf(p->err,"icc_set_version: Unsupported version 0x%x",ver);
- return p->errc = 1;
- }
- return 0;
-}
-
-
-/* Check that the ICC profile looks like it will be legal. */
-/* Return non-zero and set error string if not */
-static int check_icc_legal(
- icc *p
-) {
- int i, j;
- icProfileClassSignature sig;
- icColorSpaceSignature colsig;
- icColorSpaceSignature pcssig;
- int dchans;
-
- if (p->header == NULL) {
- sprintf(p->err,"icc_check_legal: Header is missing");
- return p->errc = 1;
- }
-
- sig = p->header->deviceClass;
- colsig = p->header->colorSpace;
- dchans = number_ColorSpaceSignature(colsig);
- pcssig = p->header->pcs;
-
- /* Find a matching table entry */
- for (i = 0; tagchecktable[i].sig != icMaxEnumType; i++) {
- if ( tagchecktable[i].sig == sig
- && ( tagchecktable[i].chans == dchans /* Exactly matches */
- || tagchecktable[i].chans == -dchans /* Exactly matches, but can try next table */
- || tagchecktable[i].chans < -99) /* Doesn't have to match or try next table */
- && ( tagchecktable[i].colsig == colsig
- || (tagchecktable[i].colsig == icSigPCSData
- && (colsig == icSigXYZData || colsig == icSigLabData))
- || tagchecktable[i].colsig == icMaxEnumData)
- && ( tagchecktable[i].pcssig == pcssig
- || (tagchecktable[i].pcssig == icSigPCSData
- && (pcssig == icSigXYZData || pcssig == icSigLabData))
- || tagchecktable[i].pcssig == icMaxEnumData)) {
-
- /* Found entry, so now check that all the required tags are present. */
- for (j = 0; tagchecktable[i].tags[j] != icMaxEnumType; j++) {
- if (p->find_tag(p, tagchecktable[i].tags[j]) != 0) { /* Not present! */
- if (tagchecktable[i].chans == -200
- || tagchecktable[i].chans == -dchans) { /* But can try next table */
- break;
- }
- sprintf(p->err,"icc_check_legal: deviceClass %s is missing required tag %s",
- tag2str(sig), tag2str(tagchecktable[i].tags[j]));
- return p->errc = 1;
- }
- }
- if (tagchecktable[i].tags[j] == icMaxEnumType) {
- break; /* Fount all required tags */
- }
- }
- }
-
- /* According to the spec. if the deviceClass is:
- an Abstract Class: both in and out color spaces should be PCS
- an Link Class: both in and out color spaces can be any, and should
- be the input space of the first profile in the link, and the
- input space of the last profile in the link respectively.
- a Named Class: in and out color spaces are not defined in the spec.
- Input, Display, Output and ColorSpace Classes, input color
- space can be any, and the output space must be PCS.
- ~~ should check this here ???
- */
-
- return 0; /* Assume anything is ok */
-}
-
-
-/* read the object, return 0 on success, error code on fail */
-/* NOTE: this doesn't read the tag types, they should be read on demand. */
-/* NOTE: fp ownership is taken even if the function fails. */
-static int icc_read_x(
- icc *p,
- icmFile *fp, /* File to read from */
- unsigned int of, /* File offset to read from */
- int take_fp /* NZ if icc is to take ownership of fp */
-) {
- char tcbuf[4]; /* Tag count read buffer */
- unsigned int i, len;
- unsigned int minoff, maxoff; /* Minimum and maximum offsets of tag data */
- int er = 0; /* Error code */
-
- p->fp = fp;
- if (take_fp)
- p->del_fp = 1;
- p->of = of;
- if (p->header == NULL) {
- sprintf(p->err,"icc_read: No header defined");
- return p->errc = 1;
- }
-
- /* Read the header */
- if (p->header->read(p->header, 128, of)) {
- return 1;
- }
-
- /* Read the tag count */
- if ( p->fp->seek(p->fp, of + 128) != 0
- || p->fp->read(p->fp, tcbuf, 1, 4) != 4) {
- sprintf(p->err,"icc_read: fseek() or fread() failed on tag count");
- return p->errc = 1;
- }
- p->count = read_UInt32Number(tcbuf);
-
- /* Sanity check it */
- if (p->count > 357913940 /* (2^32-5)/12 */
- || (p->count > ((p->header->size - 128 - 4) / 12))) {
- sprintf(p->err,"icc_read: tag count %d is too large to be legal",p->count);
- return p->errc = 1;
- }
- minoff = 128 + 4 + p->count * 12;
- maxoff = p->header->size;
-
- if (p->count > 0) {
- char *bp, *buf;
-
- if (ovr_mul(p->count, sizeof(icmTag))) {
- sprintf(p->err,"icc_read: size overflow");
- return p->errc = 1;
- }
-
- /* Read the table into memory */
- if ((p->data = (icmTag *) p->al->calloc(p->al, p->count, sizeof(icmTag))) == NULL) {
- sprintf(p->err,"icc_read: Tag table malloc() failed");
- return p->errc = 2;
- }
-
- len = sat_mul(p->count, 12);
- if ((buf = (char *) p->al->malloc(p->al, len)) == NULL) {
- sprintf(p->err,"icc_read: Tag table read buffer malloc() failed");
- p->al->free(p->al, p->data);
- p->data = NULL;
- return p->errc = 2;
- }
- if ( p->fp->seek(p->fp, of + 128 + 4) != 0
- || p->fp->read(p->fp, buf, 1, len) != len) {
- sprintf(p->err,"icc_read: fseek() or fread() failed on tag table");
- p->al->free(p->al, p->data);
- p->data = NULL;
- p->al->free(p->al, buf);
- return p->errc = 1;
- }
-
- /* Fill in the tag table structure for each tag */
- for (bp = buf, i = 0; i < p->count; i++, bp += 12) {
- p->data[i].sig = (icTagSignature)read_SInt32Number(bp + 0);
- p->data[i].offset = read_UInt32Number(bp + 4);
- p->data[i].size = read_UInt32Number(bp + 8);
- }
- p->al->free(p->al, buf);
-
- /* Check that each tag lies within the nominated space available, */
- /* and has a reasonable size. */
- for (i = 0; i < p->count; i++) {
- if (p->data[i].offset < minoff
- || p->data[i].offset > maxoff
- || p->data[i].size < 4
- || p->data[i].size > (maxoff - minoff)
- || (p->data[i].offset + p->data[i].size) < p->data[i].offset /* Overflow */
- || (p->data[i].offset + p->data[i].size) > p->header->size) {
- sprintf(p->err,"icc_read: tag %d is out of range of the nominated file size",i);
- p->al->free(p->al, p->data);
- p->data = NULL;
- return p->errc = 1;
- }
- }
-
- /* Read each tag type */
- for (i = 0; i < p->count; i++) {
- if ( p->fp->seek(p->fp, of + p->data[i].offset) != 0
- || p->fp->read(p->fp, tcbuf, 1, 4) != 4) {
- sprintf(p->err,"icc_read: fseek() or fread() failed on tag headers");
- p->al->free(p->al, p->data);
- p->data = NULL;
- return p->errc = 1;
- }
- p->data[i].ttype = (icTagTypeSignature) read_SInt32Number(tcbuf); /* Tag type */
- p->data[i].objp = NULL; /* Read on demand */
- }
- } /* p->count > 0 */
-
- return er;
-}
-
-/* read the object, return 0 on success, error code on fail */
-/* NOTE: this doesn't read the tag types, they should be read on demand. */
-/* (backward compatible version) */
-static int icc_read(
- icc *p,
- icmFile *fp, /* File to read from */
- unsigned int of /* File offset to read from */
-) {
- return icc_read_x(p, fp, of, 0);
-}
-
-/* Check the profiles ID. We assume the file has already been read. */
-/* Return 0 if OK, 1 if no ID to check, 2 if doesn't match, 3 if some other error. */
-/* NOTE: this reads the whole file again, to compute the checksum. */
-static int icc_check_id(
- icc *p,
- ORD8 *rid /* Optionaly return computed ID */
-) {
- unsigned char buf[128];
- ORD8 id[16];
- icmMD5 *md5 = NULL;
- unsigned int len;
-
- if (p->header == NULL) {
- sprintf(p->err,"icc_check_id: No header defined");
- return p->errc = 3;
- }
- len = p->header->size; /* Claimed size of profile */
-
- /* See if there is an ID to compare against */
- for (len = 0; len < 16; len++) {
- if (p->header->id[len] != 0)
- break;
- }
- if (len >= 16) {
- return 1;
- }
-
- if ((md5 = new_icmMD5(p->al)) == NULL) {
- sprintf(p->err,"icc_check_id: new_icmMD5 failed");
- return p->errc = 3;
- }
-
- /* Check the header */
- if ( p->fp->seek(p->fp, p->of) != 0
- || p->fp->read(p->fp, buf, 1, 128) != 128) {
- sprintf(p->err,"icc_check_id: fseek() or fread() failed");
- return p->errc = 3;
- }
-
- /* Zero the appropriate bytes in the header */
- buf[44] = buf[45] = buf[46] = buf[47] = 0;
- buf[64] = buf[65] = buf[66] = buf[67] = 0;
- buf[84] = buf[85] = buf[86] = buf[87] =
- buf[88] = buf[89] = buf[90] = buf[91] =
- buf[92] = buf[93] = buf[94] = buf[95] =
- buf[96] = buf[97] = buf[98] = buf[99] = 0;
-
- md5->add(md5, buf, 128);
-
- /* Suck in the rest of the profile */
- for (;len > 0;) {
- unsigned int rsize = 128;
- if (rsize > len)
- rsize = len;
- if (p->fp->read(p->fp, buf, 1, rsize) != rsize) {
- sprintf(p->err,"icc_check_id: fread() failed");
- return p->errc = 3;
- }
- md5->add(md5, buf, rsize);
- len -= rsize;
- }
-
- md5->get(md5, id);
- md5->del(md5);
-
- if (rid != NULL) {
- for (len = 0; len < 16; len++)
- rid[len] = id[len];
- }
-
- /* Check the ID */
- for (len = 0; len < 16; len++) {
- if (p->header->id[len] != id[len])
- break;
- }
- if (len >= 16) {
- return 0; /* Matched */
- }
- return 2; /* Didn't match */
-}
-
-/* Return the total size needed for the profile */
-/* Return 0 on error. */
-static unsigned int icc_get_size(
- icc *p
-) {
- unsigned int i, size = 0;
-
-#ifdef ICM_STRICT
- /* Check that the right tags etc. are present for a legal ICC profile */
- if (check_icc_legal(p) != 0) {
- return 0;
- }
-#endif /* ICM_STRICT */
-
- /* Compute the total size and tag element data offsets */
- if (p->header == NULL) {
- sprintf(p->err,"icc_get_size: No header defined");
- p->errc = 1;
- return 0;
- }
-
- size = sat_add(size, p->header->get_size(p->header));
- /* Assume header is aligned */
- size = sat_addaddmul(size, 4, p->count, 12); /* Tag table length */
- size = sat_align(ALIGN_SIZE, size);
-
- if (size == UINT_MAX) {
- sprintf(p->err,"icc_get_size: size overflow");
- return p->errc = 1;
- }
-
- /* Reset touched flag for each tag type */
- for (i = 0; i < p->count; i++) {
- if (p->data[i].objp == NULL) {
- sprintf(p->err,"icc_get_size: Internal error - NULL tag element");
- p->errc = 1;
- return 0;
- }
- p->data[i].objp->touched = 0;
- }
- /* Get size for each tag type, skipping links */
- for (i = 0; i < p->count; i++) {
- if (p->data[i].objp->touched == 0) { /* Not alllowed for previously */
- size = sat_add(size, p->data[i].objp->get_size(p->data[i].objp));
- size = sat_align(ALIGN_SIZE, size);
- p->data[i].objp->touched = 1; /* Don't account for this again */
- }
- }
-
- return size; /* Total size needed, or UINT_MAX if overflow */
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-/* NOTE: fp ownership is taken even if the function fails. */
-static int icc_write_x(
- icc *p,
- icmFile *fp, /* File to write to */
- unsigned int of, /* File offset to write to */
- int take_fp /* NZ if icc is to take ownership of fp */
-) {
- char *bp, *buf; /* tag table buffer */
- unsigned int len;
- int rv = 0;
- unsigned int i, size = 0;
- unsigned char pbuf[ALIGN_SIZE];
-
- p->fp = fp; /* Open file pointer */
- if (take_fp)
- p->del_fp = 1;
- p->of = of; /* Offset of ICC profile */
-
- for (i = 0; i < ALIGN_SIZE; i++)
- pbuf[i] = 0;
-
- /* Check that the right tags etc. are present for a legal ICC profile */
- if ((rv = check_icc_legal(p)) != 0) {
- return rv;
- }
-
- /* Compute the total size and tag element data offsets */
- if (p->header == NULL) {
- sprintf(p->err,"icc_write: No header defined");
- return p->errc = 1;
- }
-
- size = sat_add(size, p->header->get_size(p->header));
- /* Assume header is aligned */
- len = sat_addmul(4, p->count, 12); /* Tag table length */
- len = sat_sub(sat_align(ALIGN_SIZE, sat_add(size, len)), size); /* Aligned size */
- size = sat_align(ALIGN_SIZE, sat_add(size, len));
-
- if (len == UINT_MAX) {
- sprintf(p->err,"icc_write get_size overflow");
- return p->errc = 1;
- }
-
- /* Allocate memory buffer for tag table */
- if ((buf = (char *) p->al->calloc(p->al, 1, len)) == NULL) {
- sprintf(p->err,"icc_write calloc() failed");
- return p->errc = 2;
- }
- bp = buf;
-
- if ((rv = write_UInt32Number(p->count, bp)) != 0) { /* Tag count */
- sprintf(p->err,"icc_write: write_UInt32Number() failed on tag count");
- p->al->free(p->al, buf);
- return p->errc = rv;
- }
- bp += 4;
- /* Reset touched flag for each tag type */
- for (i = 0; i < p->count; i++) {
- if (p->data[i].objp == NULL) {
- sprintf(p->err,"icc_write: Internal error - NULL tag element");
- p->al->free(p->al, buf);
- return p->errc = 1;
- }
- p->data[i].objp->touched = 0;
- }
- /* Set the offset and size for each tag type, create the tag table write data */
- /* and compute the total profile size. */
- for (i = 0; i < p->count; i++) {
- if (p->data[i].objp->touched == 0) { /* Allocate space for tag type */
- p->data[i].offset = size; /* Profile relative target */
- p->data[i].size = p->data[i].objp->get_size(p->data[i].objp);
- size = sat_add(size, p->data[i].size);
- p->data[i].pad = sat_sub(sat_align(ALIGN_SIZE, size), size);
- size = sat_align(ALIGN_SIZE, size);
- p->data[i].objp->touched = 1; /* Allocated space for it */
- if (size == UINT_MAX) {
- sprintf(p->err,"icc_write: size overflow");
- return p->errc = 1;
- }
- } else { /* must be linked - copy allocation */
- unsigned int k;
- for (k = 0; k < p->count; k++) { /* Find linked tag */
- if (p->data[k].objp == p->data[i].objp)
- break;
- }
- if (k == p->count) {
- sprintf(p->err,"icc_write: corrupted link");
- return p->errc = 2;
- }
- p->data[i].offset = p->data[k].offset;
- p->data[i].size = p->data[k].size;
- p->data[i].pad = p->data[k].pad;
- }
- /* Write tag table entry for this tag */
- if ((rv = write_SInt32Number((int)p->data[i].sig,bp + 0)) != 0) {
- sprintf(p->err,"icc_write: write_SInt32Number() failed on tag signature");
- p->al->free(p->al, buf);
- return p->errc = rv;
- }
- if ((rv = write_UInt32Number(p->data[i].offset, bp + 4)) != 0) {
- sprintf(p->err,"icc_write: write_UInt32Number() failed on tag offset");
- p->al->free(p->al, buf);
- return p->errc = rv;
- }
- if ((rv = write_UInt32Number(p->data[i].size, bp + 8)) != 0) {
- sprintf(p->err,"icc_write: write_UInt32Number() failed on tag size");
- p->al->free(p->al, buf);
- return p->errc = rv;
- }
- bp += 12;
- }
- p->header->size = size; /* Record total icc padded size */
-
-
- /* If V4.0+, Compute the MD5 id for the profile. */
- /* We do this by writing to a fake icmFile */
- if (p->ver) {
- icmMD5 *md5 = NULL;
- icmFile *ofp, *dfp = NULL;
-
- if ((md5 = new_icmMD5(p->al)) == NULL) {
- sprintf(p->err,"icc_write: new_icmMD5 failed");
- p->al->free(p->al, buf);
- return p->errc = 2;
- }
-
- if ((dfp = new_icmFileMD5_a(md5, p->al)) == NULL) {
- sprintf(p->err,"icc_write: new_icmFileMD5 failed");
- md5->del(md5);
- p->al->free(p->al, buf);
- return p->errc = 2;
- }
-
- ofp = p->fp;
- p->fp = dfp;
-
- /* Dumy write the header */
- if ((rv = p->header->write(p->header, 0, 1)) != 0) {
- p->al->free(p->al, buf);
- return rv;
- }
-
- /* Dumy write the tag table */
- if ( p->fp->seek(p->fp, 128) != 0
- || p->fp->write(p->fp, buf, 1, len) != len) {
- sprintf(p->err,"icc_write: seek() or write() failed");
- p->al->free(p->al, buf);
- return p->errc = 1;
- }
-
- /* Dumy write all the tag element data */
- /* (We invert meaning of touched here) */
- for (i = 0; i < p->count; i++) { /* For all the tag element data */
- if (p->data[i].objp->touched == 0)
- continue; /* Must be linked, and we've already written it */
- if ((rv = p->data[i].objp->write(p->data[i].objp, p->data[i].offset)) != 0) {
- p->al->free(p->al, buf);
- return rv;
- }
- /* Pad with 0 to next boundary */
- if (p->data[i].pad > 0) {
- if (p->fp->write(p->fp, pbuf, 1, p->data[i].pad) != p->data[i].pad) {
- sprintf(p->err,"icc_write: write() failed");
- p->al->free(p->al, buf);
- return p->errc = 1;
- }
- }
- p->data[i].objp->touched = 0; /* Written it, so don't write it again. */
- }
-
- if (p->fp->flush(p->fp) != 0) {
- sprintf(p->err,"icc_write flush() failed");
- p->al->free(p->al, buf);
- return p->errc = 1;
- }
-
- if ((p->errc = ((icmFileMD5 *)dfp)->get_errc(dfp)) != 0) {
- sprintf(p->err,"icc_write compute ID failed with code %d", p->errc);
- p->al->free(p->al, buf);
- return p->errc;
- }
-
- /* Get the MD5 checksum ID */
- md5->get(md5, p->header->id);
-
- dfp->del(dfp);
- md5->del(md5);
- p->fp = ofp;
-
- /* Reset the touched flags */
- for (i = 0; i < p->count; i++)
- p->data[i].objp->touched = 1;
- }
-
- /* Now write out the profile for real. */
- /* Although it may appear like we're seeking for each element, */
- /* in fact elements will be written in file order. */
-
- /* Write the header */
- if ((rv = p->header->write(p->header, of, 0)) != 0) {
- p->al->free(p->al, buf);
- return rv;
- }
-
- /* Write the tag table */
- if ( p->fp->seek(p->fp, of + 128) != 0
- || p->fp->write(p->fp, buf, 1, len) != len) {
- sprintf(p->err,"icc_write: seek() or write() failed");
- p->al->free(p->al, buf);
- return p->errc = 1;
- }
- p->al->free(p->al, buf);
-
- /* Write all the tag element data */
- /* (We invert the meaning of touched here) */
- for (i = 0; i < p->count; i++) { /* For all the tag element data */
- if (p->data[i].objp->touched == 0)
- continue; /* Must be linked, and we've already written it */
- if ((rv = p->data[i].objp->write(p->data[i].objp, of + p->data[i].offset)) != 0) {
- return rv;
- }
- /* Pad with 0 to next boundary */
- if (p->data[i].pad > 0) {
- if (p->fp->write(p->fp, pbuf, 1, p->data[i].pad) != p->data[i].pad) {
- sprintf(p->err,"icc_write: write() failed");
- return p->errc = 1;
- }
- }
- p->data[i].objp->touched = 0; /* Written it, so don't write it again. */
- }
-
- if (p->fp->flush(p->fp) != 0) {
- sprintf(p->err,"icc_write flush() failed");
- return p->errc = 1;
- }
-
- return rv;
-}
-
-/* Write the contents of the object. Return 0 on sucess, error code on failure */
-/* (backwards compatible version) */
-static int icc_write(
- icc *p,
- icmFile *fp, /* File to write to */
- unsigned int of /* File offset to write to */
-) {
- return icc_write_x(p, fp, of, 0);
-}
-
-/* Create and add a tag with the given signature. */
-/* Returns a pointer to the element object */
-/* Returns NULL if error - icc->errc will contain */
-/* 2 on system error, */
-/* 3 if unknown tag */
-/* NOTE: that we prevent tag duplication */
-/* NOTE: to create a tag type icmSigUnknownType, set ttype to icmSigUnknownType, */
-/* and set the actual tag type in icmSigUnknownType->uttype */
-static icmBase *icc_add_tag(
- icc *p,
- icTagSignature sig, /* Tag signature - may be unknown */
- icTagTypeSignature ttype /* Tag type */
-) {
- icmBase *tp;
- icmBase *nob;
- int i = 0, ok = 1;
- unsigned int j;
-
- if (ttype != icmSigUnknownType) { /* Check only for possibly known types */
-
- /* Check that a known signature has an acceptable type */
- for (i = 0; sigtypetable[i].sig != icMaxEnumType; i++) {
- if (sigtypetable[i].sig == sig) { /* recognized signature */
- ok = 0;
- for (j = 0; sigtypetable[i].ttypes[j] != icMaxEnumType; j++) {
- if (sigtypetable[i].ttypes[j] == ttype) /* recognized type */
- ok = 1;
- }
- break;
- }
- }
- if (!ok) {
- sprintf(p->err,"icc_add_tag: wrong tag type for signature");
- p->errc = 1;
- return NULL;
- }
-
- /* Check that we know how to handle this type */
- for (i = 0; typetable[i].ttype != icMaxEnumType; i++) {
- if (typetable[i].ttype == ttype)
- break;
- }
- if (typetable[i].ttype == icMaxEnumType) {
- sprintf(p->err,"icc_add_tag: unsupported tag type");
- p->errc = 1;
- return NULL;
- }
- }
-
- /* Check that this tag doesn't already exist */
- /* (Perhaps we should simply replace it, rather than erroring ?) */
- for (j = 0; j < p->count; j++) {
- if (p->data[j].sig == sig) {
- sprintf(p->err,"icc_add_tag: Already have tag '%s' in profile",tag2str(p->data[j].sig));
- p->errc = 1;
- return NULL;
- }
- }
-
- /* Make space in tag table for new tag item */
- if (ovr_mul(sat_add(p->count,1), sizeof(icmTag))) {
- sprintf(p->err,"icc_add_tag: size overflow");
- p->errc = 1;
- return NULL;
- }
- if (p->data == NULL)
- tp = (icmBase *)p->al->malloc(p->al, (p->count+1) * sizeof(icmTag));
- else
- tp = (icmBase *)p->al->realloc(p->al, (void *)p->data, (p->count+1) * sizeof(icmTag));
- if (tp == NULL) {
- sprintf(p->err,"icc_add_tag: Tag table realloc() failed");
- p->errc = 2;
- return NULL;
- }
- p->data = (icmTag *)tp;
-
- if (ttype == icmSigUnknownType) {
- if ((nob = new_icmUnknown(p)) == NULL)
- return NULL;
- } else {
- /* Allocate the empty object */
- if ((nob = typetable[i].new_obj(p)) == NULL)
- return NULL;
- }
-
- /* Fill out our tag table entry */
- p->data[p->count].sig = sig; /* The tag signature */
- p->data[p->count].ttype = nob->ttype = ttype; /* The tag type signature */
- p->data[p->count].offset = 0; /* Unknown offset yet */
- p->data[p->count].size = 0; /* Unknown size yet */
- p->data[p->count].objp = nob; /* Empty object */
- p->count++;
-
- return nob;
-}
-
-/* Create and add a tag which is a link to an existing tag. */
-/* Returns a pointer to the element object */
-/* Returns NULL if error - icc->errc will contain */
-/* 3 if incompatible tag */
-/* NOTE: that we prevent tag duplication */
-static icmBase *icc_link_tag(
- icc *p,
- icTagSignature sig, /* Tag signature - may be unknown */
- icTagSignature ex_sig /* Tag signature of tag to link to */
-) {
- icmBase *tp;
- unsigned int j, exi;
- int i, ok = 1;
-
- /* Search for existing signature */
- for (exi = 0; exi < p->count; exi++) {
- if (p->data[exi].sig == ex_sig) /* Found it */
- break;
- }
- if (exi == p->count) {
- sprintf(p->err,"icc_link_tag: Can't find existing tag '%s'",tag2str(ex_sig));
- p->errc = 1;
- return NULL;
- }
-
- if (p->data[exi].objp == NULL) {
- sprintf(p->err,"icc_link_tag: Existing tag '%s' isn't loaded",tag2str(ex_sig));
- p->errc = 1;
- return NULL;
- }
-
- /* Check that a known signature has an acceptable type */
- for (i = 0; sigtypetable[i].sig != icMaxEnumType; i++) {
- if (sigtypetable[i].sig == sig) { /* recognized signature */
- ok = 0;
- for (j = 0; sigtypetable[i].ttypes[j] != icMaxEnumType; j++) {
- if (sigtypetable[i].ttypes[j] == p->data[exi].ttype) /* recognized type */
- ok = 1;
- }
- break;
- }
- }
- if (!ok) {
- sprintf(p->err,"icc_link_tag: wrong tag type for signature");
- p->errc = 1;
- return NULL;
- }
-
- /* Check that this tag doesn't already exits */
- for (j = 0; j < p->count; j++) {
- if (p->data[j].sig == sig) {
- sprintf(p->err,"icc_link_tag: Already have tag '%s' in profile",tag2str(p->data[j].sig));
- p->errc = 1;
- return NULL;
- }
- }
-
- /* Make space in tag table for new tag item */
- if (p->data == NULL)
- tp = (icmBase *)p->al->malloc(p->al, (p->count+1) * sizeof(icmTag));
- else
- tp = (icmBase *)p->al->realloc(p->al, (void *)p->data, (p->count+1) * sizeof(icmTag));
- if (tp == NULL) {
- sprintf(p->err,"icc_link_tag: Tag table realloc() failed");
- p->errc = 2;
- return NULL;
- }
- p->data = (icmTag *)tp;
-
- /* Fill out our tag table entry */
- p->data[p->count].sig = sig; /* The tag signature */
- p->data[p->count].ttype = p->data[exi].ttype; /* The tag type signature */
- p->data[p->count].offset = p->data[exi].offset; /* Same offset (may not be allocated yet) */
- p->data[p->count].size = p->data[exi].size; /* Same size (may not be allocated yet) */
- p->data[p->count].objp = p->data[exi].objp; /* Shared object */
- p->data[exi].objp->refcount++; /* Bump reference count on tag type */
- p->count++;
-
- return p->data[exi].objp;
-}
-
-/* Search for tag signature */
-/* return: */
-/* 0 if found */
-/* 1 if found but not handled type */
-/* 2 if not found */
-/* NOTE: doesn't set icc->errc or icc->err[] */
-/* NOTE: we don't handle tag duplication - you'll always get the first in the file. */
-static int icc_find_tag(
- icc *p,
- icTagSignature sig /* Tag signature - may be unknown */
-) {
- unsigned int i;
- int j;
-
- /* Search for signature */
- for (i = 0; i < p->count; i++) {
- if (p->data[i].sig == sig) /* Found it */
- break;
- }
- if (i == p->count)
- return 2;
-
- /* See if we can handle this type */
- for (j = 0; typetable[j].ttype != icMaxEnumType; j++) {
- if (typetable[j].ttype == p->data[i].ttype)
- break;
- }
- if (typetable[j].ttype == icMaxEnumType)
- return 1;
-
- return 0;
-}
-
-/* Read the specific tag element data, and return a pointer to the object */
-/* (This is an internal function) */
-/* Returns NULL if error - icc->errc will contain: */
-/* 2 if not found */
-/* Returns an icmSigUnknownType object if the tag type isn't handled by a */
-/* specific object and alow_unk is NZ */
-/* NOTE: we don't handle tag duplication - you'll always get the first in the file */
-static icmBase *icc_read_tag_ix(
- icc *p,
- unsigned int i, /* Index from 0.. p->count-1 */
- int alow_unk /* NZ to allow unknown tag to load */
-) {
- icTagTypeSignature ttype; /* Tag type we will create */
- icmBase *nob;
- unsigned int k;
- int j;
-
- if (i >= p->count) {
- sprintf(p->err,"icc_read_tag_ix: index %d is out of range",i);
- p->errc = 2;
- return NULL;
- }
-
- /* See if it's already been read */
- if (p->data[i].objp != NULL) {
- return p->data[i].objp; /* Just return it */
- }
-
- /* See if this should be a link */
- for (k = 0; k < p->count; k++) {
- if (i == k)
- continue;
- if (p->data[i].ttype == p->data[k].ttype /* Exact match and already read */
- && p->data[i].offset == p->data[k].offset
- && p->data[i].size == p->data[k].size
- && p->data[k].objp != NULL)
- break;
- }
- if (k < p->count) { /* Make this a link */
- p->data[i].objp = p->data[k].objp;
- p->data[k].objp->refcount++; /* Bump reference count */
- return p->data[k].objp; /* Done */
- }
-
- /* See if we can handle this type */
- for (j = 0; typetable[j].ttype != icMaxEnumType; j++) {
- if (typetable[j].ttype == p->data[i].ttype)
- break;
- }
-
- if (typetable[j].ttype == icMaxEnumType) {
- if (!alow_unk) {
- p->errc = 2;
- return NULL;
- }
- ttype = icmSigUnknownType; /* Use the Unknown type to handle an unknown tag type */
- } else {
- ttype = p->data[i].ttype; /* We known this type */
- }
-
- /* Create and read in the object */
- if (ttype == icmSigUnknownType)
- nob = new_icmUnknown(p);
- else
- nob = typetable[j].new_obj(p);
-
- if (nob == NULL)
- return NULL;
-
- if ((nob->read(nob, p->data[i].size, p->of + p->data[i].offset)) != 0) {
- nob->del(nob); /* Failed, so destroy it */
- return NULL;
- }
- p->data[i].objp = nob;
- return nob;
-}
-
-/* Read the tag element data of the first matching, and return a pointer to the object */
-/* Returns NULL if error - icc->errc will contain: */
-/* 2 if not found */
-/* Doesn't read uknown type tags */
-static icmBase *icc_read_tag(
- icc *p,
- icTagSignature sig /* Tag signature - may be unknown */
-) {
- unsigned int i;
-
- /* Search for signature */
- for (i = 0; i < p->count; i++) {
- if (p->data[i].sig == sig) /* Found it */
- break;
- }
- if (i >= p->count) {
- sprintf(p->err,"icc_read_tag: Tag '%s' not found",string_TagSignature(sig));
- p->errc = 2;
- return NULL;
- }
-
- /* Let read_tag_ix do all the work */
- return icc_read_tag_ix(p, i, 0);
-}
-
-/* Read the tag element data of the first matching, and return a pointer to the object */
-/* Returns NULL if error.
-/* Returns an icmSigUnknownType object if the tag type isn't handled by a specific object. */
-/* NOTE: we don't handle tag duplication - you'll always get the first in the file. */
-static icmBase *icc_read_tag_any(
- icc *p,
- icTagSignature sig /* Tag signature - may be unknown */
-) {
- unsigned int i;
-
- /* Search for signature */
- for (i = 0; i < p->count; i++) {
- if (p->data[i].sig == sig) /* Found it */
- break;
- }
- if (i >= p->count) {
- sprintf(p->err,"icc_read_tag: Tag '%s' not found",string_TagSignature(sig));
- p->errc = 2;
- return NULL;
- }
-
- /* Let read_tag_ix do all the work */
- return icc_read_tag_ix(p, i, 1);
-}
-
-/* Rename a tag signature */
-static int icc_rename_tag(
- icc *p,
- icTagSignature sig, /* Existing Tag signature - may be unknown */
- icTagSignature sigNew /* New Tag signature - may be unknown */
-) {
- unsigned int k;
- int i, j, ok = 1;
-
- /* Search for signature */
- for (k = 0; k < p->count; k++) {
- if (p->data[k].sig == sig) /* Found it */
- break;
- }
- if (k >= p->count) {
- sprintf(p->err,"icc_rename_tag: Tag '%s' not found",string_TagSignature(sig));
- return p->errc = 2;
- }
-
- /* Check that a known new signature has an acceptable type */
- for (i = 0; sigtypetable[i].sig != icMaxEnumType; i++) {
- if (sigtypetable[i].sig == sigNew) { /* recognized signature */
- ok = 0;
- for (j = 0; sigtypetable[i].ttypes[j] != icMaxEnumType; j++) {
- if (sigtypetable[i].ttypes[j] == p->data[k].ttype) /* recognized type */
- ok = 1;
- }
- break;
- }
- }
-
- if (!ok) {
- sprintf(p->err,"icc_rename_tag: wrong signature for tag type");
- p->errc = 1;
- return p->errc;
- }
-
- /* change its signature */
- p->data[k].sig = sigNew;
-
- return 0;
-}
-
-/* Unread a specific tag, and free the underlying tag type data */
-/* if this was the last reference to it. */
-/* (This is an internal function) */
-/* Returns non-zero on error: */
-/* tag not found - icc->errc will contain 2 */
-/* tag not read - icc->errc will contain 2 */
-static int icc_unread_tag_ix(
- icc *p,
- unsigned int i /* Index from 0.. p->count-1 */
-) {
- if (i >= p->count) {
- sprintf(p->err,"icc_unread_tag_ix: index %d is out of range",i);
- return p->errc = 2;
- }
-
- /* See if it's been read */
- if (p->data[i].objp == NULL) {
- sprintf(p->err,"icc_unread_tag: Tag '%s' not currently loaded",string_TagSignature(p->data[i].sig));
- return p->errc = 2;
- }
-
- if (--(p->data[i].objp->refcount) == 0) /* decrement reference count */
- (p->data[i].objp->del)(p->data[i].objp); /* Last reference */
- p->data[i].objp = NULL;
-
- return 0;
-}
-
-/* Unread the tag, and free the underlying tag type */
-/* if this was the last reference to it. */
-/* Returns non-zero on error: */
-/* tag not found - icc->errc will contain 2 */
-/* tag not read - icc->errc will contain 2 */
-/* NOTE: we don't handle tag duplication - you'll always get the first in the file */
-static int icc_unread_tag(
- icc *p,
- icTagSignature sig /* Tag signature - may be unknown */
-) {
- unsigned int i;
-
- /* Search for signature */
- for (i = 0; i < p->count; i++) {
- if (p->data[i].sig == sig) /* Found it */
- break;
- }
- if (i >= p->count) {
- sprintf(p->err,"icc_unread_tag: Tag '%s' not found",string_TagSignature(sig));
- return p->errc = 2;
- }
-
- return icc_unread_tag(p, i);
-}
-
-/* Delete the tag, and free the underlying tag type, */
-/* if this was the last reference to it. */
-/* Note this finds the first tag with a matching signature */
-/* Returns non-zero on error: */
-/* tag not found - icc->errc will contain 2 */
-static int icc_delete_tag_ix(
- icc *p,
- unsigned int i /* Index from 0.. p->count-1 */
-) {
- if (i >= p->count) {
- sprintf(p->err,"icc_delete_tag_ix: index %d of range",i);
- return p->errc = 2;
- }
-
- /* If it's been read into memory, decrement the reference count */
- if (p->data[i].objp != NULL) {
- if (--(p->data[i].objp->refcount) == 0) /* decrement reference count */
- (p->data[i].objp->del)(p->data[i].objp); /* Last reference */
- p->data[i].objp = NULL;
- }
-
- /* Now remove it from the tag list */
- for (; i < (p->count-1); i++)
- p->data[i] = p->data[i+1]; /* Copy the structure down */
-
- p->count--; /* One less tag in list */
-
- return 0;
-}
-
-/* Delete the tag, and free the underlying tag type, */
-/* if this was the last reference to it. */
-/* Note this finds the first tag with a matching signature. */
-/* Returns non-zero on error: */
-/* tag not found - icc->errc will contain 2 */
-static int icc_delete_tag(
- icc *p,
- icTagSignature sig /* Tag signature - may be unknown */
-) {
- unsigned int i;
-
- /* Search for signature */
- for (i = 0; i < p->count; i++) {
- if (p->data[i].sig == sig) /* Found it */
- break;
- }
- if (i >= p->count) {
- sprintf(p->err,"icc_delete_tag: Tag '%s' not found",string_TagSignature(sig));
- return p->errc = 2;
- }
-
- return icc_delete_tag_ix(p, i);
-}
-
-/* Read all the tags into memory, including unknown types. */
-/* Returns non-zero on error. */
-static int icc_read_all_tags(
- icc *p
-) {
- unsigned int i;
-
- for (i = 0; i < p->count; i++) { /* For all the tag element data */
- if (icc_read_tag_ix(p, i, 1) == NULL)
- return p->errc;
- }
- return 0;
-}
-
-
-static void icc_dump(
- icc *p,
- icmFile *op, /* Output to dump to */
- int verb /* Verbosity level */
-) {
- unsigned int i;
- if (verb <= 0)
- return;
-
- op->gprintf(op,"icc:\n");
-
- /* Dump the header */
- if (p->header != NULL)
- p->header->dump(p->header,op,verb);
-
- /* Dump all the tag elements */
- for (i = 0; i < p->count; i++) { /* For all the tag element data */
- icmBase *ob;
- int tr;
- op->gprintf(op,"tag %d:\n",i);
- op->gprintf(op," sig %s\n",tag2str(p->data[i].sig));
- op->gprintf(op," type %s\n",tag2str(p->data[i].ttype));
- op->gprintf(op," offset %d\n", p->data[i].offset);
- op->gprintf(op," size %d\n", p->data[i].size);
- tr = 0;
- if (p->data[i].objp == NULL) {
- /* The object is not loaded, so load it then free it */
- if (icc_read_tag_ix(p, i, 1) == NULL)
- op->gprintf(op,"Unable to read: %d, %s\n",p->errc,p->err);
- tr = 1;
- }
- if ((ob = p->data[i].objp) != NULL) {
- /* op->gprintf(op," refcount %d\n", ob->refcount); */
- ob->dump(ob,op,verb-1);
-
- if (tr != 0) { /* Cleanup if temporary */
- icc_unread_tag_ix(p, i);
- }
- }
- op->gprintf(op,"\n");
- }
-}
-
-static void icc_delete(
- icc *p
-) {
- unsigned int i;
- icmAlloc *al = p->al;
- int del_al = p->del_al;
-
- /* Free up the header */
- if (p->header != NULL)
- (p->header->del)(p->header);
-
- /* Free up the tag data objects */
- if (p->data != NULL) {
- for (i = 0; i < p->count; i++) {
- if (p->data[i].objp != NULL) {
- if (--(p->data[i].objp->refcount) == 0) /* decrement reference count */
- (p->data[i].objp->del)(p->data[i].objp); /* Last reference */
- p->data[i].objp = NULL;
- }
- }
- /* Free tag table */
- al->free(al, p->data);
- }
-
- /* We are responsible for deleting the file object */
- if (p->del_fp && p->fp != NULL)
- p->fp->del(p->fp);
-
- /* This object */
- al->free(al, p);
-
- if (del_al) /* We are responsible for deleting allocator */
- al->del(al);
-}
-
-/* ================================================== */
-/* Lut Color normalizing and de-normalizing functions */
-
-/* As a rule, I am representing Lut in memory as values in machine form as real */
-/* numbers in the range 0.0 - 1.0. For many color spaces (ie. RGB, Gray, */
-/* hsv, hls, cmyk and other device coords), this is entirely appropriate. */
-/* For CIE based spaces though, this is not correct, since (I assume!) the binary */
-/* representation will be consistent with the encoding in Annex A, page 74 */
-/* of the standard. Note that the standard doesn't specify the encoding of */
-/* many color spaces (ie. Yuv, Yxy etc.), and is unclear about PCS. */
-
-/* The following functions convert to and from the CIE base spaces */
-/* and the real Lut input/output values. These are used to convert real color */
-/* space values into/out of the raw lut 0.0-1.0 representation (which subsequently */
-/* get converted to ICC integer values in the obvious way as a mapping to 0 .. 2^n-1). */
-
-/* This is used internally to support the Lut->lookup() function, */
-/* and can also be used by someone writing a Lut based profile to determine */
-/* the colorspace range that the input lut indexes cover, as well */
-/* as processing the output luts values into normalized form ready */
-/* for writing. */
-
-/* These functions should be accessed by calling icc.getNormFuncs() */
-
-/* - - - - - - - - - - - - - - - - */
-/* According to 6.5.5 and 6.5.6 of the spec., */
-/* XYZ index values are represented the same as their table */
-/* values, ie. as a u1.15 representation, with a value */
-/* range from 0.0 -> 1.999969482422 */
-
-/* Convert Lut index/value to XYZ coord. */
-static void Lut_Lut2XYZ(double *out, double *in) {
- out[0] = in[0] * (1.0 + 32767.0/32768); /* X */
- out[1] = in[1] * (1.0 + 32767.0/32768); /* Y */
- out[2] = in[2] * (1.0 + 32767.0/32768); /* Z */
-}
-
-/* Convert XYZ coord to Lut index/value. */
-static void Lut_XYZ2Lut(double *out, double *in) {
- out[0] = in[0] * (1.0/(1.0 + 32767.0/32768));
- out[1] = in[1] * (1.0/(1.0 + 32767.0/32768));
- out[2] = in[2] * (1.0/(1.0 + 32767.0/32768));
-}
-
-/* Convert Lut index/value to Y coord. */
-static void Lut_Lut2Y(double *out, double *in) {
- out[0] = in[0] * (1.0 + 32767.0/32768); /* Y */
-}
-
-/* Convert Y coord to Lut index/value. */
-static void Lut_Y2Lut(double *out, double *in) {
- out[0] = in[0] * (1.0/(1.0 + 32767.0/32768));
-}
-
-/* - - - - - - - - - - - - - - - - */
-/* Convert 8 bit Lab to Lut numbers */
-/* Annex A specifies 8 and 16 bit encoding, but is */
-/* silent on the Lut index normalization. */
-/* Following Michael Bourgoin's 1998 SIGGRAPH course comment on this, */
-/* we assume here that the index encoding is the same as the */
-/* value encoding. */
-
-/* Convert Lut8 table index/value to Lab */
-static void Lut_Lut2Lab_8(double *out, double *in) {
- out[0] = in[0] * 100.0; /* L */
- out[1] = (in[1] * 255.0) - 128.0; /* a */
- out[2] = (in[2] * 255.0) - 128.0; /* b */
-}
-
-/* Convert Lab to Lut8 table index/value */
-static void Lut_Lab2Lut_8(double *out, double *in) {
- out[0] = in[0] * 1.0/100.0; /* L */
- out[1] = (in[1] + 128.0) * 1.0/255.0; /* a */
- out[2] = (in[2] + 128.0) * 1.0/255.0; /* b */
-}
-
-/* Convert Lut8 table index/value to L */
-static void Lut_Lut2L_8(double *out, double *in) {
- out[0] = in[0] * 100.0; /* L */
-}
-
-/* Convert L to Lut8 table index/value */
-static void Lut_L2Lut_8(double *out, double *in) {
- out[0] = in[0] * 1.0/100.0; /* L */
-}
-
-/* - - - - - - - - - - - - - - - - */
-/* Convert 16 bit Lab to Lut numbers, V2 */
-
-/* Convert Lut16 table index/value to Lab */
-static void Lut_Lut2LabV2_16(double *out, double *in) {
- out[0] = in[0] * (100.0 * 65535.0)/65280.0; /* L */
- out[1] = (in[1] * (255.0 * 65535.0)/65280) - 128.0; /* a */
- out[2] = (in[2] * (255.0 * 65535.0)/65280) - 128.0; /* b */
-}
-
-/* Convert Lab to Lut16 table index/value */
-static void Lut_Lab2LutV2_16(double *out, double *in) {
- out[0] = in[0] * 65280.0/(100.0 * 65535.0); /* L */
- out[1] = (in[1] + 128.0) * 65280.0/(255.0 * 65535.0); /* a */
- out[2] = (in[2] + 128.0) * 65280.0/(255.0 * 65535.0); /* b */
-}
-
-/* Convert Lut16 table index/value to L */
-static void Lut_Lut2LV2_16(double *out, double *in) {
- out[0] = in[0] * (100.0 * 65535.0)/65280.0; /* L */
-}
-
-/* Convert Lab to Lut16 table index/value */
-static void Lut_L2LutV2_16(double *out, double *in) {
- out[0] = in[0] * 65280.0/(100.0 * 65535.0); /* L */
-}
-
-/* - - - - - - - - - - - - - - - - */
-/* Convert 16 bit Lab to Lut numbers, V4 */
-
-/* Convert Lut16 table index/value to Lab */
-static void Lut_Lut2LabV4_16(double *out, double *in) {
- out[0] = in[0] * 100.0; /* L */
- out[1] = (in[1] * 255.0) - 128.0; /* a */
- out[2] = (in[2] * 255.0) - 128.0; /* b */
-}
-
-/* Convert Lab to Lut16 table index/value */
-static void Lut_Lab2LutV4_16(double *out, double *in) {
- out[0] = in[0] * 1.0/100.0; /* L */
- out[1] = (in[1] + 128.0) * 1.0/255.0; /* a */
- out[2] = (in[2] + 128.0) * 1.0/255.0; /* b */
-}
-
-/* Convert Lut16 table index/value to L */
-static void Lut_Lut2LV4_16(double *out, double *in) {
- out[0] = in[0] * 100.0; /* L */
-}
-
-/* Convert L to Lut16 table index/value */
-static void Lut_L2LutV4_16(double *out, double *in) {
- out[0] = in[0] * 1.0/100.0; /* L */
-}
-
-/* - - - - - - - - - - - - - - - - */
-/* Convert Luv to Lut number */
-/* This data normalization is taken from Apples */
-/* Colorsync specification. */
-/* As per other color spaces, we assume that the index */
-/* normalization is the same as the data normalization. */
-
-/* Convert Lut table index/value to Luv */
-static void Lut_Lut2Luv(double *out, double *in) {
- out[0] = in[0] * 100.0; /* L */
- out[1] = (in[1] * 65535.0/256.0) - 128.0; /* u */
- out[2] = (in[2] * 65535.0/256.0) - 128.0; /* v */
-}
-
-/* Convert Luv to Lut table index/value */
-static void Lut_Luv2Lut(double *out, double *in) {
- out[0] = in[0] * 1.0/100.0; /* L */
- out[1] = (in[1] + 128.0) * 256.0/65535.0; /* u */
- out[2] = (in[2] + 128.0) * 256.0/65535.0; /* v */
-}
-
-/* - - - - - - - - - - - - - - - - */
-/* Default N component conversions */
-static void Lut_N(double *out, double *in, int nc) {
- for (--nc; nc >= 0; nc--)
- out[nc] = in[nc];
-}
-
-/* 1 */
-static void Lut_1(double *out, double *in) {
- out[0] = in[0];
-}
-
-/* 2 */
-static void Lut_2(double *out, double *in) {
- out[0] = in[0];
- out[1] = in[1];
-}
-
-/* 3 */
-static void Lut_3(double *out, double *in) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
-}
-
-/* 4 */
-static void Lut_4(double *out, double *in) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- out[3] = in[3];
-}
-
-/* 5 */
-static void Lut_5(double *out, double *in) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- out[3] = in[3];
- out[4] = in[4];
-}
-
-/* 6 */
-static void Lut_6(double *out, double *in) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- out[3] = in[3];
- out[4] = in[4];
- out[5] = in[5];
-}
-
-/* 7 */
-static void Lut_7(double *out, double *in) {
- Lut_N(out, in, 7);
-}
-
-/* 8 */
-static void Lut_8(double *out, double *in) {
- Lut_N(out, in, 8);
-}
-
-/* 9 */
-static void Lut_9(double *out, double *in) {
- Lut_N(out, in, 9);
-}
-
-/* 10 */
-static void Lut_10(double *out, double *in) {
- Lut_N(out, in, 10);
-}
-
-/* 11 */
-static void Lut_11(double *out, double *in) {
- Lut_N(out, in, 11);
-}
-
-/* 12 */
-static void Lut_12(double *out, double *in) {
- Lut_N(out, in, 12);
-}
-
-/* 13 */
-static void Lut_13(double *out, double *in) {
- Lut_N(out, in, 13);
-}
-
-/* 14 */
-static void Lut_14(double *out, double *in) {
- Lut_N(out, in, 14);
-}
-
-/* 15 */
-static void Lut_15(double *out, double *in) {
- Lut_N(out, in, 15);
-}
-
-/* Function table - match conversions to color spaces. */
-/* Anything not here, we don't know how to convert. */
-/* (ie. YCbCr) */
-static struct {
- icColorSpaceSignature csig;
- void (*fromLut)(double *out, double *in); /* from Lut index/entry */
- void (*toLut)(double *out, double *in); /* to Lut index/entry */
-} colnormtable[] = {
- {icSigXYZData, Lut_Lut2XYZ, Lut_XYZ2Lut },
- {icmSigYData, Lut_Lut2Y, Lut_Y2Lut },
- {icmSigLab8Data, Lut_Lut2Lab_8, Lut_Lab2Lut_8 },
- {icmSigLabV2Data, Lut_Lut2LabV2_16, Lut_Lab2LutV2_16 },
- {icmSigLabV4Data, Lut_Lut2LabV4_16, Lut_Lab2LutV4_16 },
- {icmSigL8Data, Lut_Lut2L_8, Lut_L2Lut_8 },
- {icmSigLV2Data, Lut_Lut2LV2_16, Lut_L2LutV2_16 },
- {icmSigLV4Data, Lut_Lut2LV4_16, Lut_L2LutV4_16 },
- {icSigLuvData, Lut_Lut2Luv, Lut_Luv2Lut },
- {icSigYxyData, Lut_3, Lut_3 },
- {icSigRgbData, Lut_3, Lut_3 },
- {icSigGrayData, Lut_1, Lut_1 },
- {icSigHsvData, Lut_3, Lut_3 },
- {icSigHlsData, Lut_3, Lut_3 },
- {icSigCmykData, Lut_4, Lut_4 },
- {icSigCmyData, Lut_3, Lut_3 },
- {icSigMch6Data, Lut_6, Lut_6 },
- {icSig2colorData, Lut_2, Lut_2 },
- {icSig3colorData, Lut_3, Lut_3 },
- {icSig4colorData, Lut_4, Lut_4 },
- {icSig5colorData, Lut_5, Lut_5 },
- {icSig6colorData, Lut_6, Lut_6 },
- {icSig7colorData, Lut_7, Lut_7 },
- {icSigMch5Data, Lut_5, Lut_5 },
- {icSigMch6Data, Lut_6, Lut_6 },
- {icSigMch7Data, Lut_7, Lut_7 },
- {icSigMch8Data, Lut_8, Lut_8 },
- {icSig8colorData, Lut_8, Lut_8 },
- {icSig9colorData, Lut_9, Lut_9 },
- {icSig10colorData, Lut_10, Lut_10 },
- {icSig11colorData, Lut_11, Lut_11 },
- {icSig12colorData, Lut_12, Lut_12 },
- {icSig13colorData, Lut_13, Lut_13 },
- {icSig14colorData, Lut_14, Lut_14 },
- {icSig15colorData, Lut_15, Lut_15 },
- {icMaxEnumData, NULL, NULL }
-};
-
-/*
- Legacy Lab encoding:
-
- The V4 specificatins are misleading on this, since they assume in this
- instance that all devices spaces, however labeled, have no defined
- ICC encoding. The end result is simple enough though:
-
- ICC V2 Lab encoding should be used in all PCS encodings in
- a icSigLut16Type or icSigNamedColor2Type tag, and can be used
- for Lab encoding in device spaces for these tags.
-
- ICC V4 Lab encoding should be used in all PCS encodings in
- all other situations, and can be used for Lab encoding in
- device spaces for all other situtaions.
-
- [ Since the ICC spec. doesn't cover device spaces labeled as Lab,
- these are ripe for mis-matches between different implementations.]
-
- This logic has yet to be fully implemented here.
-*/
-
-/* Find appropriate conversion functions from the normalised */
-/* Lut data range 0.0 - 1.0 to/from a given colorspace value, */
-/* given the color space and Lut type. */
-/* Return 0 on success, 1 on match failure. */
-/* NOTE: doesn't set error value, message etc.! */
-static int getNormFunc(
- icc *icp,
-// icProfileClassSignature psig, /* Profile signature to use */
- icColorSpaceSignature csig, /* Colorspace to use. */
-// int lutin, /* 0 if this is for a icSigLut16Type input, nz for output */
-// icTagSignature tagSig, /* Tag signature involved (AtoB or B2A etc.) */
- icTagTypeSignature tagType, /* icSigLut8Type or icSigLut16Type or V4 lut */
- icmNormFlag flag, /* icmFromLuti, icmFromLutv or icmToLuti, icmToLutv */
- void (**nfunc)(double *out, double *in)
-) {
- int i;
- if (tagType == icSigLut8Type && csig == icSigLabData) {
- csig = icmSigLab8Data;
- }
- if (csig == icSigLabData) {
- if (tagType == icSigLut16Type) /* Lut16 retains legacy encoding */
- csig = icmSigLabV2Data;
- else { /* Other tag types use version specific encoding */
- if (icp->ver)
- csig = icmSigLabV4Data;
- else
- csig = icmSigLabV2Data;
- }
- }
-
- for (i = 0; colnormtable[i].csig != icMaxEnumData; i++) {
- if (colnormtable[i].csig == csig)
- break; /* Found it */
- }
- if (colnormtable[i].csig == icMaxEnumData) { /* Oops */
- *nfunc = NULL;
- return 1;
- }
-
- if (flag == icmFromLuti || flag == icmFromLutv) { /* Table index/value decoding functions */
- *nfunc = colnormtable[i].fromLut;
- return 0;
- } else if (flag == icmToLuti || flag == icmToLutv) { /* Table index/value encoding functions */
- *nfunc = colnormtable[i].toLut;
- return 0;
- }
- *nfunc = NULL;
- return 1;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Colorspace ranges - used instead of norm/denorm by Mono, Matrix and */
-/* override PCS */
-
-/* Function table - match ranges to color spaces. */
-/* Anything not here, we don't know how to convert. */
-/* (ie. YCbCr) */
-/* Hmm. we're not handling Lab8 properly ?? ~~~8888 */
-static struct {
- icColorSpaceSignature csig;
- int same; /* Non zero if first entry applies to all channels */
- double min[3]; /* Minimum value for this colorspace */
- double max[3]; /* Maximum value for this colorspace */
-} colorrangetable[] = {
- {icSigXYZData, 1, { 0.0 } , { 1.0 + 32767.0/32768.0 } },
- {icmSigLab8Data, 0, { 0.0, -128.0, -128.0 }, { 100.0, 127.0, 127.0 } },
- {icmSigLabV2Data, 0, { 0.0, -128.0, -128.0 },
- { 100.0 + 25500.0/65280.0, 127.0 + 255.0/256.0, 127.0 + 255.0/256.0 } },
- {icmSigLabV4Data, 0, { 0.0, -128.0, -128.0 }, { 100.0, 127.0, 127.0 } },
- {icmSigYData, 1, { 0.0 }, { 1.0 + 32767.0/32768.0 } },
- {icmSigL8Data, 1, { 0.0 }, { 100.0 } },
- {icmSigLV2Data, 1, { 0.0 }, { 100.0 + 25500.0/65280.0 } },
- {icmSigLV4Data, 1, { 0.0 }, { 100.0 } },
- {icSigLuvData, 0, { 0.0, -128.0, -128.0 },
- { 100.0, 127.0 + 255.0/256.0, 127.0 + 255.0/256.0 } },
- {icSigYCbCrData, 1, { 0.0 }, { 1.0 } }, /* ??? */
- {icSigYxyData, 1, { 0.0 }, { 1.0 } }, /* ??? */
- {icSigRgbData, 1, { 0.0 }, { 1.0 } },
- {icSigGrayData, 1, { 0.0 }, { 1.0 } },
- {icSigHsvData, 1, { 0.0 }, { 1.0 } },
- {icSigHlsData, 1, { 0.0 }, { 1.0 } },
- {icSigCmykData, 1, { 0.0 }, { 1.0 } },
- {icSigCmyData, 1, { 0.0 }, { 1.0 } },
- {icSigMch6Data, 1, { 0.0 }, { 1.0 } },
- {icSig2colorData, 1, { 0.0 }, { 1.0 } },
- {icSig3colorData, 1, { 0.0 }, { 1.0 } },
- {icSig4colorData, 1, { 0.0 }, { 1.0 } },
- {icSig5colorData, 1, { 0.0 }, { 1.0 } },
- {icSig6colorData, 1, { 0.0 }, { 1.0 } },
- {icSig7colorData, 1, { 0.0 }, { 1.0 } },
- {icSig8colorData, 1, { 0.0 }, { 1.0 } },
- {icSigMch5Data, 1, { 0.0 }, { 1.0 } },
- {icSigMch6Data, 1, { 0.0 }, { 1.0 } },
- {icSigMch7Data, 1, { 0.0 }, { 1.0 } },
- {icSigMch8Data, 1, { 0.0 }, { 1.0 } },
- {icSig9colorData, 1, { 0.0 }, { 1.0 } },
- {icSig10colorData, 1, { 0.0 }, { 1.0 } },
- {icSig11colorData, 1, { 0.0 }, { 1.0 } },
- {icSig12colorData, 1, { 0.0 }, { 1.0 } },
- {icSig13colorData, 1, { 0.0 }, { 1.0 } },
- {icSig14colorData, 1, { 0.0 }, { 1.0 } },
- {icSig15colorData, 1, { 0.0 }, { 1.0 } },
- {icMaxEnumData, 1, { 0.0 }, { 1.0 } }
-};
-
-/* Find appropriate typical encoding ranges for a */
-/* colorspace given the color space. */
-/* Return 0 on success, 1 on match failure */
-static int getRange(
- icc *icp,
-// icProfileClassSignature psig, /* Profile signature to use */
- icColorSpaceSignature csig, /* Colorspace to use. */
-// int lutin, /* 0 if this is for a icSigLut16Type input, nz for output */
-// icTagSignature tagSig, /* Tag signature involved (AtoB or B2A etc.) */
- icTagTypeSignature tagType, /* icSigLut8Type or icSigLut16Type or V4 lut */
- double *min, double *max /* Return range values */
-) {
- int i, e, ee;
-
- if (tagType == icSigLut8Type && csig == icSigLabData) {
- csig = icmSigLab8Data;
- }
- if (csig == icSigLabData) {
- if (tagType == icSigLut16Type) /* Lut16 retains legacy encoding */
- csig = icmSigLabV2Data;
- else { /* Other tag types use version specific encoding */
- if (icp->ver)
- csig = icmSigLabV4Data;
- else
- csig = icmSigLabV2Data;
- }
- }
-
- for (i = 0; colorrangetable[i].csig != icMaxEnumData; i++) {
- if (colorrangetable[i].csig == csig)
- break; /* Found it */
- }
- if (colorrangetable[i].csig == icMaxEnumData) { /* Oops */
- return 1;
- }
- ee = number_ColorSpaceSignature(csig); /* Get number of components */
-
- if (colorrangetable[i].same) { /* All channels are the same */
- for (e = 0; e < ee; e++) {
- if (min != NULL)
- min[e] = colorrangetable[i].min[0];
- if (max != NULL)
- max[e] = colorrangetable[i].max[0];
- }
- } else {
- for (e = 0; e < ee; e++) {
- if (min != NULL)
- min[e] = colorrangetable[i].min[e];
- if (max != NULL)
- max[e] = colorrangetable[i].max[e];
- }
- }
- return 0;
-}
-
-/* ============================================= */
-/* Misc. support functions. */
-
-/* Clamp a 3 vector to be +ve */
-void icmClamp3(double out[3], double in[3]) {
- int i;
- for (i = 0; i < 3; i++)
- out[i] = in[i] < 0.0 ? 0.0 : in[i];
-}
-
-/* Add two 3 vectors */
-void icmAdd3(double out[3], double in1[3], double in2[3]) {
- out[0] = in1[0] + in2[0];
- out[1] = in1[1] + in2[1];
- out[2] = in1[2] + in2[2];
-}
-
-/* Subtract two 3 vectors, out = in1 - in2 */
-void icmSub3(double out[3], double in1[3], double in2[3]) {
- out[0] = in1[0] - in2[0];
- out[1] = in1[1] - in2[1];
- out[2] = in1[2] - in2[2];
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Set a 3x3 matrix to unity */
-void icmSetUnity3x3(double mat[3][3]) {
- int i, j;
- for (j = 0; j < 3; j++) {
- for (i = 0; i < 3; i++) {
- if (i == j)
- mat[j][i] = 1.0;
- else
- mat[j][i] = 0.0;
- }
- }
-
-}
-
-/* Copy a 3x3 transform matrix */
-void icmCpy3x3(double dst[3][3], double src[3][3]) {
- int i, j;
-
- for (j = 0; j < 3; j++) {
- for (i = 0; i < 3; i++)
- dst[j][i] = src[j][i];
- }
-}
-
-/* Scale each element of a 3x3 transform matrix */
-void icmScale3x3(double dst[3][3], double src[3][3], double scale) {
- int i, j;
-
- for (j = 0; j < 3; j++) {
- for (i = 0; i < 3; i++)
- dst[j][i] = src[j][i] * scale;
- }
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/*
-
- mat in out
-
-[ ] [] []
-[ ] * [] => []
-[ ] [] []
-
- */
-
-/* Multiply 3 array by 3x3 transform matrix */
-void icmMulBy3x3(double out[3], double mat[3][3], double in[3]) {
- double tt[3];
-
- tt[0] = mat[0][0] * in[0] + mat[0][1] * in[1] + mat[0][2] * in[2];
- tt[1] = mat[1][0] * in[0] + mat[1][1] * in[1] + mat[1][2] * in[2];
- tt[2] = mat[2][0] * in[0] + mat[2][1] * in[1] + mat[2][2] * in[2];
-
- out[0] = tt[0];
- out[1] = tt[1];
- out[2] = tt[2];
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Add one 3x3 to another */
-/* dst = src1 + src2 */
-void icmAdd3x3(double dst[3][3], double src1[3][3], double src2[3][3]) {
- int i, j;
-
- for (j = 0; j < 3; j++) {
- for (i = 0; i < 3; i++)
- dst[j][i] = src1[j][i] + src2[j][i];
- }
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Tensor product. Multiply two 3 vectors to form a 3x3 matrix */
-/* src1[] forms the colums, and src2[] forms the rows in the result */
-void icmTensMul3(double dst[3][3], double src1[3], double src2[3]) {
- int i, j;
-
- for (j = 0; j < 3; j++) {
- for (i = 0; i < 3; i++)
- dst[j][i] = src1[j] * src2[i];
- }
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Multiply one 3x3 with another */
-/* dst = src * dst */
-void icmMul3x3(double dst[3][3], double src[3][3]) {
- int i, j, k;
- double td[3][3]; /* Temporary dest */
-
- for (j = 0; j < 3; j++) {
- for (i = 0; i < 3; i++) {
- double tt = 0.0;
- for (k = 0; k < 3; k++)
- tt += src[j][k] * dst[k][i];
- td[j][i] = tt;
- }
- }
-
- /* Copy result out */
- for (j = 0; j < 3; j++)
- for (i = 0; i < 3; i++)
- dst[j][i] = td[j][i];
-}
-
-/* Multiply one 3x3 with another #2 */
-/* dst = src1 * src2 */
-void icmMul3x3_2(double dst[3][3], double src1[3][3], double src2[3][3]) {
- int i, j, k;
- double td[3][3]; /* Temporary dest */
-
- for (j = 0; j < 3; j++) {
- for (i = 0; i < 3; i++) {
- double tt = 0.0;
- for (k = 0; k < 3; k++)
- tt += src1[j][k] * src2[k][i];
- td[j][i] = tt;
- }
- }
-
- /* Copy result out */
- for (j = 0; j < 3; j++)
- for (i = 0; i < 3; i++)
- dst[j][i] = td[j][i];
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/*
- Matrix Inversion
- by Richard Carling
- from "Graphics Gems", Academic Press, 1990
-*/
-
-/*
- * adjoint( original_matrix, inverse_matrix )
- *
- * calculate the adjoint of a 3x3 matrix
- *
- * Let a denote the minor determinant of matrix A obtained by
- * ij
- *
- * deleting the ith row and jth column from A.
- *
- * i+j
- * Let b = (-1) a
- * ij ji
- *
- * The matrix B = (b ) is the adjoint of A
- * ij
- */
-
-#define det2x2(a, b, c, d) (a * d - b * c)
-
-static void adjoint(
-double out[3][3],
-double in[3][3]
-) {
- double a1, a2, a3, b1, b2, b3, c1, c2, c3;
-
- /* assign to individual variable names to aid */
- /* selecting correct values */
-
- a1 = in[0][0]; b1 = in[0][1]; c1 = in[0][2];
- a2 = in[1][0]; b2 = in[1][1]; c2 = in[1][2];
- a3 = in[2][0]; b3 = in[2][1]; c3 = in[2][2];
-
- /* row column labeling reversed since we transpose rows & columns */
-
- out[0][0] = det2x2(b2, b3, c2, c3);
- out[1][0] = - det2x2(a2, a3, c2, c3);
- out[2][0] = det2x2(a2, a3, b2, b3);
-
- out[0][1] = - det2x2(b1, b3, c1, c3);
- out[1][1] = det2x2(a1, a3, c1, c3);
- out[2][1] = - det2x2(a1, a3, b1, b3);
-
- out[0][2] = det2x2(b1, b2, c1, c2);
- out[1][2] = - det2x2(a1, a2, c1, c2);
- out[2][2] = det2x2(a1, a2, b1, b2);
-}
-
-/*
- * double = icmDet3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3 )
- *
- * calculate the determinant of a 3x3 matrix
- * in the form
- *
- * | a1, b1, c1 |
- * | a2, b2, c2 |
- * | a3, b3, c3 |
- */
-
-double icmDet3x3(double in[3][3]) {
- double a1, a2, a3, b1, b2, b3, c1, c2, c3;
- double ans;
-
- a1 = in[0][0]; b1 = in[0][1]; c1 = in[0][2];
- a2 = in[1][0]; b2 = in[1][1]; c2 = in[1][2];
- a3 = in[2][0]; b3 = in[2][1]; c3 = in[2][2];
-
- ans = a1 * det2x2(b2, b3, c2, c3)
- - b1 * det2x2(a2, a3, c2, c3)
- + c1 * det2x2(a2, a3, b2, b3);
- return ans;
-}
-
-#define ICM_SMALL_NUMBER 1.e-8
-/*
- * inverse( original_matrix, inverse_matrix )
- *
- * calculate the inverse of a 4x4 matrix
- *
- * -1
- * A = ___1__ adjoint A
- * det A
- */
-
-/* Return non-zero if not invertable */
-int icmInverse3x3(
-double out[3][3],
-double in[3][3]
-) {
- int i, j;
- double det;
-
- /* calculate the 3x3 determinant
- * if the determinant is zero,
- * then the inverse matrix is not unique.
- */
- det = icmDet3x3(in);
-
- if ( fabs(det) < ICM_SMALL_NUMBER)
- return 1;
-
- /* calculate the adjoint matrix */
- adjoint(out, in);
-
- /* scale the adjoint matrix to get the inverse */
- for (i = 0; i < 3; i++)
- for(j = 0; j < 3; j++)
- out[i][j] /= det;
- return 0;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Transpose a 3x3 matrix */
-void icmTranspose3x3(double out[3][3], double in[3][3]) {
- int i, j;
- if (out != in) {
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++)
- out[i][j] = in[j][i];
- } else {
- double tt[3][3];
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++)
- tt[i][j] = in[j][i];
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++)
- out[i][j] = tt[i][j];
- }
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Compute the dot product of two 3 vectors */
-double icmDot3(double in1[3], double in2[3]) {
- return in1[0] * in2[0] + in1[1] * in2[1] + in1[2] * in2[2];
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Compute the cross product of two 3D vectors, out = in1 x in2 */
-void icmCross3(double out[3], double in1[3], double in2[3]) {
- double tt[3];
- tt[0] = (in1[1] * in2[2]) - (in1[2] * in2[1]);
- tt[1] = (in1[2] * in2[0]) - (in1[0] * in2[2]);
- tt[2] = (in1[0] * in2[1]) - (in1[1] * in2[0]);
- out[0] = tt[0];
- out[1] = tt[1];
- out[2] = tt[2];
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Compute the norm (length) squared of a 3 vector */
-double icmNorm3sq(double in[3]) {
- return in[0] * in[0] + in[1] * in[1] + in[2] * in[2];
-}
-
-/* Compute the norm (length) of a 3 vector */
-double icmNorm3(double in[3]) {
- return sqrt(in[0] * in[0] + in[1] * in[1] + in[2] * in[2]);
-}
-
-/* Scale a 3 vector by the given ratio */
-void icmScale3(double out[3], double in[3], double rat) {
- out[0] = in[0] * rat;
- out[1] = in[1] * rat;
- out[2] = in[2] * rat;
-}
-
-/* Compute a blend between in0 and in1 */
-void icmBlend3(double out[3], double in0[3], double in1[3], double bf) {
- out[0] = (1.0 - bf) * in0[0] + bf * in1[0];
- out[1] = (1.0 - bf) * in0[1] + bf * in1[1];
- out[2] = (1.0 - bf) * in0[2] + bf * in1[2];
-}
-
-/* Normalise a 3 vector to the given length. Return nz if not normalisable */
-int icmNormalize3(double out[3], double in[3], double len) {
- double tt = sqrt(in[0] * in[0] + in[1] * in[1] + in[2] * in[2]);
-
- if (tt < ICM_SMALL_NUMBER)
- return 1;
- tt = len/tt;
- out[0] = in[0] * tt;
- out[1] = in[1] * tt;
- out[2] = in[2] * tt;
- return 0;
-}
-
-/* Compute the norm (length) squared of a vector define by two points */
-double icmNorm33sq(double in1[3], double in0[3]) {
- int j;
- double rv;
- for (rv = 0.0, j = 0; j < 3; j++) {
- double tt = in1[j] - in0[j];
- rv += tt * tt;
- }
- return rv;
-}
-
-/* Compute the norm (length) of a vector define by two points */
-double icmNorm33(double in1[3], double in0[3]) {
- int j;
- double rv;
- for (rv = 0.0, j = 0; j < 3; j++) {
- double tt = in1[j] - in0[j];
- rv += tt * tt;
- }
- return sqrt(rv);
-}
-
-/* Scale a two point vector by the given ratio. in0[] is the origin */
-void icmScale33(double out[3], double in1[3], double in0[3], double rat) {
- out[0] = in0[0] + (in1[0] - in0[0]) * rat;
- out[1] = in0[1] + (in1[1] - in0[1]) * rat;
- out[2] = in0[2] + (in1[2] - in0[2]) * rat;
-}
-
-/* Normalise a two point vector to the given length. */
-/* The new location of in1[] is returned in out[]. */
-/* Return nz if not normalisable */
-int icmNormalize33(double out[3], double in1[3], double in0[3], double len) {
- int j;
- double vl;
-
- for (vl = 0.0, j = 0; j < 3; j++) {
- double tt = in1[j] - in0[j];
- vl += tt * tt;
- }
- vl = sqrt(vl);
- if (vl < ICM_SMALL_NUMBER)
- return 1;
-
- vl = len/vl;
- for (j = 0; j < 3; j++) {
- out[j] = in0[j] + (in1[j] - in0[j]) * vl;
- }
- return 0;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Given two 3D points, create a matrix that rotates */
-/* and scales one onto the other about the origin 0,0,0. */
-/* The maths is from page 52 of Tomas Moller and Eric Haines "Real-Time Rendering". */
-/* s is source vector, t is target vector. */
-/* Usage of icmRotMat: */
-/* t[0] == mat[0][0] * s[0] + mat[0][1] * s[1] + mat[0][2] * s[2]; */
-/* t[1] == mat[1][0] * s[0] + mat[1][1] * s[1] + mat[1][2] * s[2]; */
-/* t[2] == mat[2][0] * s[0] + mat[2][1] * s[1] + mat[2][2] * s[2]; */
-/* i.e. use icmMulBy3x3 */
-void icmRotMat(double m[3][3], double s[3], double t[3]) {
- double sl, tl, sn[3], tn[3];
- double v[3]; /* Cross product */
- double e; /* Dot product */
- double h; /* 1-e/Cross product dot squared */
-
- /* Normalise input vectors */
- /* The rotation will be about 0,0,0 */
- sl = sqrt(s[0] * s[0] + s[1] * s[1] + s[2] * s[2]);
- tl = sqrt(t[0] * t[0] + t[1] * t[1] + t[2] * t[2]);
-
- if (sl < 1e-12 || tl < 1e-12) { /* Hmm. Do nothing */
- m[0][0] = 1.0;
- m[0][1] = 0.0;
- m[0][2] = 0.0;
- m[1][0] = 0.0;
- m[1][1] = 1.0;
- m[1][2] = 0.0;
- m[2][0] = 0.0;
- m[2][1] = 0.0;
- m[2][2] = 1.0;
- return;
- }
-
- sn[0] = s[0]/sl; sn[1] = s[1]/sl; sn[2] = s[2]/sl;
- tn[0] = t[0]/tl; tn[1] = t[1]/tl; tn[2] = t[2]/tl;
-
- /* Compute the cross product */
- v[0] = (sn[1] * tn[2]) - (sn[2] * tn[1]);
- v[1] = (sn[2] * tn[0]) - (sn[0] * tn[2]);
- v[2] = (sn[0] * tn[1]) - (sn[1] * tn[0]);
-
- /* Compute the dot product */
- e = sn[0] * tn[0] + sn[1] * tn[1] + sn[2] * tn[2];
-
- /* Cross product dot squared */
- h = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
-
- /* If the two input vectors are close to being parallel, */
- /* then h will be close to zero. */
- if (fabs(h) < 1e-12) {
- m[0][0] = tl/sl;
- m[0][1] = 0.0;
- m[0][2] = 0.0;
- m[1][0] = 0.0;
- m[1][1] = tl/sl;
- m[1][2] = 0.0;
- m[2][0] = 0.0;
- m[2][1] = 0.0;
- m[2][2] = tl/sl;
- } else {
- /* 1-e/Cross product dot squared */
- h = (1.0 - e) / h;
-
- m[0][0] = tl/sl * (e + h * v[0] * v[0]);
- m[0][1] = tl/sl * (h * v[0] * v[1] - v[2]);
- m[0][2] = tl/sl * (h * v[0] * v[2] + v[1]);
- m[1][0] = tl/sl * (h * v[0] * v[1] + v[2]);
- m[1][1] = tl/sl * (e + h * v[1] * v[1]);
- m[1][2] = tl/sl * (h * v[1] * v[2] - v[0]);
- m[2][0] = tl/sl * (h * v[0] * v[2] - v[1]);
- m[2][1] = tl/sl * (h * v[1] * v[2] + v[0]);
- m[2][2] = tl/sl * (e + h * v[2] * v[2]);
- }
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Multiply 2 array by 2x2 transform matrix */
-void icmMulBy2x2(double out[2], double mat[2][2], double in[2]) {
- double tt[2];
-
- tt[0] = mat[0][0] * in[0] + mat[0][1] * in[1];
- tt[1] = mat[1][0] * in[0] + mat[1][1] * in[1];
-
- out[0] = tt[0];
- out[1] = tt[1];
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Copy a 3x4 transform matrix */
-void icmCpy3x4(double dst[3][4], double src[3][4]) {
- int i, j;
-
- for (j = 0; j < 3; j++) {
- for (i = 0; i < 4; i++)
- dst[j][i] = src[j][i];
- }
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Multiply 3 array by 3x4 transform matrix */
-void icmMul3By3x4(double out[3], double mat[3][4], double in[3]) {
- double tt[3];
-
- tt[0] = mat[0][0] * in[0] + mat[0][1] * in[1] + mat[0][2] * in[2] + mat[0][3];
- tt[1] = mat[1][0] * in[0] + mat[1][1] * in[1] + mat[1][2] * in[2] + mat[1][3];
- tt[2] = mat[2][0] * in[0] + mat[2][1] * in[1] + mat[2][2] * in[2] + mat[2][3];
-
- out[0] = tt[0];
- out[1] = tt[1];
- out[2] = tt[2];
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Given two 3D vectors, create a matrix that translates, */
-/* rotates and scales one onto the other. */
-/* The maths is from page 52 of Tomas Moller and Eric Haines */
-/* "Real-Time Rendering". */
-/* s0 -> s1 is source vector, t0 -> t1 is target vector. */
-/* Usage of icmRotMat: */
-/* t[0] == mat[0][0] * s[0] + mat[0][1] * s[1] + mat[0][2] * s[2] + mat[0][3]; */
-/* t[1] == mat[1][0] * s[0] + mat[1][1] * s[1] + mat[1][2] * s[2] + mat[1][3]; */
-/* t[2] == mat[2][0] * s[0] + mat[2][1] * s[1] + mat[2][2] * s[2] + mat[2][3]; */
-/* i.e. use icmMul3By3x4 */
-void icmVecRotMat(double m[3][4], double s1[3], double s0[3], double t1[3], double t0[3]) {
- int i, j;
- double ss[3], tt[3], rr[3][3];
-
- /* Create the rotation matrix: */
- for (i = 0; i < 3; i++) {
- ss[i] = s1[i] - s0[i];
- tt[i] = t1[i] - t0[i];
- }
- icmRotMat(rr, ss, tt);
-
- /* Create rotated version of s0: */
- icmMulBy3x3(ss, rr, s0);
-
- /* Create 4x4 matrix */
- for (j = 0; j < 3; j++) {
- for (i = 0; i < 4; i++) {
- if (i < 3 && j < 3)
- m[j][i] = rr[j][i];
- else if (i == 3 && j < 3)
- m[j][i] = t0[j] - ss[j];
- else if (i == j)
- m[j][i] = 1.0;
- else
- m[j][i] = 0.0;
- }
- }
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Compute the 3D intersection of a vector and a plane */
-/* return nz if there is no intersection */
-int icmVecPlaneIsect(
-double isect[3], /* return intersection point */
-double pl_const, /* Plane equation constant */
-double pl_norm[3], /* Plane normal vector */
-double ve_1[3], /* Point on line */
-double ve_0[3] /* Second point on line */
-) {
- double den; /* denominator */
- double rv; /* Vector parameter value */
- double vvec[3]; /* Vector vector */
- double ival[3]; /* Intersection value */
-
- /* Compute vector between the two points */
- vvec[0] = ve_1[0] - ve_0[0];
- vvec[1] = ve_1[1] - ve_0[1];
- vvec[2] = ve_1[2] - ve_0[2];
-
- /* Compute the denominator */
- den = pl_norm[0] * vvec[0] + pl_norm[1] * vvec[1] + pl_norm[2] * vvec[2];
-
- /* Too small to intersect ? */
- if (fabs(den) < 1e-12) {
- return 1;
- }
-
- /* Compute the parameterized intersction point */
- rv = -(pl_norm[0] * ve_0[0] + pl_norm[1] * ve_0[1] + pl_norm[2] * ve_0[2] + pl_const)/den;
-
- /* Compute the actual intersection point */
- isect[0] = ve_0[0] + rv * vvec[0];
- isect[1] = ve_0[1] + rv * vvec[1];
- isect[2] = ve_0[2] + rv * vvec[2];
-
- return 0;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Compute the closest points between two lines a and b. */
-/* Return closest points and parameter values if not NULL. */
-/* Return nz if they are paralel. */
-/* The maths is from page 338 of Tomas Moller and Eric Haines "Real-Time Rendering". */
-int icmLineLineClosest(double ca[3], double cb[3], double *pa, double * pb,
- double la0[3], double la1[3], double lb0[3], double lb1[3]) {
- double va[3], vb[3];
- double vvab[3], vvabns; /* Cross product of va and vb and its norm squared */
- double vba0[3]; /* lb0 - la0 */
- double tt[3];
- double a, b; /* Parameter values */
-
- icmSub3(va, la1, la0);
- icmSub3(vb, lb1, lb0);
- icmCross3(vvab, va, vb);
- vvabns = icmNorm3sq(vvab);
-
- if (vvabns < 1e-12)
- return 1;
-
- icmSub3(vba0, lb0, la0);
- icmCross3(tt, vba0, vb);
- a = icmDot3(tt, vvab) / vvabns;
-
- icmCross3(tt, vba0, va);
- b = icmDot3(tt, vvab) / vvabns;
-
- if (pa != NULL)
- *pa = a;
-
- if (pb != NULL)
- *pb = b;
-
- if (ca != NULL) {
- ca[0] = la0[0] + a * va[0];
- ca[1] = la0[1] + a * va[1];
- ca[2] = la0[2] + a * va[2];
- }
-
- if (cb != NULL) {
- cb[0] = lb0[0] + b * vb[0];
- cb[1] = lb0[1] + b * vb[1];
- cb[2] = lb0[2] + b * vb[2];
- }
-
-#ifdef NEVER /* Verify */
- {
- double vab[3]; /* Vector from ca to cb */
-
- vab[0] = lb0[0] + b * vb[0] - la0[0] - a * va[0];
- vab[1] = lb0[1] + b * vb[1] - la0[1] - a * va[1];
- vab[2] = lb0[2] + b * vb[2] - la0[2] - a * va[2];
-
- if (icmDot3(va, vab) > 1e-6
- || icmDot3(vb, vab) > 1e-6)
- warning("icmLineLineClosest verify failed\n");
- }
-#endif
-
- return 0;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Given 3 3D points, compute a plane equation. */
-/* The normal will be right handed given the order of the points */
-/* The plane equation will be the 3 normal components and the constant. */
-/* Return nz if any points are cooincident or co-linear */
-int icmPlaneEqn3(double eq[4], double p0[3], double p1[3], double p2[3]) {
- double ll, v1[3], v2[3];
-
- /* Compute vectors along edges */
- v2[0] = p1[0] - p0[0];
- v2[1] = p1[1] - p0[1];
- v2[2] = p1[2] - p0[2];
-
- v1[0] = p2[0] - p0[0];
- v1[1] = p2[1] - p0[1];
- v1[2] = p2[2] - p0[2];
-
- /* Compute cross products v1 x v2, which will be the normal */
- eq[0] = v1[1] * v2[2] - v1[2] * v2[1];
- eq[1] = v1[2] * v2[0] - v1[0] * v2[2];
- eq[2] = v1[0] * v2[1] - v1[1] * v2[0];
-
- /* Normalise the equation */
- ll = sqrt(eq[0] * eq[0] + eq[1] * eq[1] + eq[2] * eq[2]);
- if (ll < 1e-10) {
- return 1;
- }
- eq[0] /= ll;
- eq[1] /= ll;
- eq[2] /= ll;
-
- /* Compute the plane equation constant */
- eq[3] = - (eq[0] * p0[0])
- - (eq[1] * p0[1])
- - (eq[2] * p0[2]);
-
- return 0;
-}
-
-/* Given a 3D point and a plane equation, return the signed */
-/* distance from the plane */
-double icmPlaneDist3(double eq[4], double p[3]) {
- double rv;
-
- rv = eq[0] * p[0]
- + eq[1] * p[1]
- + eq[2] * p[2]
- + eq[3];
-
- return rv;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* CIE Y (range 0 .. 1) to perceptual CIE 1976 L* (range 0 .. 100) */
-double
-icmY2L(double val) {
- if (val > 0.008856451586)
- val = pow(val,1.0/3.0);
- else
- val = 7.787036979 * val + 16.0/116.0;
-
- val = (116.0 * val - 16.0);
- return val;
-}
-
-/* Perceptual CIE 1976 L* (range 0 .. 100) to CIE Y (range 0 .. 1) */
-double
-icmL2Y(double val) {
- val = (val + 16.0)/116.0;
-
- if (val > 24.0/116.0)
- val = pow(val,3.0);
- else
- val = (val - 16.0/116.0)/7.787036979;
- return val;
-}
-
-/* CIE XYZ to perceptual CIE 1976 L*a*b* */
-void
-icmXYZ2Lab(icmXYZNumber *w, double *out, double *in) {
- double X = in[0], Y = in[1], Z = in[2];
- double x,y,z,fx,fy,fz;
-
- x = X/w->X;
- y = Y/w->Y;
- z = Z/w->Z;
-
- if (x > 0.008856451586)
- fx = pow(x,1.0/3.0);
- else
- fx = 7.787036979 * x + 16.0/116.0;
-
- if (y > 0.008856451586)
- fy = pow(y,1.0/3.0);
- else
- fy = 7.787036979 * y + 16.0/116.0;
-
- if (z > 0.008856451586)
- fz = pow(z,1.0/3.0);
- else
- fz = 7.787036979 * z + 16.0/116.0;
-
- out[0] = 116.0 * fy - 16.0;
- out[1] = 500.0 * (fx - fy);
- out[2] = 200.0 * (fy - fz);
-}
-
-/* Perceptual CIE 1976 L*a*b* to CIE XYZ */
-void
-icmLab2XYZ(icmXYZNumber *w, double *out, double *in) {
- double L = in[0], a = in[1], b = in[2];
- double x,y,z,fx,fy,fz;
-
- fy = (L + 16.0)/116.0;
- fx = a/500.0 + fy;
- fz = fy - b/200.0;
-
- if (fy > 24.0/116.0)
- y = pow(fy,3.0);
- else
- y = (fy - 16.0/116.0)/7.787036979;
-
- if (fx > 24.0/116.0)
- x = pow(fx,3.0);
- else
- x = (fx - 16.0/116.0)/7.787036979;
-
- if (fz > 24.0/116.0)
- z = pow(fz,3.0);
- else
- z = (fz - 16.0/116.0)/7.787036979;
-
- out[0] = x * w->X;
- out[1] = y * w->Y;
- out[2] = z * w->Z;
-}
-
-
-/* LCh to Lab */
-void icmLCh2Lab(double *out, double *in) {
- double C, h;
-
- C = in[1];
- h = 3.14159265359/180.0 * in[2];
-
- out[0] = in[0];
- out[1] = C * cos(h);
- out[2] = C * sin(h);
-}
-
-/* Lab to LCh */
-void icmLab2LCh(double *out, double *in) {
- double C, h;
-
- C = sqrt(in[1] * in[1] + in[2] * in[2]);
-
- h = (180.0/3.14159265359) * atan2(in[2], in[1]);
- h = (h < 0.0) ? h + 360.0 : h;
-
- out[0] = in[0];
- out[1] = C;
- out[2] = h;
-}
-
-/* XYZ to Yxy */
-extern ICCLIB_API void icmXYZ2Yxy(double *out, double *in) {
- double sum = in[0] + in[1] + in[2];
- double Y, x, y;
-
- if (sum < 1e-9) {
- Y = 0.0;
- y = 0.333333333;
- x = 0.333333333;
- } else {
- Y = in[1];
- x = in[0]/sum;
- y = in[1]/sum;
- }
- out[0] = Y;
- out[1] = x;
- out[2] = y;
-}
-
-/* Yxy to XYZ */
-extern ICCLIB_API void icmYxy2XYZ(double *out, double *in) {
- double Y = in[0];
- double x = in[1];
- double y = in[2];
- double z = 1.0 - x - y;
- double sum;
- if (y < 1e-9) {
- out[0] = out[1] = out[2] = 0.0;
- } else {
- sum = Y/y;
- out[0] = x * sum;
- out[1] = Y;
- out[2] = z * sum;
- }
-}
-
-
-/* CIE XYZ to perceptual CIE 1976 L*u*v* */
-extern ICCLIB_API void icmXYZ2Luv(icmXYZNumber *w, double *out, double *in) {
- double X = in[0], Y = in[1], Z = in[2];
- double un, vn, u, v, fl, fu, fv;
-
- un = (4.0 * w->X) / (w->X + 15.0 * w->Y + 3.0 * w->Z);
- vn = (9.0 * w->Y) / (w->X + 15.0 * w->Y + 3.0 * w->Z);
- u = (4.0 * X) / (X + 15.0 * Y + 3.0 * Z);
- v = (9.0 * Y) / (X + 15.0 * Y + 3.0 * Z);
-
- Y /= w->Y;
-
- if (Y > 0.008856451586)
- fl = pow(Y,1.0/3.0);
- else
- fl = 7.787036979 * Y + 16.0/116.0;
-
- fu = u - un;
- fv = v - vn;
-
- out[0] = 116.0 * fl - 16.0;
- out[1] = 13.0 * out[0] * fu;
- out[2] = 13.0 * out[0] * fv;
-}
-
-/* Perceptual CIE 1976 L*u*v* to CIE XYZ */
-extern ICCLIB_API void icmLuv2XYZ(icmXYZNumber *w, double *out, double *in) {
- double un, vn, u, v, fl, fu, fv, sum, X, Y, Z;
-
- fl = (in[0] + 16.0)/116.0;
- fu = in[1] / (13.0 * in[0]);
- fv = in[2] / (13.0 * in[0]);
-
- un = (4.0 * w->X) / (w->X + 15.0 * w->Y + 3.0 * w->Z);
- vn = (9.0 * w->Y) / (w->X + 15.0 * w->Y + 3.0 * w->Z);
-
- u = fu + un;
- v = fv + vn;
-
- if (fl > 24.0/116.0)
- Y = pow(fl,3.0);
- else
- Y = (fl - 16.0/116.0)/7.787036979;
- Y *= w->Y;
-
- sum = (9.0 * Y)/v;
- X = (u * sum)/4.0;
- Z = (sum - X - 15.0 * Y)/3.0;
-
- out[0] = X;
- out[1] = Y;
- out[2] = Z;
-}
-
-/* NOTE :- none of the following seven have been protected */
-/* against arithmmetic issues (ie. for black) */
-
-/* CIE XYZ to perceptual CIE 1976 UCS diagram Yu'v'*/
-/* (Yu'v' is a better chromaticity space than Yxy) */
-extern ICCLIB_API void icmXYZ21976UCS(double *out, double *in) {
- double X = in[0], Y = in[1], Z = in[2];
- double den, u, v;
-
- den = (X + 15.0 * Y + 3.0 * Z);
- u = (4.0 * X) / den;
- v = (9.0 * Y) / den;
-
- out[0] = Y;
- out[1] = u;
- out[2] = v;
-}
-
-/* Perceptual CIE 1976 UCS diagram Yu'v' to CIE XYZ */
-extern ICCLIB_API void icm1976UCS2XYZ(double *out, double *in) {
- double u, v, fl, fu, fv, sum, X, Y, Z;
-
- Y = in[0];
- u = in[1];
- v = in[2];
-
- X = ((9.0 * u * Y)/(4.0 * v));
- Z = -(((20.0 * v + 3.0 * u - 12.0) * Y)/(4.0 * v));
-
- out[0] = X;
- out[1] = Y;
- out[2] = Z;
-}
-
-/* CIE XYZ to perceptual CIE 1960 UCS */
-/* (This was obsoleted by the 1976UCS, but is still used */
-/* in computing color temperatures.) */
-extern ICCLIB_API void icmXYZ21960UCS(double *out, double *in) {
- double X = in[0], Y = in[1], Z = in[2];
- double u, v;
-
- u = (4.0 * X) / (X + 15.0 * Y + 3.0 * Z);
- v = (6.0 * Y) / (X + 15.0 * Y + 3.0 * Z);
-
- out[0] = Y;
- out[1] = u;
- out[2] = v;
-}
-
-/* Perceptual CIE 1960 UCS to CIE XYZ */
-extern ICCLIB_API void icm1960UCS2XYZ(double *out, double *in) {
- double u, v, fl, fu, fv, sum, X, Y, Z;
-
- Y = in[0];
- u = in[1];
- v = in[2];
-
- X = ((3.0 * u * Y)/(2.0 * v));
- Z = -(((10.0 * v + u - 4.0) * Y)/(2.0 * v));
-
- out[0] = X;
- out[1] = Y;
- out[2] = Z;
-}
-
-/* CIE XYZ to perceptual CIE 1964 WUV (U*V*W*) */
-/* (This is obsolete but still used in computing CRI) */
-extern ICCLIB_API void icmXYZ21964WUV(icmXYZNumber *w, double *out, double *in) {
- double W, U, V;
- double wucs[3];
- double iucs[3];
-
- icmXYZ2Ary(wucs, *w);
- icmXYZ21960UCS(wucs, wucs);
- icmXYZ21960UCS(iucs, in);
-
- W = 25.0 * pow(iucs[0] * 100.0/wucs[0], 1.0/3.0) - 17.0;
- U = 13.0 * W * (iucs[1] - wucs[1]);
- V = 13.0 * W * (iucs[2] - wucs[2]);
-
- out[0] = W;
- out[1] = U;
- out[2] = V;
-}
-
-/* Perceptual CIE 1964 WUV (U*V*W*) to CIE XYZ */
-extern ICCLIB_API void icm1964WUV2XYZ(icmXYZNumber *w, double *out, double *in) {
- double W, U, V;
- double wucs[3];
- double iucs[3];
-
- icmXYZ2Ary(wucs, *w);
- icmXYZ21960UCS(wucs, wucs);
-
- W = in[0];
- U = in[1];
- V = in[2];
-
- iucs[0] = pow((W + 17.0)/25.0, 3.0) * wucs[0]/100.0;
- iucs[1] = U / (13.0 * W) + wucs[1];
- iucs[2] = V / (13.0 * W) + wucs[2];
-
- icm1960UCS2XYZ(out, iucs);
-}
-
-/* CIE CIE1960 UCS to perceptual CIE 1964 WUV (U*V*W*) */
-extern ICCLIB_API void icm1960UCS21964WUV(icmXYZNumber *w, double *out, double *in) {
- double W, U, V;
- double wucs[3];
-
- icmXYZ2Ary(wucs, *w);
- icmXYZ21960UCS(wucs, wucs);
-
- W = 25.0 * pow(in[0] * 100.0/wucs[0], 1.0/3.0) - 17.0;
- U = 13.0 * W * (in[1] - wucs[1]);
- V = 13.0 * W * (in[2] - wucs[2]);
-
- out[0] = W;
- out[1] = U;
- out[2] = V;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* available D50 Illuminant */
-icmXYZNumber icmD50 = { /* Profile illuminant - D50 */
- 0.9642, 1.0000, 0.8249
-};
-
-icmXYZNumber icmD50_100 = { /* Profile illuminant - D50, scaled to 100 */
- 96.42, 100.00, 82.49
-};
-
-double icmD50_ary3[3] = { /* Profile illuminant - D50 */
- 0.9642, 1.0000, 0.8249
-};
-
-double icmD50_100_ary3[3] = { /* Profile illuminant - D50, scaled to 100 */
- 96.42, 100.00, 82.49
-};
-
-/* available D65 Illuminant */
-icmXYZNumber icmD65 = { /* Profile illuminant - D65 */
- 0.9505, 1.0000, 1.0890
-};
-
-icmXYZNumber icmD65_100 = { /* Profile illuminant - D65, scaled to 100 */
- 95.05, 100.00, 108.90
-};
-
-double icmD65_ary3[3] = { /* Profile illuminant - D65 */
- 0.9505, 1.0000, 1.0890
-};
-
-double icmD65_100_ary3[3] = { /* Profile illuminant - D65, scaled to 100 */
- 95.05, 100.00, 108.90
-};
-
-/* Default black point */
-icmXYZNumber icmBlack = {
- 0.0000, 0.0000, 0.0000
-};
-
-/* Return the normal Delta E given two Lab values */
-double icmLabDE(double *Lab0, double *Lab1) {
- double rv = 0.0, tt;
-
- tt = Lab0[0] - Lab1[0];
- rv += tt * tt;
- tt = Lab0[1] - Lab1[1];
- rv += tt * tt;
- tt = Lab0[2] - Lab1[2];
- rv += tt * tt;
-
- return sqrt(rv);
-}
-
-/* Return the normal Delta E squared, given two Lab values */
-double icmLabDEsq(double *Lab0, double *Lab1) {
- double rv = 0.0, tt;
-
- tt = Lab0[0] - Lab1[0];
- rv += tt * tt;
- tt = Lab0[1] - Lab1[1];
- rv += tt * tt;
- tt = Lab0[2] - Lab1[2];
- rv += tt * tt;
-
- return rv;
-}
-
-/* Return the normal Delta E given two XYZ values */
-extern ICCLIB_API double icmXYZLabDE(icmXYZNumber *w, double *in0, double *in1) {
- double lab0[3], lab1[3], rv;
-
- icmXYZ2Lab(w, lab0, in0);
- icmXYZ2Lab(w, lab1, in1);
- rv = icmLabDE(lab0, lab1);
- return rv;
-}
-
-/* (Note that CIE94 can give odd results for very large delta E's, */
-/* when one of the two points is near the neutral axis: */
-/* ie DE(A,B + del) != DE(A,B) + DE(del) */
-#ifdef NEVER
-{
- double w1[3] = { 99.996101, -0.058417, -0.010557 };
- double c1[3] = { 60.267956, 98.845863, -61.163277 };
- double w2[3] = { 100.014977, -0.138339, 0.089744 };
- double c2[3] = { 60.294464, 98.117104, -60.843159 };
-
- printf("DE 1 = %f, 2 = %f\n", icmLabDE(c1, w1), icmLabDE(c2, w2));
- printf("DE94 1 = %f, 2 = %f\n", icmCIE94(c1, w1), icmCIE94(c2, w2));
-}
-#endif
-
-
-/* Return the CIE94 Delta E color difference measure, squared */
-double icmCIE94sq(double Lab0[3], double Lab1[3]) {
- double desq, dhsq;
- double dlsq, dcsq;
- double c12;
-
- {
- double dl, da, db;
- dl = Lab0[0] - Lab1[0];
- dlsq = dl * dl; /* dl squared */
- da = Lab0[1] - Lab1[1];
- db = Lab0[2] - Lab1[2];
-
- /* Compute normal Lab delta E squared */
- desq = dlsq + da * da + db * db;
- }
-
- {
- double c1, c2, dc;
-
- /* Compute chromanance for the two colors */
- c1 = sqrt(Lab0[1] * Lab0[1] + Lab0[2] * Lab0[2]);
- c2 = sqrt(Lab1[1] * Lab1[1] + Lab1[2] * Lab1[2]);
- c12 = sqrt(c1 * c2); /* Symetric chromanance */
-
- /* delta chromanance squared */
- dc = c2 - c1;
- dcsq = dc * dc;
- }
-
- /* Compute delta hue squared */
- if ((dhsq = desq - dlsq - dcsq) < 0.0)
- dhsq = 0.0;
- {
- double sc, sh;
-
- /* Weighting factors for delta chromanance & delta hue */
- sc = 1.0 + 0.048 * c12;
- sh = 1.0 + 0.014 * c12;
- return dlsq + dcsq/(sc * sc) + dhsq/(sh * sh);
- }
-}
-
-/* Return the CIE94 Delta E color difference measure */
-double icmCIE94(double Lab0[3], double Lab1[3]) {
- return sqrt(icmCIE94sq(Lab0, Lab1));
-}
-
-/* Return the CIE94 Delta E color difference measure for two XYZ values */
-extern ICCLIB_API double icmXYZCIE94(icmXYZNumber *w, double *in0, double *in1) {
- double lab0[3], lab1[3];
-
- icmXYZ2Lab(w, lab0, in0);
- icmXYZ2Lab(w, lab1, in1);
- return sqrt(icmCIE94sq(lab0, lab1));
-}
-
-
-/* From the paper "The CIEDE2000 Color-Difference Formula: Implementation Notes, */
-/* Supplementary Test Data, and Mathematical Observations", by */
-/* Gaurav Sharma, Wencheng Wu and Edul N. Dalal, */
-/* Color Res. Appl., vol. 30, no. 1, pp. 21-30, Feb. 2005. */
-
-/* Return the CIEDE2000 Delta E color difference measure squared, for two Lab values */
-double icmCIE2Ksq(double *Lab0, double *Lab1) {
- double C1, C2;
- double h1, h2;
- double dL, dC, dH;
- double dsq;
-
- /* The trucated value of PI is needed to ensure that the */
- /* test cases pass, as one of them lies on the edge of */
- /* a mathematical discontinuity. The precision is still */
- /* enough for any practical use. */
-#define RAD2DEG(xx) (180.0/3.14159265358979 * (xx))
-#define DEG2RAD(xx) (3.14159265358979/180.0 * (xx))
-
- /* Compute Cromanance and Hue angles */
- {
- double C1ab, C2ab;
- double Cab, Cab7, G;
- double a1, a2;
-
- C1ab = sqrt(Lab0[1] * Lab0[1] + Lab0[2] * Lab0[2]);
- C2ab = sqrt(Lab1[1] * Lab1[1] + Lab1[2] * Lab1[2]);
- Cab = 0.5 * (C1ab + C2ab);
- Cab7 = pow(Cab,7.0);
- G = 0.5 * (1.0 - sqrt(Cab7/(Cab7 + 6103515625.0)));
- a1 = (1.0 + G) * Lab0[1];
- a2 = (1.0 + G) * Lab1[1];
- C1 = sqrt(a1 * a1 + Lab0[2] * Lab0[2]);
- C2 = sqrt(a2 * a2 + Lab1[2] * Lab1[2]);
-
- if (C1 < 1e-9)
- h1 = 0.0;
- else {
- h1 = RAD2DEG(atan2(Lab0[2], a1));
- if (h1 < 0.0)
- h1 += 360.0;
- }
-
- if (C2 < 1e-9)
- h2 = 0.0;
- else {
- h2 = RAD2DEG(atan2(Lab1[2], a2));
- if (h2 < 0.0)
- h2 += 360.0;
- }
- }
-
- /* Compute delta L, C and H */
- {
- double dh;
-
- dL = Lab1[0] - Lab0[0];
- dC = C2 - C1;
- if (C1 < 1e-9 || C2 < 1e-9) {
- dh = 0.0;
- } else {
- dh = h2 - h1;
- if (dh > 180.0)
- dh -= 360.0;
- else if (dh < -180.0)
- dh += 360.0;
- }
-
- dH = 2.0 * sqrt(C1 * C2) * sin(DEG2RAD(0.5 * dh));
- }
-
- {
- double L, C, h, T;
- double hh, ddeg;
- double C7, RC, L50sq, SL, SC, SH, RT;
- double dLsq, dCsq, dHsq, RCH;
-
- L = 0.5 * (Lab0[0] + Lab1[0]);
- C = 0.5 * (C1 + C2);
- if (C1 < 1e-9 || C2 < 1e-9) {
- h = h1 + h2;
- } else {
- h = h1 + h2;
- if (fabs(h1 - h2) > 180.0) {
- if (h < 360.0)
- h += 360.0;
- else if (h >= 360.0)
- h -= 360.0;
- }
- h *= 0.5;
- }
- T = 1.0 - 0.17 * cos(DEG2RAD(h-30.0)) + 0.24 * cos(DEG2RAD(2.0 * h))
- + 0.32 * cos(DEG2RAD(3.0 * h + 6.0)) - 0.2 * cos(DEG2RAD(4.0 * h - 63.0));
- hh = (h - 275.0)/25.0;
- ddeg = 30.0 * exp(-hh * hh);
- C7 = pow(C,7.0);
- RC = 2.0 * sqrt(C7/(C7 + 6103515625.0));
- L50sq = (L - 50.0) * (L - 50.0);
- SL = 1.0 + (0.015 * L50sq)/sqrt(20.0 + L50sq);
- SC = 1.0 + 0.045 * C;
- SH = 1.0 + 0.015 * C * T;
- RT = -sin(DEG2RAD(2 * ddeg)) * RC;
-
- dLsq = dL/SL;
- dCsq = dC/SC;
- dHsq = dH/SH;
-
- RCH = RT * dCsq * dHsq;
-
- dLsq *= dLsq;
- dCsq *= dCsq;
- dHsq *= dHsq;
-
- dsq = dLsq + dCsq + dHsq + RCH;
- }
-
- return dsq;
-
-#undef RAD2DEG
-#undef DEG2RAD
-}
-
-/* Return the CIE2DE000 Delta E color difference measure for two Lab values */
-double icmCIE2K(double *Lab0, double *Lab1) {
- return sqrt(icmCIE2Ksq(Lab0, Lab1));
-}
-
-/* Return the CIEDE2000 Delta E color difference measure for two XYZ values */
-extern ICCLIB_API double icmXYZCIE2K(icmXYZNumber *w, double *in0, double *in1) {
- double lab0[3], lab1[3];
-
- icmXYZ2Lab(w, lab0, in0);
- icmXYZ2Lab(w, lab1, in1);
- return sqrt(icmCIE2Ksq(lab0, lab1));
-}
-
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Chromatic adaptation transform utility */
-/* Return a 3x3 chromatic adaptation matrix */
-/* Use icmMulBy3x3(dst, mat, src) */
-void icmChromAdaptMatrix(
- int flags, /* Use bradford, Transform given matrix flags */
- icmXYZNumber d_wp, /* Destination white point */
- icmXYZNumber s_wp, /* Source white point */
- double mat[3][3] /* Destination matrix */
-) {
- double dst[3], src[3]; /* Source & destination white points */
- double vkmat[3][3]; /* Von Kries matrix */
-#ifdef NEVER
- static double bradford[3][3] = { /* Linear cone space matrix */
- { 1.0, 0.0, 0.0 },
- { 0.0, 1.0, 0.0 },
- { 0.0, 0.0, 1.0 }
- };
-#endif /* NEVER */
- static double bradford[3][3] = { /* Bradford cone space matrix */
- { 0.8951, 0.2664, -0.1614 },
- { -0.7502, 1.7135, 0.0367 },
- { 0.0389, -0.0685, 1.0296 }
- };
- static int inited = 0; /* Compute inverse bradford once */
- static double ibradford[3][3]; /* Inverse Bradford */
-
- /* Set initial matrix to unity */
- if (!(flags & ICM_CAM_MULMATRIX)) {
- icmSetUnity3x3(mat);
- }
-
- icmXYZ2Ary(src, s_wp);
- icmXYZ2Ary(dst, d_wp);
-
- if (flags & ICM_CAM_BRADFORD) {
- icmMulBy3x3(src, bradford, src);
- icmMulBy3x3(dst, bradford, dst);
- }
-
- /* Setup the Von Kries white point adaptation matrix */
- vkmat[0][0] = dst[0]/src[0];
- vkmat[1][1] = dst[1]/src[1];
- vkmat[2][2] = dst[2]/src[2];
- vkmat[0][1] = vkmat[0][2] = 0.0;
- vkmat[1][0] = vkmat[1][2] = 0.0;
- vkmat[2][0] = vkmat[2][1] = 0.0;
-
- /* Transform to Bradford space if requested */
- if (flags & ICM_CAM_BRADFORD) {
- icmMul3x3(mat, bradford);
- }
-
- /* Apply chromatic adaptation */
- icmMul3x3(mat, vkmat);
-
- /* Transform from Bradford space */
- if (flags & ICM_CAM_BRADFORD) {
- if (inited == 0) {
- icmInverse3x3(ibradford, bradford);
- inited = 1;
- }
- icmMul3x3(mat, ibradford);
- }
-
- /* We're done */
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* RGB primaries device to RGB->XYZ transform matrix. */
-/* We assume that the device is perfectly additive, but that */
-/* there may be a scale factor applied to the channels to */
-/* match the white point at RGB = 1. */
-
-/* Return non-zero if matrix would be singular */
-int icmRGBprim2matrix(
- icmXYZNumber white, /* White point */
- icmXYZNumber red, /* Red colorant */
- icmXYZNumber green, /* Green colorant */
- icmXYZNumber blue, /* Blue colorant */
- double mat[3][3] /* Destination matrix */
-) {
- double tmat[3][3];
- double t[3];
-
- /* Assemble the colorants into a matrix */
- tmat[0][0] = red.X;
- tmat[0][1] = green.X;
- tmat[0][2] = blue.X;
- tmat[1][0] = red.Y;
- tmat[1][1] = green.Y;
- tmat[1][2] = blue.Y;
- tmat[2][0] = red.Z;
- tmat[2][1] = green.Z;
- tmat[2][2] = blue.Z;
-
- /* Compute the inverse */
- if (icmInverse3x3(mat, tmat))
- return 1;
-
- /* Compute scale vector that maps colorants to white point */
- t[0] = mat[0][0] * white.X
- + mat[0][1] * white.Y
- + mat[0][2] * white.Z;
- t[1] = mat[1][0] * white.X
- + mat[1][1] * white.Y
- + mat[1][2] * white.Z;
- t[2] = mat[2][0] * white.X
- + mat[2][1] * white.Y
- + mat[2][2] * white.Z;
-
- /* Now formulate the transform matrix */
- mat[0][0] = red.X * t[0];
- mat[0][1] = green.X * t[1];
- mat[0][2] = blue.X * t[2];
- mat[1][0] = red.Y * t[0];
- mat[1][1] = green.Y * t[1];
- mat[1][2] = blue.Y * t[2];
- mat[2][0] = red.Z * t[0];
- mat[2][1] = green.Z * t[1];
- mat[2][2] = blue.Z * t[2];
-
- return 0;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Some PCS utility functions */
-
-/* Clip Lab, while maintaining hue angle. */
-/* Return nz if clipping occured */
-int icmClipLab(double out[3], double in[3]) {
- double C;
-
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
-
- if (out[0] >= 0.0 && out[0] <= 100.0
- && out[1] >= -128.0 && out[1] <= 127.0
- && out[2] >= -128.0 && out[2] <= 127.0)
- return 0;
-
- /* Clip L */
- if (out[0] < 0.0)
- out[0] = 0.0;
- else if (out[0] > 100.0)
- out[0] = 100.0;
-
- C = out[1];
- if (fabs(out[2]) > fabs(C))
- C = out[2];
- if (C < -128.0 || C > 127.0) {
- if (C < 0.0)
- C = -128.0/C;
- else
- C = 127.0/C;
- out[1] *= C;
- out[2] *= C;
- }
-
- return 1;
-}
-
-/* Clip XYZ, while maintaining hue angle */
-/* Return nz if clipping occured */
-int icmClipXYZ(double out[3], double in[3]) {
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
-
- if (out[0] >= 0.0 && out[0] <= 1.9999
- && out[1] >= 0.0 && out[1] <= 1.9999
- && out[2] >= 0.0 && out[2] <= 1.9999)
- return 0;
-
- /* Clip Y and scale X and Z similarly */
-
- if (out[1] > 1.9999) {
- out[0] *= 1.9999/out[1];
- out[2] *= 1.9999/out[1];
- out[1] = 1.9999;
- } else if (out[1] < 0.0) {
- out[0] = 0.0;
- out[1] = 0.0;
- out[2] = 0.0;
- }
-
- if (out[0] < 0.0 || out[0] > 1.9999
- || out[2] < 0.0 || out[2] > 1.9999) {
- double D50[3] = { 0.9642, 1.0000, 0.8249 };
- double bb = 0.0;
-
- /* Scale the D50 so that it has the same Y value as our color */
- D50[0] *= out[1];
- D50[1] *= out[1];
- D50[2] *= out[1];
-
- /* Figure out what blend factor with Y scaled D50, brings our */
- /* color X and Z values into range */
-
- if (out[0] < 0.0) {
- double b;
- b = (0.0 - out[0])/(D50[0] - out[0]);
- if (b > bb)
- bb = b;
- } else if (out[0] > 1.9999) {
- double b;
- b = (1.9999 - out[0])/(D50[0] - out[0]);
- if (b > bb)
- bb = b;
- }
- if (out[2] < 0.0) {
- double b;
- b = (0.0 - out[2])/(D50[2] - out[2]);
- if (b > bb)
- bb = b;
- } else if (out[2] > 1.9999) {
- double b;
- b = (1.9999 - out[2])/(D50[2] - out[2]);
- if (b > bb)
- bb = b;
- }
- /* Do the desaturation */
- out[0] = D50[0] * bb + (1.0 - bb) * out[0];
- out[2] = D50[2] * bb + (1.0 - bb) * out[2];
- }
- return 1;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Object for computing RFC 1321 MD5 checksums. */
-/* Derived from Colin Plumb's 1993 public domain code. */
-
-/* Reset the checksum */
-static void icmMD5_reset(icmMD5 *p) {
- p->tlen = 0;
-
- p->sum[0] = 0x67452301;
- p->sum[1] = 0xefcdab89;
- p->sum[2] = 0x98badcfe;
- p->sum[3] = 0x10325476;
-
- p->fin = 0;
-}
-
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-#define MD5STEP(f, w, x, y, z, pp, xtra, s) \
- data = (pp)[0] + ((pp)[3] << 24) + ((pp)[2] << 16) + ((pp)[1] << 8); \
- w += f(x, y, z) + data + xtra; \
- w = (w << s) | (w >> (32-s)); \
- w += x;
-
-/* Add another 64 bytes to the checksum */
-static void icmMD5_accume(icmMD5 *p, ORD8 *in) {
- ORD32 data, a, b, c, d;
-
- a = p->sum[0];
- b = p->sum[1];
- c = p->sum[2];
- d = p->sum[3];
-
- MD5STEP(F1, a, b, c, d, in + (4 * 0), 0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in + (4 * 1), 0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in + (4 * 2), 0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in + (4 * 3), 0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in + (4 * 4), 0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in + (4 * 5), 0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in + (4 * 6), 0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in + (4 * 7), 0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in + (4 * 8), 0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in + (4 * 9), 0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in + (4 * 10), 0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in + (4 * 11), 0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in + (4 * 12), 0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in + (4 * 13), 0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in + (4 * 14), 0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in + (4 * 15), 0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in + (4 * 1), 0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in + (4 * 6), 0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in + (4 * 11), 0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in + (4 * 0), 0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in + (4 * 5), 0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in + (4 * 10), 0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in + (4 * 15), 0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in + (4 * 4), 0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in + (4 * 9), 0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in + (4 * 14), 0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in + (4 * 3), 0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in + (4 * 8), 0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in + (4 * 13), 0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in + (4 * 2), 0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in + (4 * 7), 0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in + (4 * 12), 0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in + (4 * 5), 0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in + (4 * 8), 0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in + (4 * 11), 0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in + (4 * 14), 0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in + (4 * 1), 0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in + (4 * 4), 0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in + (4 * 7), 0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in + (4 * 10), 0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in + (4 * 13), 0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in + (4 * 0), 0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in + (4 * 3), 0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in + (4 * 6), 0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in + (4 * 9), 0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in + (4 * 12), 0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in + (4 * 15), 0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in + (4 * 2), 0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in + (4 * 0), 0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in + (4 * 7), 0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in + (4 * 14), 0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in + (4 * 5), 0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in + (4 * 12), 0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in + (4 * 3), 0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in + (4 * 10), 0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in + (4 * 1), 0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in + (4 * 8), 0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in + (4 * 15), 0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in + (4 * 6), 0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in + (4 * 13), 0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in + (4 * 4), 0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in + (4 * 11), 0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in + (4 * 2), 0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in + (4 * 9), 0xeb86d391, 21);
-
- p->sum[0] += a;
- p->sum[1] += b;
- p->sum[2] += c;
- p->sum[3] += d;
-}
-
-#undef F1
-#undef F2
-#undef F3
-#undef F4
-#undef MD5STEP
-
-/* Add some bytes */
-static void icmMD5_add(icmMD5 *p, ORD8 *ibuf, unsigned int len) {
- unsigned int bs;
-
- if (p->fin)
- return; /* This is actually an error */
-
- bs = p->tlen; /* Current bytes added */
- p->tlen = bs + len; /* Update length after adding this buffer */
- bs &= 0x3f; /* Bytes already in buffer */
-
- /* Deal with any existing partial bytes in p->buf */
- if (bs) {
- ORD8 *np = (ORD8 *)p->buf + bs; /* Next free location in partial buffer */
-
- bs = 64 - bs; /* Free space in partial buffer */
-
- if (len < bs) { /* Not enought new to make a full buffer */
- memmove(np, ibuf, len);
- return;
- }
-
- memmove(np, ibuf, bs); /* Now got one full buffer */
- icmMD5_accume(p, np);
- ibuf += bs;
- len -= bs;
- }
-
- /* Deal with input data 64 bytes at a time */
- while (len >= 64) {
- icmMD5_accume(p, ibuf);
- ibuf += 64;
- len -= 64;
- }
-
- /* Deal with any remaining bytes */
- memmove(p->buf, ibuf, len);
-}
-
-/* Finalise the checksum and return the result. */
-static void icmMD5_get(icmMD5 *p, ORD8 chsum[16]) {
- int i;
- unsigned count;
- ORD32 bits1, bits0;
- ORD8 *pp;
-
- if (p->fin == 0) {
-
- /* Compute number of bytes processed mod 64 */
- count = p->tlen & 0x3f;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- pp = p->buf + count;
- *pp++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64, allowing 8 bytes for length in bits. */
- if (count < 8) { /* Not enough space for padding and length */
-
- memset(pp, 0, count);
- icmMD5_accume(p, p->buf);
-
- /* Now fill the next block with 56 bytes */
- memset(p->buf, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(pp, 0, count - 8);
- }
-
- /* Compute number of bits */
- bits1 = 0x7 & (p->tlen >> (32 - 3));
- bits0 = p->tlen << 3;
-
- /* Append number of bits */
- p->buf[64 - 8] = bits0 & 0xff;
- p->buf[64 - 7] = (bits0 >> 8) & 0xff;
- p->buf[64 - 6] = (bits0 >> 16) & 0xff;
- p->buf[64 - 5] = (bits0 >> 24) & 0xff;
- p->buf[64 - 4] = bits1 & 0xff;
- p->buf[64 - 3] = (bits1 >> 8) & 0xff;
- p->buf[64 - 2] = (bits1 >> 16) & 0xff;
- p->buf[64 - 1] = (bits1 >> 24) & 0xff;
-
- icmMD5_accume(p, p->buf);
-
- p->fin = 1;
- }
-
- /* Return the result, lsb to msb */
- pp = chsum;
- for (i = 0; i < 4; i++) {
- *pp++ = p->sum[i] & 0xff;
- *pp++ = (p->sum[i] >> 8) & 0xff;
- *pp++ = (p->sum[i] >> 16) & 0xff;
- *pp++ = (p->sum[i] >> 24) & 0xff;
- }
-}
-
-
-/* Delete the instance */
-static void icmMD5_del(icmMD5 *p) {
- p->al->free(p->al, p);
-}
-
-/* Create a new MD5 checksumming object, with a reset checksum value */
-/* Return it or NULL if there is an error */
-icmMD5 *new_icmMD5(icmAlloc *al) {
- icmMD5 *p;
-
- if ((p = (icmMD5 *)al->calloc(al,1,sizeof(icmMD5))) == NULL)
- return NULL;
-
- p->al = al;
- p->reset = icmMD5_reset;
- p->add = icmMD5_add;
- p->get = icmMD5_get;
- p->del = icmMD5_del;
-
- p->reset(p);
-
- return p;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Dumy icmFile used to compute MD5 checksum on write */
-
-/* Get the size of the file (Only valid for reading file. */
-static size_t icmFileMD5_get_size(icmFile *pp) {
- icmFileMD5 *p = (icmFileMD5 *)pp;
-
- return p->size;
-}
-
-/* Set current position to offset. Return 0 on success, nz on failure. */
-/* Seek can't be supported for MD5, so and seek must be to current location. */
-static int icmFileMD5_seek(
-icmFile *pp,
-unsigned int offset
-) {
- icmFileMD5 *p = (icmFileMD5 *)pp;
-
- if (p->of != offset) {
- p->errc = 1;
- }
- if (p->of > p->size)
- p->size = p->of;
- return 0;
-}
-
-/* Read count items of size length. Return number of items successfully read. */
-/* Read is not implemented */
-static size_t icmFileMD5_read(
-icmFile *pp,
-void *buffer,
-size_t size,
-size_t count
-) {
- return 0;
-}
-
-/* write count items of size length. Return number of items successfully written. */
-/* Simply pass to MD5 to compute checksum */
-static size_t icmFileMD5_write(
-icmFile *pp,
-void *buffer,
-size_t size,
-size_t count
-) {
- icmFileMD5 *p = (icmFileMD5 *)pp;
- size_t len = size * count;
-
- p->md5->add(p->md5, (ORD8 *)buffer, len);
- p->of += len;
- if (p->of > p->size)
- p->size = p->of;
- return count;
-}
-
-/* do a printf */
-/* Not implemented */
-static int icmFileMD5_printf(
-icmFile *pp,
-const char *format,
-...
-) {
- icmFileMD5 *p = (icmFileMD5 *)pp;
- p->errc = 2;
- return 0;
-}
-
-/* flush all write data out to secondary storage. Return nz on failure. */
-static int icmFileMD5_flush(
-icmFile *pp
-) {
- return 0;
-}
-
-/* we're done with the file object, return nz on failure */
-static int icmFileMD5_delete(
-icmFile *pp
-) {
- icmFileMD5 *p = (icmFileMD5 *)pp;
-
- p->al->free(p->al, p); /* Free object */
- return 0;
-}
-
-/* Return the error code. Error code will usually be set */
-/* if we did a seek to other than the current location, */
-/* or did a printf. */
-static int icmFileMD5_geterrc(
-icmFile *pp
-) {
- icmFileMD5 *p = (icmFileMD5 *)pp;
-
- return p->errc;
-}
-
-/* Create a checksum dump file access class with allocator */
-icmFile *new_icmFileMD5_a(
-icmMD5 *md5, /* MD5 object to use */
-icmAlloc *al /* heap allocator */
-) {
- icmFileMD5 *p;
-
- if ((p = (icmFileMD5 *) al->calloc(al, 1, sizeof(icmFileMD5))) == NULL) {
- return NULL;
- }
- p->md5 = md5; /* MD5 compute object */
- p->al = al; /* Heap allocator */
- p->get_size = icmFileMD5_get_size;
- p->seek = icmFileMD5_seek;
- p->read = icmFileMD5_read;
- p->write = icmFileMD5_write;
- p->gprintf = icmFileMD5_printf;
- p->flush = icmFileMD5_flush;
- p->del = icmFileMD5_delete;
- p->get_errc = icmFileMD5_geterrc;
-
- p->of = 0;
- p->errc = 0;
-
- return (icmFile *)p;
-}
-
-
-/* ============================================= */
-/* Implementation of color transform lookups. */
-
-/* - - - - - - - - - - - - - - - - - - - - - - - */
-/* Methods common to all transforms (icmLuBase) : */
-
-/* Return information about the native lut in/out/pcs colorspaces. */
-/* Any pointer may be NULL if value is not to be returned */
-static void
-icmLutSpaces(
- struct _icmLuBase *p, /* This */
- icColorSpaceSignature *ins, /* Return Native input color space */
- int *inn, /* Return number of input components */
- icColorSpaceSignature *outs, /* Return Native output color space */
- int *outn, /* Return number of output components */
- icColorSpaceSignature *pcs /* Return Native PCS color space */
- /* (this will be the same as ins or outs */
- /* depending on the lookup direction) */
-) {
- if (ins != NULL)
- *ins = p->inSpace;
- if (inn != NULL)
- *inn = (int)number_ColorSpaceSignature(p->inSpace);
-
- if (outs != NULL)
- *outs = p->outSpace;
- if (outn != NULL)
- *outn = (int)number_ColorSpaceSignature(p->outSpace);
- if (pcs != NULL)
- *pcs = p->pcs;
-}
-
-/* Return information about the effective lookup in/out colorspaces, */
-/* including allowance for PCS override. */
-/* Any pointer may be NULL if value is not to be returned */
-static void
-icmLuSpaces(
- struct _icmLuBase *p, /* This */
- icColorSpaceSignature *ins, /* Return effective input color space */
- int *inn, /* Return number of input components */
- icColorSpaceSignature *outs, /* Return effective output color space */
- int *outn, /* Return number of output components */
- icmLuAlgType *alg, /* Return type of lookup algorithm used */
- icRenderingIntent *intt, /* Return the intent being implented */
- icmLookupFunc *fnc, /* Return the profile function being implemented */
- icColorSpaceSignature *pcs, /* Return the profile effective PCS */
- icmLookupOrder *ord /* return the search Order */
-) {
- if (ins != NULL)
- *ins = p->e_inSpace;
- if (inn != NULL)
- *inn = (int)number_ColorSpaceSignature(p->e_inSpace);
-
- if (outs != NULL)
- *outs = p->e_outSpace;
- if (outn != NULL)
- *outn = (int)number_ColorSpaceSignature(p->e_outSpace);
-
- if (alg != NULL)
- *alg = p->ttype;
-
- if (intt != NULL)
- *intt = p->intent;
-
- if (fnc != NULL)
- *fnc = p->function;
-
- if (pcs != NULL)
- *pcs = p->e_pcs;
-
- if (ord != NULL)
- *ord = p->order;
-}
-
-/* Relative to Absolute for this WP in XYZ */
-static void icmLuXYZ_Rel2Abs(icmLuBase *p, double *out, double *in) {
- icmMulBy3x3(out, p->toAbs, in);
-}
-
-/* Absolute to Relative for this WP in XYZ */
-static void icmLuXYZ_Abs2Rel(icmLuBase *p, double *out, double *in) {
- icmMulBy3x3(out, p->fromAbs, in);
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Methods common to all non-named transforms (icmLuBase) : */
-
-/* Initialise the LU white and black points from the ICC tags, */
-/* and the corresponding absolute<->relative conversion matrices */
-/* return nz on error */
-static int icmLuInit_Wh_bk(
-struct _icmLuBase *lup
-) {
- icmXYZArray *whitePointTag, *blackPointTag;
- icc *p = lup->icp;
-
- if ((whitePointTag = (icmXYZArray *)p->read_tag(p, icSigMediaWhitePointTag)) == NULL
- || whitePointTag->ttype != icSigXYZType || whitePointTag->size < 1) {
- if (p->header->deviceClass != icSigLinkClass
- && (lup->intent == icAbsoluteColorimetric
- || lup->intent == icmAbsolutePerceptual
- || lup->intent == icmAbsoluteSaturation)) {
- sprintf(p->err,"icc_lookup: Profile is missing Media White Point Tag");
- p->errc = 1;
- return 1;
- }
- p->err[0] = '\000';
- p->errc = 0;
- lup->whitePoint = icmD50; /* safe value */
- } else
- lup->whitePoint = whitePointTag->data[0]; /* Copy structure */
-
- if ((blackPointTag = (icmXYZArray *)p->read_tag(p, icSigMediaBlackPointTag)) == NULL
- || blackPointTag->ttype != icSigXYZType || blackPointTag->size < 1) {
- p->err[0] = '\000';
- p->errc = 0;
- lup->blackPoint = icmBlack; /* default */
- lup->blackisassumed = 1; /* We assumed the default */
- } else {
- lup->blackPoint = blackPointTag->data[0]; /* Copy structure */
- lup->blackisassumed = 0; /* The black is from the tag */
- }
-
- /* Create absolute <-> relative conversion matricies */
- icmChromAdaptMatrix(ICM_CAM_BRADFORD, lup->whitePoint, icmD50, lup->toAbs);
- icmChromAdaptMatrix(ICM_CAM_BRADFORD, icmD50, lup->whitePoint, lup->fromAbs);
- DBLLL(("toAbs and fromAbs created from wp %f %f %f and D50 %f %f %f\n", lup->whitePoint.X, lup->whitePoint.Y, lup->whitePoint.Z, icmD50.X, icmD50.Y, icmD50.Z));
- DBLLL(("toAbs = %f %f %f\n %f %f %f\n %f %f %f\n", lup->toAbs[0][0], lup->toAbs[0][1], lup->toAbs[0][2], lup->toAbs[1][0], lup->toAbs[1][1], lup->toAbs[1][2], lup->toAbs[2][0], lup->toAbs[2][1], lup->toAbs[2][2]));
- DBLLL(("fromAbs = %f %f %f\n %f %f %f\n %f %f %f\n", lup->fromAbs[0][0], lup->fromAbs[0][1], lup->fromAbs[0][2], lup->fromAbs[1][0], lup->fromAbs[1][1], lup->fromAbs[1][2], lup->fromAbs[2][0], lup->fromAbs[2][1], lup->fromAbs[2][2]));
-
- return 0;
-}
-
-/* Return the media white and black points in absolute XYZ space. */
-/* Note that if not in the icc, the black point will be returned as 0, 0, 0, */
-/* and the function will return nz. */
-/* Any pointer may be NULL if value is not to be returned */
-static int icmLuWh_bk_points(
-struct _icmLuBase *p,
-double *wht,
-double *blk
-) {
- if (wht != NULL) {
- icmXYZ2Ary(wht,p->whitePoint);
- }
-
- if (blk != NULL) {
- icmXYZ2Ary(blk,p->blackPoint);
- }
- if (p->blackisassumed)
- return 1;
- return 0;
-}
-
-/* Get the LU white and black points in LU PCS space, converted to XYZ. */
-/* (ie. white and black will be relative if LU is relative intent etc.) */
-/* Return nz if the black point is being assumed to be 0,0,0 rather */
-/* than being from the tag. */ \
-static int icmLuLu_wh_bk_points(
-struct _icmLuBase *p,
-double *wht,
-double *blk
-) {
- if (wht != NULL) {
- icmXYZ2Ary(wht,p->whitePoint);
- }
-
- if (blk != NULL) {
- icmXYZ2Ary(blk,p->blackPoint);
- }
- if (p->intent != icAbsoluteColorimetric
- && p->intent != icmAbsolutePerceptual
- && p->intent != icmAbsoluteSaturation) {
- if (wht != NULL)
- icmMulBy3x3(wht, p->fromAbs, wht);
- if (blk != NULL)
- icmMulBy3x3(blk, p->fromAbs, blk);
- }
- if (p->blackisassumed)
- return 1;
- return 0;
-}
-
-/* Get the native (internal) ranges for the Monochrome or Matrix profile */
-/* Arguments may be NULL */
-static void
-icmLu_get_lutranges (
- struct _icmLuBase *p,
- double *inmin, double *inmax, /* Return maximum range of inspace values */
- double *outmin, double *outmax /* Return maximum range of outspace values */
-) {
- icTagTypeSignature tagType;
-
- if (p->ttype == icmLutType) {
- icmLuLut *pp = (icmLuLut *)p;
- tagType = pp->lut->ttype;
- } else {
- tagType = icMaxEnumType;
- }
-
- /* Hmm. we have no way of handling an error from getRange. */
- /* It shouldn't ever return one unless there is a mismatch between */
- /* getRange and Lu creation... */
- getRange(p->icp, p->inSpace, tagType, inmin, inmax);
- getRange(p->icp, p->outSpace, tagType, outmin, outmax);
-}
-
-/* Get the effective (externally visible) ranges for the all profile types */
-/* Arguments may be NULL */
-static void
-icmLu_get_ranges (
- struct _icmLuBase *p,
- double *inmin, double *inmax, /* Return maximum range of inspace values */
- double *outmin, double *outmax /* Return maximum range of outspace values */
-) {
- icTagTypeSignature tagType;
-
- if (p->ttype == icmLutType) {
- icmLuLut *pp = (icmLuLut *)p;
- tagType = pp->lut->ttype;
- } else {
- tagType = icMaxEnumType;
- }
- /* Hmm. we have no way of handling an error from getRange. */
- /* It shouldn't ever return one unless there is a mismatch between */
- /* getRange and Lu creation... */
- getRange(p->icp, p->e_inSpace, tagType, inmin, inmax);
- getRange(p->icp, p->e_outSpace, tagType, outmin, outmax);
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Forward and Backward Monochrome type methods: */
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-
-/* Individual components of Fwd conversion: */
-
-/* Actual device to linearised device */
-static int
-icmLuMonoFwd_curve (
-icmLuMono *p, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- icc *icp = p->icp;
- int rv = 0;
-
- /* Translate from device to PCS scale */
- if ((rv |= p->grayCurve->lookup_fwd(p->grayCurve,&out[0],&in[0])) > 1) {
- sprintf(icp->err,"icc_lookup: Curve->lookup_fwd() failed");
- icp->errc = rv;
- return 2;
- }
-
- return rv;
-}
-
-/* Linearised device to relative PCS */
-static int
-icmLuMonoFwd_map (
-icmLuMono *p, /* This */
-double *out, /* Vector of output values (native space) */
-double *in /* Vector of input values (native space) */
-) {
- int rv = 0;
- double Y = in[0]; /* In case out == in */
-
- out[0] = p->pcswht.X;
- out[1] = p->pcswht.Y;
- out[2] = p->pcswht.Z;
- if (p->pcs == icSigLabData)
- icmXYZ2Lab(&p->pcswht, out, out); /* in Lab */
-
- /* Scale linearized device level to PCS white */
- out[0] *= Y;
- out[1] *= Y;
- out[2] *= Y;
-
- return rv;
-}
-
-/* relative PCS to absolute PCS (if required) */
-static int
-icmLuMonoFwd_abs ( /* Abs comes last in Fwd conversion */
-icmLuMono *p, /* This */
-double *out, /* Vector of output values in Effective PCS */
-double *in /* Vector of input values in Native PCS */
-) {
- int rv = 0;
-
- if (out != in) { /* Don't alter input values */
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- }
-
- /* Do absolute conversion */
- if (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation) {
-
- if (p->pcs == icSigLabData) /* Convert L to Y */
- icmLab2XYZ(&p->pcswht, out, out);
-
- /* Convert from Relative to Absolute colorimetric */
- icmMulBy3x3(out, p->toAbs, out);
-
- if (p->e_pcs == icSigLabData)
- icmXYZ2Lab(&p->pcswht, out, out);
-
- } else {
-
- /* Convert from Native to Effective output space */
- if (p->pcs == icSigLabData && p->e_pcs == icSigXYZData)
- icmLab2XYZ(&p->pcswht, out, out);
- else if (p->pcs == icSigXYZData && p->e_pcs == icSigLabData)
- icmXYZ2Lab(&p->pcswht, out, out);
- }
-
- return rv;
-}
-
-
-/* Overall Fwd conversion routine (Dev->PCS) */
-static int
-icmLuMonoFwd_lookup (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Input value */
-) {
- int rv = 0;
- icmLuMono *p = (icmLuMono *)pp;
- rv |= icmLuMonoFwd_curve(p, out, in);
- rv |= icmLuMonoFwd_map(p, out, out);
- rv |= icmLuMonoFwd_abs(p, out, out);
- return rv;
-}
-
-/* Three stage conversion routines */
-static int
-icmLuMonoFwd_lookup_in(
-icmLuBase *pp, /* This */
-double *out, /* Output value */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuMono *p = (icmLuMono *)pp;
- rv |= icmLuMonoFwd_curve(p, out, in);
- return rv;
-}
-
-static int
-icmLuMonoFwd_lookup_core(
-icmLuBase *pp, /* This */
-double *out, /* Output value */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuMono *p = (icmLuMono *)pp;
- rv |= icmLuMonoFwd_map(p, out, in);
- rv |= icmLuMonoFwd_abs(p, out, out);
- return rv;
-}
-
-static int
-icmLuMonoFwd_lookup_out(
-icmLuBase *pp, /* This */
-double *out, /* Output value */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- return rv;
-}
-
-
-/* - - - - - - - - - - - - - - */
-/* Individual components of Bwd conversion: */
-
-/* Convert from relative PCS to absolute PCS (if required) */
-static int
-icmLuMonoBwd_abs ( /* Abs comes first in Bwd conversion */
-icmLuMono *p, /* This */
-double *out, /* Vector of output values in Native PCS */
-double *in /* Vector of input values in Effective PCS */
-) {
- int rv = 0;
-
- if (out != in) { /* Don't alter input values */
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- }
-
- /* Force to monochrome locus in correct space */
- if (p->e_pcs == icSigLabData) {
- double wp[3];
-
- if (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation) {
- wp[0] = p->whitePoint.X;
- wp[1] = p->whitePoint.Y;
- wp[2] = p->whitePoint.Z;
- } else {
- wp[0] = p->pcswht.X;
- wp[1] = p->pcswht.Y;
- wp[2] = p->pcswht.Z;
- }
- icmXYZ2Lab(&p->pcswht, wp, wp); /* Convert to Lab white point */
- out[1] = out[0]/wp[0] * wp[1];
- out[2] = out[0]/wp[0] * wp[2];
-
- } else {
- if (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation) {
- out[0] = out[1]/p->whitePoint.Y * p->whitePoint.X;
- out[2] = out[1]/p->whitePoint.Y * p->whitePoint.Z;
- } else {
- out[0] = out[1]/p->pcswht.Y * p->pcswht.X;
- out[2] = out[1]/p->pcswht.Y * p->pcswht.Z;
- }
- }
-
- /* Do absolute conversion, and conversion to effective PCS */
- if (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation) {
-
- if (p->e_pcs == icSigLabData)
- icmLab2XYZ(&p->pcswht, out, out);
-
- icmMulBy3x3(out, p->fromAbs, out);
-
- /* Convert from Effective to Native input space */
- if (p->pcs == icSigLabData)
- icmXYZ2Lab(&p->pcswht, out, out);
-
- } else {
-
- /* Convert from Effective to Native input space */
- if (p->e_pcs == icSigLabData && p->pcs == icSigXYZData)
- icmLab2XYZ(&p->pcswht, out, out);
- else if (p->e_pcs == icSigXYZData && p->pcs == icSigLabData)
- icmXYZ2Lab(&p->pcswht, out, out);
- }
-
- return rv;
-}
-
-/* Map from relative PCS to linearised device */
-static int
-icmLuMonoBwd_map (
-icmLuMono *p, /* This */
-double *out, /* Output value */
-double *in /* Vector of input values (native space) */
-) {
- int rv = 0;
- double pcsw[3];
-
- pcsw[0] = p->pcswht.X;
- pcsw[1] = p->pcswht.Y;
- pcsw[2] = p->pcswht.Z;
- if (p->pcs == icSigLabData)
- icmXYZ2Lab(&p->pcswht, pcsw, pcsw); /* in Lab (should be 100.0!) */
-
- /* Divide linearized device level into PCS white luminence */
- if (p->pcs == icSigLabData)
- out[0] = in[0]/pcsw[0];
- else
- out[0] = in[1]/pcsw[1];
-
- return rv;
-}
-
-/* Map from linearised device to actual device */
-static int
-icmLuMonoBwd_curve (
-icmLuMono *p, /* This */
-double *out, /* Output value */
-double *in /* Input value */
-) {
- icc *icp = p->icp;
- int rv = 0;
-
- /* Convert to device value through curve */
- if ((rv = p->grayCurve->lookup_bwd(p->grayCurve,&out[0],&in[0])) > 1) {
- sprintf(icp->err,"icc_lookup: Curve->lookup_bwd() failed");
- icp->errc = rv;
- return 2;
- }
-
- return rv;
-}
-
-/* Overall Bwd conversion routine (PCS->Dev) */
-static int
-icmLuMonoBwd_lookup (
-icmLuBase *pp, /* This */
-double *out, /* Output value */
-double *in /* Vector of input values */
-) {
- double temp[3];
- int rv = 0;
- icmLuMono *p = (icmLuMono *)pp;
- rv |= icmLuMonoBwd_abs(p, temp, in);
- rv |= icmLuMonoBwd_map(p, out, temp);
- rv |= icmLuMonoBwd_curve(p, out, out);
- return rv;
-}
-
-/* Three stage conversion routines */
-static int
-icmLuMonoBwd_lookup_in(
-icmLuBase *pp, /* This */
-double *out, /* Output value */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- return rv;
-}
-
-static int
-icmLuMonoBwd_lookup_core(
-icmLuBase *pp, /* This */
-double *out, /* Output value */
-double *in /* Vector of input values */
-) {
- double temp[3];
- int rv = 0;
- icmLuMono *p = (icmLuMono *)pp;
- rv |= icmLuMonoBwd_abs(p, temp, in);
- rv |= icmLuMonoBwd_map(p, out, temp);
- return rv;
-}
-
-static int
-icmLuMonoBwd_lookup_out(
-icmLuBase *pp, /* This */
-double *out, /* Output value */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuMono *p = (icmLuMono *)pp;
- rv |= icmLuMonoBwd_curve(p, out, in);
- return rv;
-}
-
-/* - - - - - - - - - - - - - - */
-
-static void
-icmLuMono_delete(
-icmLuBase *p
-) {
- icc *icp = p->icp;
-
- icp->al->free(icp->al, p);
-}
-
-static icmLuBase *
-new_icmLuMono(
- struct _icc *icp,
- icColorSpaceSignature inSpace, /* Native Input color space */
- icColorSpaceSignature outSpace, /* Native Output color space */
- icColorSpaceSignature pcs, /* Native PCS */
- icColorSpaceSignature e_inSpace, /* Effective Input color space */
- icColorSpaceSignature e_outSpace, /* Effective Output color space */
- icColorSpaceSignature e_pcs, /* Effective PCS */
- icRenderingIntent intent, /* Rendering intent */
- icmLookupFunc func, /* Functionality requested */
- int dir /* 0 = fwd, 1 = bwd */
-) {
- icmLuMono *p;
-
- if ((p = (icmLuMono *) icp->al->calloc(icp->al,1,sizeof(icmLuMono))) == NULL)
- return NULL;
- p->icp = icp;
- p->del = icmLuMono_delete;
- p->lutspaces= icmLutSpaces;
- p->spaces = icmLuSpaces;
- p->XYZ_Rel2Abs = icmLuXYZ_Rel2Abs;
- p->XYZ_Abs2Rel = icmLuXYZ_Abs2Rel;
- p->get_lutranges = icmLu_get_lutranges;
- p->get_ranges = icmLu_get_ranges;
- p->init_wh_bk = icmLuInit_Wh_bk;
- p->wh_bk_points = icmLuWh_bk_points;
- p->lu_wh_bk_points = icmLuLu_wh_bk_points;
- p->fwd_lookup = icmLuMonoFwd_lookup;
- p->fwd_curve = icmLuMonoFwd_curve;
- p->fwd_map = icmLuMonoFwd_map;
- p->fwd_abs = icmLuMonoFwd_abs;
- p->bwd_lookup = icmLuMonoBwd_lookup;
- p->bwd_abs = icmLuMonoFwd_abs;
- p->bwd_map = icmLuMonoFwd_map;
- p->bwd_curve = icmLuMonoFwd_curve;
- if (dir) {
- p->ttype = icmMonoBwdType;
- p->lookup = icmLuMonoBwd_lookup;
- p->lookup_in = icmLuMonoBwd_lookup_in;
- p->lookup_core = icmLuMonoBwd_lookup_core;
- p->lookup_out = icmLuMonoBwd_lookup_out;
- p->lookup_inv_in = icmLuMonoFwd_lookup_out; /* Opposite of Bwd_lookup_in */
- } else {
- p->ttype = icmMonoFwdType;
- p->lookup = icmLuMonoFwd_lookup;
- p->lookup_in = icmLuMonoFwd_lookup_in;
- p->lookup_core = icmLuMonoFwd_lookup_core;
- p->lookup_out = icmLuMonoFwd_lookup_out;
- p->lookup_inv_in = icmLuMonoBwd_lookup_out; /* Opposite of Fwd_lookup_in */
- }
-
- /* Lookup the white and black points */
- if (p->init_wh_bk((icmLuBase *)p)) {
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* See if the color spaces are appropriate for the mono type */
- if (number_ColorSpaceSignature(icp->header->colorSpace) != 1
- || ( icp->header->pcs != icSigXYZData && icp->header->pcs != icSigLabData)) {
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* Find the appropriate tags */
- if ((p->grayCurve = (icmCurve *)icp->read_tag(icp, icSigGrayTRCTag)) == NULL
- || p->grayCurve->ttype != icSigCurveType) {
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- p->pcswht = icp->header->illuminant;
- p->intent = intent;
- p->function = func;
- p->inSpace = inSpace;
- p->outSpace = outSpace;
- p->pcs = pcs;
- p->e_inSpace = e_inSpace;
- p->e_outSpace = e_outSpace;
- p->e_pcs = e_pcs;
-
- return (icmLuBase *)p;
-}
-
-static icmLuBase *
-new_icmLuMonoFwd(
- struct _icc *icp,
- icColorSpaceSignature inSpace, /* Native Input color space */
- icColorSpaceSignature outSpace, /* Native Output color space */
- icColorSpaceSignature pcs, /* Native PCS */
- icColorSpaceSignature e_inSpace, /* Effective Input color space */
- icColorSpaceSignature e_outSpace, /* Effective Output color space */
- icColorSpaceSignature e_pcs, /* Effective PCS */
- icRenderingIntent intent, /* Rendering intent */
- icmLookupFunc func /* Functionality requested */
-) {
- return new_icmLuMono(icp, inSpace, outSpace, pcs, e_inSpace, e_outSpace, e_pcs,
- intent, func, 0);
-}
-
-
-static icmLuBase *
-new_icmLuMonoBwd(
- struct _icc *icp,
- icColorSpaceSignature inSpace, /* Native Input color space */
- icColorSpaceSignature outSpace, /* Native Output color space */
- icColorSpaceSignature pcs, /* Native PCS */
- icColorSpaceSignature e_inSpace, /* Effective Input color space */
- icColorSpaceSignature e_outSpace, /* Effective Output color space */
- icColorSpaceSignature e_pcs, /* Effective PCS */
- icRenderingIntent intent, /* Rendering intent */
- icmLookupFunc func /* Functionality requested */
-) {
- return new_icmLuMono(icp, inSpace, outSpace, pcs, e_inSpace, e_outSpace, e_pcs,
- intent, func, 1);
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - */
-/* Forward and Backward Matrix type conversion */
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-
-/* Individual components of Fwd conversion: */
-static int
-icmLuMatrixFwd_curve (
-icmLuMatrix *p, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- icc *icp = p->icp;
- int rv = 0;
-
- /* Curve lookups */
- if ((rv |= p->redCurve->lookup_fwd( p->redCurve, &out[0],&in[0])) > 1
- || (rv |= p->greenCurve->lookup_fwd(p->greenCurve,&out[1],&in[1])) > 1
- || (rv |= p->blueCurve->lookup_fwd( p->blueCurve, &out[2],&in[2])) > 1) {
- sprintf(icp->err,"icc_lookup: Curve->lookup_fwd() failed");
- icp->errc = rv;
- return 2;
- }
-
- return rv;
-}
-
-static int
-icmLuMatrixFwd_matrix (
-icmLuMatrix *p, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- double tt[3];
-
- /* Matrix */
- tt[0] = p->mx[0][0] * in[0] + p->mx[0][1] * in[1] + p->mx[0][2] * in[2];
- tt[1] = p->mx[1][0] * in[0] + p->mx[1][1] * in[1] + p->mx[1][2] * in[2];
- tt[2] = p->mx[2][0] * in[0] + p->mx[2][1] * in[1] + p->mx[2][2] * in[2];
-
- out[0] = tt[0];
- out[1] = tt[1];
- out[2] = tt[2];
-
- return rv;
-}
-
-static int
-icmLuMatrixFwd_abs (/* Abs comes last in Fwd conversion */
-icmLuMatrix *p, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
-
- if (out != in) { /* Don't alter input values */
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- }
-
- /* If required, convert from Relative to Absolute colorimetric */
- if (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation) {
- icmMulBy3x3(out, p->toAbs, out);
- }
-
- /* If e_pcs is Lab, then convert XYZ to Lab */
- if (p->e_pcs == icSigLabData)
- icmXYZ2Lab(&p->pcswht, out, out);
-
- return rv;
-}
-
-
-/* Overall Fwd conversion (Dev->PCS)*/
-static int
-icmLuMatrixFwd_lookup (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuMatrix *p = (icmLuMatrix *)pp;
- rv |= icmLuMatrixFwd_curve(p, out, in);
- rv |= icmLuMatrixFwd_matrix(p, out, out);
- rv |= icmLuMatrixFwd_abs(p, out, out);
- return rv;
-}
-
-/* Three stage conversion routines */
-static int
-icmLuMatrixFwd_lookup_in (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuMatrix *p = (icmLuMatrix *)pp;
- rv |= icmLuMatrixFwd_curve(p, out, in);
- return rv;
-}
-
-static int
-icmLuMatrixFwd_lookup_core (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuMatrix *p = (icmLuMatrix *)pp;
- rv |= icmLuMatrixFwd_matrix(p, out, in);
- rv |= icmLuMatrixFwd_abs(p, out, out);
- return rv;
-}
-
-static int
-icmLuMatrixFwd_lookup_out (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- return rv;
-}
-
-/* - - - - - - - - - - - - - - */
-/* Individual components of Bwd conversion: */
-
-static int
-icmLuMatrixBwd_abs (/* Abs comes first in Bwd conversion */
-icmLuMatrix *p, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
-
- if (out != in) { /* Don't alter input values */
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- }
-
- /* If e_pcs is Lab, then convert Lab to XYZ */
- if (p->e_pcs == icSigLabData)
- icmLab2XYZ(&p->pcswht, out, out);
-
- /* If required, convert from Absolute to Relative colorimetric */
- if (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation) {
- icmMulBy3x3(out, p->fromAbs, out);
- }
-
- return rv;
-}
-
-static int
-icmLuMatrixBwd_matrix (
-icmLuMatrix *p, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- double tt[3];
-
- tt[0] = in[0];
- tt[1] = in[1];
- tt[2] = in[2];
-
- /* Matrix */
- out[0] = p->bmx[0][0] * tt[0] + p->bmx[0][1] * tt[1] + p->bmx[0][2] * tt[2];
- out[1] = p->bmx[1][0] * tt[0] + p->bmx[1][1] * tt[1] + p->bmx[1][2] * tt[2];
- out[2] = p->bmx[2][0] * tt[0] + p->bmx[2][1] * tt[1] + p->bmx[2][2] * tt[2];
-
- return rv;
-}
-
-static int
-icmLuMatrixBwd_curve (
-icmLuMatrix *p, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- icc *icp = p->icp;
- int rv = 0;
-
- /* Curves */
- if ((rv |= p->redCurve->lookup_bwd(p->redCurve,&out[0],&in[0])) > 1
- || (rv |= p->greenCurve->lookup_bwd(p->greenCurve,&out[1],&in[1])) > 1
- || (rv |= p->blueCurve->lookup_bwd(p->blueCurve,&out[2],&in[2])) > 1) {
- sprintf(icp->err,"icc_lookup: Curve->lookup_bwd() failed");
- icp->errc = rv;
- return 2;
- }
- return rv;
-}
-
-/* Overall Bwd conversion (PCS->Dev) */
-static int
-icmLuMatrixBwd_lookup (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuMatrix *p = (icmLuMatrix *)pp;
- rv |= icmLuMatrixBwd_abs(p, out, in);
- rv |= icmLuMatrixBwd_matrix(p, out, out);
- rv |= icmLuMatrixBwd_curve(p, out, out);
- return rv;
-}
-
-/* Three stage conversion routines */
-static int
-icmLuMatrixBwd_lookup_in (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- out[0] = in[0];
- out[1] = in[1];
- out[2] = in[2];
- return rv;
-}
-
-static int
-icmLuMatrixBwd_lookup_core (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuMatrix *p = (icmLuMatrix *)pp;
- rv |= icmLuMatrixBwd_abs(p, out, in);
- rv |= icmLuMatrixBwd_matrix(p, out, out);
- return rv;
-}
-
-static int
-icmLuMatrixBwd_lookup_out (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuMatrix *p = (icmLuMatrix *)pp;
- rv |= icmLuMatrixBwd_curve(p, out, in);
- return rv;
-}
-
-/* - - - - - - - - - - - - - - */
-
-static void
-icmLuMatrix_delete(
-icmLuBase *p
-) {
- icc *icp = p->icp;
-
- icp->al->free(icp->al, p);
-}
-
-/* We setup valid fwd and bwd component conversions, */
-/* but setup only the asked for overal conversion. */
-static icmLuBase *
-new_icmLuMatrix(
- struct _icc *icp,
- icColorSpaceSignature inSpace, /* Native Input color space */
- icColorSpaceSignature outSpace, /* Native Output color space */
- icColorSpaceSignature pcs, /* Native PCS */
- icColorSpaceSignature e_inSpace, /* Effective Input color space */
- icColorSpaceSignature e_outSpace, /* Effective Output color space */
- icColorSpaceSignature e_pcs, /* Effective PCS */
- icRenderingIntent intent, /* Rendering intent */
- icmLookupFunc func, /* Functionality requested */
- int dir /* 0 = fwd, 1 = bwd */
-) {
- icmLuMatrix *p;
-
- if ((p = (icmLuMatrix *) icp->al->calloc(icp->al,1,sizeof(icmLuMatrix))) == NULL)
- return NULL;
- p->icp = icp;
- p->del = icmLuMatrix_delete;
- p->lutspaces= icmLutSpaces;
- p->spaces = icmLuSpaces;
- p->XYZ_Rel2Abs = icmLuXYZ_Rel2Abs;
- p->XYZ_Abs2Rel = icmLuXYZ_Abs2Rel;
- p->get_lutranges = icmLu_get_lutranges;
- p->get_ranges = icmLu_get_ranges;
- p->init_wh_bk = icmLuInit_Wh_bk;
- p->wh_bk_points = icmLuWh_bk_points;
- p->lu_wh_bk_points = icmLuLu_wh_bk_points;
- p->fwd_lookup = icmLuMatrixFwd_lookup;
- p->fwd_curve = icmLuMatrixFwd_curve;
- p->fwd_matrix = icmLuMatrixFwd_matrix;
- p->fwd_abs = icmLuMatrixFwd_abs;
- p->bwd_lookup = icmLuMatrixBwd_lookup;
- p->bwd_abs = icmLuMatrixBwd_abs;
- p->bwd_matrix = icmLuMatrixBwd_matrix;
- p->bwd_curve = icmLuMatrixBwd_curve;
- if (dir) {
- p->ttype = icmMatrixBwdType;
- p->lookup = icmLuMatrixBwd_lookup;
- p->lookup_in = icmLuMatrixBwd_lookup_in;
- p->lookup_core = icmLuMatrixBwd_lookup_core;
- p->lookup_out = icmLuMatrixBwd_lookup_out;
- p->lookup_inv_in = icmLuMatrixFwd_lookup_out; /* Opposite of Bwd_lookup_in */
- } else {
- p->ttype = icmMatrixFwdType;
- p->lookup = icmLuMatrixFwd_lookup;
- p->lookup_in = icmLuMatrixFwd_lookup_in;
- p->lookup_core = icmLuMatrixFwd_lookup_core;
- p->lookup_out = icmLuMatrixFwd_lookup_out;
- p->lookup_inv_in = icmLuMatrixBwd_lookup_out; /* Opposite of Fwd_lookup_in */
- }
-
- /* Lookup the white and black points */
- if (p->init_wh_bk((icmLuBase *)p)) {
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* Note that we can use matrix type even if PCS is Lab, */
- /* by simply converting it. */
-
- /* Find the appropriate tags */
- if ((p->redCurve = (icmCurve *)icp->read_tag(icp, icSigRedTRCTag)) == NULL
- || p->redCurve->ttype != icSigCurveType
- || (p->greenCurve = (icmCurve *)icp->read_tag(icp, icSigGreenTRCTag)) == NULL
- || p->greenCurve->ttype != icSigCurveType
- || (p->blueCurve = (icmCurve *)icp->read_tag(icp, icSigBlueTRCTag)) == NULL
- || p->blueCurve->ttype != icSigCurveType
- || (p->redColrnt = (icmXYZArray *)icp->read_tag(icp, icSigRedColorantTag)) == NULL
- || p->redColrnt->ttype != icSigXYZType || p->redColrnt->size < 1
- || (p->greenColrnt = (icmXYZArray *)icp->read_tag(icp, icSigGreenColorantTag)) == NULL
- || p->greenColrnt->ttype != icSigXYZType || p->greenColrnt->size < 1
- || (p->blueColrnt = (icmXYZArray *)icp->read_tag(icp, icSigBlueColorantTag)) == NULL
- || p->blueColrnt->ttype != icSigXYZType || p->blueColrnt->size < 1) {
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* Setup the matrix */
- p->mx[0][0] = p->redColrnt->data[0].X;
- p->mx[0][1] = p->greenColrnt->data[0].X;
- p->mx[0][2] = p->blueColrnt->data[0].X;
- p->mx[1][1] = p->greenColrnt->data[0].Y;
- p->mx[1][0] = p->redColrnt->data[0].Y;
- p->mx[1][2] = p->blueColrnt->data[0].Y;
- p->mx[2][1] = p->greenColrnt->data[0].Z;
- p->mx[2][0] = p->redColrnt->data[0].Z;
- p->mx[2][2] = p->blueColrnt->data[0].Z;
-
-#ifndef ICM_STRICT
- /* Workaround for buggy Kodak RGB profiles. Their matrix values */
- /* may be scaled to 100 rather than 1.0, and the colorant curves */
- /* may be scaled by 0.5 */
- if (icp->header->cmmId == str2tag("KCMS")) {
- int i, j, oc = 0;
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++)
- if (p->mx[i][j] > 5.0)
- oc++;
- if (oc > 4) { /* Looks like it */
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++)
- p->mx[i][j] /= 100.0;
- }
- }
-#endif /* ICM_STRICT */
-
- if (icmInverse3x3(p->bmx, p->mx) != 0) { /* Compute inverse */
- sprintf(icp->err,"icc_new_iccLuMatrix: Matrix wasn't invertable");
- icp->errc = 2;
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- p->pcswht = icp->header->illuminant;
- p->intent = intent;
- p->function = func;
- p->inSpace = inSpace;
- p->outSpace = outSpace;
- p->pcs = pcs;
- p->e_inSpace = e_inSpace;
- p->e_outSpace = e_outSpace;
- p->e_pcs = e_pcs;
-
- /* Lookup the white and black points */
- if (p->init_wh_bk((icmLuBase *)p)) {
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- return (icmLuBase *)p;
-}
-
-static icmLuBase *
-new_icmLuMatrixFwd(
- struct _icc *icp,
- icColorSpaceSignature inSpace, /* Native Input color space */
- icColorSpaceSignature outSpace, /* Native Output color space */
- icColorSpaceSignature pcs, /* Native PCS */
- icColorSpaceSignature e_inSpace, /* Effective Input color space */
- icColorSpaceSignature e_outSpace, /* Effective Output color space */
- icColorSpaceSignature e_pcs, /* Effective PCS */
- icRenderingIntent intent, /* Rendering intent */
- icmLookupFunc func /* Functionality requested */
-) {
- return new_icmLuMatrix(icp, inSpace, outSpace, pcs, e_inSpace, e_outSpace, e_pcs,
- intent, func, 0);
-}
-
-
-static icmLuBase *
-new_icmLuMatrixBwd(
- struct _icc *icp,
- icColorSpaceSignature inSpace, /* Native Input color space */
- icColorSpaceSignature outSpace, /* Native Output color space */
- icColorSpaceSignature pcs, /* Native PCS */
- icColorSpaceSignature e_inSpace, /* Effective Input color space */
- icColorSpaceSignature e_outSpace, /* Effective Output color space */
- icColorSpaceSignature e_pcs, /* Effective PCS */
- icRenderingIntent intent, /* Rendering intent */
- icmLookupFunc func /* Functionality requested */
-) {
- return new_icmLuMatrix(icp, inSpace, outSpace, pcs, e_inSpace, e_outSpace, e_pcs,
- intent, func, 1);
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - */
-/* Forward and Backward Multi-Dimensional Interpolation type conversion */
-/* Return 0 on success, 1 if clipping occured, 2 on other error */
-
-/* Components of overall lookup, in order */
-static int icmLuLut_in_abs(icmLuLut *p, double *out, double *in) {
- icmLut *lut = p->lut;
- int rv = 0;
-
- DBLLL(("icm in_abs: input %s\n",icmPdv(lut->inputChan, in)));
- if (out != in) {
- unsigned int i;
- for (i = 0; i < lut->inputChan; i++) /* Don't alter input values */
- out[i] = in[i];
- }
-
- /* If Bwd Lut, take care of Absolute color space and effective input space */
- if ((p->function == icmBwd || p->function == icmGamut || p->function == icmPreview)
- && (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation)) {
-
- if (p->e_inSpace == icSigLabData) {
- icmLab2XYZ(&p->pcswht, out, out);
- DBLLL(("icm in_abs: after Lab2XYZ %s\n",icmPdv(lut->inputChan, out)));
- }
-
- /* Convert from Absolute to Relative colorimetric */
- icmMulBy3x3(out, p->fromAbs, out);
- DBLLL(("icm in_abs: after fromAbs %s\n",icmPdv(lut->inputChan, out)));
-
- if (p->inSpace == icSigLabData) {
- icmXYZ2Lab(&p->pcswht, out, out);
- DBLLL(("icm in_abs: after XYZ2Lab %s\n",icmPdv(lut->inputChan, out)));
- }
-
- } else {
-
- /* Convert from Effective to Native input space */
- if (p->e_inSpace == icSigLabData && p->inSpace == icSigXYZData) {
- icmLab2XYZ(&p->pcswht, out, out);
- DBLLL(("icm in_abs: after Lab2XYZ %s\n",icmPdv(lut->inputChan, out)));
- } else if (p->e_inSpace == icSigXYZData && p->inSpace == icSigLabData) {
- icmXYZ2Lab(&p->pcswht, out, out);
- DBLLL(("icm in_abs: after XYZ2Lab %s\n",icmPdv(lut->inputChan, out)));
- }
- }
- DBLLL(("icm in_abs: returning %s\n",icmPdv(lut->inputChan, out)));
-
- return rv;
-}
-
-/* Possible matrix lookup */
-static int icmLuLut_matrix(icmLuLut *p, double *out, double *in) {
- icmLut *lut = p->lut;
- int rv = 0;
-
- if (p->usematrix)
- rv |= lut->lookup_matrix(lut,out,in);
- else if (out != in) {
- unsigned int i;
- for (i = 0; i < lut->inputChan; i++)
- out[i] = in[i];
- }
- return rv;
-}
-
-/* Do input -> input' lookup */
-static int icmLuLut_input(icmLuLut *p, double *out, double *in) {
- icmLut *lut = p->lut;
- int rv = 0;
-
- p->in_normf(out, in); /* Normalize from input color space */
- rv |= lut->lookup_input(lut,out,out); /* Lookup though input tables */
- p->in_denormf(out,out); /* De-normalize to input color space */
- return rv;
-}
-
-/* Do input'->output' lookup */
-static int icmLuLut_clut(icmLuLut *p, double *out, double *in) {
- icmLut *lut = p->lut;
- double temp[MAX_CHAN];
- int rv = 0;
-
- p->in_normf(temp, in); /* Normalize from input color space */
- rv |= p->lookup_clut(lut,out,temp); /* Lookup though clut tables */
- p->out_denormf(out,out); /* De-normalize to output color space */
- return rv;
-}
-
-/* Do output'->output lookup */
-static int icmLuLut_output(icmLuLut *p, double *out, double *in) {
- icmLut *lut = p->lut;
- int rv = 0;
-
- p->out_normf(out,in); /* Normalize from output color space */
- rv |= lut->lookup_output(lut,out,out); /* Lookup though output tables */
- p->out_denormf(out, out); /* De-normalize to output color space */
- return rv;
-}
-
-static int icmLuLut_out_abs(icmLuLut *p, double *out, double *in) {
- icmLut *lut = p->lut;
- int rv = 0;
-
- DBLLL(("icm out_abs: input %s\n",icmPdv(lut->outputChan, in)));
- if (out != in) {
- unsigned int i;
- for (i = 0; i < lut->outputChan; i++) /* Don't alter input values */
- out[i] = in[i];
- }
-
- /* If Fwd Lut, take care of Absolute color space */
- /* and convert from native to effective out PCS */
- if ((p->function == icmFwd || p->function == icmPreview)
- && (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation)) {
-
- if (p->outSpace == icSigLabData) {
- icmLab2XYZ(&p->pcswht, out, out);
- DBLLL(("icm out_abs: after Lab2XYZ %s\n",icmPdv(lut->outputChan, out)));
- }
-
- /* Convert from Relative to Absolute colorimetric XYZ */
- icmMulBy3x3(out, p->toAbs, out);
- DBLLL(("icm out_abs: after toAbs %s\n",icmPdv(lut->outputChan, out)));
-
- if (p->e_outSpace == icSigLabData) {
- icmXYZ2Lab(&p->pcswht, out, out);
- DBLLL(("icm out_abs: after XYZ2Lab %s\n",icmPdv(lut->outputChan, out)));
- }
- } else {
-
- /* Convert from Native to Effective output space */
- if (p->outSpace == icSigLabData && p->e_outSpace == icSigXYZData) {
- icmLab2XYZ(&p->pcswht, out, out);
- DBLLL(("icm out_abs: after Lab2 %s\n",icmPdv(lut->outputChan, out)));
- } else if (p->outSpace == icSigXYZData && p->e_outSpace == icSigLabData) {
- icmXYZ2Lab(&p->pcswht, out, out);
- DBLLL(("icm out_abs: after XYZ2Lab %s\n",icmPdv(lut->outputChan, out)));
- }
- }
- DBLLL(("icm out_abs: returning %s\n",icmPdv(lut->outputChan, out)));
- return rv;
-}
-
-
-/* Overall lookup */
-static int
-icmLuLut_lookup (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuLut *p = (icmLuLut *)pp;
- icmLut *lut = p->lut;
- double temp[MAX_CHAN];
-
- DBGLL(("icmLuLut_lookup: in = %s\n", icmPdv(p->inputChan, in)));
- rv |= p->in_abs(p,temp,in); /* Possible absolute conversion */
- DBGLL(("icmLuLut_lookup: in_abs = %s\n", icmPdv(p->inputChan, temp)));
- if (p->usematrix) {
- rv |= lut->lookup_matrix(lut,temp,temp);/* If XYZ, multiply by non-unity matrix */
- DBGLL(("icmLuLut_lookup: matrix = %s\n", icmPdv(p->inputChan, temp)));
- }
- p->in_normf(temp, temp); /* Normalize for input color space */
- DBGLL(("icmLuLut_lookup: norm = %s\n", icmPdv(p->inputChan, temp)));
- rv |= lut->lookup_input(lut,temp,temp); /* Lookup though input tables */
- DBGLL(("icmLuLut_lookup: input = %s\n", icmPdv(p->inputChan, temp)));
- rv |= p->lookup_clut(lut,out,temp); /* Lookup though clut tables */
- DBGLL(("icmLuLut_lookup: clut = %s\n", icmPdv(p->outputChan, out)));
- rv |= lut->lookup_output(lut,out,out); /* Lookup though output tables */
- DBGLL(("icmLuLut_lookup: output = %s\n", icmPdv(p->outputChan, out)));
- p->out_denormf(out,out); /* Normalize for output color space */
- DBGLL(("icmLuLut_lookup: denorm = %s\n", icmPdv(p->outputChan, out)));
- rv |= p->out_abs(p,out,out); /* Possible absolute conversion */
- DBGLL(("icmLuLut_lookup: out_abse = %s\n", icmPdv(p->outputChan, out)));
-
- return rv;
-}
-
-#ifdef NEVER /* The following should be identical in effect to the above. */
-
-/* Overall lookup */
-static int
-icmLuLut_lookup (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int i, rv = 0;
- icmLuLut *p = (icmLuLut *)pp;
- icmLut *lut = p->lut;
- double temp[MAX_CHAN];
-
- rv |= p->in_abs(p,temp,in);
- rv |= p->matrix(p,temp,temp);
- rv |= p->input(p,temp,temp);
- rv |= p->clut(p,out,temp);
- rv |= p->output(p,out,out);
- rv |= p->out_abs(p,out,out);
-
- return rv;
-}
-
-#endif /* NEVER */
-
-/* Three stage conversion */
-static int
-icmLuLut_lookup_in (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuLut *p = (icmLuLut *)pp;
- icmLut *lut = p->lut;
-
- /* If in_abs() or matrix() are active, then we can't have a per component input curve */
- if (((p->function == icmBwd || p->function == icmGamut || p->function == icmPreview)
- && (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation))
- || (p->e_inSpace != p->inSpace)
- || (p->usematrix)) {
- unsigned int i;
- for (i = 0; i < lut->inputChan; i++)
- out[i] = in[i];
- } else {
- rv |= p->input(p,out,in);
- }
- return rv;
-}
-
-static int
-icmLuLut_lookup_core (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuLut *p = (icmLuLut *)pp;
-
- /* If in_abs() or matrix() are active, then we have to do the per component input curve here */
- if (((p->function == icmBwd || p->function == icmGamut || p->function == icmPreview)
- && (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation))
- || (p->e_inSpace != p->inSpace)
- || (p->usematrix)) {
- double temp[MAX_CHAN];
- rv |= p->in_abs(p,temp,in);
- rv |= p->matrix(p,temp,temp);
- rv |= p->input(p,temp,temp);
- rv |= p->clut(p,out,temp);
- } else {
- rv |= p->clut(p,out,in);
- }
-
- /* If out_abs() is active, then we can't have do per component out curve here */
- if (((p->function == icmFwd || p->function == icmPreview)
- && (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation))
- || (p->outSpace != p->e_outSpace)) {
- rv |= p->output(p,out,out);
- rv |= p->out_abs(p,out,out);
- }
-
- return rv;
-}
-
-static int
-icmLuLut_lookup_out (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuLut *p = (icmLuLut *)pp;
- icmLut *lut = p->lut;
-
- /* If out_abs() is active, then we can't have a per component out curve */
- if (((p->function == icmFwd || p->function == icmPreview)
- && (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation))
- || (p->outSpace != p->e_outSpace)) {
- unsigned int i;
- for (i = 0; i < lut->outputChan; i++)
- out[i] = in[i];
- } else {
- rv |= p->output(p,out,in);
- }
-
- return rv;
-}
-
-/* Inverse three stage conversion (partly implemented) */
-static int
-icmLuLut_lookup_inv_in (
-icmLuBase *pp, /* This */
-double *out, /* Vector of output values */
-double *in /* Vector of input values */
-) {
- int rv = 0;
- icmLuLut *p = (icmLuLut *)pp;
- icmLut *lut = p->lut;
-
- /* If in_abs() or matrix() are active, then we can't have a per component input curve */
- if (((p->function == icmBwd || p->function == icmGamut || p->function == icmPreview)
- && (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation))
- || (p->e_inSpace != p->inSpace)
- || (p->usematrix)) {
- unsigned int i;
- for (i = 0; i < lut->inputChan; i++)
- out[i] = in[i];
- } else {
- rv |= p->inv_input(p,out,in);
- }
- return rv;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Some components of inverse lookup, in order */
-/* ~~ should these be in icmLut (like all the fwd transforms)? */
-
-static int icmLuLut_inv_out_abs(icmLuLut *p, double *out, double *in) {
- icmLut *lut = p->lut;
- int rv = 0;
-
- DBLLL(("icm inv_out_abs: input %s\n",icmPdv(lut->outputChan, in)));
- if (out != in) {
- unsigned int i;
- for (i = 0; i < lut->outputChan; i++) /* Don't alter input values */
- out[i] = in[i];
- }
-
- /* If Fwd Lut, take care of Absolute color space */
- /* and convert from effective to native inverse output PCS */
- /* OutSpace must be PCS: XYZ or Lab */
- if ((p->function == icmFwd || p->function == icmPreview)
- && (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation)) {
-
- if (p->e_outSpace == icSigLabData) {
- icmLab2XYZ(&p->pcswht, out, out);
- DBLLL(("icm inv_out_abs: after Lab2XYZ %s\n",icmPdv(lut->outputChan, out)));
- }
-
- /* Convert from Absolute to Relative colorimetric */
- icmMulBy3x3(out, p->fromAbs, out);
- DBLLL(("icm inv_out_abs: after fromAbs %s\n",icmPdv(lut->outputChan, out)));
-
- if (p->outSpace == icSigLabData) {
- icmXYZ2Lab(&p->pcswht, out, out);
- DBLLL(("icm inv_out_abs: after XYZ2Lab %s\n",icmPdv(lut->outputChan, out)));
- }
-
- } else {
-
- /* Convert from Effective to Native output space */
- if (p->e_outSpace == icSigLabData && p->outSpace == icSigXYZData) {
- icmLab2XYZ(&p->pcswht, out, out);
- DBLLL(("icm inv_out_abs: after Lab2XYZ %s\n",icmPdv(lut->outputChan, out)));
- } else if (p->e_outSpace == icSigXYZData && p->outSpace == icSigLabData) {
- icmXYZ2Lab(&p->pcswht, out, out);
- DBLLL(("icm inv_out_abs: after XYZ2Lab %s\n",icmPdv(lut->outputChan, out)));
- }
- }
- return rv;
-}
-
-/* Do output->output' inverse lookup */
-static int icmLuLut_inv_output(icmLuLut *p, double *out, double *in) {
- icc *icp = p->icp;
- icmLut *lut = p->lut;
- int i;
- int rv = 0;
-
- if (lut->rot[0].inited == 0) {
- for (i = 0; i < lut->outputChan; i++) {
- rv = icmTable_setup_bwd(icp, &lut->rot[i], lut->outputEnt,
- lut->outputTable + i * lut->outputEnt);
- if (rv != 0) {
- sprintf(icp->err,"icc_Lut_inv_input: Malloc failure in inverse lookup init.");
- return icp->errc = rv;
- }
- }
- }
-
- p->out_normf(out,in); /* Normalize from output color space */
- for (i = 0; i < lut->outputChan; i++) {
- /* Reverse lookup though output tables */
- rv |= icmTable_lookup_bwd(&lut->rot[i], &out[i], &out[i]);
- }
- p->out_denormf(out, out); /* De-normalize to output color space */
- return rv;
-}
-
-/* No output' -> input inverse lookup. */
-/* This is non-trivial ! */
-
-/* Do input' -> input inverse lookup */
-static int icmLuLut_inv_input(icmLuLut *p, double *out, double *in) {
- icc *icp = p->icp;
- icmLut *lut = p->lut;
- int i;
- int rv = 0;
-
- if (lut->rit[0].inited == 0) {
- for (i = 0; i < lut->inputChan; i++) {
- rv = icmTable_setup_bwd(icp, &lut->rit[i], lut->inputEnt,
- lut->inputTable + i * lut->inputEnt);
- if (rv != 0) {
- sprintf(icp->err,"icc_Lut_inv_input: Malloc failure in inverse lookup init.");
- return icp->errc = rv;
- }
- }
- }
-
- p->in_normf(out, in); /* Normalize from input color space */
- for (i = 0; i < lut->inputChan; i++) {
- /* Reverse lookup though input tables */
- rv |= icmTable_lookup_bwd(&lut->rit[i], &out[i], &out[i]);
- }
- p->in_denormf(out,out); /* De-normalize to input color space */
- return rv;
-}
-
-/* Possible inverse matrix lookup */
-static int icmLuLut_inv_matrix(icmLuLut *p, double *out, double *in) {
- icc *icp = p->icp;
- icmLut *lut = p->lut;
- int rv = 0;
-
- if (p->usematrix) {
- double tt[3];
- if (p->imx_valid == 0) {
- if (icmInverse3x3(p->imx, lut->e) != 0) { /* Compute inverse */
- sprintf(icp->err,"icc_new_iccLuMatrix: Matrix wasn't invertable");
- icp->errc = 2;
- return 2;
- }
- p->imx_valid = 1;
- }
- /* Matrix multiply */
- tt[0] = p->imx[0][0] * in[0] + p->imx[0][1] * in[1] + p->imx[0][2] * in[2];
- tt[1] = p->imx[1][0] * in[0] + p->imx[1][1] * in[1] + p->imx[1][2] * in[2];
- tt[2] = p->imx[2][0] * in[0] + p->imx[2][1] * in[1] + p->imx[2][2] * in[2];
- out[0] = tt[0], out[1] = tt[1], out[2] = tt[2];
- } else if (out != in) {
- unsigned int i;
- for (i = 0; i < lut->inputChan; i++)
- out[i] = in[i];
- }
- return rv;
-}
-
-static int icmLuLut_inv_in_abs(icmLuLut *p, double *out, double *in) {
- icmLut *lut = p->lut;
- int rv = 0;
-
- DBLLL(("icm inv_in_abs: input %s\n",icmPdv(lut->inputChan, in)));
- if (out != in) {
- unsigned int i;
- for (i = 0; i < lut->inputChan; i++) /* Don't alter input values */
- out[i] = in[i];
- }
-
- /* If Bwd Lut, take care of Absolute color space, and */
- /* convert from native to effective input space */
- if ((p->function == icmBwd || p->function == icmGamut || p->function == icmPreview)
- && (p->intent == icAbsoluteColorimetric
- || p->intent == icmAbsolutePerceptual
- || p->intent == icmAbsoluteSaturation)) {
-
- if (p->inSpace == icSigLabData) {
- icmLab2XYZ(&p->pcswht, out, out);
- DBLLL(("icm inv_in_abs: after Lab2XYZ %s\n",icmPdv(lut->inputChan, out)));
- }
-
- /* Convert from Relative to Absolute colorimetric XYZ */
- icmMulBy3x3(out, p->toAbs, out);
- DBLLL(("icm inv_in_abs: after toAbs %s\n",icmPdv(lut->inputChan, out)));
-
- if (p->e_inSpace == icSigLabData) {
- icmXYZ2Lab(&p->pcswht, out, out);
- DBLLL(("icm inv_in_abs: after XYZ2Lab %s\n",icmPdv(lut->inputChan, out)));
- }
- } else {
-
- /* Convert from Native to Effective input space */
- if (p->inSpace == icSigLabData && p->e_inSpace == icSigXYZData) {
- icmLab2XYZ(&p->pcswht, out, out);
- DBLLL(("icm inv_in_abs: after Lab2XYZ %s\n",icmPdv(lut->inputChan, out)));
- } else if (p->inSpace == icSigXYZData && p->e_inSpace == icSigLabData) {
- icmXYZ2Lab(&p->pcswht, out, out);
- DBLLL(("icm inv_in_abs: after XYZ2Lab %s\n",icmPdv(lut->inputChan, out)));
- }
- }
- DBLLL(("icm inv_in_abs: returning %s\n",icmPdv(lut->inputChan, out)));
- return rv;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Return LuLut information */
-static void icmLuLut_get_info(
- icmLuLut *p, /* this */
- icmLut **lutp, /* Pointer to icc lut type */
- icmXYZNumber *pcswhtp, /* Pointer to profile PCS white point */
- icmXYZNumber *whitep, /* Pointer to profile absolute white point */
- icmXYZNumber *blackp /* Pointer to profile absolute black point */
-) {
- if (lutp != NULL)
- *lutp = p->lut;
- if (pcswhtp != NULL)
- *pcswhtp = p->pcswht;
- if (whitep != NULL)
- *whitep = p->whitePoint;
- if (blackp != NULL)
- *blackp = p->blackPoint;
-}
-
-/* Get the native ranges for the LuLut */
-/* This is computed differently to the mono & matrix types, to */
-/* accurately take into account the different range for 8 bit Lab */
-/* lut type. The range returned for the effective PCS is not so accurate. */
-static void
-icmLuLut_get_lutranges (
- struct _icmLuBase *pp,
- double *inmin, double *inmax, /* Return maximum range of inspace values */
- double *outmin, double *outmax /* Return maximum range of outspace values */
-) {
- icmLuLut *p = (icmLuLut *)pp;
- unsigned int i;
-
- for (i = 0; i < p->lut->inputChan; i++) {
- inmin[i] = 0.0; /* Normalized range of input space values */
- inmax[i] = 1.0;
- }
- p->in_denormf(inmin,inmin); /* Convert to real colorspace range */
- p->in_denormf(inmax,inmax);
-
- /* Make sure min and max are so. */
- for (i = 0; i < p->lut->inputChan; i++) {
- if (inmin[i] > inmax[i]) {
- double tt;
- tt = inmin[i];
- inmin[i] = inmax[i];
- inmax[i] = tt;
- }
- }
-
- for (i = 0; i < p->lut->outputChan; i++) {
- outmin[i] = 0.0; /* Normalized range of output space values */
- outmax[i] = 1.0;
- }
- p->out_denormf(outmin,outmin); /* Convert to real colorspace range */
- p->out_denormf(outmax,outmax);
-
- /* Make sure min and max are so. */
- for (i = 0; i < p->lut->outputChan; i++) {
- if (outmin[i] > outmax[i]) {
- double tt;
- tt = outmin[i];
- outmin[i] = outmax[i];
- outmax[i] = tt;
- }
- }
-}
-
-/* Get the effective (externaly visible) ranges for the LuLut */
-/* This will be accurate if there is no override, but only */
-/* aproximate if a PCS override is in place. */
-static void
-icmLuLut_get_ranges (
- struct _icmLuBase *pp,
- double *inmin, double *inmax, /* Return maximum range of inspace values */
- double *outmin, double *outmax /* Return maximum range of outspace values */
-) {
- icmLuLut *p = (icmLuLut *)pp;
-
- /* Get the native ranges first */
- icmLuLut_get_lutranges(pp, inmin, inmax, outmin, outmax);
-
- /* And replace them if the effective space is different */
- if (p->e_inSpace != p->inSpace)
- getRange(p->icp, p->e_inSpace, p->lut->ttype, inmin, inmax);
-
- if (p->e_outSpace != p->outSpace)
- getRange(p->icp, p->e_outSpace, p->lut->ttype, outmin, outmax);
-}
-
-/* Return the underlying Lut matrix */
-static void
-icmLuLut_get_matrix (
- struct _icmLuLut *p,
- double m[3][3]
-) {
- int i, j;
- icmLut *lut = p->lut;
-
- if (p->usematrix) {
- for (i = 0; i < 3; i++)
- for (j = 0; j < 3; j++)
- m[i][j] = lut->e[i][j]; /* Copy from Lut */
-
- } else { /* return unity matrix */
- icmSetUnity3x3(m);
- }
-}
-
-
-static void
-icmLuLut_delete(
-icmLuBase *p
-) {
- icc *icp = p->icp;
-
- icp->al->free(icp->al, p);
-}
-
-icmLuBase *
-icc_new_icmLuLut(
- icc *icp,
- icTagSignature ttag, /* Target Lut tag */
- icColorSpaceSignature inSpace, /* Native Input color space */
- icColorSpaceSignature outSpace, /* Native Output color space */
- icColorSpaceSignature pcs, /* Native PCS (from header) */
- icColorSpaceSignature e_inSpace, /* Effective Input color space */
- icColorSpaceSignature e_outSpace, /* Effective Output color space */
- icColorSpaceSignature e_pcs, /* Effective PCS */
- icRenderingIntent intent, /* Rendering intent (For absolute) */
- icmLookupFunc func /* Functionality requested (for icmLuSpaces()) */
-) {
- icmLuLut *p;
-
- if ((p = (icmLuLut *) icp->al->calloc(icp->al,1,sizeof(icmLuLut))) == NULL)
- return NULL;
- p->ttype = icmLutType;
- p->icp = icp;
- p->del = icmLuLut_delete;
- p->lutspaces= icmLutSpaces;
- p->spaces = icmLuSpaces;
- p->XYZ_Rel2Abs = icmLuXYZ_Rel2Abs;
- p->XYZ_Abs2Rel = icmLuXYZ_Abs2Rel;
- p->init_wh_bk = icmLuInit_Wh_bk;
- p->wh_bk_points = icmLuWh_bk_points;
- p->lu_wh_bk_points = icmLuLu_wh_bk_points;
-
- p->lookup = icmLuLut_lookup;
- p->lookup_in = icmLuLut_lookup_in;
- p->lookup_core = icmLuLut_lookup_core;
- p->lookup_out = icmLuLut_lookup_out;
- p->lookup_inv_in = icmLuLut_lookup_inv_in;
-
- p->in_abs = icmLuLut_in_abs;
- p->matrix = icmLuLut_matrix;
- p->input = icmLuLut_input;
- p->clut = icmLuLut_clut;
- p->output = icmLuLut_output;
- p->out_abs = icmLuLut_out_abs;
-
- p->inv_in_abs = icmLuLut_inv_in_abs;
- p->inv_matrix = icmLuLut_inv_matrix;
- p->inv_input = icmLuLut_inv_input;
- p->inv_output = icmLuLut_inv_output;
- p->inv_out_abs = icmLuLut_inv_out_abs;
-
- p->pcswht = icp->header->illuminant;
- p->intent = intent; /* used to trigger absolute processing */
- p->function = func;
- p->inSpace = inSpace;
- p->outSpace = outSpace;
- p->pcs = pcs;
- p->e_inSpace = e_inSpace;
- p->e_outSpace = e_outSpace;
- p->e_pcs = e_pcs;
- p->get_info = icmLuLut_get_info;
- p->get_lutranges = icmLuLut_get_lutranges;
- p->get_ranges = icmLuLut_get_ranges;
- p->get_matrix = icmLuLut_get_matrix;
-
- /* Lookup the white and black points */
- if (p->init_wh_bk((icmLuBase *)p)) {
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* Get the Lut tag, & check that it is expected type */
- if ((p->lut = (icmLut *)icp->read_tag(icp, ttag)) == NULL
- || (p->lut->ttype != icSigLut8Type && p->lut->ttype != icSigLut16Type)) {
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* Check if matrix should be used */
- if (inSpace == icSigXYZData && p->lut->nu_matrix(p->lut))
- p->usematrix = 1;
- else
- p->usematrix = 0;
-
- /* Lookup input color space to normalized index function */
- if (getNormFunc(icp, inSpace, p->lut->ttype, icmToLuti, &p->in_normf)) {
- sprintf(icp->err,"icc_get_luobj: Unknown colorspace");
- icp->errc = 1;
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* Lookup normalized index to input color space function */
- if (getNormFunc(icp, inSpace, p->lut->ttype, icmFromLuti, &p->in_denormf)) {
- sprintf(icp->err,"icc_get_luobj: Unknown colorspace");
- icp->errc = 1;
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* Lookup output color space to normalized Lut entry value function */
- if (getNormFunc(icp, outSpace, p->lut->ttype, icmToLutv, &p->out_normf)) {
- sprintf(icp->err,"icc_get_luobj: Unknown colorspace");
- icp->errc = 1;
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* Lookup normalized Lut entry value to output color space function */
- if (getNormFunc(icp, outSpace, p->lut->ttype, icmFromLutv, &p->out_denormf)) {
- sprintf(icp->err,"icc_get_luobj: Unknown colorspace");
- icp->errc = 1;
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* Note that the following two are only used in computing the expected */
- /* value ranges of the effective PCS. This might not be the best way of */
- /* doing this. */
- /* Lookup normalized index to effective input color space function */
- if (getNormFunc(icp, e_inSpace, p->lut->ttype, icmFromLuti, &p->e_in_denormf)) {
- sprintf(icp->err,"icc_get_luobj: Unknown effective colorspace");
- icp->errc = 1;
- p->del((icmLuBase *)p);
- return NULL;
- }
-
- /* Lookup normalized Lut entry value to effective output color space function */
- if (getNormFunc(icp, e_outSpace, p->lut->ttype, icmFromLutv, &p->e_out_denormf)) {
- sprintf(icp->err,"icc_get_luobj: Unknown effective colorspace");
- icp->errc = 1;
- p->del((icmLuBase *)p);
- return NULL;
- }
-
-// ~~~999
-#ifndef NEVER
- /* Standard code */
- /* Determine appropriate clut lookup algorithm */
- {
- int use_sx; /* -1 = undecided, 0 = N-linear, 1 = Simplex lookup */
- icColorSpaceSignature ins, outs; /* In and out Lut color spaces */
- int inn, outn; /* in and out number of Lut components */
-
- p->lutspaces((icmLuBase *)p, &ins, &inn, &outs, &outn, NULL);
-
- /* Determine if the input space is "Device" like, */
- /* ie. luminance will be expected to vary most strongly */
- /* with the diagonal change in input coordinates. */
- switch(ins) {
-
- /* Luminence is carried by the sum of all the output channels, */
- /* so output luminence will dominantly be in diagonal direction. */
- case icSigXYZData: /* This seems to be appropriate ? */
- case icSigRgbData:
- case icSigGrayData:
- case icSigCmykData:
- case icSigCmyData:
- case icSigMch6Data:
- use_sx = 1; /* Simplex interpolation is appropriate */
- break;
-
- /* A single channel carries the luminence information */
- case icSigLabData:
- case icSigLuvData:
- case icSigYCbCrData:
- case icSigYxyData:
- case icSigHlsData:
- case icSigHsvData:
- use_sx = 0; /* N-linear interpolation is appropriate */
- break;
- default:
- use_sx = -1; /* undecided */
- break;
- }
-
- /* If we couldn't figure it out from the input space, */
- /* check output luminance variation with a diagonal input */
- /* change. */
- if (use_sx == -1) {
- int lc; /* Luminance channel */
-
- /* Determine where the luminence is carried in the output */
- switch(outs) {
-
- /* Luminence is carried by the sum of all the output channels */
- case icSigRgbData:
- case icSigGrayData:
- case icSigCmykData:
- case icSigCmyData:
- case icSigMch6Data:
- lc = -1; /* Average all channels */
- break;
-
- /* A single channel carries the luminence information */
- case icSigLabData:
- case icSigLuvData:
- case icSigYCbCrData:
- case icSigYxyData:
- lc = 0;
- break;
-
- case icSigXYZData:
- case icSigHlsData:
- lc = 1;
- break;
-
- case icSigHsvData:
- lc = 2;
- break;
-
- /* default means give up and use N-linear type lookup */
- default:
- lc = -2;
- break;
- }
-
- /* If we know how luminance is represented in output space */
- if (lc != -2) {
- double tout1[MAX_CHAN]; /* Test output values */
- double tout2[MAX_CHAN];
- double tt, diag;
- int n;
-
- /* Determine input space location of min and max of */
- /* given output channel (chan = -1 means average of all) */
- p->lut->min_max(p->lut, tout1, tout2, lc);
-
- /* Convert to vector and then calculate normalized */
- /* dot product with diagonal vector (1,1,1...) */
- for (tt = 0.0, n = 0; n < inn; n++) {
- tout1[n] = tout2[n] - tout1[n];
- tt += tout1[n] * tout1[n];
- }
- if (tt > 0.0)
- tt = sqrt(tt); /* normalizing factor for maximum delta */
- else
- tt = 1.0; /* Hmm. */
- tt *= sqrt((double)inn); /* Normalizing factor for diagonal vector */
- for (diag = 0.0, n = 0; n < outn; n++)
- diag += tout1[n] / tt;
- diag = fabs(diag);
-
- /* I'm not really convinced that this is a reliable */
- /* indicator of whether simplex interpolation should be used ... */
- /* It does seem to do the right thing with YCC space though. */
- if (diag > 0.8) /* Diagonal is dominant ? */
- use_sx = 1;
-
- /* If we couldn't figure it out, use N-linear interpolation */
- if (use_sx == -1)
- use_sx = 0;
- }
- }
-
- if (use_sx) {
- p->lookup_clut = p->lut->lookup_clut_sx;
- } else {
- p->lookup_clut = p->lut->lookup_clut_nl;
- }
- }
-#else /* Development code */
- /* Determine appropriate clut lookup algorithm, */
- /* and set optimised simplex tables */
- {
- int lualg = 0; /* 0 = simplex, 1 = multi-linear, 2 = optimised simlpex */
- icColorSpaceSignature ins, outs; /* In and out Lut color spaces */
- int inn, outn; /* in and out number of Lut components */
-
- p->lutspaces((icmLuBase *)p, &ins, &inn, &outs, &outn, NULL);
-
- /* Determine which type of Lut lookup algorithm is likely to give */
- /* minimal interpolation errors. */
- /* To use the optimised simplex, we should ideally determine */
- /* the simplex cell orientation that makes the simplex split diagonal */
- /* always point towards the white or black points. */
- switch(ins) {
-
- case icSigXYZData: /* This seems to be appropriate ? */
- case icSigRgbData:
- case icSigGrayData:
- case icSigCmykData:
- case icSigCmyData:
- case icSigMch6Data:
- lualg = 0; /* Simplex interpolation is appropriate */
- break;
-
- case icSigLabData:
-// ~~~~9999 this isn't right! need to lookup Lab 50,0,0 through input curves then */
-/* quantize to clut nodes to figure threshold for axis flips */
- p->lut->finfo[0].fth = 0.5; p->lut->finfo[0].bthff = 0; p->lut->finfo[0].athff = 1;
- p->lut->finfo[1].fth = 0.5; p->lut->finfo[1].bthff = 1; p->lut->finfo[1].athff = 0;
- p->lut->finfo[2].fth = 0.5; p->lut->finfo[2].bthff = 1; p->lut->finfo[2].athff = 0;
- lualg = 2;
- break;
-
- /* !!! Should switch to optimised simplex for these too !!! */
- case icSigLuvData:
- case icSigYCbCrData:
- case icSigYxyData:
- case icSigHlsData:
- case icSigHsvData:
- lualg = 1; /* Multi-linear is best as a default for these ? */
- break;
-
- default:
- lualg = 0; /* Simplex is best if we known nothing. */
- break;
- }
-
- if (lualg == 2) {
- p->lookup_clut = icmLut_lookup_clut_osx;
- } else if (lualg == 1) {
- p->lookup_clut = p->lut->lookup_clut_nl;
- } else {
- p->lookup_clut = p->lut->lookup_clut_sx;
- }
- }
-#endif
- return (icmLuBase *)p;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Return an appropriate lookup object */
-/* Return NULL on error, and detailed error in icc */
-static icmLuBase* icc_get_luobj (
- icc *p, /* ICC */
- icmLookupFunc func, /* Conversion functionality */
- icRenderingIntent intent, /* Rendering intent, including icmAbsoluteColorimetricXYZ */
- icColorSpaceSignature pcsor,/* PCS override (0 = def) */
- icmLookupOrder order /* Conversion representation search Order */
-) {
- icmLuBase *luobj = NULL; /* Lookup object to return */
- icColorSpaceSignature pcs, e_pcs; /* PCS and effective PCS */
-
-#ifdef ICM_STRICT
- int rv;
- /* Check that the profile is legal, since we depend on it ? */
- if ((rv = check_icc_legal(p)) != 0)
- return NULL;
-#endif /* ICM_STRICT */
-
- /* Figure out the native and effective PCS */
- e_pcs = pcs = p->header->pcs;
- if (pcsor != icmSigDefaultData)
- e_pcs = pcsor; /* Override */
-
- /* How we expect to execute the request depends firstly on the type of profile */
- switch (p->header->deviceClass) {
- case icSigInputClass:
- case icSigDisplayClass:
- case icSigColorSpaceClass:
-
- /* Look for Intent based AToBX profile + optional BToAX reverse */
- /* or for AToB0 based profile + optional BToA0 reverse */
- /* or three component matrix profile (reversable) */
- /* or momochrome table profile (reversable) */
- /* No Lut intent for ICC < V2.4, but possible for >= V2.4, */
- /* so fall back if we can't find the chosen Lut intent.. */
- /* Device <-> PCS */
- /* Determine the algorithm and set its parameters */
-
- switch (func) {
- icRenderingIntent fbintent; /* Fallback intent */
- icTagSignature ttag, fbtag;
-
- case icmFwd: /* Device to PCS */
- if (intent == icmDefaultIntent)
- intent = icPerceptual; /* Make this the default */
-
- switch (intent) {
- case icAbsoluteColorimetric:
- ttag = icSigAToB1Tag;
- fbtag = icSigAToB0Tag;
- fbintent = intent;
- break;
- case icRelativeColorimetric:
- ttag = icSigAToB1Tag;
- fbtag = icSigAToB0Tag;
- fbintent = icmDefaultIntent;
- break;
- case icPerceptual:
- ttag = icSigAToB0Tag;
- fbtag = icSigAToB0Tag;
- fbintent = icmDefaultIntent;
- break;
- case icSaturation:
- ttag = icSigAToB2Tag;
- fbtag = icSigAToB0Tag;
- fbintent = icmDefaultIntent;
- break;
- case icmAbsolutePerceptual: /* Special icclib intent */
- ttag = icSigAToB0Tag;
- fbtag = icSigAToB0Tag;
- fbintent = intent;
- break;
- case icmAbsoluteSaturation: /* Special icclib intent */
- ttag = icSigAToB2Tag;
- fbtag = icSigAToB0Tag;
- fbintent = intent;
- break;
- default:
- sprintf(p->err,"icc_get_luobj: Unknown intent");
- p->errc = 1;
- return NULL;
- }
-
- if (order != icmLuOrdRev) {
- /* Try Lut type lookup with the chosen intent first */
- if ((luobj = icc_new_icmLuLut(p, ttag,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* Try the fallback tag */
- if ((luobj = icc_new_icmLuLut(p, fbtag,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- fbintent, func)) != NULL)
- break;
-
- /* See if it could be a matrix lookup */
- if ((luobj = new_icmLuMatrixFwd(p,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* See if it could be a monochrome lookup */
- if ((luobj = new_icmLuMonoFwd(p,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
-
- } else {
- /* See if it could be a monochrome lookup */
- if ((luobj = new_icmLuMonoFwd(p,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* See if it could be a matrix lookup */
- if ((luobj = new_icmLuMatrixFwd(p,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* Try Lut type lookup last */
- if ((luobj = icc_new_icmLuLut(p, ttag,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* Try the fallback tag */
- if ((luobj = icc_new_icmLuLut(p, fbtag,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- fbintent, func)) != NULL)
- break;
- }
- break;
-
- case icmBwd: /* PCS to Device */
- if (intent == icmDefaultIntent)
- intent = icPerceptual; /* Make this the default */
-
- switch (intent) {
- case icAbsoluteColorimetric:
- ttag = icSigBToA1Tag;
- fbtag = icSigBToA0Tag;
- fbintent = intent;
- break;
- case icRelativeColorimetric:
- ttag = icSigBToA1Tag;
- fbtag = icSigBToA0Tag;
- fbintent = icmDefaultIntent;
- break;
- case icPerceptual:
- ttag = icSigBToA0Tag;
- fbtag = icSigBToA0Tag;
- fbintent = icmDefaultIntent;
- break;
- case icSaturation:
- ttag = icSigBToA2Tag;
- fbtag = icSigBToA0Tag;
- fbintent = icmDefaultIntent;
- break;
- case icmAbsolutePerceptual: /* Special icclib intent */
- ttag = icSigBToA0Tag;
- fbtag = icSigBToA0Tag;
- fbintent = intent;
- break;
- case icmAbsoluteSaturation: /* Special icclib intent */
- ttag = icSigBToA2Tag;
- fbtag = icSigBToA0Tag;
- fbintent = intent;
- break;
- default:
- sprintf(p->err,"icc_get_luobj: Unknown intent");
- p->errc = 1;
- return NULL;
- }
-
-
- if (order != icmLuOrdRev) {
- /* Try Lut type lookup first */
- if ((luobj = icc_new_icmLuLut(p, ttag,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* Try the fallback Lut */
- if ((luobj = icc_new_icmLuLut(p, fbtag,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- fbintent, func)) != NULL)
- break;
-
- /* See if it could be a matrix lookup */
- if ((luobj = new_icmLuMatrixBwd(p,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* See if it could be a monochrome lookup */
- if ((luobj = new_icmLuMonoBwd(p,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
- } else {
- /* See if it could be a monochrome lookup */
- if ((luobj = new_icmLuMonoBwd(p,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* See if it could be a matrix lookup */
- if ((luobj = new_icmLuMatrixBwd(p,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* Try Lut type lookup last */
- if ((luobj = icc_new_icmLuLut(p, ttag,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* Try the fallback Lut */
- if ((luobj = icc_new_icmLuLut(p, fbtag,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- fbintent, func)) != NULL)
- break;
- }
- break;
-
- default:
- sprintf(p->err,"icc_get_luobj: Inaproptiate function requested");
- p->errc = 1;
- return NULL;
- }
- break;
-
- case icSigOutputClass:
- /* Expect BToA Lut and optional AToB Lut, All intents, expect gamut */
- /* or momochrome table profile (reversable) */
- /* Device <-> PCS */
- /* Gamut Lut - no intent */
- /* Optional preview links PCS <-> PCS */
-
- /* Determine the algorithm and set its parameters */
- switch (func) {
- icTagSignature ttag;
-
- case icmFwd: /* Device to PCS */
-
- if (intent == icmDefaultIntent)
- intent = icPerceptual; /* Make this the default */
-
- switch (intent) {
- case icRelativeColorimetric:
- case icAbsoluteColorimetric:
- ttag = icSigAToB1Tag;
- break;
- case icPerceptual:
- case icmAbsolutePerceptual: /* Special icclib intent */
- ttag = icSigAToB0Tag;
- break;
- case icSaturation:
- case icmAbsoluteSaturation: /* Special icclib intent */
- ttag = icSigAToB2Tag;
- break;
- default:
- sprintf(p->err,"icc_get_luobj: Unknown intent");
- p->errc = 1;
- return NULL;
- }
-
- if (order != icmLuOrdRev) {
- /* Try Lut type lookup first */
- if ((luobj = icc_new_icmLuLut(p, ttag,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL) {
- break;
- }
-
- /* See if it could be a matrix lookup */
- if ((luobj = new_icmLuMatrixFwd(p,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* See if it could be a monochrome lookup */
- if ((luobj = new_icmLuMonoFwd(p,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
- } else {
- /* See if it could be a monochrome lookup */
- if ((luobj = new_icmLuMonoFwd(p,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* See if it could be a matrix lookup */
- if ((luobj = new_icmLuMatrixFwd(p,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* Try Lut type lookup last */
- if ((luobj = icc_new_icmLuLut(p, ttag,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, e_pcs, e_pcs,
- intent, func)) != NULL)
- break;
- }
- break;
-
- case icmBwd: /* PCS to Device */
-
- if (intent == icmDefaultIntent)
- intent = icPerceptual; /* Make this the default */
-
- switch (intent) {
- case icRelativeColorimetric:
- case icAbsoluteColorimetric:
- ttag = icSigBToA1Tag;
- break;
- case icPerceptual:
- case icmAbsolutePerceptual: /* Special icclib intent */
- ttag = icSigBToA0Tag;
- break;
- case icSaturation:
- case icmAbsoluteSaturation: /* Special icclib intent */
- ttag = icSigBToA2Tag;
- break;
- default:
- sprintf(p->err,"icc_get_luobj: Unknown intent");
- p->errc = 1;
- return NULL;
- }
-
- if (order != icmLuOrdRev) {
- /* Try Lut type lookup first */
- if ((luobj = icc_new_icmLuLut(p, ttag,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* See if it could be a matrix lookup */
- if ((luobj = new_icmLuMatrixBwd(p,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* See if it could be a monochrome lookup */
- if ((luobj = new_icmLuMonoBwd(p,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
- } else {
- /* See if it could be a monochrome lookup */
- if ((luobj = new_icmLuMonoBwd(p,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* See if it could be a matrix lookup */
- if ((luobj = new_icmLuMatrixBwd(p,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
-
- /* Try Lut type lookup last */
- if ((luobj = icc_new_icmLuLut(p, ttag,
- pcs, p->header->colorSpace, pcs,
- e_pcs, p->header->colorSpace, e_pcs,
- intent, func)) != NULL)
- break;
- }
- break;
-
- case icmGamut: /* PCS to 1D */
-
-#ifdef ICM_STRICT /* Allow only default and absolute */
- if (intent != icmDefaultIntent
- && intent != icAbsoluteColorimetric) {
- sprintf(p->err,"icc_get_luobj: Intent is inappropriate for Gamut table");
- p->errc = 1;
- return NULL;
- }
-#else /* Be more forgiving */
- switch (intent) {
- case icAbsoluteColorimetric:
- case icmAbsolutePerceptual: /* Special icclib intent */
- case icmAbsoluteSaturation: /* Special icclib intent */
- break;
- case icmDefaultIntent:
- case icRelativeColorimetric:
- case icPerceptual:
- case icSaturation:
- intent = icmDefaultIntent; /* Make all other look like default */
- break;
- default:
- sprintf(p->err,"icc_get_luobj: Unknown intent (0x%x)",intent);
- p->errc = 1;
- return NULL;
- }
-
-#endif
- /* If the target tag exists, and it is a Lut */
- luobj = icc_new_icmLuLut(p, icSigGamutTag,
- pcs, icSigGrayData, pcs,
- e_pcs, icSigGrayData, e_pcs,
- intent, func);
- break;
-
- case icmPreview: /* PCS to PCS */
-
- switch (intent) {
- case icRelativeColorimetric:
- ttag = icSigPreview1Tag;
- break;
- case icPerceptual:
- ttag = icSigPreview0Tag;
- break;
- case icSaturation:
- ttag = icSigPreview2Tag;
- break;
- case icAbsoluteColorimetric:
- case icmAbsolutePerceptual: /* Special icclib intent */
- case icmAbsoluteSaturation: /* Special icclib intent */
- sprintf(p->err,"icc_get_luobj: Intent is inappropriate for preview table");
- p->errc = 1;
- return NULL;
- default:
- sprintf(p->err,"icc_get_luobj: Unknown intent");
- p->errc = 1;
- return NULL;
- }
-
- /* If the target tag exists, and it is a Lut */
- luobj = icc_new_icmLuLut(p, ttag,
- pcs, pcs, pcs,
- e_pcs, e_pcs, e_pcs,
- intent, func);
- break;
-
- default:
- sprintf(p->err,"icc_get_luobj: Inaproptiate function requested");
- p->errc = 1;
- return NULL;
- }
- break;
-
- case icSigLinkClass:
- /* Expect AToB0 Lut and optional BToA0 Lut, One intent in header */
- /* Device <-> Device */
-
- if (intent != p->header->renderingIntent
- && intent != icmDefaultIntent) {
- sprintf(p->err,"icc_get_luobj: Intent is inappropriate for Link profile");
- p->errc = 1;
- return NULL;
- }
- intent = p->header->renderingIntent;
-
- /* Determine the algorithm and set its parameters */
- switch (func) {
- case icmFwd: /* Device to PCS (== Device) */
-
- luobj = icc_new_icmLuLut(p, icSigAToB0Tag,
- p->header->colorSpace, pcs, pcs,
- p->header->colorSpace, pcs, pcs,
- intent, func);
- break;
-
- case icmBwd: /* PCS (== Device) to Device */
-
- luobj = icc_new_icmLuLut(p, icSigBToA0Tag,
- pcs, p->header->colorSpace, pcs,
- pcs, p->header->colorSpace, pcs,
- intent, func);
- break;
-
- default:
- sprintf(p->err,"icc_get_luobj: Inaproptiate function requested");
- p->errc = 1;
- return NULL;
- }
- break;
-
- case icSigAbstractClass:
- /* Expect AToB0 Lut and option BToA0 Lut, with either relative or absolute intent. */
- /* PCS <-> PCS */
- /* Determine the algorithm and set its parameters */
-
- if (intent != icmDefaultIntent
- && intent != icRelativeColorimetric
- && intent != icAbsoluteColorimetric) {
- sprintf(p->err,"icc_get_luobj: Intent is inappropriate for Abstract profile");
- p->errc = 1;
- return NULL;
- }
-
- switch (func) {
- case icmFwd: /* PCS (== Device) to PCS */
-
- luobj = icc_new_icmLuLut(p, icSigAToB0Tag,
- p->header->colorSpace, pcs, pcs,
- e_pcs, e_pcs, e_pcs,
- intent, func);
- break;
-
- case icmBwd: /* PCS to PCS (== Device) */
-
- luobj = icc_new_icmLuLut(p, icSigBToA0Tag,
- pcs, p->header->colorSpace, pcs,
- e_pcs, e_pcs, e_pcs,
- intent, func);
- break;
-
- default:
- sprintf(p->err,"icc_get_luobj: Inaproptiate function requested");
- p->errc = 1;
- return NULL;
- }
- break;
-
- case icSigNamedColorClass:
- /* Expect Name -> Device, Optional PCS */
- /* and a reverse lookup would be useful */
- /* (ie. PCS or Device coords to closest named color) */
- /* ~~ to be implemented ~~ */
-
- /* ~~ Absolute intent is valid for processing of */
- /* PCS from named Colors. Also allow for e_pcs */
- if (intent != icmDefaultIntent
- && intent != icRelativeColorimetric
- && intent != icAbsoluteColorimetric) {
- sprintf(p->err,"icc_get_luobj: Intent is inappropriate for Named Color profile");
- p->errc = 1;
- return NULL;
- }
-
- sprintf(p->err,"icc_get_luobj: Named Colors not handled yet");
- p->errc = 1;
- return NULL;
-
- default:
- sprintf(p->err,"icc_get_luobj: Unknown profile class");
- p->errc = 1;
- return NULL;
- }
-
- if (luobj == NULL) {
- sprintf(p->err,"icc_get_luobj: Unable to locate usable conversion");
- p->errc = 1;
- } else {
- luobj->order = order;
- }
-
- return luobj;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Returns total ink limit and channel maximums. */
-/* Returns -1.0 if not applicable for this type of profile. */
-/* Returns -1.0 for grey, additive, or any profiles < 4 channels. */
-/* This is a place holder that uses a heuristic, */
-/* until there is a private or standard tag for this information */
-static double icm_get_tac( /* return TAC */
-icc *p,
-double *chmax, /* device return channel sums. May be NULL */
-void (*calfunc)(void *cntx, double *out, double *in), /* Optional calibration func. */
-void *cntx
-) {
- icmHeader *rh = p->header;
- icmLuBase *luo;
- icmLuLut *ll;
- icmLut *lut;
- icColorSpaceSignature outs; /* Type of output space */
- int inn, outn; /* Number of components */
- icmLuAlgType alg; /* Type of lookup algorithm */
- double tac = 0.0;
- double max[MAX_CHAN]; /* Channel maximums */
- int i, f;
- unsigned int uf;
- int size; /* Lut table size */
- double *gp; /* Pointer to grid cube base */
-
- /* If not something that can really have a TAC */
- if (rh->deviceClass != icSigDisplayClass
- && rh->deviceClass != icSigOutputClass
- && rh->deviceClass != icSigLinkClass) {
- return -1.0;
- }
-
- /* If not a suitable color space */
- switch (rh->colorSpace) {
- /* Not applicable */
- case icSigXYZData:
- case icSigLabData:
- case icSigLuvData:
- case icSigYCbCrData:
- case icSigYxyData:
- case icSigHsvData:
- case icSigHlsData:
- return -1.0;
-
- /* Assume no limit */
- case icSigGrayData:
- case icSig2colorData:
- case icSig3colorData:
- case icSigRgbData:
- return -1.0;
-
- default:
- break;
- }
-
- /* Get a PCS->device colorimetric lookup */
- if ((luo = p->get_luobj(p, icmBwd, icRelativeColorimetric, icmSigDefaultData, icmLuOrdNorm)) == NULL) {
- if ((luo = p->get_luobj(p, icmBwd, icmDefaultIntent, icmSigDefaultData, icmLuOrdNorm)) == NULL) {
- return -1.0;
- }
- }
-
- /* Get details of conversion (Arguments may be NULL if info not needed) */
- luo->spaces(luo, NULL, &inn, &outs, &outn, &alg, NULL, NULL, NULL, NULL);
-
- /* Assume any non-Lut type doesn't have a TAC */
- if (alg != icmLutType) {
- return -1.0;
- }
-
- ll = (icmLuLut *)luo;
-
- /* We have a Lut type. Search the lut for the largest values */
- for (f = 0; f < outn; f++)
- max[f] = 0.0;
-
- lut = ll->lut;
- gp = lut->clutTable; /* Base of grid array */
- size = sat_pow(lut->clutPoints,lut->inputChan);
- for (i = 0; i < size; i++) {
- double tot, vv[MAX_CHAN];
-
- lut->lookup_output(lut,vv,gp); /* Lookup though output tables */
- ll->out_denormf(vv,vv); /* Normalize for output color space */
-
- if (calfunc != NULL)
- calfunc(cntx, vv, vv); /* Apply device calibration */
-
- for (tot = 0.0, uf = 0; uf < lut->outputChan; uf++) {
- tot += vv[uf];
- if (vv[uf] > max[uf])
- max[uf] = vv[uf];
- }
- if (tot > tac)
- tac = tot;
- gp += lut->outputChan;
- }
-
- if (chmax != NULL) {
- for (f = 0; f < outn; f++)
- chmax[f] = max[f];
- }
-
- luo->del(luo);
-
- return tac;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Create an empty object. Return NULL on error */
-icc *new_icc_a(
-icmAlloc *al /* Memory allocator */
-) {
- unsigned int i;
- icc *p;
-
- if ((p = (icc *) al->calloc(al, 1,sizeof(icc))) == NULL) {
- return NULL;
- }
- p->ver = 0; /* default is V2 profile */
-
- p->al = al; /* Heap allocator */
-
- p->get_rfp = icc_get_rfp;
- p->set_version = icc_set_version;
- p->get_size = icc_get_size;
- p->read = icc_read;
- p->read_x = icc_read_x;
- p->write = icc_write;
- p->write_x = icc_write_x;
- p->dump = icc_dump;
- p->del = icc_delete;
- p->add_tag = icc_add_tag;
- p->link_tag = icc_link_tag;
- p->find_tag = icc_find_tag;
- p->read_tag = icc_read_tag;
- p->read_tag_any = icc_read_tag_any;
- p->rename_tag = icc_rename_tag;
- p->unread_tag = icc_unread_tag;
- p->read_all_tags = icc_read_all_tags;
- p->delete_tag = icc_delete_tag;
- p->check_id = icc_check_id;
- p->get_tac = icm_get_tac;
- p->get_luobj = icc_get_luobj;
- p->new_clutluobj = icc_new_icmLuLut;
-
-#if defined(__IBMC__) && defined(_M_IX86)
- _control87(EM_UNDERFLOW, EM_UNDERFLOW);
-#endif
-
- /* Allocate a header object */
- if ((p->header = new_icmHeader(p)) == NULL) {
- al->free(al, p);
- return NULL;
- }
-
- /* Values that must be set before writing */
- p->header->deviceClass = icMaxEnumClass;/* Type of profile - must be set! */
- p->header->colorSpace = icMaxEnumData; /* Clr space of data - must be set! */
- p->header->pcs = icMaxEnumData; /* PCS: XYZ or Lab - must be set! */
- p->header->renderingIntent = icMaxEnumIntent; /* Rendering intent - must be set ! */
-
- /* Values that should be set before writing */
- p->header->manufacturer = -1; /* Dev manufacturer - should be set ! */
- p->header->model = -1; /* Dev model number - should be set ! */
- p->header->attributes.l = 0; /* ICC Device attributes - should set ! */
- p->header->flags = 0; /* Embedding flags - should be set ! */
-
- /* Values that may be set before writing */
- p->header->attributes.h = 0; /* Dev Device attributes - may be set ! */
- p->header->creator = str2tag("argl"); /* Profile creator - Argyll - may be set ! */
-
- /* Init default values in header */
- p->header->cmmId = str2tag("argl"); /* CMM for profile - Argyll CMM */
- p->header->majv = 2; /* Current version 2.2.0 */
- p->header->minv = 2;
- p->header->bfv = 0;
- setcur_DateTimeNumber(&p->header->date);/* Creation Date */
- p->header->platform = icSigMicrosoft; /* Primary Platform */
- p->header->illuminant = icmD50; /* Profile illuminant - D50 */
-
- /* Values that will be created automatically */
- for (i = 0; i < 16; i++)
- p->header->id[i] = 0;
-
- return p;
-}
-
-
-/* ---------------------------------------------------------- */
-/* Print an int vector to a string. */
-/* Returned static buffer is re-used every 5 calls. */
-char *icmPiv(int di, int *p) {
- static char buf[5][MAX_CHAN * 16];
- static int ix = 0;
- int e;
- char *bp;
-
- if (++ix >= 5)
- ix = 0;
- bp = buf[ix];
-
- if (di > MAX_CHAN)
- di = MAX_CHAN; /* Make sure that buf isn't overrun */
-
- for (e = 0; e < di; e++) {
- if (e > 0)
- *bp++ = ' ';
- sprintf(bp, "%d", p[e]); bp += strlen(bp);
- }
- return buf[ix];
-}
-
-/* Print a double color vector to a string. */
-/* Returned static buffer is re-used every 5 calls. */
-char *icmPdv(int di, double *p) {
- static char buf[5][MAX_CHAN * 16];
- static int ix = 0;
- int e;
- char *bp;
-
- if (++ix >= 5)
- ix = 0;
- bp = buf[ix];
-
- if (di > MAX_CHAN)
- di = MAX_CHAN; /* Make sure that buf isn't overrun */
-
- for (e = 0; e < di; e++) {
- if (e > 0)
- *bp++ = ' ';
- sprintf(bp, "%f", p[e]); bp += strlen(bp);
- }
- return buf[ix];
-}
-
-/* Print a float color vector to a string. */
-/* Returned static buffer is re-used every 5 calls. */
-char *icmPfv(int di, float *p) {
- static char buf[5][MAX_CHAN * 16];
- static int ix = 0;
- int e;
- char *bp;
-
- if (++ix >= 5)
- ix = 0;
- bp = buf[ix];
-
- if (di > MAX_CHAN)
- di = MAX_CHAN; /* Make sure that buf isn't overrun */
-
- for (e = 0; e < di; e++) {
- if (e > 0)
- *bp++ = ' ';
- sprintf(bp, "%f", p[e]); bp += strlen(bp);
- }
- return buf[ix];
-}
-
-/* Print an 0..1 range XYZ as a D50 Lab string */
-/* Returned static buffer is re-used every 5 calls. */
-char *icmPLab(double *p) {
- static char buf[5][MAX_CHAN * 16];
- static int ix = 0;
- int e;
- char *bp;
- double lab[3];
-
- if (++ix >= 5)
- ix = 0;
- bp = buf[ix];
-
- icmXYZ2Lab(&icmD50, lab, p);
-
- for (e = 0; e < 3; e++) {
- if (e > 0)
- *bp++ = ' ';
- sprintf(bp, "%f", lab[e]); bp += strlen(bp);
- }
- return buf[ix];
-}
-
-
-/* ---------------------------------------------------------- */
-