[gs-commits] mupdf/master - 0_6-240-g5778eaf - Treat JPXDecode images as a special case bypassing the regular filter logic.

Tor Andersson tor at ghostscript.com
Tue Aug 3 12:09:46 UTC 2010


commit 5778eafa7bfcf62a684984891e9cf0a69186f5e3
Author: Tor Andersson <tor at ghostscript.com>
Date:   Fri Jul 30 01:16:14 2010 +0000

    Treat JPXDecode images as a special case bypassing the regular filter logic.
    
    Ignore-this: 5017638e0599c726f3949b80b6e5c744
    
    darcs-hash:20100730011614-f546f-681e40d6f6255821b1b0029ac18efe15f78a626f.gz

 5 files changed, 117 insertions(+), 102 deletions(-)

diff --git a/fitz/filt_jpxd.c b/fitz/filt_jpxd.c
index 01f15c1..f4530ad 100644
--- a/fitz/filt_jpxd.c
+++ b/fitz/filt_jpxd.c
@@ -1,17 +1,9 @@
 #include "fitz.h"
+#include "mupdf.h"
 
 #define OPJ_STATIC
 #include <openjpeg.h>
 
-typedef struct fz_jpxd_s fz_jpxd;
-
-struct fz_jpxd_s
-{
-	fz_stream *chain;
-	opj_image_t *image;
-	int x, y, k;
-};
-
 static void fz_opj_error_callback(const char *msg, void *client_data)
 {
 	fprintf(stderr, "openjpeg error: %s", msg);
@@ -24,132 +16,130 @@ static void fz_opj_warning_callback(const char *msg, void *client_data)
 
 static void fz_opj_info_callback(const char *msg, void *client_data)
 {
-	/* fprintf(stdout, "openjpeg info: %s", msg); */
+	char buf[80];
+	int len = fz_strlcpy(buf, msg, sizeof buf);
+	if (len > 0) buf[len-1] = 0;
+	pdf_logimage("%s\n", buf);
 }
 
-static int
-readjpxd(fz_stream *stm, unsigned char *outbuf, int outlen)
+fz_error
+pdf_loadjpximage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
 {
-	fz_jpxd *state = stm->state;
-	unsigned char *p = outbuf;
+	pdf_image *img;
 	opj_event_mgr_t evtmgr;
 	opj_dparameters_t params;
 	opj_dinfo_t *info;
 	opj_cio_t *cio;
+	opj_image_t *jpx;
+	fz_error error;
+	fz_buffer *buf;
+	unsigned char *p;
 	int format;
 	int n, w, h, depth, sgnd;
-	int k, v;
+	int x, y, k, v;
 
-	if (!state->image)
-	{
-		fz_error error;
-		fz_buffer *buf;
+	pdf_logimage("load jpx image (%d %d R) {\n", fz_tonum(dict), fz_togen(dict));
 
-		error = fz_readall(&buf, state->chain);
-		if (error)
-			return fz_throw("read error in jpx filter");
+	error = pdf_loadstream(&buf, xref, fz_tonum(dict), fz_togen(dict));
+	if (error)
+		return fz_throw("read error in jpx image");
 
-		if (buf->len < 2)
-		{
-			fz_dropbuffer(buf);
-			return fz_throw("not enough data to determine image format");
-		}
+	if (buf->len < 2)
+	{
+		fz_dropbuffer(buf);
+		return fz_throw("not enough data to determine image format");
+	}
 
-		/* Check for SOC marker -- if found we have a bare J2K stream */
-		if (buf->data[0] == 0xFF && buf->data[1] == 0x4F)
-			format = CODEC_J2K;
-		else
-			format = CODEC_JP2;
+	/* Check for SOC marker -- if found we have a bare J2K stream */
+	if (buf->data[0] == 0xFF && buf->data[1] == 0x4F)
+		format = CODEC_J2K;
+	else
+		format = CODEC_JP2;
 
-		memset(&evtmgr, 0, sizeof(evtmgr));
-		evtmgr.error_handler = fz_opj_error_callback;
-		evtmgr.warning_handler = fz_opj_warning_callback;
-		evtmgr.info_handler = fz_opj_info_callback;
+	memset(&evtmgr, 0, sizeof(evtmgr));
+	evtmgr.error_handler = fz_opj_error_callback;
+	evtmgr.warning_handler = fz_opj_warning_callback;
+	evtmgr.info_handler = fz_opj_info_callback;
 
-		opj_set_default_decoder_parameters(&params);
+	opj_set_default_decoder_parameters(&params);
 
-		info = opj_create_decompress(format);
-		opj_set_event_mgr((opj_common_ptr)info, &evtmgr, stderr);
-		opj_setup_decoder(info, &params);
+	info = opj_create_decompress(format);
+	opj_set_event_mgr((opj_common_ptr)info, &evtmgr, stderr);
+	opj_setup_decoder(info, &params);
 
-		cio = opj_cio_open((opj_common_ptr)info, buf->data, buf->len);
+	cio = opj_cio_open((opj_common_ptr)info, buf->data, buf->len);
 
-		state->image = opj_decode(info, cio);
+	jpx = opj_decode(info, cio);
 
-		opj_cio_close(cio);
-		opj_destroy_decompress(info);
-		fz_dropbuffer(buf);
+	opj_cio_close(cio);
+	opj_destroy_decompress(info);
+	fz_dropbuffer(buf);
 
-		if (!state->image)
-			return fz_throw("opj_decode failed");
+	if (!jpx)
+		return fz_throw("opj_decode failed");
 
-		for (k = 1; k < state->image->numcomps; k++)
-		{
-			if (state->image->comps[k].w != state->image->comps[0].w)
-				return fz_throw("image components have different width");
-			if (state->image->comps[k].h != state->image->comps[0].h)
-				return fz_throw("image components have different height");
-			if (state->image->comps[k].prec != state->image->comps[0].prec)
-				return fz_throw("image components have different precision");
-		}
+	for (k = 1; k < jpx->numcomps; k++)
+	{
+		if (jpx->comps[k].w != jpx->comps[0].w)
+			return fz_throw("image components have different width");
+		if (jpx->comps[k].h != jpx->comps[0].h)
+			return fz_throw("image components have different height");
+		if (jpx->comps[k].prec != jpx->comps[0].prec)
+			return fz_throw("image components have different precision");
 	}
 
-	n = state->image->numcomps;
-	w = state->image->comps[0].w;
-	h = state->image->comps[0].h;
-	depth = state->image->comps[0].prec;
-	sgnd = state->image->comps[0].sgnd;
+	n = jpx->numcomps;
+	w = jpx->comps[0].w;
+	h = jpx->comps[0].h;
+	depth = jpx->comps[0].prec;
+	sgnd = jpx->comps[0].sgnd;
+
+	img = fz_malloc(sizeof(pdf_image));
+	memset(img, 0, sizeof(pdf_image));
+	img->refs = 1;
+	img->w = w;
+	img->h = h;
+	img->bpc = 8;
+	img->n = n;
+	img->stride = w * n;
+	img->samples = fz_newbuffer(w * n * h);
+	img->samples->len = img->samples->cap;
+
+	switch (n)
+	{
+	default:
+	case 1: img->colorspace = fz_devicegray; break;
+	case 3: img->colorspace = fz_devicergb; break;
+	case 4: img->colorspace = fz_devicecmyk; break;
+	}
+
+	for (k = 0; k < n; k++)
+	{
+		img->decode[k * 2] = 0;
+		img->decode[k * 2 + 1] = 1;
+	}
 
-	while (state->y < h)
+	p = img->samples->data;
+	for (y = 0; y < h; y++)
 	{
-		while (state->x < w)
+		for (x = 0; x < w; x++)
 		{
-			while (state->k < n)
+			for (k = 0; k < n; k++)
 			{
-				if (p == outbuf + outlen)
-					return p - outbuf;
-
-				v = state->image->comps[state->k].data[state->y * w + state->x];
+				v = jpx->comps[k].data[y * w + x];
 				if (sgnd)
 					v = v + (1 << (depth - 1));
 				if (depth > 8)
 					v = v >> (depth - 8);
-
 				*p++ = v;
-
-				state->k ++;
 			}
-			state->x ++;
-			state->k = 0;
 		}
-		state->y ++;
-		state->x = 0;
 	}
 
-	return p - outbuf;
-}
-
-static void
-closejpxd(fz_stream *stm)
-{
-	fz_jpxd *state = stm->state;
-	if (state->image)
-		opj_image_destroy(state->image);
-	fz_close(state->chain);
-	fz_free(state);
-}
-
-fz_stream *
-fz_openjpxd(fz_stream *chain)
-{
-	fz_jpxd *state;
+	opj_image_destroy(jpx);
 
-	state = fz_malloc(sizeof(fz_jpxd));
-	state->chain = chain;
-	state->image = nil;
-	state->x = 0;
-	state->y = 0;
-	state->k = 0;
+	pdf_logimage("}\n");
 
-	return fz_newstream(state, readjpxd, closejpxd);
+	*imgp = img;
+	return fz_okay;
 }
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 696a901..1af70f6 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -546,7 +546,6 @@ fz_stream * fz_openflated(fz_stream *chain);
 fz_stream * fz_openlzwd(fz_stream *chain, fz_obj *param);
 fz_stream * fz_openpredict(fz_stream *chain, fz_obj *param);
 fz_stream * fz_openjbig2d(fz_stream *chain, fz_buffer *global);
-fz_stream * fz_openjpxd(fz_stream *chain);
 
 /*
  * Resources and other graphics related objects.
diff --git a/mupdf/mupdf.h b/mupdf/mupdf.h
index fa42f30..1a0aebb 100644
--- a/mupdf/mupdf.h
+++ b/mupdf/mupdf.h
@@ -279,6 +279,8 @@ fz_pixmap *pdf_loadtile(pdf_image *image);
 pdf_image *pdf_keepimage(pdf_image *img);
 void pdf_dropimage(pdf_image *img);
 
+fz_error pdf_loadjpximage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict);
+
 /*
  * CMap
  */
diff --git a/mupdf/pdf_image.c b/mupdf/pdf_image.c
index b10133e..839107c 100644
--- a/mupdf/pdf_image.c
+++ b/mupdf/pdf_image.c
@@ -178,12 +178,25 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref,
 	return fz_okay;
 }
 
+static int
+pdf_isjpximage(fz_obj *filter)
+{
+	int i;
+	if (!strcmp(fz_toname(filter), "JPXDecode"))
+		return 1;
+	for (i = 0; i < fz_arraylen(filter); i++)
+		if (!strcmp(fz_toname(fz_arrayget(filter, i)), "JPXDecode"))
+			return 1;
+	return 0;
+}
+
 fz_error
 pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
 {
 	fz_error error;
 	fz_stream *stm;
 	pdf_image *img;
+	fz_obj *obj;
 	int i, n;
 
 	if ((*imgp = pdf_finditem(xref->store, pdf_dropimage, dict)))
@@ -192,6 +205,16 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
 		return fz_okay;
 	}
 
+	/* special case for JPEG2000 images */
+	obj = fz_dictgets(dict, "Filter");
+	if (pdf_isjpximage(obj))
+	{
+		error = pdf_loadjpximage(&img, xref, rdb, dict);
+		if (error)
+			return fz_rethrow(error, "cannot load jpx image");
+		goto skip;
+	}
+
 	pdf_logimage("load image (%d %d R) {\n", fz_tonum(dict), fz_togen(dict));
 
 	error = pdf_loadimageheader(&img, xref, rdb, dict);
@@ -211,7 +234,7 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
 	{
 		pdf_dropimage(img);
 		fz_close(stm);
-		return fz_rethrow(n, "cannot load inline image data");
+		return fz_rethrow(n, "cannot load image data");
 	}
 	img->samples->len = n;
 
@@ -235,6 +258,7 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict)
 
 	pdf_logimage("}\n");
 
+skip:
 	pdf_storeitem(xref->store, pdf_keepimage, pdf_dropimage, dict, img);
 
 	*imgp = img;
diff --git a/mupdf/pdf_stream.c b/mupdf/pdf_stream.c
index 2e4032c..c564529 100644
--- a/mupdf/pdf_stream.c
+++ b/mupdf/pdf_stream.c
@@ -109,7 +109,7 @@ buildfilter(fz_stream *chain, pdf_xref * xref, fz_obj * f, fz_obj * p, int num,
 	}
 
 	else if (!strcmp(s, "JPXDecode"))
-		return fz_openjpxd(chain);
+		return chain; /* JPX decoding is special cased in the image loading code */
 
 	else if (!strcmp(s, "Crypt"))
 	{

--
git/hooks/post-receive


More information about the gs-commits mailing list