summaryrefslogtreecommitdiff
path: root/icc/icc.c
diff options
context:
space:
mode:
Diffstat (limited to 'icc/icc.c')
-rwxr-xr-x[-rw-r--r--]icc/icc.c217
1 files changed, 135 insertions, 82 deletions
diff --git a/icc/icc.c b/icc/icc.c
index 87ce500..92611c3 100644..100755
--- a/icc/icc.c
+++ b/icc/icc.c
@@ -74,7 +74,7 @@
#endif
#include "icc.h"
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(vsnprintf)
#define vsnprintf _vsnprintf
#define snprintf _snprintf
#endif
@@ -11801,7 +11801,7 @@ static int icc_check_id(
return 1;
}
- if ((md5 = new_icmMD5(p->al)) == NULL) {
+ if ((md5 = new_icmMD5_a(p->al)) == NULL) {
sprintf(p->err,"icc_check_id: new_icmMD5 failed");
return p->errc = 3;
}
@@ -11855,84 +11855,11 @@ static int icc_check_id(
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 */
-}
-
void quantize3x3S15Fixed16(double targ[3], double mat[3][3], double in[3]);
-/* 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 */
-
- /* 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;
- }
+/* Add any automatically created tags. */
+/* (Hmm. Should we remove them if they shouldn't be there ?) */
+static int icc_add_auto_tags(icc *p) {
/* If we're using the ArgyllCMS 'arts' tag to record the chromatic */
/* adapation cone matrix used for the Media Relative WP Transformation, */
@@ -11940,6 +11867,7 @@ static int icc_write_x(
/* Don't write it if there is to 'wtpt' tag (i.e. it's a device link) */
if (p->useArts
&& p->find_tag(p, icSigMediaWhitePointTag) == 0) {
+ int rv;
icmS15Fixed16Array *artsTag;
/* Make sure no 'arts' tag currently exists */
@@ -11981,6 +11909,7 @@ static int icc_write_x(
/* ICCV4 style, then set the media white point tag to D50 and save */
/* the chromatic adapation matrix to the 'chad' tag. */
{
+ int rv;
icmXYZArray *whitePointTag;
icmS15Fixed16Array *chadTag;
@@ -12035,6 +11964,94 @@ static int icc_write_x(
whitePointTag->data[0] = icmD50;
}
}
+ return 0;
+}
+
+/* Return the total size needed for the profile. */
+/* This will add any automatic tags such as 'arts' tag, */
+/* so the current information needs to be final enough */
+/* for the automatic tag creation to be correct. */
+/* Return 0 on error. */
+static unsigned int icc_get_size(
+ icc *p
+) {
+ unsigned int i, size = 0;
+
+ /* Ignore any errors this time */
+ icc_add_auto_tags(p);
+
+#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];
+
+ if ((rv = icc_add_auto_tags(p)) != 0)
+ return rv;
+
+ p->fp = fp; /* Open file pointer */
+ if (take_fp)
+ p->del_fp = 1;
+ p->of = of; /* Offset of ICC profile */
+
+ /* 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;
+ }
/* Check that the right tags etc. are present for a legal ICC profile */
if ((rv = check_icc_legal(p)) != 0) {
@@ -12132,7 +12149,7 @@ static int icc_write_x(
icmMD5 *md5 = NULL;
icmFile *ofp, *dfp = NULL;
- if ((md5 = new_icmMD5(p->al)) == NULL) {
+ if ((md5 = new_icmMD5_a(p->al)) == NULL) {
sprintf(p->err,"icc_write: new_icmMD5 failed");
p->al->free(p->al, buf);
return p->errc = 2;
@@ -13747,7 +13764,7 @@ void icmScale33(double out[3], double in1[3], double in0[3], double rat) {
out[2] = in0[2] + (in1[2] - in0[2]) * rat;
}
-/* Normalise a two point vector to the given length. */
+/* Normalise a vector from 0->1 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) {
@@ -13964,6 +13981,35 @@ double ve_0[3] /* Second point on line */
}
/* - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Compute the closest point on a line to a point. */
+/* Return closest point and parameter value if not NULL. */
+/* Return nz if the line length is zero */
+int icmLinePointClosest(double cp[3], double *pa,
+ double la0[3], double la1[3], double pp[3]) {
+ double va[3], vp[3];
+ double val; /* Vector length */
+ double a; /* Parameter value */
+
+ icmSub3(va, la1, la0); /* Line vector */
+ val = icmNorm3(va); /* Vector length */
+
+ if (val < 1e-12)
+ return 1;
+
+ icmSub3(vp, pp, la0); /* Point vector to line base */
+
+ a = icmDot3(vp, va) / val; /* Normalised dist of point projected onto line */
+
+ if (cp != NULL)
+ icmBlend3(cp, la0, la1, a);
+
+ if (pa != NULL)
+ *pa = a;
+
+ 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. */
@@ -15909,12 +15955,19 @@ static void icmMD5_get(icmMD5 *p, ORD8 chsum[16]) {
/* Delete the instance */
static void icmMD5_del(icmMD5 *p) {
- p->al->free(p->al, p);
+ icmAlloc *al = p->al;
+ int del_al = p->del_al;
+
+ /* This object */
+ al->free(al, p);
+
+ if (del_al) /* We are responsible for deleting allocator */
+ al->del(al);
}
/* 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 *new_icmMD5_a(icmAlloc *al) {
icmMD5 *p;
if ((p = (icmMD5 *)al->calloc(al,1,sizeof(icmMD5))) == NULL)