static fz_pixmap * pdf_image_get_pixmap(fz_context *ctx, fz_image *image_, int w, int h) { pdf_image *image = (pdf_image *)image_; fz_pixmap *tile; fz_stream *stm; int l2factor; pdf_image_key key; int native_l2factor; int indexed; /* Check for 'simple' images which are just pixmaps */ if (image->buffer == NULL) { tile = image->tile; if (!tile) return NULL; return fz_keep_pixmap(ctx, tile); /* That's all we can give you! */ } /* Ensure our expectations for tile size are reasonable */ if (w > image->base.w) w = image->base.w; if (h > image->base.h) h = image->base.h; /* What is our ideal factor? */ if (w == 0 || h == 0) l2factor = 0; else for (l2factor=0; image->base.w>>(l2factor+1) >= w && image->base.h>>(l2factor+1) >= h && l2factor < 8; l2factor++); /* Can we find any suitable tiles in the cache? */ key.refs = 1; key.image = &image->base; key.l2factor = l2factor; do { tile = fz_find_item(ctx, fz_free_pixmap_imp, &key, &pdf_image_store_type); if (tile) return tile; key.l2factor--; } while (key.l2factor >= 0); /* We need to make a new one. */ native_l2factor = l2factor; stm = fz_open_image_decomp_stream(ctx, image->buffer, &native_l2factor); indexed = fz_colorspace_is_indexed(image->base.colorspace); return decomp_image_from_stream(ctx, stm, image, 0, indexed, l2factor, native_l2factor, 1); }
fz_image * fz_new_image(fz_context *ctx, int w, int h, int bpc, fz_colorspace *colorspace, int xres, int yres, int interpolate, int imagemask, float *decode, int *colorkey, fz_compressed_buffer *buffer, fz_image *mask) { fz_image *image; assert(mask == NULL || mask->mask == NULL); fz_try(ctx) { image = fz_malloc_struct(ctx, fz_image); FZ_INIT_STORABLE(image, 1, fz_free_image); image->get_pixmap = fz_image_get_pixmap; image->w = w; image->h = h; image->xres = xres; image->yres = yres; image->bpc = bpc; image->n = (colorspace ? colorspace->n : 1); image->colorspace = colorspace; image->interpolate = interpolate; image->imagemask = imagemask; image->usecolorkey = (colorkey != NULL); if (colorkey) memcpy(image->colorkey, colorkey, sizeof(int)*image->n*2); if (decode) memcpy(image->decode, decode, sizeof(float)*image->n*2); else { float maxval = fz_colorspace_is_indexed(colorspace) ? (1 << bpc) - 1 : 1; int i; for (i = 0; i < image->n; i++) { image->decode[2*i] = 0; image->decode[2*i+1] = maxval; } } image->mask = mask; image->buffer = buffer; } fz_catch(ctx) { fz_free_compressed_buffer(ctx, buffer); fz_rethrow(ctx); } return image; }
static fz_pixmap * standard_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h, int *l2factor) { int native_l2factor; fz_stream *stm; int indexed; fz_pixmap *tile; /* We need to make a new one. */ /* First check for ones that we can't decode using streams */ switch (image->buffer->params.type) { case FZ_IMAGE_PNG: tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; case FZ_IMAGE_GIF: tile = fz_load_gif(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; case FZ_IMAGE_TIFF: tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; case FZ_IMAGE_JXR: tile = fz_load_jxr(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; case FZ_IMAGE_JPEG: /* Scan JPEG stream and patch missing height values in header */ { unsigned char *s = image->buffer->buffer->data; unsigned char *e = s + image->buffer->buffer->len; unsigned char *d; for (d = s + 2; s < d && d < e - 9 && d[0] == 0xFF; d += (d[2] << 8 | d[3]) + 2) { if (d[1] < 0xC0 || (0xC3 < d[1] && d[1] < 0xC9) || 0xCB < d[1]) continue; if ((d[5] == 0 && d[6] == 0) || ((d[5] << 8) | d[6]) > image->h) { d[5] = (image->h >> 8) & 0xFF; d[6] = image->h & 0xFF; } } } /* fall through */ default: native_l2factor = l2factor ? *l2factor : 0; stm = fz_open_image_decomp_stream_from_buffer(ctx, image->buffer, l2factor); if (l2factor) native_l2factor -= *l2factor; indexed = fz_colorspace_is_indexed(ctx, image->colorspace); tile = fz_decomp_image_from_stream(ctx, stm, image, indexed, native_l2factor); /* CMYK JPEGs in XPS documents have to be inverted */ if (image->invert_cmyk_jpeg && image->buffer->params.type == FZ_IMAGE_JPEG && image->colorspace == fz_device_cmyk(ctx) && image->buffer->params.u.jpeg.color_transform) { fz_invert_pixmap(ctx, tile); } break; }
fz_pixmap * fz_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h) { fz_pixmap *tile; fz_stream *stm; int l2factor; fz_image_key key; int native_l2factor; int indexed; fz_image_key *keyp; /* Check for 'simple' images which are just pixmaps */ if (image->buffer == NULL) { tile = image->tile; if (!tile) return NULL; return fz_keep_pixmap(ctx, tile); /* That's all we can give you! */ } /* Ensure our expectations for tile size are reasonable */ if (w > image->w) w = image->w; if (h > image->h) h = image->h; /* What is our ideal factor? */ if (w == 0 || h == 0) l2factor = 0; else for (l2factor=0; image->w>>(l2factor+1) >= w && image->h>>(l2factor+1) >= h && l2factor < 8; l2factor++); /* Can we find any suitable tiles in the cache? */ key.refs = 1; key.image = image; key.l2factor = l2factor; do { tile = fz_find_item(ctx, fz_free_pixmap_imp, &key, &fz_image_store_type); if (tile) return tile; key.l2factor--; } while (key.l2factor >= 0); /* We need to make a new one. */ /* First check for ones that we can't decode using streams */ switch (image->buffer->params.type) { case FZ_IMAGE_PNG: tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; case FZ_IMAGE_TIFF: tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; default: native_l2factor = l2factor; stm = fz_open_image_decomp_stream(ctx, image->buffer, &native_l2factor); indexed = fz_colorspace_is_indexed(image->colorspace); tile = fz_decomp_image_from_stream(ctx, stm, image, 0, indexed, l2factor, native_l2factor); break; } /* Now we try to cache the pixmap. Any failure here will just result * in us not caching. */ fz_var(keyp); fz_try(ctx) { fz_pixmap *existing_tile; keyp = fz_malloc_struct(ctx, fz_image_key); keyp->refs = 1; keyp->image = fz_keep_image(ctx, image); keyp->l2factor = l2factor; existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type); if (existing_tile) { /* We already have a tile. This must have been produced by a * racing thread. We'll throw away ours and use that one. */ fz_drop_pixmap(ctx, tile); tile = existing_tile; } } fz_always(ctx) { fz_drop_image_key(ctx, keyp); } fz_catch(ctx) { /* Do nothing */ } return tile; }
static void pdf_out_BI(fz_context *ctx, pdf_processor *proc, fz_image *img) { fz_output *out = ((pdf_output_processor*)proc)->out; int ahx = ((pdf_output_processor*)proc)->ahxencode; fz_compressed_buffer *cbuf; fz_buffer *buf; int i; if (img == NULL) return; cbuf = fz_compressed_image_buffer(ctx, img); if (cbuf == NULL) return; buf = cbuf->buffer; if (buf == NULL) return; fz_printf(ctx, out, "BI\n"); fz_printf(ctx, out, "/W %d\n", img->w); fz_printf(ctx, out, "/H %d\n", img->h); fz_printf(ctx, out, "/BPC %d\n", img->bpc); if (img->imagemask) fz_printf(ctx, out, "/IM true\n"); else if (img->colorspace == fz_device_gray(ctx)) fz_printf(ctx, out, "/CS/G\n"); else if (img->colorspace == fz_device_rgb(ctx)) fz_printf(ctx, out, "/CS/RGB\n"); else if (img->colorspace == fz_device_cmyk(ctx)) fz_printf(ctx, out, "/CS/CMYK\n"); else if (fz_colorspace_is_indexed(ctx, img->colorspace)) fz_printf(ctx, out, "/CS/I\n"); if (img->interpolate) fz_printf(ctx, out, "/I true\n"); fz_printf(ctx, out, "/D["); for (i = 0; i < img->n * 2; ++i) { if (i > 0) fz_putc(ctx, out, ' '); fz_printf(ctx, out, "%g", img->decode[i]); } fz_printf(ctx, out, "]\n"); switch (cbuf->params.type) { default: fz_throw(ctx, FZ_ERROR_GENERIC, "unknown compressed buffer type"); break; case FZ_IMAGE_JPEG: fz_printf(ctx, out, ahx ? "/F[/AHx/DCT]\n" : "/F/DCT\n"); if (cbuf->params.u.jpeg.color_transform != -1) fz_printf(ctx, out, "/DP<</ColorTransform %d>>\n", cbuf->params.u.jpeg.color_transform); break; case FZ_IMAGE_FAX: fz_printf(ctx, out, ahx ? "/F[/AHx/CCF]\n/DP[null<<\n" : "/F/CCF\n/DP<<\n"); fz_printf(ctx, out, "/K %d\n", cbuf->params.u.fax.k); if (cbuf->params.u.fax.columns != 1728) fz_printf(ctx, out, "/Columns %d\n", cbuf->params.u.fax.columns); if (cbuf->params.u.fax.rows > 0) fz_printf(ctx, out, "/Rows %d\n", cbuf->params.u.fax.rows); if (cbuf->params.u.fax.end_of_line) fz_printf(ctx, out, "/EndOfLine true\n"); if (cbuf->params.u.fax.encoded_byte_align) fz_printf(ctx, out, "/EncodedByteAlign true\n"); if (!cbuf->params.u.fax.end_of_block) fz_printf(ctx, out, "/EndOfBlock false\n"); if (cbuf->params.u.fax.black_is_1) fz_printf(ctx, out, "/BlackIs1 true\n"); if (cbuf->params.u.fax.damaged_rows_before_error > 0) fz_printf(ctx, out, "/DamagedRowsBeforeError %d\n", cbuf->params.u.fax.damaged_rows_before_error); fz_printf(ctx, out, ahx ? ">>]\n" : ">>\n"); break; case FZ_IMAGE_RAW: if (ahx) fz_printf(ctx, out, "/F/AHx\n"); break; case FZ_IMAGE_RLD: fz_printf(ctx, out, ahx ? "/F[/AHx/RL]\n" : "/F/RL\n"); break; case FZ_IMAGE_FLATE: fz_printf(ctx, out, ahx ? "/F[/AHx/Fl]\n" : "/F/Fl\n"); if (cbuf->params.u.flate.predictor > 1) { fz_printf(ctx, out, ahx ? "/DP[null<<\n" : "/DP<<\n"); fz_printf(ctx, out, "/Predictor %d\n", cbuf->params.u.flate.predictor); if (cbuf->params.u.flate.columns != 1) fz_printf(ctx, out, "/Columns %d\n", cbuf->params.u.flate.columns); if (cbuf->params.u.flate.colors != 1) fz_printf(ctx, out, "/Colors %d\n", cbuf->params.u.flate.colors); if (cbuf->params.u.flate.bpc != 8) fz_printf(ctx, out, "/BitsPerComponent %d\n", cbuf->params.u.flate.bpc); fz_printf(ctx, out, ahx ? ">>]\n" : ">>\n"); } break; case FZ_IMAGE_LZW: fz_printf(ctx, out, ahx ? "/F[/AHx/LZW]\n" : "/F/LZW\n"); if (cbuf->params.u.lzw.predictor > 1) { fz_printf(ctx, out, ahx ? "/DP[<<null\n" : "/DP<<\n"); fz_printf(ctx, out, "/Predictor %d\n", cbuf->params.u.lzw.predictor); if (cbuf->params.u.lzw.columns != 1) fz_printf(ctx, out, "/Columns %d\n", cbuf->params.u.lzw.columns); if (cbuf->params.u.lzw.colors != 1) fz_printf(ctx, out, "/Colors %d\n", cbuf->params.u.lzw.colors); if (cbuf->params.u.lzw.bpc != 8) fz_printf(ctx, out, "/BitsPerComponent %d\n", cbuf->params.u.lzw.bpc); if (cbuf->params.u.lzw.early_change != 1) fz_printf(ctx, out, "/EarlyChange %d\n", cbuf->params.u.lzw.early_change); fz_printf(ctx, out, ahx ? ">>]\n" : ">>\n"); } break; } fz_printf(ctx, out, "ID\n"); if (ahx) { size_t z; for (z = 0; z < buf->len; ++z) { int c = buf->data[z]; fz_putc(ctx, out, "0123456789abcdef"[(c >> 4) & 0xf]); fz_putc(ctx, out, "0123456789abcdef"[c & 0xf]); if ((z & 31) == 31) fz_putc(ctx, out, '\n'); } fz_putc(ctx, out, '>'); } else {
static fz_image * pdf_load_image_imp(pdf_document *doc, pdf_obj *rdb, pdf_obj *dict, fz_stream *cstm, int forcemask) { fz_stream *stm = NULL; fz_image *image = NULL; pdf_obj *obj, *res; int w, h, bpc, n; int imagemask; int interpolate; int indexed; fz_image *mask = NULL; /* explicit mask/soft mask image */ int usecolorkey = 0; fz_colorspace *colorspace = NULL; float decode[FZ_MAX_COLORS * 2]; int colorkey[FZ_MAX_COLORS * 2]; int stride; int i; fz_context *ctx = doc->ctx; fz_compressed_buffer *buffer; fz_var(stm); fz_var(mask); fz_var(image); fz_var(colorspace); fz_try(ctx) { /* special case for JPEG2000 images */ if (pdf_is_jpx_image(ctx, dict)) { // image = pdf_load_jpx(doc, dict, forcemask); // // if (forcemask) // { // fz_pixmap *mask_pixmap; // if (image->n != 2) // { // fz_pixmap *gray; // fz_irect bbox; // fz_warn(ctx, "soft mask should be grayscale"); // gray = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), fz_pixmap_bbox(ctx, image->tile, &bbox)); // fz_convert_pixmap(ctx, gray, image->tile); // fz_drop_pixmap(ctx, image->tile); // image->tile = gray; // } // mask_pixmap = fz_alpha_from_gray(ctx, image->tile, 1); // fz_drop_pixmap(ctx, image->tile); // image->tile = mask_pixmap; // } break; /* Out of fz_try */ } w = pdf_to_int(pdf_dict_getsa(dict, "Width", "W")); h = pdf_to_int(pdf_dict_getsa(dict, "Height", "H")); bpc = pdf_to_int(pdf_dict_getsa(dict, "BitsPerComponent", "BPC")); if (bpc == 0) bpc = 8; imagemask = pdf_to_bool(pdf_dict_getsa(dict, "ImageMask", "IM")); interpolate = pdf_to_bool(pdf_dict_getsa(dict, "Interpolate", "I")); indexed = 0; usecolorkey = 0; if (imagemask) bpc = 1; if (w <= 0) fz_throw(ctx, FZ_ERROR_GENERIC, "image width is zero (or less)"); if (h <= 0) fz_throw(ctx, FZ_ERROR_GENERIC, "image height is zero (or less)"); if (bpc <= 0) fz_throw(ctx, FZ_ERROR_GENERIC, "image depth is zero (or less)"); if (bpc > 16) fz_throw(ctx, FZ_ERROR_GENERIC, "image depth is too large: %d", bpc); if (w > (1 << 16)) fz_throw(ctx, FZ_ERROR_GENERIC, "image is too wide"); if (h > (1 << 16)) fz_throw(ctx, FZ_ERROR_GENERIC, "image is too high"); obj = pdf_dict_getsa(dict, "ColorSpace", "CS"); if (obj && !imagemask && !forcemask) { /* colorspace resource lookup is only done for inline images */ if (pdf_is_name(obj)) { res = pdf_dict_get(pdf_dict_gets(rdb, "ColorSpace"), obj); if (res) obj = res; } colorspace = pdf_load_colorspace(doc, obj); indexed = fz_colorspace_is_indexed(colorspace); n = colorspace->n; } else { n = 1; } obj = pdf_dict_getsa(dict, "Decode", "D"); if (obj) { for (i = 0; i < n * 2; i++) decode[i] = pdf_to_real(pdf_array_get(obj, i)); } else { float maxval = indexed ? (1 << bpc) - 1 : 1; for (i = 0; i < n * 2; i++) decode[i] = i & 1 ? maxval : 0; } obj = pdf_dict_getsa(dict, "SMask", "Mask"); if (pdf_is_dict(obj)) { /* Not allowed for inline images or soft masks */ if (cstm) fz_warn(ctx, "Ignoring invalid inline image soft mask"); else if (forcemask) fz_warn(ctx, "Ignoring recursive image soft mask"); else { mask = pdf_load_image_imp(doc, rdb, obj, NULL, 1); obj = pdf_dict_gets(obj, "Matte"); if (pdf_is_array(obj)) { usecolorkey = 1; for (i = 0; i < n; i++) colorkey[i] = pdf_to_real(pdf_array_get(obj, i)) * 255; } } } else if (pdf_is_array(obj)) { usecolorkey = 1; for (i = 0; i < n * 2; i++) { if (!pdf_is_int(pdf_array_get(obj, i))) { fz_warn(ctx, "invalid value in color key mask"); usecolorkey = 0; } colorkey[i] = pdf_to_int(pdf_array_get(obj, i)); } } /* Do we load from a ref, or do we load an inline stream? */ if (cstm == NULL) { /* Just load the compressed image data now and we can * decode it on demand. */ int num = pdf_to_num(dict); int gen = pdf_to_gen(dict); buffer = pdf_load_compressed_stream(doc, num, gen); image = fz_new_image(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, usecolorkey ? colorkey : NULL, buffer, mask); } else { /* Inline stream */ stride = (w * n * bpc + 7) / 8; image = fz_new_image(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, usecolorkey ? colorkey : NULL, NULL, mask); pdf_load_compressed_inline_image(doc, dict, stride * h, cstm, indexed, image); } } fz_catch(ctx) { fz_drop_colorspace(ctx, colorspace); fz_drop_image(ctx, mask); fz_drop_image(ctx, image); fz_rethrow(ctx); } return image; }
static fz_image * pdf_load_jpx(pdf_document *doc, pdf_obj *dict, int forcemask) { fz_buffer *buf = NULL; fz_colorspace *colorspace = NULL; fz_pixmap *img = NULL; pdf_obj *obj; fz_context *ctx = doc->ctx; int indexed = 0; fz_image *mask = NULL; fz_var(img); fz_var(buf); fz_var(colorspace); fz_var(mask); buf = pdf_load_stream(doc, pdf_to_num(dict), pdf_to_gen(dict)); /* FIXME: We can't handle decode arrays for indexed images currently */ fz_try(ctx) { obj = pdf_dict_gets(dict, "ColorSpace"); if (obj) { colorspace = pdf_load_colorspace(doc, obj); indexed = fz_colorspace_is_indexed(colorspace); } img = fz_load_jpx(ctx, buf->data, buf->len, colorspace, indexed); obj = pdf_dict_getsa(dict, "SMask", "Mask"); if (pdf_is_dict(obj)) { if (forcemask) fz_warn(ctx, "Ignoring recursive JPX soft mask"); else mask = pdf_load_image_imp(doc, NULL, obj, NULL, 1); } obj = pdf_dict_getsa(dict, "Decode", "D"); if (obj && !indexed) { float decode[FZ_MAX_COLORS * 2]; int i; for (i = 0; i < img->n * 2; i++) decode[i] = pdf_to_real(pdf_array_get(obj, i)); fz_decode_tile(img, decode); } } fz_always(ctx) { fz_drop_colorspace(ctx, colorspace); fz_drop_buffer(ctx, buf); } fz_catch(ctx) { fz_drop_pixmap(ctx, img); fz_rethrow(ctx); } return fz_new_image_from_pixmap(ctx, img, mask); }
static fz_image * pdf_load_image_imp(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *dict, fz_stream *cstm, int forcemask) { fz_image *image = NULL; pdf_obj *obj, *res; int w, h, bpc, n; int imagemask; int interpolate; int indexed; fz_image *mask = NULL; /* explicit mask/soft mask image */ int use_colorkey = 0; fz_colorspace *colorspace = NULL; float decode[FZ_MAX_COLORS * 2]; int colorkey[FZ_MAX_COLORS * 2]; int stride; int i; fz_compressed_buffer *buffer; /* special case for JPEG2000 images */ if (pdf_is_jpx_image(ctx, dict)) return pdf_load_jpx_imp(ctx, doc, rdb, dict, cstm, forcemask); w = pdf_to_int(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(Width), PDF_NAME(W))); h = pdf_to_int(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(Height), PDF_NAME(H))); bpc = pdf_to_int(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(BitsPerComponent), PDF_NAME(BPC))); if (bpc == 0) bpc = 8; imagemask = pdf_to_bool(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(ImageMask), PDF_NAME(IM))); interpolate = pdf_to_bool(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(Interpolate), PDF_NAME(I))); indexed = 0; use_colorkey = 0; if (imagemask) bpc = 1; if (w <= 0) fz_throw(ctx, FZ_ERROR_GENERIC, "image width is zero (or less)"); if (h <= 0) fz_throw(ctx, FZ_ERROR_GENERIC, "image height is zero (or less)"); if (bpc <= 0) fz_throw(ctx, FZ_ERROR_GENERIC, "image depth is zero (or less)"); if (bpc > 16) fz_throw(ctx, FZ_ERROR_GENERIC, "image depth is too large: %d", bpc); if (w > (1 << 16)) fz_throw(ctx, FZ_ERROR_GENERIC, "image is too wide"); if (h > (1 << 16)) fz_throw(ctx, FZ_ERROR_GENERIC, "image is too high"); fz_var(mask); fz_var(image); fz_var(colorspace); fz_try(ctx) { obj = pdf_dict_geta(ctx, dict, PDF_NAME(ColorSpace), PDF_NAME(CS)); if (obj && !imagemask && !forcemask) { /* colorspace resource lookup is only done for inline images */ if (pdf_is_name(ctx, obj)) { res = pdf_dict_get(ctx, pdf_dict_get(ctx, rdb, PDF_NAME(ColorSpace)), obj); if (res) obj = res; } colorspace = pdf_load_colorspace(ctx, obj); indexed = fz_colorspace_is_indexed(ctx, colorspace); n = fz_colorspace_n(ctx, colorspace); } else { n = 1; } obj = pdf_dict_geta(ctx, dict, PDF_NAME(Decode), PDF_NAME(D)); if (obj) { for (i = 0; i < n * 2; i++) decode[i] = pdf_array_get_real(ctx, obj, i); } else if (fz_colorspace_is_lab(ctx, colorspace) || fz_colorspace_is_lab_icc(ctx, colorspace)) { decode[0] = 0; decode[1] = 100; decode[2] = -128; decode[3] = 127; decode[4] = -128; decode[5] = 127; } else { float maxval = indexed ? (1 << bpc) - 1 : 1; for (i = 0; i < n * 2; i++) decode[i] = i & 1 ? maxval : 0; } obj = pdf_dict_geta(ctx, dict, PDF_NAME(SMask), PDF_NAME(Mask)); if (pdf_is_dict(ctx, obj)) { /* Not allowed for inline images or soft masks */ if (cstm) fz_warn(ctx, "Ignoring invalid inline image soft mask"); else if (forcemask) fz_warn(ctx, "Ignoring recursive image soft mask"); else { mask = pdf_load_image_imp(ctx, doc, rdb, obj, NULL, 1); obj = pdf_dict_get(ctx, obj, PDF_NAME(Matte)); if (pdf_is_array(ctx, obj)) { use_colorkey = 1; for (i = 0; i < n; i++) colorkey[i] = pdf_array_get_real(ctx, obj, i) * 255; } } } else if (pdf_is_array(ctx, obj)) { use_colorkey = 1; for (i = 0; i < n * 2; i++) { if (!pdf_is_int(ctx, pdf_array_get(ctx, obj, i))) { fz_warn(ctx, "invalid value in color key mask"); use_colorkey = 0; } colorkey[i] = pdf_array_get_int(ctx, obj, i); } } /* Do we load from a ref, or do we load an inline stream? */ if (cstm == NULL) { /* Just load the compressed image data now and we can decode it on demand. */ buffer = pdf_load_compressed_stream(ctx, doc, pdf_to_num(ctx, dict)); image = fz_new_image_from_compressed_buffer(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, use_colorkey ? colorkey : NULL, buffer, mask); image->invert_cmyk_jpeg = 0; } else { /* Inline stream */ stride = (w * n * bpc + 7) / 8; image = fz_new_image_from_compressed_buffer(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, use_colorkey ? colorkey : NULL, NULL, mask); image->invert_cmyk_jpeg = 0; pdf_load_compressed_inline_image(ctx, doc, dict, stride * h, cstm, indexed, (fz_compressed_image *)image); } } fz_always(ctx) { fz_drop_colorspace(ctx, colorspace); fz_drop_image(ctx, mask); } fz_catch(ctx) { fz_drop_image(ctx, image); fz_rethrow(ctx); } return image; }
static fz_image * pdf_load_jpx(fz_context *ctx, pdf_document *doc, pdf_obj *dict, int forcemask) { fz_buffer *buf = NULL; fz_colorspace *colorspace = NULL; fz_pixmap *pix = NULL; pdf_obj *obj; fz_image *mask = NULL; fz_image *img = NULL; fz_var(pix); fz_var(buf); fz_var(colorspace); fz_var(mask); buf = pdf_load_stream(ctx, dict); /* FIXME: We can't handle decode arrays for indexed images currently */ fz_try(ctx) { unsigned char *data; size_t len; obj = pdf_dict_get(ctx, dict, PDF_NAME(ColorSpace)); if (obj) colorspace = pdf_load_colorspace(ctx, obj); len = fz_buffer_storage(ctx, buf, &data); pix = fz_load_jpx(ctx, data, len, colorspace); obj = pdf_dict_geta(ctx, dict, PDF_NAME(SMask), PDF_NAME(Mask)); if (pdf_is_dict(ctx, obj)) { if (forcemask) fz_warn(ctx, "Ignoring recursive JPX soft mask"); else mask = pdf_load_image_imp(ctx, doc, NULL, obj, NULL, 1); } obj = pdf_dict_geta(ctx, dict, PDF_NAME(Decode), PDF_NAME(D)); if (obj && !fz_colorspace_is_indexed(ctx, colorspace)) { float decode[FZ_MAX_COLORS * 2]; int i; for (i = 0; i < pix->n * 2; i++) decode[i] = pdf_array_get_real(ctx, obj, i); fz_decode_tile(ctx, pix, decode); } img = fz_new_image_from_pixmap(ctx, pix, mask); } fz_always(ctx) { fz_drop_image(ctx, mask); fz_drop_pixmap(ctx, pix); fz_drop_colorspace(ctx, colorspace); fz_drop_buffer(ctx, buf); } fz_catch(ctx) { fz_rethrow(ctx); } return img; }