diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2011-04-06 01:50:08 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2011-04-06 02:21:38 +0200 |
commit | 4156e3fd2e8c70faea1d5f39170e7629ed451a2a (patch) | |
tree | f90daa9eeea431b42653b68f9e9d3c34e7c9e631 | |
parent | 65af65d1e82fd2bda7ba05ecea0b8d586c25c6c1 (diff) | |
download | mupdf-4156e3fd2e8c70faea1d5f39170e7629ed451a2a.tar.xz |
Improve handling of JPX colorspaces.
-rw-r--r-- | fitz/filt_jpxd.c | 56 | ||||
-rw-r--r-- | fitz/fitz.h | 2 | ||||
-rw-r--r-- | pdf/pdf_image.c | 48 |
3 files changed, 61 insertions, 45 deletions
diff --git a/fitz/filt_jpxd.c b/fitz/filt_jpxd.c index f5a65851..097d34de 100644 --- a/fitz/filt_jpxd.c +++ b/fitz/filt_jpxd.c @@ -19,7 +19,7 @@ static void fz_opj_info_callback(const char *msg, void *client_data) } fz_error -fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size) +fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace *defcs) { fz_pixmap *img; opj_event_mgr_t evtmgr; @@ -30,7 +30,7 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size) fz_colorspace *colorspace; unsigned char *p; int format; - int n, w, h, depth, sgnd; + int a, n, w, h, depth, sgnd; int x, y, k, v; if (size < 2) @@ -79,15 +79,34 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size) depth = jpx->comps[0].prec; sgnd = jpx->comps[0].sgnd; - switch (n) + if (jpx->color_space == CLRSPC_SRGB && n == 4) { n = 3; a = 1; } + else if (jpx->color_space == CLRSPC_SYCC && n == 4) { n = 3; a = 1; } + else if (n == 2) { n = 1; a = 1; } + else if (n > 4) { n = 4; a = 1; } + else { a = 0; } + + if (defcs) { - case 1: colorspace = fz_device_gray; break; - case 3: colorspace = fz_device_rgb; break; - case 4: colorspace = fz_device_cmyk; break; - default: - /* TODO: SMaskInData */ - opj_image_destroy(jpx); - return fz_throw("unknown jpx colorspace (%d components)", n); + if (defcs->n == n) + { + colorspace = defcs; + } + else + { + fz_warn("jpx file and dict colorspaces do not match"); + fz_drop_colorspace(defcs); + defcs = NULL; + } + } + + if (!defcs) + { + switch (n) + { + case 1: colorspace = fz_device_gray; break; + case 3: colorspace = fz_device_rgb; break; + case 4: colorspace = fz_device_cmyk; break; + } } img = fz_new_pixmap(colorspace, 0, 0, w, h); @@ -97,7 +116,7 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size) { for (x = 0; x < w; x++) { - for (k = 0; k < n; k++) + for (k = 0; k < n + a; k++) { v = jpx->comps[k].data[y * w + x]; if (sgnd) @@ -106,8 +125,21 @@ fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size) v = v >> (depth - 8); *p++ = v; } - *p++ = 255; /* TODO: SMaskInData */ + if (!a) + *p++ = 255; + } + } + + if (a) + { + if (n == 4) + { + fz_pixmap *tmp = fz_new_pixmap(fz_device_rgb, 0, 0, w, h); + fz_convert_pixmap(img, tmp); + fz_drop_pixmap(img); + img = tmp; } + fz_premultiply_pixmap(img); } opj_image_destroy(jpx); diff --git a/fitz/fitz.h b/fitz/fitz.h index f0f3ecdb..4833ffd6 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -697,7 +697,7 @@ fz_error fz_write_pnm(fz_pixmap *pixmap, char *filename); fz_error fz_write_pam(fz_pixmap *pixmap, char *filename, int savealpha); fz_error fz_write_png(fz_pixmap *pixmap, char *filename, int savealpha); -fz_error fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size); +fz_error fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace *dcs); /* * Colorspace resources. diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c index dc12c232..0b2f2547 100644 --- a/pdf/pdf_image.c +++ b/pdf/pdf_image.c @@ -304,22 +304,37 @@ pdf_load_jpx_image(fz_pixmap **imgp, pdf_xref *xref, fz_obj *dict) { fz_error error; fz_buffer *buf; + fz_colorspace *colorspace; fz_pixmap *img; fz_obj *obj; pdf_log_image("jpeg2000\n"); + colorspace = NULL; + error = pdf_load_stream(&buf, xref, fz_to_num(dict), fz_to_gen(dict)); if (error) return fz_rethrow(error, "cannot load jpx image data"); - error = fz_load_jpx_image(&img, buf->data, buf->len); + obj = fz_dict_gets(dict, "ColorSpace"); + if (obj) + { + error = pdf_load_colorspace(&colorspace, xref, obj); + if (error) + fz_catch(error, "cannot load image colorspace"); + } + + error = fz_load_jpx_image(&img, buf->data, buf->len, colorspace); if (error) { + if (colorspace) + fz_drop_colorspace(colorspace); fz_drop_buffer(buf); return fz_rethrow(error, "cannot load jpx image"); } + if (colorspace) + fz_drop_colorspace(colorspace); fz_drop_buffer(buf); obj = fz_dict_getsa(dict, "SMask", "Mask"); @@ -333,37 +348,6 @@ pdf_load_jpx_image(fz_pixmap **imgp, pdf_xref *xref, fz_obj *dict) } } - obj = fz_dict_gets(dict, "ColorSpace"); - if (obj) - { - fz_colorspace *original = img->colorspace; - img->colorspace = NULL; - - error = pdf_load_colorspace(&img->colorspace, xref, obj); - if (error) - { - fz_drop_colorspace(original); - return fz_rethrow(error, "cannot load image colorspace"); - } - - if (original->n != img->colorspace->n) - { - fz_warn("jpeg-2000 colorspace (%s) does not match promised colorspace (%s)", original->name, img->colorspace->name); - fz_drop_colorspace(img->colorspace); - img->colorspace = original; - } - else - fz_drop_colorspace(original); - - if (!strcmp(img->colorspace->name, "Indexed")) - { - fz_pixmap *conv; - conv = pdf_expand_indexed_pixmap(img); - fz_drop_pixmap(img); - img = conv; - } - } - *imgp = img; return fz_okay; } |