summaryrefslogtreecommitdiff
path: root/fitz
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 /fitz
parent47dd54d16a6132b14103fbc146970d22172f07c3 (diff)
downloadmupdf-a8a47bb3f214467016d2b37d95e98ffdec4f7ba1.tar.xz
Refactor colorspace and PDF image parsing code.
Diffstat (limited to 'fitz')
-rw-r--r--fitz/fitz.h12
-rw-r--r--fitz/res_colorspace.c449
-rw-r--r--fitz/stm_buffer.c18
3 files changed, 447 insertions, 32 deletions
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;