[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(¶ms);
+ opj_set_default_decoder_parameters(¶ms);
- info = opj_create_decompress(format);
- opj_set_event_mgr((opj_common_ptr)info, &evtmgr, stderr);
- opj_setup_decoder(info, ¶ms);
+ info = opj_create_decompress(format);
+ opj_set_event_mgr((opj_common_ptr)info, &evtmgr, stderr);
+ opj_setup_decoder(info, ¶ms);
- 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