summaryrefslogtreecommitdiff
path: root/fitz/res_colorspace.c
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/res_colorspace.c
parent47dd54d16a6132b14103fbc146970d22172f07c3 (diff)
downloadmupdf-a8a47bb3f214467016d2b37d95e98ffdec4f7ba1.tar.xz
Refactor colorspace and PDF image parsing code.
Diffstat (limited to 'fitz/res_colorspace.c')
-rw-r--r--fitz/res_colorspace.c449
1 files changed, 425 insertions, 24 deletions
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);
+}
+