summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/pdfextract.c10
-rw-r--r--draw/imageunpack.c333
-rw-r--r--fitz/dev_draw.c2
-rw-r--r--fitz/fitz.h12
-rw-r--r--fitz/res_colorspace.c30
-rw-r--r--mupdf/mupdf.h5
-rw-r--r--mupdf/pdf_build.c19
-rw-r--r--mupdf/pdf_colorspace.c36
-rw-r--r--mupdf/pdf_image.c126
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;
}