diff options
author | Sebastian Rasmussen <sebras@gmail.com> | 2018-09-13 17:36:24 +0800 |
---|---|---|
committer | Sebastian Rasmussen <sebras@gmail.com> | 2018-09-13 20:39:36 +0800 |
commit | 57160d72260914d90171027dfd9402997d221a6d (patch) | |
tree | 4beed09ab9933275551bcd62f177040ad59ff7d8 /source/fitz | |
parent | 16f293dc292f46a16659a033ea728be2562dce19 (diff) | |
download | mupdf-57160d72260914d90171027dfd9402997d221a6d.tar.xz |
jpx: Handle ICC color profiles.
Diffstat (limited to 'source/fitz')
-rw-r--r-- | source/fitz/load-jpx.c | 81 |
1 files changed, 65 insertions, 16 deletions
diff --git a/source/fitz/load-jpx.c b/source/fitz/load-jpx.c index fb4e66de..49d7a811 100644 --- a/source/fitz/load-jpx.c +++ b/source/fitz/load-jpx.c @@ -298,34 +298,59 @@ jpx_read_image(fz_context *ctx, fz_jpxd *state, const unsigned char *data, size_ if (state->xres == 0 || state->yres == 0) state->xres = state->yres = 72; + state->cs = NULL; + if (defcs) { if (fz_colorspace_n(ctx, defcs) == nchans) { - state->cs = defcs; + state->cs = fz_keep_colorspace(ctx, defcs); } else { fz_warn(ctx, "jpx file (%lu) and dict colorspace (%d, %s) do not match", nchans, fz_colorspace_n(ctx, defcs), fz_colorspace_name(ctx, defcs)); - defcs = NULL; } } - if (!defcs) + if (!state->cs && colorspace == cJP2_Colorspace_Palette_ICCa) + { + unsigned char *iccprofile = NULL; + unsigned long size = 0; + fz_stream *cstm = NULL; + fz_var(cstm); + + err = JP2_Decompress_GetICC(doc, &iccprofile, &size); + if (err != cJP2_Error_OK) + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get ICC color profile: %d", (int) err); + + fz_try(ctx) + { + cstm = fz_open_memory(ctx, iccprofile, size); + state->cs = fz_new_icc_colorspace_from_stream(ctx, FZ_COLORSPACE_NONE, cstm); + } + fz_always(ctx) + fz_drop_stream(ctx, cstm); + fz_catch(ctx) + { + fz_warn(ctx, "cannot load ICC profile: %s", fz_caught_message(ctx)); + } + } + + if (!state->cs) { switch (colors) { - case 4: state->cs = fz_device_cmyk(ctx); break; + case 4: state->cs = fz_keep_colorspace(ctx, fz_device_cmyk(ctx)); break; case 3: if (colorspace == cJP2_Colorspace_CIE_LABa) - state->cs = fz_device_lab(ctx); + state->cs = fz_keep_colorspace(ctx, fz_device_lab(ctx)); else - state->cs = fz_device_rgb(ctx); + state->cs = fz_keep_colorspace(ctx, fz_device_rgb(ctx)); break; - case 1: state->cs = fz_device_gray(ctx); break; + case 1: state->cs = fz_keep_colorspace(ctx, fz_device_gray(ctx)); break; case 0: if (alphas == 1) { /* alpha only images are rendered as grayscale */ - state->cs = fz_device_gray(ctx); + state->cs = fz_keep_colorspace(ctx, fz_device_gray(ctx)); colors = 1; alphas = 0; break; @@ -337,6 +362,7 @@ jpx_read_image(fz_context *ctx, fz_jpxd *state, const unsigned char *data, size_ } fz_catch(ctx) { + fz_drop_colorspace(ctx, state->cs); JP2_Decompress_End(doc); fz_rethrow(ctx); } @@ -411,7 +437,10 @@ jpx_read_image(fz_context *ctx, fz_jpxd *state, const unsigned char *data, size_ } } fz_always(ctx) + { + fz_drop_colorspace(ctx, state->cs); JP2_Decompress_End(doc); + } fz_catch(ctx) { fz_drop_pixmap(ctx, state->pix); @@ -436,7 +465,7 @@ fz_load_jpx_info(fz_context *ctx, const unsigned char *data, size_t size, int *w jpx_read_image(ctx, &state, data, size, NULL, 1); - *cspacep = fz_keep_colorspace(ctx, state.cs); /* state.cs is a borrowed device colorspace */ + *cspacep = state.cs; *wp = state.width; *hp = state.height; *xresp = state.xres; @@ -737,22 +766,39 @@ jpx_read_image(fz_context *ctx, fz_jpxd *state, const unsigned char *data, size_ { if (fz_colorspace_n(ctx, defcs) == n) { - state->cs = defcs; + state->cs = fz_keep_colorspace(ctx, defcs); } else { fz_warn(ctx, "jpx file and dict colorspace do not match"); - defcs = NULL; } } - if (!defcs) + if (!state->cs && jpx->icc_profile_buf) + { + fz_stream *cstm = NULL; + fz_var(cstm); + + fz_try(ctx) + { + cstm = fz_open_memory(ctx, jpx->icc_profile_buf, jpx->icc_profile_len); + state->cs = fz_new_icc_colorspace_from_stream(ctx, FZ_COLORSPACE_NONE, cstm); + } + fz_always(ctx) + fz_drop_stream(ctx, cstm); + fz_catch(ctx) + { + fz_warn(ctx, "cannot load ICC profile: %s", fz_caught_message(ctx)); + } + } + + if (!state->cs) { switch (n) { - case 1: state->cs = fz_device_gray(ctx); break; - case 3: state->cs = fz_device_rgb(ctx); break; - case 4: state->cs = fz_device_cmyk(ctx); break; + case 1: state->cs = fz_keep_colorspace(ctx, fz_device_gray(ctx)); break; + case 3: state->cs = fz_keep_colorspace(ctx, fz_device_rgb(ctx)); break; + case 4: state->cs = fz_keep_colorspace(ctx, fz_device_cmyk(ctx)); break; default: { opj_image_destroy(jpx); @@ -825,7 +871,10 @@ jpx_read_image(fz_context *ctx, fz_jpxd *state, const unsigned char *data, size_ fz_premultiply_pixmap(ctx, img); } fz_always(ctx) + { + fz_drop_colorspace(ctx, state->cs); opj_image_destroy(jpx); + } fz_catch(ctx) { fz_drop_pixmap(ctx, img); @@ -869,7 +918,7 @@ fz_load_jpx_info(fz_context *ctx, const unsigned char *data, size_t size, int *w fz_catch(ctx) fz_rethrow(ctx); - *cspacep = fz_keep_colorspace(ctx, state.cs); + *cspacep = state.cs; *wp = state.width; *hp = state.height; *xresp = state.xres; |