From a8a47bb3f214467016d2b37d95e98ffdec4f7ba1 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Sat, 10 Jul 2010 21:08:52 +0200 Subject: Refactor colorspace and PDF image parsing code. --- fitz/fitz.h | 12 +- fitz/res_colorspace.c | 449 +++++++++++++++++++++++++++++++++++++++++++++++--- fitz/stm_buffer.c | 18 ++ 3 files changed, 447 insertions(+), 32 deletions(-) (limited to 'fitz') 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 @@ -52,6 +52,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) { -- cgit v1.2.3