[gs-commits] mupdf - 0.6-143-g146a628 - Refactor image pixel unpacking.

tor tor at ghostscript.com
Sun Jul 11 15:00:24 UTC 2010


commit 146a62892669d53abd2373bccc3770019d0f3559
Author: tor <tor at ghostscript.com>
Date:   Sun Jul 11 14:02:39 2010 +0000

    Refactor image pixel unpacking.

 9 files changed, 197 insertions(+), 376 deletions(-)

diff --git a/apps/pdfextract.c b/apps/pdfextract.c
index 00bddc1..4012b60 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 6e5467a..b899a8a 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 9dfa58f..e769f10 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 8ad7232..2d64d63 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 6cad3f1..3e8660a 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 1c6f964..3511779 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 b64cd98..a2a5432 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 fd20d6b..4cb61ab 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 e125545..221dd50 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;
 }

--
git/hooks/post-receive


More information about the gs-commits mailing list