summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2010-07-10 21:08:52 +0200
committerTor Andersson <tor@ghostscript.com>2010-07-10 21:08:52 +0200
commita8a47bb3f214467016d2b37d95e98ffdec4f7ba1 (patch)
tree616430e11d8d66b397572ff982c899f63e25a2a4
parent47dd54d16a6132b14103fbc146970d22172f07c3 (diff)
downloadmupdf-a8a47bb3f214467016d2b37d95e98ffdec4f7ba1.tar.xz
Refactor colorspace and PDF image parsing code.
-rw-r--r--apps/pdfextract.c8
-rw-r--r--draw/imageunpack.c27
-rw-r--r--fitz/fitz.h12
-rw-r--r--fitz/res_colorspace.c449
-rw-r--r--fitz/stm_buffer.c18
-rw-r--r--mupdf/mupdf.h35
-rw-r--r--mupdf/pdf_build.c72
-rw-r--r--mupdf/pdf_colorspace.c924
-rw-r--r--mupdf/pdf_image.c539
-rw-r--r--mupdf/pdf_interpret.c14
-rw-r--r--mupdf/pdf_pattern.c2
-rw-r--r--mupdf/pdf_store.c2
-rw-r--r--mupdf/pdf_xobject.c4
13 files changed, 742 insertions, 1364 deletions
diff --git a/apps/pdfextract.c b/apps/pdfextract.c
index 9da182d7..00bddc11 100644
--- a/apps/pdfextract.c
+++ b/apps/pdfextract.c
@@ -38,11 +38,11 @@ static void saveimage(int num, int gen)
xref->store = pdf_newstore();
- error = pdf_loadimage(&img, xref, ref);
+ error = pdf_loadimage(&img, xref, nil, ref);
if (error)
die(error);
- pix = fz_newpixmap(img->cs, 0, 0, img->w, img->h);
+ pix = fz_newpixmap(img->colorspace, 0, 0, img->w, img->h);
error = pdf_loadtile(img, pix);
if (error)
@@ -68,13 +68,13 @@ static void saveimage(int num, int gen)
pix = temp;
}
- if (img->cs && strcmp(img->cs->name, "DeviceRGB"))
+ if (img->colorspace && strcmp(img->colorspace->name, "DeviceRGB"))
{
fz_pixmap *temp;
temp = fz_newpixmap(pdf_devicergb, pix->x, pix->y, pix->w, pix->h);
- fz_convertpixmap(img->cs, pix, pdf_devicergb, temp);
+ fz_convertpixmap(img->colorspace, pix, pdf_devicergb, temp);
fz_droppixmap(pix);
pix = temp;
}
diff --git a/draw/imageunpack.c b/draw/imageunpack.c
index 25a21770..6e5467ad 100644
--- a/draw/imageunpack.c
+++ b/draw/imageunpack.c
@@ -6,7 +6,7 @@ typedef unsigned char byte;
* Apply decode parameters
*/
-static void decodetile(fz_pixmap *pix, int skip, float *decode)
+static void decodetile(fz_pixmap *pix, int imagemask, float *decode)
{
int min[FZ_MAXCOLORS];
int max[FZ_MAXCOLORS];
@@ -17,9 +17,8 @@ static void decodetile(fz_pixmap *pix, int skip, float *decode)
int wh = pix->w * pix->h;
int i;
int justinvert = 1;
- unsigned int mask;
- for (i = 0; i < n-skip; i++)
+ for (i = 0; i < n - imagemask; i++)
{
min[i] = decode[i * 2] * 255;
max[i] = decode[i * 2 + 1] * 255;
@@ -28,18 +27,13 @@ static void decodetile(fz_pixmap *pix, int skip, float *decode)
justinvert &= min[i] == 255 && max[i] == 0 && sub[i] == -255;
}
- if (skip)
+ if (imagemask)
{
min[i] = 0;
max[i] = 255;
sub[i] = 255;
}
- if (fz_isbigendian())
- mask = 0x00ff00ff;
- else
- mask = 0xff00ff00;
-
if (!needed)
return;
@@ -52,9 +46,10 @@ static void decodetile(fz_pixmap *pix, int skip, float *decode)
}
break;
case 2:
- if (justinvert) {
+ if (justinvert)
+ {
+ unsigned mask = fz_isbigendian() ? 0x00ff00ff : 0xff00ff00;
unsigned *wp = (unsigned *)p;
-
if ((((char *)wp - (char *)0) & 3) == 0) {
int hwh = wh / 2;
wh = wh - 2 * hwh;
@@ -72,11 +67,13 @@ static void decodetile(fz_pixmap *pix, int skip, float *decode)
}
}
else
- while (wh--)
{
- p[0] = min[0] + fz_mul255(sub[0], p[0]);
- p[1] = min[1] + fz_mul255(sub[1], p[1]);
- p += 2;
+ while (wh--)
+ {
+ p[0] = min[0] + fz_mul255(sub[0], p[0]);
+ p[1] = min[1] + fz_mul255(sub[1], p[1]);
+ p += 2;
+ }
}
break;
default:
diff --git a/fitz/fitz.h b/fitz/fitz.h
index e74f12cc..8ad72322 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -474,6 +474,7 @@ struct fz_buffer_s
fz_buffer * fz_newbuffer(int size);
fz_buffer * fz_newbufferwithmemory(unsigned char *data, int size);
+void fz_resizebuffer(fz_buffer *buf, int size);
void fz_rewindbuffer(fz_buffer *buf);
void fz_growbuffer(fz_buffer *buf);
@@ -711,30 +712,25 @@ extern fz_colorspace *pdf_devicegray;
extern fz_colorspace *pdf_devicergb;
extern fz_colorspace *pdf_devicebgr;
extern fz_colorspace *pdf_devicecmyk;
-extern fz_colorspace *pdf_devicelab;
-extern fz_colorspace *pdf_devicepattern;
struct fz_colorspace_s
{
int refs;
char name[16];
int n;
- void (*convpixmap)(fz_colorspace *ss, fz_pixmap *sp, fz_colorspace *ds, fz_pixmap *dp);
- void (*convcolor)(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv);
void (*toxyz)(fz_colorspace *, float *src, float *xyz);
void (*fromxyz)(fz_colorspace *, float *xyz, float *dst);
- void (*freefunc)(fz_colorspace *);
+ void (*freedata)(fz_colorspace *);
+ void *data;
};
+fz_colorspace *fz_newcolorspace(char *name, int n);
fz_colorspace *fz_keepcolorspace(fz_colorspace *cs);
void fz_dropcolorspace(fz_colorspace *cs);
void fz_convertcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv);
void fz_convertpixmap(fz_colorspace *srcs, fz_pixmap *srcv, fz_colorspace *dsts, fz_pixmap *dstv);
-void fz_stdconvcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv);
-void fz_stdconvpixmap(fz_colorspace *srcs, fz_pixmap *srcv, fz_colorspace *dsts, fz_pixmap *dstv);
-
/*
* Fonts come in two variants:
* Regular fonts are handled by FreeType.
diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c
index 79ca8ff4..6cad3f16 100644
--- a/fitz/res_colorspace.c
+++ b/fitz/res_colorspace.c
@@ -1,15 +1,17 @@
#include "fitz.h"
-void
-fz_convertpixmap(fz_colorspace *srcs, fz_pixmap *src, fz_colorspace *dsts, fz_pixmap *dst)
-{
- srcs->convpixmap(srcs, src, dsts, dst);
-}
-
-void
-fz_convertcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv)
+fz_colorspace *
+fz_newcolorspace(char *name, int n)
{
- srcs->convcolor(srcs, srcv, dsts, dstv);
+ fz_colorspace *cs = fz_malloc(sizeof(fz_colorspace));
+ cs->refs = 1;
+ fz_strlcpy(cs->name, name, sizeof cs->name);
+ cs->n = n;
+ cs->toxyz = NULL;
+ cs->fromxyz = NULL;
+ cs->freedata = NULL;
+ cs->data = NULL;
+ return cs;
}
fz_colorspace *
@@ -28,33 +30,262 @@ fz_dropcolorspace(fz_colorspace *cs)
return;
if (cs && --cs->refs == 0)
{
- if (cs->freefunc)
- cs->freefunc(cs);
+ if (cs->freedata && cs->data)
+ cs->freedata(cs);
fz_free(cs);
}
}
-void
-fz_stdconvcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv)
+/*
+ * Fast Device color spaces
+ */
+
+static void graytoxyz(fz_colorspace *cs, float *gray, float *xyz)
{
- float xyz[3];
- int i;
+ xyz[0] = gray[0];
+ xyz[1] = gray[0];
+ xyz[2] = gray[0];
+}
- if (srcs != dsts)
+static void xyztogray(fz_colorspace *cs, float *xyz, float *gray)
+{
+ float r = xyz[0];
+ float g = xyz[1];
+ float b = xyz[2];
+ gray[0] = r * 0.3f + g * 0.59f + b * 0.11f;
+}
+
+static void rgbtoxyz(fz_colorspace *cs, float *rgb, float *xyz)
+{
+ xyz[0] = rgb[0];
+ xyz[1] = rgb[1];
+ xyz[2] = rgb[2];
+}
+
+static void xyztorgb(fz_colorspace *cs, float *xyz, float *rgb)
+{
+ rgb[0] = xyz[0];
+ rgb[1] = xyz[1];
+ rgb[2] = xyz[2];
+}
+
+static void bgrtoxyz(fz_colorspace *cs, float *bgr, float *xyz)
+{
+ xyz[0] = bgr[2];
+ xyz[1] = bgr[1];
+ xyz[2] = bgr[0];
+}
+
+static void xyztobgr(fz_colorspace *cs, float *xyz, float *bgr)
+{
+ bgr[0] = xyz[2];
+ bgr[1] = xyz[1];
+ bgr[2] = xyz[0];
+}
+
+static void cmyktoxyz(fz_colorspace *cs, float *cmyk, float *xyz)
+{
+ xyz[0] = 1 - MIN(1, cmyk[0] + cmyk[3]);
+ xyz[1] = 1 - MIN(1, cmyk[1] + cmyk[3]);
+ xyz[2] = 1 - MIN(1, cmyk[2] + cmyk[3]);
+}
+
+static void xyztocmyk(fz_colorspace *cs, float *xyz, float *cmyk)
+{
+ float c, m, y, k;
+ c = 1 - xyz[0];
+ m = 1 - xyz[1];
+ y = 1 - xyz[2];
+ k = MIN(c, MIN(m, y));
+ cmyk[0] = c - k;
+ cmyk[1] = m - k;
+ cmyk[2] = y - k;
+ cmyk[3] = k;
+}
+
+static fz_colorspace kdevicegray = { -1, "DeviceGray", 1, graytoxyz, xyztogray };
+static fz_colorspace kdevicergb = { -1, "DeviceRGB", 3, rgbtoxyz, xyztorgb };
+static fz_colorspace kdevicebgr = { -1, "DeviceRGB", 3, bgrtoxyz, xyztobgr };
+static fz_colorspace kdevicecmyk = { -1, "DeviceCMYK", 4, cmyktoxyz, xyztocmyk };
+
+fz_colorspace *pdf_devicegray = &kdevicegray;
+fz_colorspace *pdf_devicergb = &kdevicergb;
+fz_colorspace *pdf_devicebgr = &kdevicebgr;
+fz_colorspace *pdf_devicecmyk = &kdevicecmyk;
+
+/*
+ * Pixmap color conversions
+ */
+
+static void fastgraytorgb(fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int n = src->w * src->h;
+ while (n--)
{
- srcs->toxyz(srcs, srcv, xyz);
- dsts->fromxyz(dsts, xyz, dstv);
- for (i = 0; i < dsts->n; i++)
- dstv[i] = CLAMP(dstv[i], 0, 1);
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ d[3] = s[1];
+ s += 2;
+ d += 4;
}
- else
+}
+
+static void fastgraytocmyk(fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int n = src->w * src->h;
+ while (n--)
{
- for (i = 0; i < srcs->n; i++)
- dstv[i] = srcv[i];
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = s[0];
+ d[4] = s[1];
+ s += 2;
+ d += 5;
}
}
-void
+static void fastrgbtogray(fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int n = src->w * src->h;
+ while (n--)
+ {
+ d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
+ d[1] = s[3];
+ s += 4;
+ d += 2;
+ }
+}
+
+static void fastbgrtogray(fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int n = src->w * src->h;
+ while (n--)
+ {
+ d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
+ d[1] = s[3];
+ s += 4;
+ d += 2;
+ }
+}
+
+static void fastrgbtocmyk(fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int n = src->w * src->h;
+ while (n--)
+ {
+ unsigned char c = 255 - s[0];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[2];
+ unsigned char k = MIN(c, MIN(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = s[3];
+ s += 4;
+ d += 5;
+ }
+}
+
+static void fastbgrtocmyk(fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int n = src->w * src->h;
+ while (n--)
+ {
+ unsigned char c = 255 - s[2];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[0];
+ unsigned char k = MIN(c, MIN(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = s[3];
+ s += 4;
+ d += 5;
+ }
+}
+
+static void fastcmyktogray(fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int n = src->w * src->h;
+ while (n--)
+ {
+ unsigned char c = fz_mul255(s[0], 77);
+ unsigned char m = fz_mul255(s[1], 150);
+ unsigned char y = fz_mul255(s[2], 28);
+ d[0] = 255 - MIN(c + m + y + s[3], 255);
+ d[1] = s[4];
+ s += 5;
+ d += 2;
+ }
+}
+
+static void fastcmyktorgb(fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int n = src->w * src->h;
+ while (n--)
+ {
+ d[0] = 255 - MIN(s[0] + s[3], 255);
+ d[1] = 255 - MIN(s[1] + s[3], 255);
+ d[2] = 255 - MIN(s[2] + s[3], 255);
+ d[3] = s[4];
+ s += 5;
+ d += 4;
+ }
+}
+
+static void fastcmyktobgr(fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int n = src->w * src->h;
+ while (n--)
+ {
+ d[0] = 255 - MIN(s[2] + s[3], 255);
+ d[1] = 255 - MIN(s[1] + s[3], 255);
+ d[2] = 255 - MIN(s[0] + s[3], 255);
+ d[3] = s[4];
+ s += 5;
+ d += 4;
+ }
+}
+
+static void fastrgbtobgr(fz_pixmap *src, fz_pixmap *dst)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int n = src->w * src->h;
+ while (n--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ d[3] = s[3];
+ s += 4;
+ d += 4;
+ }
+}
+
+static void
fz_stdconvpixmap(fz_colorspace *srcs, fz_pixmap *src, fz_colorspace *dsts, fz_pixmap *dst)
{
float srcv[FZ_MAXCOLORS];
@@ -85,3 +316,173 @@ fz_stdconvpixmap(fz_colorspace *srcs, fz_pixmap *src, fz_colorspace *dsts, fz_pi
}
}
+void
+fz_convertpixmap(fz_colorspace *ss, fz_pixmap *sp, fz_colorspace *ds, fz_pixmap *dp)
+{
+ if (ss == pdf_devicegray)
+ {
+ if (ds == pdf_devicergb) fastgraytorgb(sp, dp);
+ else if (ds == pdf_devicebgr) fastgraytorgb(sp, dp); /* bgr == rgb here */
+ else if (ds == pdf_devicecmyk) fastgraytocmyk(sp, dp);
+ else fz_stdconvpixmap(ss, sp, ds, dp);
+ }
+
+ else if (ss == pdf_devicergb)
+ {
+ if (ds == pdf_devicegray) fastrgbtogray(sp, dp);
+ else if (ds == pdf_devicebgr) fastrgbtobgr(sp, dp);
+ else if (ds == pdf_devicecmyk) fastrgbtocmyk(sp, dp);
+ else fz_stdconvpixmap(ss, sp, ds, dp);
+
+ }
+
+ else if (ss == pdf_devicebgr)
+ {
+ if (ds == pdf_devicegray) fastbgrtogray(sp, dp);
+ else if (ds == pdf_devicergb) fastrgbtobgr(sp, dp); /* bgr = rgb here */
+ else if (ds == pdf_devicecmyk) fastbgrtocmyk(sp, dp);
+ else fz_stdconvpixmap(ss, sp, ds, dp);
+
+ }
+
+ else if (ss == pdf_devicecmyk)
+ {
+ if (ds == pdf_devicegray) fastcmyktogray(sp, dp);
+ else if (ds == pdf_devicebgr) fastcmyktobgr(sp, dp);
+ else if (ds == pdf_devicergb) fastcmyktorgb(sp, dp);
+ else fz_stdconvpixmap(ss, sp, ds, dp);
+ }
+
+ else fz_stdconvpixmap(ss, sp, ds, dp);
+}
+
+/*
+ * Convert a single color
+ */
+
+static void
+fz_stdconvcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv)
+{
+ float xyz[3];
+ int i;
+
+ if (srcs != dsts)
+ {
+ assert(srcs->toxyz && dsts->fromxyz);
+ srcs->toxyz(srcs, srcv, xyz);
+ dsts->fromxyz(dsts, xyz, dstv);
+ for (i = 0; i < dsts->n; i++)
+ dstv[i] = CLAMP(dstv[i], 0, 1);
+ }
+ else
+ {
+ for (i = 0; i < srcs->n; i++)
+ dstv[i] = srcv[i];
+ }
+}
+
+void
+fz_convertcolor(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv)
+{
+ if (ss == pdf_devicegray)
+ {
+ if ((ds == pdf_devicergb) || (ds == pdf_devicebgr))
+ {
+ dv[0] = sv[0];
+ dv[1] = sv[0];
+ dv[2] = sv[0];
+ }
+ else if (ds == pdf_devicecmyk)
+ {
+ dv[0] = 0;
+ dv[1] = 0;
+ dv[2] = 0;
+ dv[3] = sv[0];
+ }
+ else
+ fz_stdconvcolor(ss, sv, ds, dv);
+ }
+
+ else if (ss == pdf_devicergb)
+ {
+ if (ds == pdf_devicegray)
+ {
+ dv[0] = sv[0] * 0.3f + sv[1] * 0.59f + sv[2] * 0.11f;
+ }
+ else if (ds == pdf_devicebgr)
+ {
+ dv[0] = sv[2];
+ dv[1] = sv[1];
+ dv[2] = sv[0];
+ }
+ else if (ds == pdf_devicecmyk)
+ {
+ float c = 1 - sv[0];
+ float m = 1 - sv[1];
+ float y = 1 - sv[2];
+ float k = MIN(c, MIN(m, y));
+ dv[0] = c - k;
+ dv[1] = m - k;
+ dv[2] = y - k;
+ dv[3] = k;
+ }
+ else
+ fz_stdconvcolor(ss, sv, ds, dv);
+ }
+
+ else if (ss == pdf_devicebgr)
+ {
+ if (ds == pdf_devicegray)
+ {
+ dv[0] = sv[0] * 0.11f + sv[1] * 0.59f + sv[2] * 0.3f;
+ }
+ else if (ds == pdf_devicebgr)
+ {
+ dv[0] = sv[2];
+ dv[1] = sv[1];
+ dv[2] = sv[0];
+ }
+ else if (ds == pdf_devicecmyk)
+ {
+ float c = 1 - sv[2];
+ float m = 1 - sv[1];
+ float y = 1 - sv[0];
+ float k = MIN(c, MIN(m, y));
+ dv[0] = c - k;
+ dv[1] = m - k;
+ dv[2] = y - k;
+ dv[3] = k;
+ }
+ else
+ fz_stdconvcolor(ss, sv, ds, dv);
+ }
+
+ else if (ss == pdf_devicecmyk)
+ {
+ if (ds == pdf_devicegray)
+ {
+ float c = sv[1] * 0.3f;
+ float m = sv[2] * 0.59f;
+ float y = sv[2] * 0.11f;
+ dv[0] = 1 - MIN(c + m + y + sv[3], 1);
+ }
+ else if (ds == pdf_devicergb)
+ {
+ dv[0] = 1 - MIN(sv[0] + sv[3], 1);
+ dv[1] = 1 - MIN(sv[1] + sv[3], 1);
+ dv[2] = 1 - MIN(sv[2] + sv[3], 1);
+ }
+ else if (ds == pdf_devicebgr)
+ {
+ dv[0] = 1 - MIN(sv[2] + sv[3], 1);
+ dv[1] = 1 - MIN(sv[1] + sv[3], 1);
+ dv[2] = 1 - MIN(sv[0] + sv[3], 1);
+ }
+ else
+ fz_stdconvcolor(ss, sv, ds, dv);
+ }
+
+ else
+ fz_stdconvcolor(ss, sv, ds, dv);
+}
+
diff --git a/fitz/stm_buffer.c b/fitz/stm_buffer.c
index 3879f871..7886bd49 100644
--- a/fitz/stm_buffer.c
+++ b/fitz/stm_buffer.c
@@ -53,6 +53,24 @@ fz_dropbuffer(fz_buffer *buf)
}
void
+fz_resizebuffer(fz_buffer *buf, int size)
+{
+ int rp = MIN(buf->rp - buf->bp, size);
+ int wp = MIN(buf->wp - buf->bp, size);
+
+ if (!buf->ownsdata)
+ {
+ fz_warn("assert: resize borrowed memory");
+ return;
+ }
+
+ buf->bp = fz_realloc(buf->bp, size);
+ buf->rp = buf->bp + rp;
+ buf->wp = buf->bp + wp;
+ buf->ep = buf->bp + size;
+}
+
+void
fz_growbuffer(fz_buffer *buf)
{
int rp = buf->rp - buf->bp;
diff --git a/mupdf/mupdf.h b/mupdf/mupdf.h
index 387595a2..1c6f964e 100644
--- a/mupdf/mupdf.h
+++ b/mupdf/mupdf.h
@@ -209,22 +209,9 @@ pdf_function *pdf_keepfunction(pdf_function *func);
void pdf_dropfunction(pdf_function *func);
/*
- * ColorSpace
+ * Colorspace
*/
-typedef struct pdf_indexed_s pdf_indexed;
-
-struct pdf_indexed_s
-{
- fz_colorspace super; /* hmmm... */
- fz_colorspace *base;
- int high;
- unsigned char *lookup;
-};
-
-void pdf_convcolor(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv);
-void pdf_convpixmap(fz_colorspace *ss, fz_pixmap *sp, fz_colorspace *ds, fz_pixmap *dp);
-
fz_error pdf_loadcolorspace(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj);
/*
@@ -286,20 +273,21 @@ typedef struct pdf_image_s pdf_image;
struct pdf_image_s
{
int refs;
- int w, h, n, a;
- fz_colorspace *cs;
- pdf_image *mask; /* explicit mask with subimage */
- int usecolorkey; /* explicit color-keyed masking */
+ int w, h, bpc, n;
+ int imagemask;
+ int interpolate;
+ fz_colorspace *colorspace;
+ int indexed;
+ pdf_image *mask; /* explicit mask/softmask image */
+ int usecolorkey; /* color-keyed masking */
int colorkey[FZ_MAXCOLORS * 2];
- pdf_indexed *indexed;
- float decode[32];
- int bpc;
+ float decode[FZ_MAXCOLORS * 2];
int stride;
fz_buffer *samples;
};
fz_error pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file);
-fz_error pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *obj);
+fz_error pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *obj);
fz_error pdf_loadtile(pdf_image *image, fz_pixmap *tile);
pdf_image *pdf_keepimage(pdf_image *img);
void pdf_dropimage(pdf_image *img);
@@ -569,8 +557,6 @@ enum
{
PDF_MNONE,
PDF_MCOLOR,
- PDF_MLAB,
- PDF_MINDEXED,
PDF_MPATTERN,
PDF_MSHADE,
};
@@ -579,7 +565,6 @@ struct pdf_material_s
{
int kind;
fz_colorspace *cs;
- pdf_indexed *indexed;
pdf_pattern *pattern;
fz_shade *shade;
float parentalpha;
diff --git a/mupdf/pdf_build.c b/mupdf/pdf_build.c
index e7012a2a..b64cd986 100644
--- a/mupdf/pdf_build.c
+++ b/mupdf/pdf_build.c
@@ -18,7 +18,6 @@ pdf_initgstate(pdf_gstate *gs, fz_matrix ctm)
gs->stroke.kind = PDF_MCOLOR;
gs->stroke.cs = fz_keepcolorspace(pdf_devicegray);
gs->stroke.v[0] = 0;
- gs->stroke.indexed = nil;
gs->stroke.pattern = nil;
gs->stroke.shade = nil;
gs->stroke.parentalpha = 1;
@@ -27,7 +26,6 @@ pdf_initgstate(pdf_gstate *gs, fz_matrix ctm)
gs->fill.kind = PDF_MCOLOR;
gs->fill.cs = fz_keepcolorspace(pdf_devicegray);
gs->fill.v[0] = 0;
- gs->fill.indexed = nil;
gs->fill.pattern = nil;
gs->fill.shade = nil;
gs->fill.parentalpha = 1;
@@ -60,29 +58,18 @@ pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs)
mat->kind = PDF_MCOLOR;
mat->cs = fz_keepcolorspace(cs);
- mat->v[0] = 0; /* FIXME: default color */
- mat->v[1] = 0; /* FIXME: default color */
- mat->v[2] = 0; /* FIXME: default color */
- mat->v[3] = 1; /* FIXME: default color */
-
- if (!strcmp(cs->name, "Indexed"))
- {
- mat->kind = PDF_MINDEXED;
- mat->indexed = (pdf_indexed*)cs;
- mat->cs = mat->indexed->base;
- }
-
- if (!strcmp(cs->name, "Lab"))
- mat->kind = PDF_MLAB;
+ mat->v[0] = 0;
+ mat->v[1] = 0;
+ mat->v[2] = 0;
+ mat->v[3] = 1;
}
void
pdf_setcolor(pdf_csi *csi, int what, float *v)
{
pdf_gstate *gs = csi->gstate + csi->gtop;
- pdf_indexed *ind;
pdf_material *mat;
- int i, k;
+ int i;
pdf_flushtext(csi);
@@ -91,32 +78,16 @@ pdf_setcolor(pdf_csi *csi, int what, float *v)
switch (mat->kind)
{
case PDF_MPATTERN:
- if (!strcmp(mat->cs->name, "Lab"))
- goto Llab;
- if (!strcmp(mat->cs->name, "Indexed"))
- goto Lindexed;
- /* fall through */
-
case PDF_MCOLOR:
+ if (!strcmp(mat->cs->name, "Lab"))
+ {
+ mat->v[0] = v[0] / 100;
+ mat->v[1] = (v[1] + 100) / 200;
+ mat->v[2] = (v[2] + 100) / 200;
+ }
for (i = 0; i < mat->cs->n; i++)
mat->v[i] = v[i];
break;
-
- case PDF_MLAB:
-Llab:
- mat->v[0] = v[0] / 100;
- mat->v[1] = (v[1] + 100) / 200;
- mat->v[2] = (v[2] + 100) / 200;
- break;
-
- case PDF_MINDEXED:
-Lindexed:
- ind = mat->indexed;
- i = CLAMP(v[0], 0, ind->high);
- for (k = 0; k < ind->base->n; k++)
- mat->v[k] = ind->lookup[ind->base->n * i + k] / 255.0f;
- break;
-
default:
fz_warn("color incompatible with material");
}
@@ -133,12 +104,7 @@ pdf_unsetpattern(pdf_csi *csi, int what)
if (mat->pattern)
pdf_droppattern(mat->pattern);
mat->pattern = nil;
- if (!strcmp(mat->cs->name, "Lab"))
- mat->kind = PDF_MLAB;
- else if (!strcmp(mat->cs->name, "Indexed"))
- mat->kind = PDF_MINDEXED;
- else
- mat->kind = PDF_MCOLOR;
+ mat->kind = PDF_MCOLOR;
}
}
@@ -265,7 +231,7 @@ pdf_showimage(pdf_csi *csi, pdf_image *image)
fz_pixmap *tile;
fz_error error;
- tile = fz_newpixmap(image->cs, 0, 0, image->w, image->h);
+ tile = fz_newpixmap(image->colorspace, 0, 0, image->w, image->h);
error = pdf_loadtile(image, tile);
if (error)
{
@@ -284,7 +250,7 @@ pdf_showimage(pdf_csi *csi, pdf_image *image)
fz_droppixmap(mask);
}
- if (image->n == 0 && image->a == 1)
+ if (image->imagemask)
{
fz_rect bbox;
@@ -293,8 +259,6 @@ pdf_showimage(pdf_csi *csi, pdf_image *image)
case PDF_MNONE:
break;
case PDF_MCOLOR:
- case PDF_MINDEXED:
- case PDF_MLAB:
csi->dev->fillimagemask(csi->dev->user, tile, gstate->ctm,
gstate->fill.cs, gstate->fill.v, gstate->fill.alpha);
break;
@@ -353,8 +317,6 @@ pdf_showpath(pdf_csi *csi, int doclose, int dofill, int dostroke, int evenodd)
case PDF_MNONE:
break;
case PDF_MCOLOR:
- case PDF_MINDEXED:
- case PDF_MLAB:
csi->dev->fillpath(csi->dev->user, path, evenodd, gstate->ctm,
gstate->fill.cs, gstate->fill.v, gstate->fill.alpha);
break;
@@ -379,8 +341,6 @@ pdf_showpath(pdf_csi *csi, int doclose, int dofill, int dostroke, int evenodd)
case PDF_MNONE:
break;
case PDF_MCOLOR:
- case PDF_MINDEXED:
- case PDF_MLAB:
csi->dev->strokepath(csi->dev->user, path, &gstate->strokestate, gstate->ctm,
gstate->stroke.cs, gstate->stroke.v, gstate->stroke.alpha);
break;
@@ -471,8 +431,6 @@ pdf_flushtext(pdf_csi *csi)
case PDF_MNONE:
break;
case PDF_MCOLOR:
- case PDF_MINDEXED:
- case PDF_MLAB:
csi->dev->filltext(csi->dev->user, text, gstate->ctm,
gstate->fill.cs, gstate->fill.v, gstate->fill.alpha);
break;
@@ -497,8 +455,6 @@ pdf_flushtext(pdf_csi *csi)
case PDF_MNONE:
break;
case PDF_MCOLOR:
- case PDF_MINDEXED:
- case PDF_MLAB:
csi->dev->stroketext(csi->dev->user, text, &gstate->strokestate, gstate->ctm,
gstate->stroke.cs, gstate->stroke.v, gstate->stroke.alpha);
break;
diff --git a/mupdf/pdf_colorspace.c b/mupdf/pdf_colorspace.c
index de18e452..fd20d6b2 100644
--- a/mupdf/pdf_colorspace.c
+++ b/mupdf/pdf_colorspace.c
@@ -1,468 +1,33 @@
#include "fitz.h"
#include "mupdf.h"
-#define noUSECAL
-
-static void initcs(fz_colorspace *cs, char *name, int n,
- void(*to)(fz_colorspace*,float*,float*),
- void(*from)(fz_colorspace*,float*,float*),
- void(*freefunc)(fz_colorspace*))
-{
- fz_strlcpy(cs->name, name, sizeof cs->name);
- cs->refs = 1;
- cs->convpixmap = pdf_convpixmap;
- cs->convcolor = pdf_convcolor;
- cs->toxyz = to;
- cs->fromxyz = from;
- cs->freefunc = freefunc;
- cs->n = n;
-}
-
/*
- * Optimized color conversions for Device colorspaces
+ * ICCBased
*/
-static void fastgraytorgb(fz_pixmap *src, fz_pixmap *dst)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = s[0];
- d[1] = s[0];
- d[2] = s[0];
- d[3] = s[1];
- s += 2;
- d += 4;
- }
-}
-
-static void fastgraytocmyk(fz_pixmap *src, fz_pixmap *dst)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = 0;
- d[1] = 0;
- d[2] = 0;
- d[3] = s[0];
- d[4] = s[1];
- s += 2;
- d += 5;
- }
-}
-
-static void fastrgbtogray(fz_pixmap *src, fz_pixmap *dst)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
- d[1] = s[3];
- s += 4;
- d += 2;
- }
-}
-
-static void fastbgrtogray(fz_pixmap *src, fz_pixmap *dst)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
- d[1] = s[3];
- s += 4;
- d += 2;
- }
-}
-
-static void fastrgbtocmyk(fz_pixmap *src, fz_pixmap *dst)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- unsigned char c = 255 - s[0];
- unsigned char m = 255 - s[1];
- unsigned char y = 255 - s[2];
- unsigned char k = MIN(c, MIN(m, y));
- d[0] = c - k;
- d[1] = m - k;
- d[2] = y - k;
- d[3] = k;
- d[4] = s[3];
- s += 4;
- d += 5;
- }
-}
-
-static void fastbgrtocmyk(fz_pixmap *src, fz_pixmap *dst)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- unsigned char c = 255 - s[2];
- unsigned char m = 255 - s[1];
- unsigned char y = 255 - s[0];
- unsigned char k = MIN(c, MIN(m, y));
- d[0] = c - k;
- d[1] = m - k;
- d[2] = y - k;
- d[3] = k;
- d[4] = s[3];
- s += 4;
- d += 5;
- }
-}
-
-static void fastcmyktogray(fz_pixmap *src, fz_pixmap *dst)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- unsigned char c = fz_mul255(s[0], 77);
- unsigned char m = fz_mul255(s[1], 150);
- unsigned char y = fz_mul255(s[2], 28);
- d[0] = 255 - MIN(c + m + y + s[3], 255);
- d[1] = s[4];
- s += 5;
- d += 2;
- }
-}
-
-static void fastcmyktorgb(fz_pixmap *src, fz_pixmap *dst)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = 255 - MIN(s[0] + s[3], 255);
- d[1] = 255 - MIN(s[1] + s[3], 255);
- d[2] = 255 - MIN(s[2] + s[3], 255);
- d[3] = s[4];
- s += 5;
- d += 4;
- }
-}
-
-static void fastcmyktobgr(fz_pixmap *src, fz_pixmap *dst)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = 255 - MIN(s[2] + s[3], 255);
- d[1] = 255 - MIN(s[1] + s[3], 255);
- d[2] = 255 - MIN(s[0] + s[3], 255);
- d[3] = s[4];
- s += 5;
- d += 4;
- }
-}
-
-static void fastrgbtobgr(fz_pixmap *src, fz_pixmap *dst)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = s[2];
- d[1] = s[1];
- d[2] = s[0];
- d[3] = s[3];
- s += 4;
- d += 4;
- }
-}
-
-void pdf_convpixmap(fz_colorspace *ss, fz_pixmap *sp, fz_colorspace *ds, fz_pixmap *dp)
-{
- pdf_logimage("convert pixmap from %s to %s\n", ss->name, ds->name);
-
- if (ss == pdf_devicegray)
- {
- if (ds == pdf_devicergb) fastgraytorgb(sp, dp);
- else if (ds == pdf_devicebgr) fastgraytorgb(sp, dp); /* bgr == rgb here */
- else if (ds == pdf_devicecmyk) fastgraytocmyk(sp, dp);
- else fz_stdconvpixmap(ss, sp, ds, dp);
- }
-
- else if (ss == pdf_devicergb)
- {
- if (ds == pdf_devicegray) fastrgbtogray(sp, dp);
- else if (ds == pdf_devicebgr) fastrgbtobgr(sp, dp);
- else if (ds == pdf_devicecmyk) fastrgbtocmyk(sp, dp);
- else fz_stdconvpixmap(ss, sp, ds, dp);
-
- }
-
- else if (ss == pdf_devicebgr)
- {
- if (ds == pdf_devicegray) fastbgrtogray(sp, dp);
- else if (ds == pdf_devicergb) fastrgbtobgr(sp, dp); /* bgr = rgb here */
- else if (ds == pdf_devicecmyk) fastbgrtocmyk(sp, dp);
- else fz_stdconvpixmap(ss, sp, ds, dp);
-
- }
-
- else if (ss == pdf_devicecmyk)
- {
- if (ds == pdf_devicegray) fastcmyktogray(sp, dp);
- else if (ds == pdf_devicebgr) fastcmyktobgr(sp, dp);
- else if (ds == pdf_devicergb) fastcmyktorgb(sp, dp);
- else fz_stdconvpixmap(ss, sp, ds, dp);
- }
-
- else fz_stdconvpixmap(ss, sp, ds, dp);
-}
-
-void pdf_convcolor(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv)
+static fz_error
+loadiccbased(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict)
{
+ int n;
- if (ss == pdf_devicegray)
- {
- if ((ds == pdf_devicergb) || (ds == pdf_devicebgr))
- {
- dv[0] = sv[0];
- dv[1] = sv[0];
- dv[2] = sv[0];
- }
- else if (ds == pdf_devicecmyk)
- {
- dv[0] = 0;
- dv[1] = 0;
- dv[2] = 0;
- dv[3] = sv[0];
- }
- else
- fz_stdconvcolor(ss, sv, ds, dv);
- }
-
- else if (ss == pdf_devicergb)
- {
- if (ds == pdf_devicegray)
- {
- dv[0] = sv[0] * 0.3f + sv[1] * 0.59f + sv[2] * 0.11f;
- }
- else if (ds == pdf_devicebgr)
- {
- dv[0] = sv[2];
- dv[1] = sv[1];
- dv[2] = sv[0];
- }
- else if (ds == pdf_devicecmyk)
- {
- float c = 1 - sv[0];
- float m = 1 - sv[1];
- float y = 1 - sv[2];
- float k = MIN(c, MIN(m, y));
- dv[0] = c - k;
- dv[1] = m - k;
- dv[2] = y - k;
- dv[3] = k;
- }
- else
- fz_stdconvcolor(ss, sv, ds, dv);
- }
+ pdf_logrsrc("load ICCBased\n");
- else if (ss == pdf_devicebgr)
- {
- if (ds == pdf_devicegray)
- {
- dv[0] = sv[0] * 0.11f + sv[1] * 0.59f + sv[2] * 0.3f;
- }
- else if (ds == pdf_devicebgr)
- {
- dv[0] = sv[2];
- dv[1] = sv[1];
- dv[2] = sv[0];
- }
- else if (ds == pdf_devicecmyk)
- {
- float c = 1 - sv[2];
- float m = 1 - sv[1];
- float y = 1 - sv[0];
- float k = MIN(c, MIN(m, y));
- dv[0] = c - k;
- dv[1] = m - k;
- dv[2] = y - k;
- dv[3] = k;
- }
- else
- fz_stdconvcolor(ss, sv, ds, dv);
- }
+ n = fz_toint(fz_dictgets(dict, "N"));
- else if (ss == pdf_devicecmyk)
+ switch (n)
{
- if (ds == pdf_devicegray)
- {
- float c = sv[1] * 0.3f;
- float m = sv[2] * 0.59f;
- float y = sv[2] * 0.11f;
- dv[0] = 1 - MIN(c + m + y + sv[3], 1);
- }
- else if (ds == pdf_devicergb)
- {
- dv[0] = 1 - MIN(sv[0] + sv[3], 1);
- dv[1] = 1 - MIN(sv[1] + sv[3], 1);
- dv[2] = 1 - MIN(sv[2] + sv[3], 1);
- }
- else if (ds == pdf_devicebgr)
- {
- dv[0] = 1 - MIN(sv[2] + sv[3], 1);
- dv[1] = 1 - MIN(sv[1] + sv[3], 1);
- dv[2] = 1 - MIN(sv[0] + sv[3], 1);
- }
- else
- fz_stdconvcolor(ss, sv, ds, dv);
+ case 1: *csp = pdf_devicegray; return fz_okay;
+ case 3: *csp = pdf_devicergb; return fz_okay;
+ case 4: *csp = pdf_devicecmyk; return fz_okay;
}
- else
- fz_stdconvcolor(ss, sv, ds, dv);
-}
-
-/*
- * CalGray
- */
-
-struct calgray
-{
- fz_colorspace super;
- float white[3];
- float black[3];
- float gamma;
-};
-
-static void graytoxyz(fz_colorspace *fzcs, float *gray, float *xyz)
-{
- struct calgray *cs = (struct calgray *) fzcs;
- xyz[0] = powf(gray[0], cs->gamma) * cs->white[0];
- xyz[1] = powf(gray[0], cs->gamma) * cs->white[1];
- xyz[2] = powf(gray[0], cs->gamma) * cs->white[2];
-}
-
-static void xyztogray(fz_colorspace *fzcs, float *xyz, float *gray)
-{
- struct calgray *cs = (struct calgray *) fzcs;
- float r = powf(xyz[0], 1 / cs->gamma) / cs->white[0];
- float g = powf(xyz[1], 1 / cs->gamma) / cs->white[1];
- float b = powf(xyz[2], 1 / cs->gamma) / cs->white[2];
- gray[0] = r * 0.3f + g * 0.59f + b * 0.11f;
-}
-
-/*
- * CalRGB
- */
-
-struct calrgb
-{
- fz_colorspace super;
- float white[3];
- float black[3];
- float gamma[3];
- float matrix[9];
- float invmat[9];
-};
-
-static void rgbtoxyz(fz_colorspace *fzcs, float *rgb, float *xyz)
-{
- struct calrgb *cs = (struct calrgb *) fzcs;
- float a = powf(rgb[0], cs->gamma[0]) * cs->white[0];
- float b = powf(rgb[1], cs->gamma[1]) * cs->white[1];
- float c = powf(rgb[2], cs->gamma[2]) * cs->white[2];
- xyz[0] = a * cs->matrix[0] + b * cs->matrix[1] + c * cs->matrix[2];
- xyz[1] = a * cs->matrix[3] + b * cs->matrix[4] + c * cs->matrix[5];
- xyz[2] = a * cs->matrix[6] + b * cs->matrix[7] + c * cs->matrix[8];
-}
-
-static void xyztorgb(fz_colorspace *fzcs, float *xyz, float *rgb)
-{
- struct calrgb *cs = (struct calrgb *) fzcs;
- float a = xyz[0] * cs->invmat[0] + xyz[1] * cs->invmat[1] + xyz[2] * cs->invmat[2];
- float b = xyz[0] * cs->invmat[3] + xyz[1] * cs->invmat[4] + xyz[2] * cs->invmat[5];
- float c = xyz[0] * cs->invmat[6] + xyz[1] * cs->invmat[7] + xyz[2] * cs->invmat[8];
- rgb[0] = powf(a, 1 / cs->gamma[0]) / cs->white[0];
- rgb[1] = powf(b, 1 / cs->gamma[1]) / cs->white[1];
- rgb[2] = powf(c, 1 / cs->gamma[2]) / cs->white[2];
-}
-
-/*
- * DeviceCMYK piggybacks on DeviceRGB
- */
-
-static void devicecmyktoxyz(fz_colorspace *cs, float *cmyk, float *xyz)
-{
- float rgb[3];
- rgb[0] = 1 - MIN(1, cmyk[0] + cmyk[3]);
- rgb[1] = 1 - MIN(1, cmyk[1] + cmyk[3]);
- rgb[2] = 1 - MIN(1, cmyk[2] + cmyk[3]);
- rgbtoxyz(pdf_devicergb, rgb, xyz);
-}
-
-static void xyztodevicecmyk(fz_colorspace *cs, float *xyz, float *cmyk)
-{
- float rgb[3];
- float c, m, y, k;
- xyztorgb(pdf_devicergb, xyz, rgb);
- c = 1 - rgb[0];
- m = 1 - rgb[0];
- y = 1 - rgb[0];
- k = MIN(c, MIN(m, y));
- cmyk[0] = c - k;
- cmyk[1] = m - k;
- cmyk[2] = y - k;
- cmyk[3] = k;
-}
-
-/*
- * DeviceBGR piggybacks on DeviceRGB
- */
-
-static void bgrtoxyz(fz_colorspace *cs, float *bgr, float *xyz)
-{
- float rgb[3];
- rgb[0] = bgr[2];
- rgb[1] = bgr[1];
- rgb[2] = bgr[0];
- rgbtoxyz(pdf_devicergb, rgb, xyz);
-}
-
-static void xyztobgr(fz_colorspace *cs, float *xyz, float *bgr)
-{
- float rgb[3];
- xyztorgb(pdf_devicergb, xyz, rgb);
- bgr[0] = rgb[2];
- bgr[1] = rgb[1];
- bgr[2] = rgb[0];
+ return fz_throw("syntaxerror: ICCBased must have 1, 3 or 4 components");
}
/*
- * CIE Lab
+ * Lab
*/
-struct cielab
-{
- fz_colorspace super;
- float white[3];
- float black[3];
- float range[4];
-};
-
static inline float fung(float x)
{
if (x >= 6.0f / 29.0f)
@@ -477,289 +42,43 @@ static inline float invg(float x)
return (7.787f * x) + (16.0f / 116.0f);
}
-static void labtoxyz(fz_colorspace *fzcs, float *lab, float *xyz)
+static void
+labtoxyz(fz_colorspace *cs, float *lab, float *xyz)
{
- struct cielab *cs = (struct cielab *) fzcs;
float lstar, astar, bstar, l, m, n;
float tmp[3];
tmp[0] = lab[0] * 100;
tmp[1] = lab[1] * 200 - 100;
tmp[2] = lab[2] * 200 - 100;
lstar = tmp[0];
- astar = MAX(MIN(tmp[1], cs->range[1]), cs->range[0]);
- bstar = MAX(MIN(tmp[2], cs->range[3]), cs->range[2]);
+ astar = CLAMP(tmp[1], -100, 100);
+ bstar = CLAMP(tmp[2], -100, 100);
l = (lstar + 16) / 116 + astar / 500;
m = (lstar + 16) / 116;
n = (lstar + 16) / 116 - bstar / 200;
- xyz[0] = fung(l) * cs->white[0];
- xyz[1] = fung(m) * cs->white[1];
- xyz[2] = fung(n) * cs->white[2];
+ xyz[0] = fung(l);
+ xyz[1] = fung(m);
+ xyz[2] = fung(n);
}
-static void xyztolab(fz_colorspace *fzcs, float *xyz, float *lab)
+static void
+xyztolab(fz_colorspace *cs, float *xyz, float *lab)
{
- struct cielab *cs = (struct cielab *) fzcs;
float tmp[3];
- float yyn = xyz[1] / cs->white[1];
+ float yyn = xyz[1];
if (yyn < 0.008856f)
tmp[0] = 116.0f * yyn * (1.0f / 3.0f) - 16.0f;
else
tmp[0] = 903.3f * yyn;
- tmp[1] = 500 * (invg(xyz[0]/cs->white[0]) - invg(xyz[1]/cs->white[1]));
- tmp[2] = 200 * (invg(xyz[1]/cs->white[1]) - invg(xyz[2]/cs->white[2]));
+ tmp[1] = 500 * (invg(xyz[0]) - invg(xyz[1]));
+ tmp[2] = 200 * (invg(xyz[1]) - invg(xyz[2]));
lab[0] = tmp[0] / 100;
lab[1] = (tmp[1] + 100) / 200;
lab[2] = (tmp[2] + 100) / 200;
}
-/*
- * Define global Device* colorspaces as Cal*
- */
-
-static struct calgray kdevicegray =
-{
- { -1, "DeviceGray", 1, pdf_convpixmap, pdf_convcolor, graytoxyz, xyztogray, nil },
- { 1, 1, 1 },
- { 0, 0, 0 },
- 1
-};
-
-static struct calrgb kdevicergb =
-{
- { -1, "DeviceRGB", 3, pdf_convpixmap, pdf_convcolor, rgbtoxyz, xyztorgb, nil },
- { 1, 1, 1 },
- { 0, 0, 0 },
- { 1, 1, 1 },
- { 1,0,0, 0,1,0, 0,0,1 },
- { 1,0,0, 0,1,0, 0,0,1 },
-};
-
-static struct calrgb kdevicebgr =
-{
- { -1, "DeviceBGR", 3, pdf_convpixmap, pdf_convcolor, bgrtoxyz, xyztobgr, nil },
- { 1, 1, 1 },
- { 0, 0, 0 },
- { 1, 1, 1 },
- { 1,0,0, 0,1,0, 0,0,1 },
- { 1,0,0, 0,1,0, 0,0,1 },
-};
-
-static fz_colorspace kdevicecmyk =
-{
- -1, "DeviceCMYK", 4, pdf_convpixmap, pdf_convcolor, devicecmyktoxyz, xyztodevicecmyk, nil
-};
-
-static struct cielab kdevicelab =
-{
- { -1, "Lab", 3, pdf_convpixmap, fz_stdconvcolor, labtoxyz, xyztolab, nil },
- { 1, 1, 1 },
- { 0, 0, 0 },
- { -100, 100, -100, 100 },
-};
-
-static fz_colorspace kdevicepattern =
-{
- -1, "Pattern", 0, nil, nil, nil, nil, nil
-};
-
-fz_colorspace *pdf_devicegray = &kdevicegray.super;
-fz_colorspace *pdf_devicergb = &kdevicergb.super;
-fz_colorspace *pdf_devicebgr = &kdevicebgr.super;
-fz_colorspace *pdf_devicecmyk = &kdevicecmyk;
-fz_colorspace *pdf_devicelab = &kdevicelab.super;
-fz_colorspace *pdf_devicepattern = &kdevicepattern;
-
-/*
- * Colorspace parsing
- */
-
-#ifdef USECAL
-static fz_colorspace *
-loadcalgray(pdf_xref *xref, fz_obj *dict)
-{
- struct calgray *cs;
- fz_obj *tmp;
-
- cs = fz_malloc(sizeof(struct calgray));
-
- pdf_logrsrc("load CalGray\n");
-
- initcs((fz_colorspace*)cs, "CalGray", 1, graytoxyz, xyztogray, nil);
-
- cs->white[0] = 1;
- cs->white[1] = 1;
- cs->white[2] = 1;
-
- cs->black[0] = 0;
- cs->black[1] = 0;
- cs->black[2] = 0;
-
- cs->gamma = 1;
-
- tmp = fz_dictgets(dict, "WhitePoint");
- if (fz_isarray(tmp))
- {
- cs->white[0] = fz_toreal(fz_arrayget(tmp, 0));
- cs->white[1] = fz_toreal(fz_arrayget(tmp, 1));
- cs->white[2] = fz_toreal(fz_arrayget(tmp, 2));
- }
-
- tmp = fz_dictgets(dict, "BlackPoint");
- if (fz_isarray(tmp))
- {
- cs->black[0] = fz_toreal(fz_arrayget(tmp, 0));
- cs->black[1] = fz_toreal(fz_arrayget(tmp, 1));
- cs->black[2] = fz_toreal(fz_arrayget(tmp, 2));
- }
-
- tmp = fz_dictgets(dict, "Gamma");
- if (fz_isreal(tmp))
- cs->gamma = fz_toreal(tmp);
-
- return (fz_colorspace*) cs;
-}
-
-static fz_colorspace *
-loadcalrgb(pdf_xref *xref, fz_obj *dict)
-{
- struct calrgb *cs;
- fz_obj *tmp;
- int i;
-
- cs = fz_malloc(sizeof(struct calrgb));
-
- pdf_logrsrc("load CalRGB\n");
-
- initcs((fz_colorspace*)cs, "CalRGB", 3, rgbtoxyz, xyztorgb, nil);
-
- cs->white[0] = 1;
- cs->white[1] = 1;
- cs->white[2] = 1;
-
- cs->black[0] = 0;
- cs->black[1] = 0;
- cs->black[2] = 0;
-
- cs->gamma[0] = 1;
- cs->gamma[1] = 1;
- cs->gamma[2] = 1;
-
- cs->matrix[0] = 1; cs->matrix[1] = 0; cs->matrix[2] = 0;
- cs->matrix[3] = 0; cs->matrix[4] = 1; cs->matrix[5] = 0;
- cs->matrix[6] = 0; cs->matrix[7] = 0; cs->matrix[8] = 1;
-
- tmp = fz_dictgets(dict, "WhitePoint");
- if (fz_isarray(tmp))
- {
- cs->white[0] = fz_toreal(fz_arrayget(tmp, 0));
- cs->white[1] = fz_toreal(fz_arrayget(tmp, 1));
- cs->white[2] = fz_toreal(fz_arrayget(tmp, 2));
- }
-
- tmp = fz_dictgets(dict, "BlackPoint");
- if (fz_isarray(tmp))
- {
- cs->black[0] = fz_toreal(fz_arrayget(tmp, 0));
- cs->black[1] = fz_toreal(fz_arrayget(tmp, 1));
- cs->black[2] = fz_toreal(fz_arrayget(tmp, 2));
- }
-
- tmp = fz_dictgets(dict, "Gamma");
- if (fz_isarray(tmp))
- {
- cs->gamma[0] = fz_toreal(fz_arrayget(tmp, 0));
- cs->gamma[1] = fz_toreal(fz_arrayget(tmp, 1));
- cs->gamma[2] = fz_toreal(fz_arrayget(tmp, 2));
- }
-
- tmp = fz_dictgets(dict, "Matrix");
- if (fz_isarray(tmp))
- {
- for (i = 0; i < 9; i++)
- cs->matrix[i] = fz_toreal(fz_arrayget(tmp, i));
- }
-
- fz_invert3x3(cs->invmat, cs->matrix);
-
- return (fz_colorspace*) cs;
-}
-
-static fz_colorspace *
-loadlab(pdf_xref *xref, fz_obj *dict)
-{
- struct cielab *cs;
- fz_obj *tmp;
-
- cs = fz_malloc(sizeof(struct cielab));
-
- pdf_logrsrc("load Lab\n");
-
- initcs((fz_colorspace*)cs, "Lab", 3, labtoxyz, xyztolab, nil);
-
- cs->white[0] = 1;
- cs->white[1] = 1;
- cs->white[2] = 1;
-
- cs->black[0] = 0;
- cs->black[1] = 0;
- cs->black[2] = 0;
-
- cs->range[0] = -100;
- cs->range[1] = 100;
- cs->range[2] = -100;
- cs->range[3] = 100;
-
- tmp = fz_dictgets(dict, "WhitePoint");
- if (fz_isarray(tmp))
- {
- cs->white[0] = fz_toreal(fz_arrayget(tmp, 0));
- cs->white[1] = fz_toreal(fz_arrayget(tmp, 1));
- cs->white[2] = fz_toreal(fz_arrayget(tmp, 2));
- }
-
- tmp = fz_dictgets(dict, "BlackPoint");
- if (fz_isarray(tmp))
- {
- cs->black[0] = fz_toreal(fz_arrayget(tmp, 0));
- cs->black[1] = fz_toreal(fz_arrayget(tmp, 1));
- cs->black[2] = fz_toreal(fz_arrayget(tmp, 2));
- }
-
- tmp = fz_dictgets(dict, "Range");
- if (fz_isarray(tmp))
- {
- cs->range[0] = fz_toreal(fz_arrayget(tmp, 0));
- cs->range[1] = fz_toreal(fz_arrayget(tmp, 1));
- cs->range[2] = fz_toreal(fz_arrayget(tmp, 2));
- cs->range[3] = fz_toreal(fz_arrayget(tmp, 3));
- }
-
- return (fz_colorspace*) cs;
-}
-#endif
-
-/*
- * ICCBased
- */
-
-static fz_error
-loadiccbased(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict)
-{
- int n;
-
- pdf_logrsrc("load ICCBased\n");
-
- n = fz_toint(fz_dictgets(dict, "N"));
-
- switch (n)
- {
- case 1: *csp = pdf_devicegray; return fz_okay;
- case 3: *csp = pdf_devicergb; return fz_okay;
- case 4: *csp = pdf_devicecmyk; return fz_okay;
- }
-
- return fz_throw("syntaxerror: ICCBased must have 1, 3 or 4 components");
-}
+static fz_colorspace kdevicelab = { -1, "Lab", 3, labtoxyz, xyztolab };
+static fz_colorspace *pdf_devicelab = &kdevicelab;
/*
* Separation and DeviceN
@@ -767,18 +86,18 @@ loadiccbased(fz_colorspace **csp, pdf_xref *xref, fz_obj *dict)
struct separation
{
- fz_colorspace super;
fz_colorspace *base;
pdf_function *tint;
};
-static void separationtoxyz(fz_colorspace *fzcs, float *sep, float *xyz)
+static void
+separationtoxyz(fz_colorspace *cs, float *color, float *xyz)
{
- struct separation *cs = (struct separation *)fzcs;
+ struct separation *sep = cs->data;
fz_error error;
float alt[FZ_MAXCOLORS];
- error = pdf_evalfunction(cs->tint, sep, fzcs->n, alt, cs->base->n);
+ error = pdf_evalfunction(sep->tint, color, cs->n, alt, sep->base->n);
if (error)
{
fz_catch(error, "cannot evaluate separation function");
@@ -788,22 +107,24 @@ static void separationtoxyz(fz_colorspace *fzcs, float *sep, float *xyz)
return;
}
- cs->base->toxyz(cs->base, alt, xyz);
+ sep->base->toxyz(sep->base, alt, xyz);
}
static void
-freeseparation(fz_colorspace *fzcs)
+freeseparation(fz_colorspace *cs)
{
- struct separation *cs = (struct separation *)fzcs;
- fz_dropcolorspace(cs->base);
- pdf_dropfunction(cs->tint);
+ struct separation *sep = cs->data;
+ fz_dropcolorspace(sep->base);
+ pdf_dropfunction(sep->tint);
+ fz_free(sep);
}
static fz_error
loadseparation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
{
fz_error error;
- struct separation *cs;
+ fz_colorspace *cs;
+ struct separation *sep;
fz_obj *nameobj = fz_arrayget(array, 1);
fz_obj *baseobj = fz_arrayget(array, 2);
fz_obj *tintobj = fz_arrayget(array, 3);
@@ -834,21 +155,18 @@ loadseparation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
return fz_rethrow(error, "cannot load tint function (%d %d R)", fz_tonum(tintobj), fz_togen(tintobj));
}
- cs = fz_malloc(sizeof(struct separation));
+ sep = fz_malloc(sizeof(struct separation));
+ sep->base = base;
+ sep->tint = tint;
- initcs((fz_colorspace*)cs,
- n == 1 ? "Separation" : "DeviceN", n,
- separationtoxyz, nil, freeseparation);
-
- cs->base = fz_keepcolorspace(base);
- cs->tint = pdf_keepfunction(tint);
-
- fz_dropcolorspace(base);
- pdf_dropfunction(tint);
+ cs = fz_newcolorspace(n == 1 ? "Separation" : "DeviceN", n);
+ cs->toxyz = separationtoxyz;
+ cs->freedata = freeseparation;
+ cs->data = sep;
pdf_logrsrc("}\n");
- *csp = (fz_colorspace*)cs;
+ *csp = cs;
return fz_okay;
}
@@ -856,34 +174,42 @@ loadseparation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
* Indexed
*/
-#if 0
+struct indexed
+{
+ fz_colorspace *base;
+ int high;
+ unsigned char *lookup;
+};
+
static void
-indexedtoxyz(fz_colorspace *fzcs, float *ind, float *xyz)
+indexedtoxyz(fz_colorspace *cs, float *color, float *xyz)
{
- pdf_indexed *cs = (pdf_indexed *)fzcs;
+ struct indexed *idx = cs->data;
float alt[FZ_MAXCOLORS];
int i, k;
- i = ind[0] * 255;
- i = CLAMP(i, 0, cs->high);
- for (k = 0; k < cs->base->n; k++)
- alt[k] = cs->lookup[i * cs->base->n + k] / 255.0f;
- cs->base->toxyz(cs->base, alt, xyz);
+ i = color[0] * 255;
+ i = CLAMP(i, 0, idx->high);
+ for (k = 0; k < idx->base->n; k++)
+ alt[k] = idx->lookup[i * idx->base->n + k] / 255.0f;
+ idx->base->toxyz(idx->base, alt, xyz);
}
-#endif
static void
-freeindexed(fz_colorspace *fzcs)
+freeindexed(fz_colorspace *cs)
{
- pdf_indexed *cs = (pdf_indexed *)fzcs;
- if (cs->base) fz_dropcolorspace(cs->base);
- if (cs->lookup) fz_free(cs->lookup);
+ struct indexed *idx = cs->data;
+ if (idx->base)
+ fz_dropcolorspace(idx->base);
+ fz_free(idx->lookup);
+ fz_free(idx);
}
static fz_error
loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
{
fz_error error;
- pdf_indexed *cs;
+ fz_colorspace *cs;
+ struct indexed *idx;
fz_obj *baseobj = fz_arrayget(array, 1);
fz_obj *highobj = fz_arrayget(array, 2);
fz_obj *lookup = fz_arrayget(array, 3);
@@ -898,17 +224,16 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
pdf_logrsrc("base %s\n", base->name);
- cs = fz_malloc(sizeof(pdf_indexed));
+ idx = fz_malloc(sizeof(struct indexed));
+ idx->base = base;
+ idx->high = fz_toint(highobj);
+ n = base->n * (idx->high + 1);
+ idx->lookup = fz_malloc(n);
- initcs((fz_colorspace*)cs, "Indexed", 1, nil, nil, freeindexed);
-
- cs->base = fz_keepcolorspace(base);
- cs->high = fz_toint(highobj);
-
- fz_dropcolorspace(base);
-
- n = base->n * (cs->high + 1);
- cs->lookup = fz_malloc(n);
+ cs = fz_newcolorspace("Indexed", 1);
+ cs->toxyz = indexedtoxyz;
+ cs->freedata = freeindexed;
+ cs->data = idx;
if (fz_isstring(lookup) && fz_tostrlen(lookup) == n)
{
@@ -919,7 +244,7 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
buf = (unsigned char *) fz_tostrbuf(lookup);
for (i = 0; i < n; i++)
- cs->lookup[i] = buf[i];
+ idx->lookup[i] = buf[i];
}
else if (fz_isindirect(lookup))
{
@@ -931,24 +256,24 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
error = pdf_loadstream(&buf, xref, fz_tonum(lookup), fz_togen(lookup));
if (error)
{
- fz_dropcolorspace((fz_colorspace*)cs);
+ fz_dropcolorspace(cs);
return fz_rethrow(error, "cannot load colorpsace lookup table (%d %d R)", fz_tonum(lookup), fz_togen(lookup));
}
for (i = 0; i < n && i < (buf->wp - buf->rp); i++)
- cs->lookup[i] = buf->rp[i];
+ idx->lookup[i] = buf->rp[i];
fz_dropbuffer(buf);
}
else
{
- fz_dropcolorspace((fz_colorspace*)cs);
+ fz_dropcolorspace(cs);
return fz_throw("cannot parse colorspace lookup table");
}
pdf_logrsrc("}\n");
- *csp = (fz_colorspace*)cs;
+ *csp = cs;
return fz_okay;
}
@@ -961,20 +286,23 @@ pdf_loadcolorspaceimp(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj)
{
if (fz_isname(obj))
{
- if (!strcmp(fz_toname(obj), "DeviceGray"))
+ if (!strcmp(fz_toname(obj), "Pattern"))
+ {
+fz_warn("uncolored pattern colorspace (name)");
*csp = pdf_devicegray;
- else if (!strcmp(fz_toname(obj), "DeviceRGB"))
- *csp = pdf_devicergb;
- else if (!strcmp(fz_toname(obj), "DeviceCMYK"))
- *csp = pdf_devicecmyk;
+ }
else if (!strcmp(fz_toname(obj), "G"))
*csp = pdf_devicegray;
else if (!strcmp(fz_toname(obj), "RGB"))
*csp = pdf_devicergb;
else if (!strcmp(fz_toname(obj), "CMYK"))
*csp = pdf_devicecmyk;
- else if (!strcmp(fz_toname(obj), "Pattern"))
- *csp = pdf_devicepattern;
+ else if (!strcmp(fz_toname(obj), "DeviceGray"))
+ *csp = pdf_devicegray;
+ else if (!strcmp(fz_toname(obj), "DeviceRGB"))
+ *csp = pdf_devicergb;
+ else if (!strcmp(fz_toname(obj), "DeviceCMYK"))
+ *csp = pdf_devicecmyk;
else
return fz_throw("unknown colorspace: %s", fz_toname(obj));
return fz_okay;
@@ -986,49 +314,16 @@ pdf_loadcolorspaceimp(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj)
if (fz_isname(name))
{
- if (!strcmp(fz_toname(name), "CalCMYK"))
- *csp = pdf_devicecmyk;
-
-#ifdef USECAL
- else if (!strcmp(fz_toname(name), "CalGray"))
- *csp = loadcalgray(xref, fz_arrayget(obj, 1));
- else if (!strcmp(fz_toname(name), "CalRGB"))
- *csp = loadcalrgb(xref, fz_arrayget(obj, 1));
- else if (!strcmp(fz_toname(name), "Lab"))
- *csp = loadlab(xref, fz_arrayget(obj, 1));
-#else
- else if (!strcmp(fz_toname(name), "CalGray"))
- *csp = pdf_devicegray;
- else if (!strcmp(fz_toname(name), "CalRGB"))
- *csp = pdf_devicergb;
- else if (!strcmp(fz_toname(name), "Lab"))
- *csp = pdf_devicelab;
-#endif
-
- else if (!strcmp(fz_toname(name), "ICCBased"))
- return loadiccbased(csp, xref, fz_arrayget(obj, 1));
-
- else if (!strcmp(fz_toname(name), "Indexed"))
- return loadindexed(csp, xref, obj);
-
- else if (!strcmp(fz_toname(name), "I"))
- return loadindexed(csp, xref, obj);
-
- else if (!strcmp(fz_toname(name), "Separation"))
- return loadseparation(csp, xref, obj);
-
- else if (!strcmp(fz_toname(name), "DeviceN"))
- return loadseparation(csp, xref, obj);
-
/* load base colorspace instead */
- else if (!strcmp(fz_toname(name), "Pattern"))
+ if (!strcmp(fz_toname(name), "Pattern"))
{
fz_error error;
obj = fz_arrayget(obj, 1);
if (!obj)
{
- *csp = pdf_devicepattern;
+fz_warn("uncolored pattern colorspace (array)");
+ *csp = pdf_devicegray;
return fz_okay;
}
@@ -1037,18 +332,40 @@ pdf_loadcolorspaceimp(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj)
return fz_rethrow(error, "cannot load pattern (%d %d R)", fz_tonum(obj), fz_togen(obj));
}
+ else if (!strcmp(fz_toname(name), "G"))
+ *csp = pdf_devicegray;
+ else if (!strcmp(fz_toname(name), "RGB"))
+ *csp = pdf_devicergb;
+ else if (!strcmp(fz_toname(name), "CMYK"))
+ *csp = pdf_devicecmyk;
else if (!strcmp(fz_toname(name), "DeviceGray"))
*csp = pdf_devicegray;
else if (!strcmp(fz_toname(name), "DeviceRGB"))
*csp = pdf_devicergb;
else if (!strcmp(fz_toname(name), "DeviceCMYK"))
*csp = pdf_devicecmyk;
- else if (!strcmp(fz_toname(name), "G"))
+ else if (!strcmp(fz_toname(name), "CalGray"))
*csp = pdf_devicegray;
- else if (!strcmp(fz_toname(name), "RGB"))
+ else if (!strcmp(fz_toname(name), "CalRGB"))
*csp = pdf_devicergb;
- else if (!strcmp(fz_toname(name), "CMYK"))
+ else if (!strcmp(fz_toname(name), "CalCMYK"))
*csp = pdf_devicecmyk;
+ else if (!strcmp(fz_toname(name), "Lab"))
+ *csp = pdf_devicelab;
+
+ else if (!strcmp(fz_toname(name), "ICCBased"))
+ return loadiccbased(csp, xref, fz_arrayget(obj, 1));
+
+ else if (!strcmp(fz_toname(name), "Indexed"))
+ return loadindexed(csp, xref, obj);
+ else if (!strcmp(fz_toname(name), "I"))
+ return loadindexed(csp, xref, obj);
+
+ else if (!strcmp(fz_toname(name), "Separation"))
+ return loadseparation(csp, xref, obj);
+
+ else if (!strcmp(fz_toname(name), "DeviceN"))
+ return loadseparation(csp, xref, obj);
else
return fz_throw("syntaxerror: unknown colorspace %s", fz_toname(name));
@@ -1079,4 +396,3 @@ pdf_loadcolorspace(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj)
return fz_okay;
}
-
diff --git a/mupdf/pdf_image.c b/mupdf/pdf_image.c
index e4cfabe6..e125545b 100644
--- a/mupdf/pdf_image.c
+++ b/mupdf/pdf_image.c
@@ -1,10 +1,10 @@
-/*
- * TODO: this needs serious cleaning up, and error checking.
- */
-
#include "fitz.h"
#include "mupdf.h"
+/* TODO: special case JPXDecode image loading */
+/* TODO: store JPEG compressed samples */
+/* TODO: store flate compressed samples */
+
pdf_image *
pdf_keepimage(pdf_image *image)
{
@@ -17,169 +17,146 @@ pdf_dropimage(pdf_image *img)
{
if (img && --img->refs == 0)
{
- fz_dropbuffer(img->samples);
- if (img->cs)
- fz_dropcolorspace(img->cs);
- if (img->indexed)
- fz_dropcolorspace((fz_colorspace *) img->indexed);
+ if (img->colorspace)
+ fz_dropcolorspace(img->colorspace);
if (img->mask)
pdf_dropimage(img->mask);
+ if (img->samples)
+ fz_dropbuffer(img->samples);
fz_free(img);
}
}
-fz_error
-pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref,
- fz_obj *rdb, fz_obj *dict, fz_stream *file)
+static fz_error
+pdf_loadimageheader(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
{
- fz_error error;
pdf_image *img;
- fz_filter *filter;
- fz_obj *f;
- fz_obj *cs;
- fz_obj *d;
- int ismask;
+ fz_error error;
+ fz_obj *obj, *res;
int i;
img = fz_malloc(sizeof(pdf_image));
-
- pdf_logimage("load inline image %p {\n", img);
+ memset(img, 0, sizeof(pdf_image));
img->refs = 1;
- img->cs = nil;
- img->n = 0;
- img->a = 0;
- img->indexed = nil;
- img->usecolorkey = 0;
- img->mask = nil;
-
img->w = fz_toint(fz_dictgetsa(dict, "Width", "W"));
img->h = fz_toint(fz_dictgetsa(dict, "Height", "H"));
img->bpc = fz_toint(fz_dictgetsa(dict, "BitsPerComponent", "BPC"));
- ismask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM"));
- d = fz_dictgetsa(dict, "Decode", "D");
- cs = fz_dictgetsa(dict, "ColorSpace", "CS");
+ img->imagemask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM"));
+ img->interpolate = fz_tobool(fz_dictgetsa(dict, "Interpolate", "I"));
+
+ if (img->imagemask)
+ img->bpc = 1;
+
if (img->w == 0)
- fz_warn("inline image width is zero or undefined");
+ fz_warn("image width is zero");
if (img->h == 0)
- fz_warn("inline image height is zero or undefined");
+ fz_warn("image height is zero");
+ if (img->bpc == 0)
+ fz_warn("image bit depth is zero"); /* okay for JPX */
- pdf_logimage("size %dx%d %d\n", img->w, img->h, img->bpc);
-
- if (cs)
+ obj = fz_dictgetsa(dict, "ColorSpace", "CS");
+ if (obj)
{
- fz_obj *csd = nil;
- fz_obj *cso = nil;
-
- /* Attempt to lookup any name in the resource dictionary */
- if (fz_isname(cs))
+ if (fz_isname(obj))
{
- csd = fz_dictgets(rdb, "ColorSpace");
- cso = fz_dictget(csd, cs);
+ res = fz_dictget(fz_dictgets(rdb, "ColorSpace"), obj);
+ if (res)
+ obj = res;
}
- /* If no colorspace found in resource dictionary,
- * assume that reference is a standard name */
- if (!cso)
- cso = cs;
-
- error = pdf_loadcolorspace(&img->cs, xref, cso);
+ error = pdf_loadcolorspace(&img->colorspace, xref, obj);
if (error)
{
pdf_dropimage(img);
- return fz_rethrow(error, "cannot load colorspace (%d %d R)", fz_tonum(cso), fz_togen(cso));
+ return fz_rethrow(error, "cannot load image colorspace");
}
- if (!img->cs)
- return fz_throw("image is missing colorspace");
-
- if (!strcmp(img->cs->name, "Indexed"))
- {
- pdf_logimage("indexed\n");
- img->indexed = (pdf_indexed*)img->cs;
- img->cs = img->indexed->base;
- fz_keepcolorspace(img->cs);
- }
+ if (!strcmp(img->colorspace->name, "Indexed"))
+ img->indexed = 1;
- pdf_logimage("colorspace %s\n", img->cs->name);
-
- img->n = img->cs->n;
- img->a = 0;
+ img->n = img->colorspace->n;
}
-
- if (ismask)
+ else
{
- pdf_logimage("is mask\n");
- if (img->cs)
- {
- fz_warn("masks can not have colorspace, proceeding anyway.");
- fz_dropcolorspace(img->cs);
- img->cs = nil;
- }
- if (img->bpc != 1)
- fz_warn("masks can only have one component, proceeding anyway.");
-
- img->bpc = 1;
- img->n = 0;
- img->a = 1;
+ img->colorspace = pdf_devicegray;
+ img->n = 1;
}
- else if (!cs)
- return fz_throw("image is missing colorspace");
- if (fz_isarray(d))
+ obj = fz_dictgetsa(dict, "Decode", "D");
+ if (obj)
{
- pdf_logimage("decode array\n");
- if (img->indexed)
- for (i = 0; i < 2; i++)
- img->decode[i] = fz_toreal(fz_arrayget(d, i));
- else
- for (i = 0; i < (img->n + img->a) * 2; i++)
- img->decode[i] = fz_toreal(fz_arrayget(d, i));
+ for (i = 0; i < img->n * 2; i++)
+ img->decode[i] = fz_toreal(fz_arrayget(obj, i));
}
else
{
- if (img->indexed)
- for (i = 0; i < 2; i++)
- img->decode[i] = i & 1 ? (1 << img->bpc) - 1 : 0;
- else
- for (i = 0; i < (img->n + img->a) * 2; i++)
- img->decode[i] = i & 1;
+ for (i = 0; i < img->n * 2; i++)
+ if (i & 1)
+ img->decode[i] = 1;
+ else
+ img->decode[i] = 0;
}
- if (img->indexed)
- img->stride = (img->w * img->bpc + 7) / 8;
- else
- img->stride = (img->w * (img->n + img->a) * img->bpc + 7) / 8;
-
- /* load image data */
-
- f = fz_dictgetsa(dict, "Filter", "F");
- if (!f || (fz_isarray(f) && fz_arraylen(f) == 0))
+ obj = fz_dictgetsa(dict, "Mask", "SMask");
+ if (pdf_isstream(xref, fz_tonum(obj), fz_togen(obj)))
{
- img->samples = fz_newbuffer(img->h * img->stride);
-
- error = fz_read(&i, file, img->samples->bp, img->h * img->stride);
+ error = pdf_loadimage(&img->mask, xref, rdb, obj);
if (error)
- return error;
-
- img->samples->wp += img->h * img->stride;
+ {
+ pdf_dropimage(img);
+ return fz_rethrow(error, "cannot load image mask/softmask");
+ }
+ img->mask->imagemask = 1;
}
- else
+ else if (fz_isarray(obj))
{
- fz_stream *tempfile;
+ img->usecolorkey = 1;
+ for (i = 0; i < img->n * 2; i++)
+ img->colorkey[i] = fz_toint(fz_arrayget(obj, i));
+ }
- filter = pdf_buildinlinefilter(xref, dict);
+ img->stride = (img->w * img->n * img->bpc + 7) / 8;
- tempfile = fz_openfilter(filter, file);
+ pdf_logimage("size %dx%d n=%d bpc=%d (imagemask=%d)\n", img->w, img->h, img->n, img->bpc, img->imagemask);
- img->samples = fz_readall(tempfile, img->stride * img->h);
- fz_dropstream(tempfile);
+ *imgp = img;
+ return fz_okay;
+}
+
+fz_error
+pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref,
+ fz_obj *rdb, fz_obj *dict, fz_stream *file)
+{
+ fz_error error;
+ pdf_image *img;
+ fz_filter *filter;
+ fz_stream *subfile;
+ int n;
+
+ pdf_logimage("load inline image {\n");
+
+ error = pdf_loadimageheader(&img, xref, rdb, dict);
+ if (error)
+ return fz_rethrow(error, "cannot load inline image");
+
+ filter = pdf_buildinlinefilter(xref, dict);
+ subfile = fz_openfilter(filter, file);
- fz_dropfilter(filter);
+ img->samples = fz_newbuffer(img->h * img->stride);
+ error = fz_read(&n, file, img->samples->bp, img->h * img->stride);
+ if (error)
+ {
+ pdf_dropimage(img);
+ return fz_rethrow(error, "cannot load inline image data");
}
+ img->samples->wp += n;
+
+ fz_dropstream(subfile);
+ fz_dropfilter(filter);
/* 0 means opaque and 1 means transparent, so we invert to get alpha */
- if (ismask)
+ if (img->imagemask)
{
unsigned char *p;
for (p = img->samples->bp; p < img->samples->ep; p++)
@@ -192,48 +169,11 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref,
return fz_okay;
}
-static void
-loadcolorkey(int *colorkey, int bpc, int indexed, fz_obj *obj)
-{
- int scale = 1;
- int i;
-
- pdf_logimage("keyed mask\n");
-
- if (!indexed)
- {
- switch (bpc)
- {
- case 1: scale = 255; break;
- case 2: scale = 85; break;
- case 4: scale = 17; break;
- case 8: scale = 1; break;
- }
- }
-
- for (i = 0; i < fz_arraylen(obj); i++)
- colorkey[i] = fz_toint(fz_arrayget(obj, i)) * scale;
-}
-
-/* TODO error cleanup */
fz_error
-pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict)
+pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
{
fz_error error;
pdf_image *img;
- pdf_image *mask;
- int ismask;
- fz_obj *obj;
- int i;
-
- int w, h, bpc;
- int n = 0;
- int a = 0;
- int usecolorkey = 0;
- fz_colorspace *cs = nil;
- pdf_indexed *indexed = nil;
- int stride;
- int realsize, expectedsize;
if ((*imgp = pdf_finditem(xref->store, PDF_KIMAGE, dict)))
{
@@ -241,208 +181,36 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict)
return fz_okay;
}
- img = fz_malloc(sizeof(pdf_image));
-
- pdf_logimage("load image (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), img);
-
- /*
- * Dimensions, BPC and ColorSpace
- */
-
- w = fz_toint(fz_dictgets(dict, "Width"));
- if (w == 0)
- fz_warn("image width is zero or undefined");
-
- h = fz_toint(fz_dictgets(dict, "Height"));
- if (h == 0)
- fz_warn("image height is zero or undefined");
-
- bpc = fz_toint(fz_dictgets(dict, "BitsPerComponent"));
-
- pdf_logimage("size %dx%d %d\n", w, h, bpc);
-
- cs = nil;
- obj = fz_dictgets(dict, "ColorSpace");
- if (obj)
- {
- error = pdf_loadcolorspace(&cs, xref, obj);
- if (error)
- {
- pdf_dropimage(img);
- return fz_rethrow(error, "cannot load colorspace (%d %d R)", fz_tonum(obj), fz_togen(obj));
- }
-
- if (!strcmp(cs->name, "Indexed"))
- {
- pdf_logimage("indexed\n");
- indexed = (pdf_indexed*)cs;
- cs = indexed->base;
- fz_keepcolorspace(cs);
- }
- n = cs->n;
- a = 0;
-
- pdf_logimage("colorspace %s\n", cs->name);
- }
-
- /*
- * ImageMask, Mask and SoftMask
- */
-
- mask = nil;
-
- ismask = fz_tobool(fz_dictgets(dict, "ImageMask"));
- if (ismask)
- {
- pdf_logimage("is mask\n");
- if (cs)
- {
- fz_warn("masks can not have colorspace, proceeding anyway.");
- fz_dropcolorspace(cs);
- cs = nil;
- }
- if (bpc != 0 && bpc != 1)
- fz_warn("masks can only have one component, proceeding anyway.");
-
- bpc = 1;
- n = 0;
- a = 1;
- }
- else
- {
- if (!cs)
- return fz_throw("colorspace missing for image");
- if (bpc == 0)
- return fz_throw("image has no bits per component");
- }
-
- obj = fz_dictgets(dict, "SMask");
- if (fz_isindirect(obj))
- {
- pdf_logimage("has soft mask\n");
-
- error = pdf_loadimage(&mask, xref, obj);
- if (error)
- return error;
-
- if (mask->cs && mask->cs != pdf_devicegray)
- return fz_throw("syntaxerror: SMask must be DeviceGray");
-
- mask->cs = nil;
- mask->n = 0;
- mask->a = 1;
- }
-
- obj = fz_dictgets(dict, "Mask");
- if (fz_isindirect(obj))
- {
- if (fz_isarray(obj))
- {
- usecolorkey = 1;
- loadcolorkey(img->colorkey, bpc, indexed != nil, obj);
- }
- else
- {
- pdf_logimage("has mask\n");
- if (mask)
- {
- fz_warn("image has both a mask and a soft mask. ignoring the soft mask.");
- pdf_dropimage(mask);
- mask = nil;
- }
- error = pdf_loadimage(&mask, xref, obj);
- if (error)
- return error;
- }
- }
- else if (fz_isarray(obj))
- {
- usecolorkey = 1;
- loadcolorkey(img->colorkey, bpc, indexed != nil, obj);
- }
-
- /*
- * Decode
- */
-
- obj = fz_dictgets(dict, "Decode");
- if (fz_isarray(obj))
- {
- pdf_logimage("decode array\n");
- if (indexed)
- for (i = 0; i < 2; i++)
- img->decode[i] = fz_toreal(fz_arrayget(obj, i));
- else
- for (i = 0; i < (n + a) * 2; i++)
- img->decode[i] = fz_toreal(fz_arrayget(obj, i));
- }
- else
- {
- if (indexed)
- for (i = 0; i < 2; i++)
- img->decode[i] = i & 1 ? (1 << bpc) - 1 : 0;
- else
- for (i = 0; i < (n + a) * 2; i++)
- img->decode[i] = i & 1;
- }
-
- /*
- * Load samples
- */
+ pdf_logimage("load image (%d %d R) {\n", fz_tonum(dict), fz_togen(dict));
- if (indexed)
- stride = (w * bpc + 7) / 8;
- else
- stride = (w * (n + a) * bpc + 7) / 8;
+ error = pdf_loadimageheader(&img, xref, rdb, dict);
+ if (error)
+ return fz_rethrow(error, "cannot load image (%d %d R)", fz_tonum(dict), fz_togen(dict));
error = pdf_loadstream(&img->samples, xref, fz_tonum(dict), fz_togen(dict));
if (error)
{
- /* TODO: colorspace? */
- fz_free(img);
- return error;
+ pdf_dropimage(img);
+ return fz_rethrow(error, "cannot load image data (%d %d R)", fz_tonum(dict), fz_togen(dict));
}
- expectedsize = stride *h;
- realsize = img->samples->wp - img->samples->bp;
- if (realsize < expectedsize)
+ /* Pad truncated images */
+ if (img->samples->wp - img->samples->bp < img->stride * img->h)
{
- /* don't treat truncated image as fatal - get as much as possible and
- fill the rest with 0 */
- fz_buffer *buf;
- buf = fz_newbuffer(expectedsize);
- memset(buf->bp, 0, expectedsize);
- memmove(buf->bp, img->samples->bp, realsize);
- buf->wp = buf->bp + expectedsize;
- fz_dropbuffer(img->samples);
- img->samples = buf;
- fz_warn("truncated image; proceeding anyway");
+ fz_warn("padding truncated image");
+ fz_resizebuffer(img->samples, img->stride * img->h);
+ memset(img->samples->wp, 0, img->samples->ep - img->samples->wp);
+ img->samples->wp = img->samples->bp + img->stride * img->h;
}
/* 0 means opaque and 1 means transparent, so we invert to get alpha */
- if (ismask)
+ if (img->imagemask)
{
unsigned char *p;
for (p = img->samples->bp; p < img->samples->ep; p++)
*p = ~*p;
}
- /*
- * Create image object
- */
-
- img->refs = 1;
- img->cs = cs;
- img->w = w;
- img->h = h;
- img->n = n;
- img->a = a;
- img->indexed = indexed;
- img->stride = stride;
- img->bpc = bpc;
- img->mask = mask;
- img->usecolorkey = usecolorkey;
-
pdf_logimage("}\n");
pdf_storeitem(xref->store, PDF_KIMAGE, dict, img);
@@ -452,15 +220,15 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict)
}
static void
-maskcolorkey(fz_pixmap *pix, int *colorkey)
+pdf_maskcolorkey(fz_pixmap *pix, int n, int *colorkey, int scale)
{
unsigned char *p = pix->samples;
int i, k, t;
for (i = 0; i < pix->w * pix->h; i++)
{
t = 1;
- for (k = 1; k < pix->n; k++)
- if (p[k] < colorkey[k * 2 - 2] || p[k] > colorkey[k * 2 - 1])
+ for (k = 0; k < n; k++)
+ if (p[k] < colorkey[k * 2] * scale || p[k] > colorkey[k * 2 + 1] * scale)
t = 0;
if (t)
for (k = 0; k < pix->n; k++)
@@ -469,23 +237,6 @@ maskcolorkey(fz_pixmap *pix, int *colorkey)
}
}
-static void
-maskcolorkeyindexed(fz_pixmap *ind, fz_pixmap *pix, int *colorkey)
-{
- unsigned char *s = ind->samples;
- unsigned char *d = pix->samples;
- int i, k;
-
- for (i = 0; i < pix->w * pix->h; i++)
- {
- if (s[0] >= colorkey[0] && s[0] <= colorkey[1])
- for (k = 0; k < pix->n; k++)
- d[k] = 0;
- s += ind->n;
- d += pix->n;
- }
-}
-
fz_error
pdf_loadtile(pdf_image *src, fz_pixmap *tile)
{
@@ -493,7 +244,7 @@ pdf_loadtile(pdf_image *src, fz_pixmap *tile)
assert(tile->x == 0); /* can't handle general tile yet, only y-banding */
- assert(tile->n == src->n + 1);
+ assert(tile->n == src->n + 1 - src->imagemask);
assert(tile->x >= 0);
assert(tile->y >= 0);
assert(tile->x + tile->w <= src->w);
@@ -510,62 +261,30 @@ pdf_loadtile(pdf_image *src, fz_pixmap *tile)
return fz_throw("rangecheck: unsupported bit depth: %d", src->bpc);
}
- if (src->indexed)
- {
- fz_pixmap *tmp;
- int x, y, k, i;
- int bpcfact = 1;
-
- tmp = fz_newpixmap(nil, tile->x, tile->y, tile->w, tile->h);
+ tilefunc(src->samples->rp + (tile->y * src->stride), src->stride,
+ tile->samples, tile->w * tile->n,
+ tile->w * src->n, tile->h, src->imagemask ? 0 : src->n);
- switch (src->bpc)
- {
- case 1: bpcfact = 255; break;
- case 2: bpcfact = 85; break;
- case 4: bpcfact = 17; break;
- case 8: bpcfact = 1; break;
- }
-
- tilefunc(src->samples->rp + (tile->y * src->stride), src->stride,
- tmp->samples, tmp->w,
- tmp->w, tmp->h, 0);
-
- for (y = 0; y < tile->h; y++)
+ if (src->usecolorkey)
+ {
+ int scale = 1; /* tilefunc scaled image samples to 0..255 */
+ if (!src->indexed)
{
- int dn = tile->n;
- unsigned char *dst = tile->samples + y * tile->w * dn;
- unsigned char *st = tmp->samples + y * tmp->w;
- unsigned char *index = src->indexed->lookup;
- int high = src->indexed->high;
- int sn = src->indexed->base->n;
- for (x = 0; x < tile->w; x++)
+ switch (src->bpc)
{
- i = st[x] / bpcfact;
- i = CLAMP(i, 0, high);
- for (k = 0; k < sn; k++)
- {
- dst[x * dn + k] = index[i * sn + k];
- }
- dst[x * dn + sn] = 255; /* alpha */
+ case 1: scale = 255; break;
+ case 2: scale = 85; break;
+ case 4: scale = 17; break;
+ case 8: scale = 1; break;
+ case 16:
+ fz_warn("color-key masked 16-bpc images are not supported");
+ break;
}
}
-
- if (src->usecolorkey)
- maskcolorkeyindexed(tmp, tile, src->colorkey);
-
- fz_droppixmap(tmp);
+ pdf_maskcolorkey(tile, src->n, src->colorkey, scale);
}
- else
- {
- tilefunc(src->samples->rp + (tile->y * src->stride), src->stride,
- tile->samples, tile->w * tile->n,
- tile->w * (src->n + src->a), tile->h, src->a ? 0 : src->n);
- if (src->usecolorkey)
- maskcolorkey(tile, src->colorkey);
- fz_decodetile(tile, !src->a, src->decode);
- }
+ fz_decodetile(tile, !src->imagemask, src->decode);
return fz_okay;
}
-
diff --git a/mupdf/pdf_interpret.c b/mupdf/pdf_interpret.c
index bda4a601..f45b9299 100644
--- a/mupdf/pdf_interpret.c
+++ b/mupdf/pdf_interpret.c
@@ -45,8 +45,6 @@ pdf_keepmaterial(pdf_material *mat)
{
if (mat->cs)
fz_keepcolorspace(mat->cs);
- if (mat->indexed)
- fz_keepcolorspace(&mat->indexed->super);
if (mat->pattern)
pdf_keeppattern(mat->pattern);
if (mat->shade)
@@ -59,8 +57,6 @@ pdf_dropmaterial(pdf_material *mat)
{
if (mat->cs)
fz_dropcolorspace(mat->cs);
- if (mat->indexed)
- fz_dropcolorspace(&mat->indexed->super);
if (mat->pattern)
pdf_droppattern(mat->pattern);
if (mat->shade)
@@ -573,7 +569,7 @@ Lsetcolorspace:
if ((csi->dev->hints & FZ_IGNOREIMAGE) == 0)
{
pdf_image *img;
- error = pdf_loadimage(&img, csi->xref, obj);
+ error = pdf_loadimage(&img, csi->xref, rdb, obj);
if (error)
return fz_rethrow(error, "cannot load image (%d %d R)", fz_tonum(obj), fz_togen(obj));
pdf_showimage(csi, img);
@@ -743,15 +739,7 @@ Lsetcolor:
case PDF_MNONE:
return fz_throw("cannot set color in mask objects");
- case PDF_MINDEXED:
- if (csi->top < 1)
- goto syntaxerror;
- v[0] = fz_toreal(csi->stack[0]);
- pdf_setcolor(csi, what, v);
- break;
-
case PDF_MCOLOR:
- case PDF_MLAB:
if (csi->top < mat->cs->n)
goto syntaxerror;
for (i = 0; i < csi->top; i++)
diff --git a/mupdf/pdf_pattern.c b/mupdf/pdf_pattern.c
index 678698ef..d083c855 100644
--- a/mupdf/pdf_pattern.c
+++ b/mupdf/pdf_pattern.c
@@ -62,6 +62,8 @@ pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict)
return fz_rethrow(error, "cannot load pattern stream (%d %d R)", fz_tonum(dict), fz_togen(dict));
}
+ pdf_logrsrc("}\n");
+
*patp = pat;
return fz_okay;
}
diff --git a/mupdf/pdf_store.c b/mupdf/pdf_store.c
index a5fc3cfe..519ec9e8 100644
--- a/mupdf/pdf_store.c
+++ b/mupdf/pdf_store.c
@@ -228,7 +228,7 @@ pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val)
}
else
{
- pdf_logrsrc("store item %s: ... = %p\n", kindstr(kind), val);
+ pdf_logrsrc("store item %s (...) = %p\n", kindstr(kind), val);
item->next = store->root;
store->root = item;
diff --git a/mupdf/pdf_xobject.c b/mupdf/pdf_xobject.c
index a083a38d..38310163 100644
--- a/mupdf/pdf_xobject.c
+++ b/mupdf/pdf_xobject.c
@@ -19,11 +19,11 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict)
form->resources = nil;
form->contents = nil;
+ pdf_logrsrc("load xobject (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), form);
+
/* Store item immediately, to avoid possible recursion if objects refer back to this one */
pdf_storeitem(xref->store, PDF_KXOBJECT, dict, form);
- pdf_logrsrc("load xobject (%d %d R) ptr=%p {\n", fz_tonum(dict), fz_togen(dict), form);
-
obj = fz_dictgets(dict, "BBox");
form->bbox = pdf_torect(obj);