diff options
author | Tor Andersson <tor@ghostscript.com> | 2010-07-11 16:02:39 +0200 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2010-07-11 16:02:39 +0200 |
commit | 2420b5d3aecb9aa286436215f975513f83828fc5 (patch) | |
tree | a222a2769cdc5dd78a358efc12c5ca57451df4e4 | |
parent | 92c206d6adc86ae645d54612b20e3de2df6afc45 (diff) | |
download | mupdf-2420b5d3aecb9aa286436215f975513f83828fc5.tar.xz |
Refactor image pixel unpacking.
-rw-r--r-- | apps/pdfextract.c | 10 | ||||
-rw-r--r-- | draw/imageunpack.c | 333 | ||||
-rw-r--r-- | fitz/dev_draw.c | 2 | ||||
-rw-r--r-- | fitz/fitz.h | 12 | ||||
-rw-r--r-- | fitz/res_colorspace.c | 30 | ||||
-rw-r--r-- | mupdf/mupdf.h | 5 | ||||
-rw-r--r-- | mupdf/pdf_build.c | 19 | ||||
-rw-r--r-- | mupdf/pdf_colorspace.c | 36 | ||||
-rw-r--r-- | mupdf/pdf_image.c | 126 |
9 files changed, 197 insertions, 376 deletions
diff --git a/apps/pdfextract.c b/apps/pdfextract.c index 00bddc11..4012b609 100644 --- a/apps/pdfextract.c +++ b/apps/pdfextract.c @@ -42,11 +42,7 @@ static void saveimage(int num, int gen) if (error) die(error); - pix = fz_newpixmap(img->colorspace, 0, 0, img->w, img->h); - - error = pdf_loadtile(img, pix); - if (error) - die(error); + pix = pdf_loadtile(img); if (img->bpc == 1 && img->n == 0) { @@ -71,10 +67,8 @@ static void saveimage(int num, int gen) 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->colorspace, pix, pdf_devicergb, temp); + fz_convertpixmap(pix, temp); fz_droppixmap(pix); pix = temp; } diff --git a/draw/imageunpack.c b/draw/imageunpack.c index 6e5467ad..b899a8ad 100644 --- a/draw/imageunpack.c +++ b/draw/imageunpack.c @@ -1,308 +1,83 @@ #include "fitz.h" -typedef unsigned char byte; - /* - * Apply decode parameters + * Unpack image samples and optionally pad pixels with opaque alpha */ -static void decodetile(fz_pixmap *pix, int imagemask, float *decode) -{ - int min[FZ_MAXCOLORS]; - int max[FZ_MAXCOLORS]; - int sub[FZ_MAXCOLORS]; - int needed = 0; - int n = pix->n; - byte *p = pix->samples; - int wh = pix->w * pix->h; - int i; - int justinvert = 1; +#define get1(buf,x) ((buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1 ) +#define get2(buf,x) ((buf[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3 ) +#define get4(buf,x) ((buf[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15 ) +#define get8(buf,x) (buf[x]) +#define get16(buf,x) (buf[x << 1]) - for (i = 0; i < n - imagemask; i++) - { - min[i] = decode[i * 2] * 255; - max[i] = decode[i * 2 + 1] * 255; - sub[i] = max[i] - min[i]; - needed |= (min[i] != 0) | (max[i] != 255); - justinvert &= min[i] == 255 && max[i] == 0 && sub[i] == -255; - } +void +fz_unpacktile(fz_pixmap *dst, unsigned char * restrict src, int n, int depth, int stride) +{ + int pad, x, y, k; - if (imagemask) - { - min[i] = 0; - max[i] = 255; - sub[i] = 255; - } + pad = 0; + if (dst->n > n) + pad = (1 << depth) - 1; - if (!needed) - return; + /* TODO: reinsert Robin Watts' specialized loops here */ - switch (n) { - case 1: - while (wh--) - { - p[0] = min[0] + fz_mul255(sub[0], p[0]); - p ++; - } - break; - case 2: - 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; - while(hwh--) { - unsigned in = *wp; - unsigned out = in ^ mask; - *wp++ = out; - } - p = (byte *)wp; - } - if (wh--) { - p[0] = p[0]; - p[1] = 255 - p[1]; - p += 2; - } - } - else + for (y = 0; y < dst->h; y++) + { + unsigned char *sp = src + y * stride; + unsigned char *dp = dst->samples + y * (dst->w * dst->n); + int b = 0; + for (x = 0; x < dst->w; x++) { - while (wh--) + for (k = 0; k < n; k++) { - p[0] = min[0] + fz_mul255(sub[0], p[0]); - p[1] = min[1] + fz_mul255(sub[1], p[1]); - p += 2; + switch (depth) + { + case 1: *dp++ = get1(sp, b); break; + case 2: *dp++ = get2(sp, b); break; + case 4: *dp++ = get4(sp, b); break; + case 8: *dp++ = get8(sp, b); break; + case 16: *dp++ = get16(sp, b); break; + } + b++; } - } - break; - default: - while (wh--) - { - for (i = 0; i < n; i++) - p[i] = min[i] + fz_mul255(sub[i], p[i]); - p += n; + if (pad) + *dp++ = pad; } } } /* - * Unpack image samples and optionally pad pixels with opaque alpha + * Apply decode parameters and scale integers */ -#define tbit(buf,x) ((buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1 ) * 255 -#define ttwo(buf,x) ((buf[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3 ) * 85 -#define tnib(buf,x) ((buf[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15 ) * 17 -#define toct(buf,x) (buf[x]) -#define thex(buf,x) (buf[x << 1]) - -static byte t1pad0[256][8]; -static byte t1pad1[256][16]; - -static void init1(void) -{ - static int inited = 0; - byte bits[1]; - int i, k, x; - - if (inited) - return; - - for (i = 0; i < 256; i++) - { - bits[0] = i; - for (k = 0; k < 8; k++) - { - x = tbit(bits, k); - t1pad0[i][k] = x; - t1pad1[i][k * 2 + 0] = x; - t1pad1[i][k * 2 + 1] = 255; - } - } - - inited = 1; -} - -static void loadtile1(byte * restrict src, int sw, byte * restrict dst, int dw, int w, int h, int pad) +void +fz_decodetile(fz_pixmap *pix, float *decode, int scale) { - byte *sp; - byte *dp; - int x; - - init1(); - - if (pad == 0) - { - int w3 = w >> 3; - while (h--) - { - sp = src; - dp = dst; - for (x = 0; x < w3; x++) - { - memcpy(dp, t1pad0[*sp++], 8); - dp += 8; - } - x = x << 3; - if (x < w) - memcpy(dp, t1pad0[*sp], w - x); - src += sw; - dst += dw; - } - } + int min[FZ_MAXCOLORS + 2]; + int max[FZ_MAXCOLORS + 2]; + int sub[FZ_MAXCOLORS + 2]; + unsigned char *p = pix->samples; + int len = pix->w * pix->h; + int n = pix->n; + int needed; + int k; - else if (pad == 1) + needed = scale != 1; + for (k = 0; k < n; k++) { - int w3 = w >> 3; - while (h--) - { - sp = src; - dp = dst; - for (x = 0; x < w3; x++) - { - memcpy(dp, t1pad1[*sp++], 16); - dp += 16; - } - x = x << 3; - if (x < w) - memcpy(dp, t1pad1[*sp], (w - x) << 1); - src += sw; - dst += dw; - } + min[k] = decode[k * 2] * 255; + max[k] = decode[k * 2 + 1] * 255; + sub[k] = max[k] - min[k]; + needed |= min[k] != 0 || max[k] != 255; } - else - { - while (h--) - { - dp = dst; - for (x = 0; x < w; x++) - { - if ((x % pad) == pad-1) - *dp++ = 255; - *dp++ = tbit(src, x); - } - src += sw; - dst += dw; - } - } -} - -#define TILE(getf) \ -{ \ - int x; \ - if (!pad) \ - while (h--) \ - { \ - for (x = 0; x < w; x++) \ - dst[x] = getf(src, x); \ - src += sw; \ - dst += dw; \ - } \ - else { \ - int tpad; \ - while (h--) \ - { \ - byte *dp = dst; \ - tpad = pad; \ - for (x = 0; x < w; x++) \ - { \ - *dp++ = getf(src, x); \ - if (--tpad == 0) { \ - tpad = pad; \ - *dp++ = 255; \ - } \ - } \ - src += sw; \ - dst += dw; \ - } \ - } \ -} - -static void loadtile2(byte * restrict src, int sw, byte * restrict dst, int dw, int w, int h, int pad) -TILE(ttwo) -static void loadtile4(byte * restrict src, int sw, byte * restrict dst, int dw, int w, int h, int pad) -TILE(tnib) -static void loadtile8(byte * restrict src, int sw, byte * restrict dst, int dw, int w, int h, int pad) -{ - if ((h == 0) || (w == 0)) + if (!needed) return; - switch (pad) + while (len--) { - case 0: - while (h--) - { - memcpy(dst, src, w); - src += sw; - dst += dw; - } - break; - - case 1: - sw -= w; - dw -= w<<1; - while (h--) - { - int x; - for (x = w; x > 0; x --) - { - *dst++ = *src++; - *dst++ = 255; - } - src += sw; - dst += dw; - } - break; - - case 3: - sw -= w; - while (h--) - { - byte *dp = dst; - int x; - for (x = w; x > 0; x -= 3) - { - *dp++ = *src++; - *dp++ = *src++; - *dp++ = *src++; - *dp++ = 255; - } - src += sw; - dst += dw; - } - break; - - default: - sw -= w; - while (h--) - { - byte *dp = dst; - int tpad = pad; - int x; - for (x = w; x > 0; x--) - { - *dp++ = *src++; - tpad--; - if (tpad == 0) { - tpad = pad; - *dp++ = 255; - } - } - src += sw; - dst += dw; - } - break; + for (k = 0; k < n; k++) + p[k] = min[k] + fz_mul255(sub[k], p[k] * scale); + p += n; } } - -static void loadtile16(byte * restrict src, int sw, byte * restrict dst, int dw, int w, int h, int pad) -TILE(thex) - -void (*fz_decodetile)(fz_pixmap *pix, int skip, float *decode) = decodetile; -void (*fz_loadtile1)(byte*restrict, int sw, byte*restrict, int dw, int w, int h, int pad) = loadtile1; -void (*fz_loadtile2)(byte*restrict, int sw, byte*restrict, int dw, int w, int h, int pad) = loadtile2; -void (*fz_loadtile4)(byte*restrict, int sw, byte*restrict, int dw, int w, int h, int pad) = loadtile4; -void (*fz_loadtile8)(byte*restrict, int sw, byte*restrict, int dw, int w, int h, int pad) = loadtile8; -void (*fz_loadtile16)(byte*restrict, int sw, byte*restrict, int dw, int w, int h, int pad) = loadtile16; - diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c index 9dfa58fc..e769f10a 100644 --- a/fitz/dev_draw.c +++ b/fitz/dev_draw.c @@ -578,7 +578,7 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm) if (image->colorspace != dev->model) { converted = fz_newpixmap(dev->model, image->x, image->y, image->w, image->h); - fz_convertpixmap(image->colorspace, image, dev->model, converted); + fz_convertpixmap(image, converted); image = converted; } diff --git a/fitz/fitz.h b/fitz/fitz.h index 8ad72322..2d64d63a 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -729,7 +729,7 @@ 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_convertpixmap(fz_pixmap *src, fz_pixmap *dst); /* * Fonts come in two variants: @@ -1113,6 +1113,9 @@ void fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix ctm); extern void fz_accelerate(void); extern void fz_acceleratearch(void); +extern void fz_decodetile(fz_pixmap *pix, float *decode, int scale); +extern void fz_unpacktile(fz_pixmap *dst, unsigned char * restrict src, int n, int depth, int stride); + extern void (*fz_duff_ni1on)(unsigned char*restrict,int,int,unsigned char*restrict,int,unsigned char*restrict,int,int,int); extern void (*fz_duff_1i1o1)(unsigned char*restrict,int,unsigned char*restrict,int,unsigned char*restrict,int,int,int); extern void (*fz_duff_2i1o2)(unsigned char*restrict,int,unsigned char*restrict,int,unsigned char*restrict,int,int,int); @@ -1133,13 +1136,6 @@ extern void (*fz_img_2o2)(unsigned char*restrict,unsigned char,int,unsigned char extern void (*fz_img_w2i1o2)(unsigned char*,unsigned char*restrict,unsigned char,int,unsigned char*restrict,fz_pixmap*,int u, int v, int fa, int fb); extern void (*fz_img_w4i1o4)(unsigned char*,unsigned char*restrict,unsigned char,int,unsigned char*restrict,fz_pixmap*,int u, int v, int fa, int fb); -extern void (*fz_decodetile)(fz_pixmap *pix, int skip, float *decode); -extern void (*fz_loadtile1)(unsigned char*restrict, int sw, unsigned char*restrict, int dw, int w, int h, int pad); -extern void (*fz_loadtile2)(unsigned char*restrict, int sw, unsigned char*restrict, int dw, int w, int h, int pad); -extern void (*fz_loadtile4)(unsigned char*restrict, int sw, unsigned char*restrict, int dw, int w, int h, int pad); -extern void (*fz_loadtile8)(unsigned char*restrict, int sw, unsigned char*restrict, int dw, int w, int h, int pad); -extern void (*fz_loadtile16)(unsigned char*restrict, int sw, unsigned char*restrict, int dw, int w, int h, int pad); - extern void (*fz_srown)(unsigned char *restrict, unsigned char *restrict, int w, int denom, int n); extern void (*fz_srow1)(unsigned char *restrict, unsigned char *restrict, int w, int denom); extern void (*fz_srow2)(unsigned char *restrict, unsigned char *restrict, int w, int denom); diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c index 6cad3f16..3e8660ab 100644 --- a/fitz/res_colorspace.c +++ b/fitz/res_colorspace.c @@ -286,18 +286,21 @@ static void fastrgbtobgr(fz_pixmap *src, fz_pixmap *dst) } static void -fz_stdconvpixmap(fz_colorspace *srcs, fz_pixmap *src, fz_colorspace *dsts, fz_pixmap *dst) +fz_stdconvpixmap(fz_pixmap *src, fz_pixmap *dst) { float srcv[FZ_MAXCOLORS]; float dstv[FZ_MAXCOLORS]; int y, x, k; + fz_colorspace *ss = src->colorspace; + fz_colorspace *ds = dst->colorspace; + unsigned char *s = src->samples; unsigned char *d = dst->samples; assert(src->w == dst->w && src->h == dst->h); - assert(src->n == srcs->n + 1); - assert(dst->n == dsts->n + 1); + assert(src->n == ss->n + 1); + assert(dst->n == ds->n + 1); for (y = 0; y < src->h; y++) { @@ -306,7 +309,7 @@ fz_stdconvpixmap(fz_colorspace *srcs, fz_pixmap *src, fz_colorspace *dsts, fz_pi for (k = 0; k < src->n - 1; k++) srcv[k] = *s++ / 255.0f; - fz_convertcolor(srcs, srcv, dsts, dstv); + fz_convertcolor(ss, srcv, ds, dstv); for (k = 0; k < dst->n - 1; k++) *d++ = dstv[k] * 255; @@ -317,14 +320,19 @@ 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) +fz_convertpixmap(fz_pixmap *sp, fz_pixmap *dp) { + fz_colorspace *ss = sp->colorspace; + fz_colorspace *ds = dp->colorspace; + + assert(ss && ds); + 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 fz_stdconvpixmap(sp, dp); } else if (ss == pdf_devicergb) @@ -332,8 +340,7 @@ fz_convertpixmap(fz_colorspace *ss, fz_pixmap *sp, fz_colorspace *ds, fz_pixmap 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 fz_stdconvpixmap(sp, dp); } else if (ss == pdf_devicebgr) @@ -341,8 +348,7 @@ fz_convertpixmap(fz_colorspace *ss, fz_pixmap *sp, fz_colorspace *ds, fz_pixmap 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 fz_stdconvpixmap(sp, dp); } else if (ss == pdf_devicecmyk) @@ -350,10 +356,10 @@ fz_convertpixmap(fz_colorspace *ss, fz_pixmap *sp, fz_colorspace *ds, fz_pixmap 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(sp, dp); } - else fz_stdconvpixmap(ss, sp, ds, dp); + else fz_stdconvpixmap(sp, dp); } /* diff --git a/mupdf/mupdf.h b/mupdf/mupdf.h index 1c6f964e..35117790 100644 --- a/mupdf/mupdf.h +++ b/mupdf/mupdf.h @@ -213,6 +213,7 @@ void pdf_dropfunction(pdf_function *func); */ fz_error pdf_loadcolorspace(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj); +fz_pixmap *pdf_expandindexedpixmap(fz_pixmap *src); /* * Pattern @@ -281,14 +282,14 @@ struct pdf_image_s pdf_image *mask; /* explicit mask/softmask image */ int usecolorkey; /* color-keyed masking */ int colorkey[FZ_MAXCOLORS * 2]; - float decode[FZ_MAXCOLORS * 2]; + float decode[FZ_MAXCOLORS * 2 + 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 *rdb, fz_obj *obj); -fz_error pdf_loadtile(pdf_image *image, fz_pixmap *tile); +fz_pixmap *pdf_loadtile(pdf_image *image); pdf_image *pdf_keepimage(pdf_image *img); void pdf_dropimage(pdf_image *img); diff --git a/mupdf/pdf_build.c b/mupdf/pdf_build.c index b64cd986..a2a5432a 100644 --- a/mupdf/pdf_build.c +++ b/mupdf/pdf_build.c @@ -228,28 +228,17 @@ void pdf_showimage(pdf_csi *csi, pdf_image *image) { pdf_gstate *gstate = csi->gstate + csi->gtop; - fz_pixmap *tile; - fz_error error; - - tile = fz_newpixmap(image->colorspace, 0, 0, image->w, image->h); - error = pdf_loadtile(image, tile); - if (error) - { - fz_droppixmap(tile); - fz_catch(error, "cannot load image data"); - return; - } + fz_pixmap *tile, *mask; if (image->mask) { - fz_pixmap *mask = fz_newpixmap(NULL, 0, 0, image->mask->w, image->mask->h); - error = pdf_loadtile(image->mask, mask); - if (error) - fz_catch(error, "cannot load image mask data"); + mask = pdf_loadtile(image->mask); csi->dev->clipimagemask(csi->dev->user, mask, gstate->ctm); fz_droppixmap(mask); } + tile = pdf_loadtile(image); + if (image->imagemask) { fz_rect bbox; diff --git a/mupdf/pdf_colorspace.c b/mupdf/pdf_colorspace.c index fd20d6b2..4cb61abc 100644 --- a/mupdf/pdf_colorspace.c +++ b/mupdf/pdf_colorspace.c @@ -204,6 +204,42 @@ freeindexed(fz_colorspace *cs) fz_free(idx); } +fz_pixmap * +pdf_expandindexedpixmap(fz_pixmap *src) +{ + struct indexed *idx; + fz_pixmap *dst; + unsigned char *s, *d; + int y, x, k, n, high; + unsigned char *lookup; + + assert(src->colorspace->toxyz == indexedtoxyz); + assert(src->n == 2); + + idx = src->colorspace->data; + high = idx->high; + lookup = idx->lookup; + n = idx->base->n; + + dst = fz_newpixmap(idx->base, src->x, src->y, src->w, src->h); + s = src->samples; + d = dst->samples; + + for (y = 0; y < src->h; y++) + { + for (x = 0; x < src->w; x++) + { + int v = *s++; + v = MIN(v, high); + for (k = 0; k < n; k++) + *d++ = lookup[v * n + k]; + *d++ = *s++; + } + } + + return dst; +} + static fz_error loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) { diff --git a/mupdf/pdf_image.c b/mupdf/pdf_image.c index e125545b..221dd507 100644 --- a/mupdf/pdf_image.c +++ b/mupdf/pdf_image.c @@ -79,7 +79,6 @@ pdf_loadimageheader(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) } else { - img->colorspace = pdf_devicegray; img->n = 1; } @@ -92,12 +91,22 @@ pdf_loadimageheader(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) else { for (i = 0; i < img->n * 2; i++) + { if (i & 1) - img->decode[i] = 1; + { + if (img->indexed) + img->decode[i] = (1 << img->bpc) - 1; + else + img->decode[i] = 1; + } else + { img->decode[i] = 0; + } + } } + /* Not allowed for inline images */ obj = fz_dictgetsa(dict, "Mask", "SMask"); if (pdf_isstream(xref, fz_tonum(obj), fz_togen(obj))) { @@ -107,7 +116,12 @@ pdf_loadimageheader(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) pdf_dropimage(img); return fz_rethrow(error, "cannot load image mask/softmask"); } - img->mask->imagemask = 1; + img->mask->imagemask = 1; /* TODO: this triggers bit inversion later. should we? */ + if (img->mask->colorspace) + { + fz_dropcolorspace(img->mask->colorspace); + img->mask->colorspace = nil; + } } else if (fz_isarray(obj)) { @@ -116,6 +130,21 @@ pdf_loadimageheader(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) img->colorkey[i] = fz_toint(fz_arrayget(obj, i)); } + if (img->imagemask) + { + if (img->colorspace) + { + fz_dropcolorspace(img->colorspace); + img->colorspace = nil; + } + } + else + { + /* add an entry for alpha channel */ + img->decode[img->n * 2] = 0; + img->decode[img->n * 2 + 1] = 1; + } + img->stride = (img->w * img->n * img->bpc + 7) / 8; pdf_logimage("size %dx%d n=%d bpc=%d (imagemask=%d)\n", img->w, img->h, img->n, img->bpc, img->imagemask); @@ -152,17 +181,17 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, } img->samples->wp += n; - fz_dropstream(subfile); - fz_dropfilter(filter); - - /* 0 means opaque and 1 means transparent, so we invert to get alpha */ if (img->imagemask) { + /* 0=opaque and 1=transparent so we need to invert */ unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = ~*p; } + fz_dropstream(subfile); + fz_dropfilter(filter); + pdf_logimage("}\n"); *imgp = img; @@ -203,9 +232,9 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) img->samples->wp = img->samples->bp + img->stride * img->h; } - /* 0 means opaque and 1 means transparent, so we invert to get alpha */ if (img->imagemask) { + /* 0=opaque and 1=transparent so we need to invert */ unsigned char *p; for (p = img->samples->bp; p < img->samples->ep; p++) *p = ~*p; @@ -220,15 +249,16 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) } static void -pdf_maskcolorkey(fz_pixmap *pix, int n, int *colorkey, int scale) +pdf_maskcolorkey(fz_pixmap *pix, int n, int *colorkey) { unsigned char *p = pix->samples; - int i, k, t; - for (i = 0; i < pix->w * pix->h; i++) + int len = pix->w * pix->h; + int k, t; + while (len--) { t = 1; for (k = 0; k < n; k++) - if (p[k] < colorkey[k * 2] * scale || p[k] > colorkey[k * 2 + 1] * scale) + if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1]) t = 0; if (t) for (k = 0; k < pix->n; k++) @@ -237,54 +267,48 @@ pdf_maskcolorkey(fz_pixmap *pix, int n, int *colorkey, int scale) } } -fz_error -pdf_loadtile(pdf_image *src, fz_pixmap *tile) +fz_pixmap * +pdf_loadtile(pdf_image *img /* ...bbox/y+h should go here... */) { - void (*tilefunc)(unsigned char*restrict,int,unsigned char*restrict, int, int, int, int); - - assert(tile->x == 0); /* can't handle general tile yet, only y-banding */ + fz_pixmap *tile; + int scale; - assert(tile->n == src->n + 1 - src->imagemask); - assert(tile->x >= 0); - assert(tile->y >= 0); - assert(tile->x + tile->w <= src->w); - assert(tile->y + tile->h <= src->h); + tile = fz_newpixmap(img->colorspace, 0, 0, img->w, img->h); - switch (src->bpc) + scale = 1; + switch (img->bpc) { - case 1: tilefunc = fz_loadtile1; break; - case 2: tilefunc = fz_loadtile2; break; - case 4: tilefunc = fz_loadtile4; break; - case 8: tilefunc = fz_loadtile8; break; - case 16: tilefunc = fz_loadtile16; break; - default: - return fz_throw("rangecheck: unsupported bit depth: %d", src->bpc); + case 1: scale = 255; break; + case 2: scale = 85; break; + case 4: scale = 17; break; } - 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); + fz_unpacktile(tile, img->samples->bp, img->n, img->bpc, img->stride); - if (src->usecolorkey) + if (img->usecolorkey) + pdf_maskcolorkey(tile, img->n, img->colorkey); + + if (!img->indexed) { - int scale = 1; /* tilefunc scaled image samples to 0..255 */ - if (!src->indexed) - { - switch (src->bpc) - { - 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; - } - } - pdf_maskcolorkey(tile, src->n, src->colorkey, scale); + fz_decodetile(tile, img->decode, scale); } - fz_decodetile(tile, !src->imagemask, src->decode); + if (img->indexed) + { + fz_pixmap *conv; + float decode[4]; - return fz_okay; + decode[0] = img->decode[0] * scale / 255; + decode[1] = img->decode[1] * scale / 255; + decode[2] = img->decode[2]; + decode[3] = img->decode[3]; + + fz_decodetile(tile, decode, scale); + + conv = pdf_expandindexedpixmap(tile); + fz_droppixmap(tile); + tile = conv; + } + + return tile; } |