/* Image specific methods */ static void res_image_init(fz_context *ctx, pdf_document *doc, pdf_res_table *table) { int len, k; pdf_obj *obj; pdf_obj *type; pdf_obj *res = NULL; fz_image *image = NULL; unsigned char digest[16]; fz_var(obj); fz_var(image); fz_var(res); fz_try(ctx) { table->hash = fz_new_hash_table(ctx, 4096, 16, -1); len = pdf_count_objects(ctx, doc); for (k = 1; k < len; k++) { obj = pdf_load_object(ctx, doc, k, 0); type = pdf_dict_get(ctx, obj, PDF_NAME_Subtype); if (pdf_name_eq(ctx, type, PDF_NAME_Image)) { image = pdf_load_image(ctx, doc, obj); res_image_get_md5(ctx, image, digest); fz_drop_image(ctx, image); image = NULL; /* Don't allow overwrites. */ if (fz_hash_find(ctx, table->hash, digest) == NULL) fz_hash_insert(ctx, table->hash, digest, obj); } else { pdf_drop_obj(ctx, obj); } obj = NULL; } } fz_always(ctx) { fz_drop_image(ctx, image); pdf_drop_obj(ctx, obj); } fz_catch(ctx) { res_table_free(ctx, table); fz_rethrow(ctx); } }
fz_image * fz_new_image_from_pixmap(fz_context *ctx, fz_pixmap *pixmap, 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->w = pixmap->w; image->h = pixmap->h; image->n = pixmap->n; image->colorspace = pixmap->colorspace; image->bpc = 8; image->buffer = NULL; image->get_pixmap = fz_image_get_pixmap; image->xres = pixmap->xres; image->yres = pixmap->yres; image->tile = pixmap; image->mask = mask; } fz_catch(ctx) { fz_drop_image(ctx, mask); fz_rethrow(ctx); } return image; }
static img_document * img_open_document_with_stream(fz_context *ctx, fz_stream *stm) { fz_buffer *buffer = NULL; fz_image *image = NULL; img_document *doc; fz_var(buffer); fz_var(image); fz_try(ctx) { buffer = fz_read_all(ctx, stm, 1024); image = fz_new_image_from_buffer(ctx, buffer); doc = img_new_document(ctx, image); } fz_always(ctx) { fz_drop_image(ctx, image); fz_drop_buffer(ctx, buffer); } fz_catch(ctx) fz_rethrow(ctx); return doc; }
static fz_image * parse_inline_image(fz_context *ctx, pdf_csi *csi, fz_stream *stm) { pdf_document *doc = csi->doc; pdf_obj *rdb = csi->rdb; pdf_obj *obj = NULL; fz_image *img = NULL; int ch, found; fz_var(obj); fz_var(img); fz_try(ctx) { obj = pdf_parse_dict(ctx, doc, stm, &doc->lexbuf.base); /* read whitespace after ID keyword */ ch = fz_read_byte(ctx, stm); if (ch == '\r') if (fz_peek_byte(ctx, stm) == '\n') fz_read_byte(ctx, stm); img = pdf_load_inline_image(ctx, doc, rdb, obj, stm); /* find EI */ found = 0; ch = fz_read_byte(ctx, stm); do { while (ch != 'E' && ch != EOF) ch = fz_read_byte(ctx, stm); if (ch == 'E') { ch = fz_read_byte(ctx, stm); if (ch == 'I') { ch = fz_peek_byte(ctx, stm); if (ch == ' ' || ch <= 32 || ch == EOF || ch == '<' || ch == '/') { found = 1; break; } } } } while (ch != EOF); if (!found) fz_throw(ctx, FZ_ERROR_GENERIC, "syntax error after inline image"); } fz_always(ctx) { pdf_drop_obj(ctx, obj); } fz_catch(ctx) { fz_drop_image(ctx, img); fz_rethrow(ctx); } return img; }
static void tiff_drop_page_imp(fz_context *ctx, tiff_page *page) { if (!page) return; fz_drop_image(ctx, page->image); }
static void saveimage(int num) { fz_image *image = NULL; fz_pixmap *pix = NULL; pdf_obj *ref; char buf[32]; ref = pdf_new_indirect(ctx, doc, num, 0); fz_var(image); fz_var(pix); fz_try(ctx) { /* TODO: detect DCTD and save as jpeg */ image = pdf_load_image(ctx, doc, ref); pix = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0); snprintf(buf, sizeof(buf), "img-%04d", num); writepixmap(ctx, pix, buf, dorgb); } fz_always(ctx) { fz_drop_image(ctx, image); fz_drop_pixmap(ctx, pix); pdf_drop_obj(ctx, ref); } fz_catch(ctx) fz_rethrow(ctx); }
void cbz_free_page(cbz_document *doc, cbz_page *page) { if (!page) return; fz_drop_image(doc->ctx, page->image); fz_free(doc->ctx, page); }
static void fz_drop_image_block(fz_context *ctx, fz_image_block *block) { if (block == NULL) return; fz_drop_image(ctx, block->image); fz_drop_colorspace(ctx, block->cspace); fz_free(ctx, block); }
static void fz_drop_image_key(fz_context *ctx, void *key_) { fz_image_key *key = (fz_image_key *)key_; if (fz_drop_imp(ctx, key, &key->refs)) { fz_drop_image(ctx, key->image); fz_free(ctx, key); } }
static void fz_drop_html_flow(fz_context *ctx, fz_html_flow *flow) { while (flow) { fz_html_flow *next = flow->next; if (flow->type == FLOW_IMAGE) fz_drop_image(ctx, flow->content.image); flow = next; } }
void fz_drop_image_imp(fz_context *ctx, fz_storable *image_) { fz_image *image = (fz_image *)image_; if (image == NULL) return; fz_drop_pixmap(ctx, image->tile); fz_drop_compressed_buffer(ctx, image->buffer); fz_drop_colorspace(ctx, image->colorspace); fz_drop_image(ctx, image->mask); fz_free(ctx, image); }
static void pdf_free_image(fz_context *ctx, fz_storable *image_) { pdf_image *image = (pdf_image *)image_; if (image == NULL) return; fz_drop_pixmap(ctx, image->tile); fz_free_compressed_buffer(ctx, image->buffer); fz_drop_colorspace(ctx, image->base.colorspace); fz_drop_image(ctx, image->base.mask); fz_free(ctx, image); }
bool PdfCreator::AddImagePage(HBITMAP hbmp, SizeI size, float imgDpi) { if (!ctx || !doc) return false; fz_image *image = nullptr; fz_try(ctx) { image = render_to_pixmap(ctx, hbmp, size); } fz_catch(ctx) { return false; } bool ok = AddImagePage(image, imgDpi); fz_drop_image(ctx, image); return ok; }
static void pdf_drop_image_key(fz_context *ctx, void *key_) { pdf_image_key *key = (pdf_image_key *)key_; int drop; fz_lock(ctx, FZ_LOCK_ALLOC); drop = --key->refs; fz_unlock(ctx, FZ_LOCK_ALLOC); if (drop == 0) { fz_drop_image(ctx, key->image); fz_free(ctx, key); } }
static void fz_free_display_node(fz_context *ctx, fz_display_node *node) { switch (node->cmd) { case FZ_CMD_FILL_PATH: case FZ_CMD_STROKE_PATH: case FZ_CMD_CLIP_PATH: case FZ_CMD_CLIP_STROKE_PATH: fz_free_path(ctx, node->item.path); break; case FZ_CMD_FILL_TEXT: case FZ_CMD_STROKE_TEXT: case FZ_CMD_CLIP_TEXT: case FZ_CMD_CLIP_STROKE_TEXT: case FZ_CMD_IGNORE_TEXT: fz_free_text(ctx, node->item.text); break; case FZ_CMD_FILL_SHADE: fz_drop_shade(ctx, node->item.shade); break; case FZ_CMD_FILL_IMAGE: case FZ_CMD_FILL_IMAGE_MASK: case FZ_CMD_CLIP_IMAGE_MASK: fz_drop_image(ctx, node->item.image); break; case FZ_CMD_POP_CLIP: case FZ_CMD_BEGIN_MASK: case FZ_CMD_END_MASK: case FZ_CMD_BEGIN_GROUP: case FZ_CMD_END_GROUP: case FZ_CMD_BEGIN_TILE: case FZ_CMD_END_TILE: case FZ_CMD_BEGIN_PAGE: case FZ_CMD_END_PAGE: break; /* SumatraPDF: support transfer functions */ case FZ_CMD_APPLY_TRANSFER_FUNCTION: fz_drop_transfer_function(ctx, node->item.tr); break; } if (node->stroke) fz_drop_stroke_state(ctx, node->stroke); if (node->colorspace) fz_drop_colorspace(ctx, node->colorspace); fz_free(ctx, node); }
bool PdfCreator::AddImagePage(const char *data, size_t len, float imgDpi) { CrashIf(!ctx || !doc); if (!ctx || !doc) return false; const WCHAR *ext = GfxFileExtFromData(data, len); if (str::Eq(ext, L".jpg") || str::Eq(ext, L".jp2")) { Size size = BitmapSizeFromData(data, len); fz_image *image = nullptr; fz_try(ctx) { image = (str::Eq(ext, L".jpg") ? pack_jpeg : pack_jp2)(ctx, data, len, SizeI(size.Width, size.Height)); } fz_catch(ctx) { return false; } bool ok = AddImagePage(image, imgDpi); fz_drop_image(ctx, image); return ok; }
static tiff_page * tiff_load_page(fz_context *ctx, tiff_document *doc, int number) { fz_pixmap *pixmap = NULL; fz_image *image = NULL; tiff_page *page = NULL; if (number < 0 || number >= doc->page_count) return NULL; fz_var(pixmap); fz_var(image); fz_var(page); fz_try(ctx) { size_t len; unsigned char *data; len = fz_buffer_storage(ctx, doc->buffer, &data); pixmap = fz_load_tiff_subimage(ctx, data, len, number); image = fz_new_image_from_pixmap(ctx, pixmap, NULL); page = fz_new_page(ctx, sizeof *page); page->super.bound_page = (fz_page_bound_page_fn *)tiff_bound_page; page->super.run_page_contents = (fz_page_run_page_contents_fn *)tiff_run_page; page->super.drop_page = (fz_page_drop_page_fn *)tiff_drop_page; page->image = fz_keep_image(ctx, image); } fz_always(ctx) { fz_drop_image(ctx, image); fz_drop_pixmap(ctx, pixmap); } fz_catch(ctx) { fz_free(ctx, page); fz_rethrow(ctx); } return page; }
static void fz_free_display_node(fz_context *ctx, fz_display_node *node) { switch (node->cmd) { case FZ_CMD_FILL_PATH: case FZ_CMD_STROKE_PATH: case FZ_CMD_CLIP_PATH: case FZ_CMD_CLIP_STROKE_PATH: fz_free_path(ctx, node->item.path); break; case FZ_CMD_FILL_TEXT: case FZ_CMD_STROKE_TEXT: case FZ_CMD_CLIP_TEXT: case FZ_CMD_CLIP_STROKE_TEXT: case FZ_CMD_IGNORE_TEXT: fz_free_text(ctx, node->item.text); break; case FZ_CMD_FILL_SHADE: fz_drop_shade(ctx, node->item.shade); break; case FZ_CMD_FILL_IMAGE: case FZ_CMD_FILL_IMAGE_MASK: case FZ_CMD_CLIP_IMAGE_MASK: fz_drop_image(ctx, node->item.image); break; case FZ_CMD_POP_CLIP: case FZ_CMD_BEGIN_MASK: case FZ_CMD_END_MASK: case FZ_CMD_BEGIN_GROUP: case FZ_CMD_END_GROUP: case FZ_CMD_BEGIN_TILE: case FZ_CMD_END_TILE: break; } if (node->stroke) fz_drop_stroke_state(ctx, node->stroke); if (node->colorspace) fz_drop_colorspace(ctx, node->colorspace); fz_free(ctx, node); }
static void saveimage(int num) { fz_image *image; fz_pixmap *pix; pdf_obj *ref; char buf[32]; ref = pdf_new_indirect(doc, num, 0); /* TODO: detect DCTD and save as jpeg */ image = pdf_load_image(doc, ref); pix = fz_new_pixmap_from_image(ctx, image, 0, 0); fz_drop_image(ctx, image); snprintf(buf, sizeof(buf), "img-%04d", num); writepixmap(ctx, pix, buf, dorgb); fz_drop_pixmap(ctx, pix); pdf_drop_obj(ref); }
static void generate_image(fz_context *ctx, fz_pool *pool, fz_archive *zip, const char *base_uri, fz_html *box, const char *src) { fz_image *img = NULL; fz_buffer *buf = NULL; char path[2048]; fz_html *flow = box; while (flow->type != BOX_FLOW) flow = flow->up; fz_strlcpy(path, base_uri, sizeof path); fz_strlcat(path, "/", sizeof path); fz_strlcat(path, src, sizeof path); fz_urldecode(path); fz_cleanname(path); fz_var(buf); fz_var(img); fz_try(ctx) { buf = fz_read_archive_entry(ctx, zip, path); img = fz_new_image_from_buffer(ctx, buf); add_flow_image(ctx, pool, flow, &box->style, img); } fz_always(ctx) { fz_drop_buffer(ctx, buf); fz_drop_image(ctx, img); } fz_catch(ctx) { const char *alt = "[image]"; fz_warn(ctx, "html: cannot add image src='%s'", src); add_flow_word(ctx, pool, flow, &box->style, alt, alt + 7); } }
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; }
static void img_drop_page_imp(fz_context *ctx, img_page *page) { fz_drop_image(ctx, page->image); }
static fz_image * pdf_load_image_imp(pdf_document *xref, 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 i; fz_context *ctx = xref->ctx; 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(xref, dict, forcemask); if (forcemask) { fz_pixmap *mask_pixmap; if (image->n != 2) { /* SumatraPDF: ignore invalid JPX softmasks */ fz_warn(ctx, "soft mask must be grayscale"); mask_pixmap = fz_new_pixmap(ctx, NULL, image->tile->w, image->tile->h); fz_clear_pixmap_with_value(ctx, mask_pixmap, 255); } else 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; mask = NULL; if (imagemask) bpc = 1; if (w <= 0) fz_throw(ctx, "image width is zero (or less)"); if (h <= 0) fz_throw(ctx, "image height is zero (or less)"); if (bpc <= 0) fz_throw(ctx, "image depth is zero (or less)"); if (bpc > 16) fz_throw(ctx, "image depth is too large: %d", bpc); if (w > (1 << 16)) fz_throw(ctx, "image is too wide"); if (h > (1 << 16)) fz_throw(ctx, "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(xref, obj); if (!strcmp(colorspace->name, "Indexed")) indexed = 1; 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(xref, rdb, obj, NULL, 1); } 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)); } } /* Now, do we load a ref, or do we load the actual thing? */ if (!cstm) { /* 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); fz_compressed_buffer *buffer = pdf_load_compressed_stream(xref, num, gen); image = fz_new_image(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, usecolorkey ? colorkey : NULL, buffer, mask); break; /* Out of fz_try */ } /* We need to decompress the image now */ if (cstm) { int stride = (w * n * bpc + 7) / 8; stm = pdf_open_inline_stream(xref, dict, stride * h, cstm, NULL); } else { stm = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict)); } image = fz_new_image(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, usecolorkey ? colorkey : NULL, NULL, mask); image->tile = fz_decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 0, 0); } fz_catch(ctx) { /* SumatraPDF: fix memory leak */ if (!image) fz_drop_colorspace(ctx, colorspace); else fz_drop_image(ctx, image); fz_rethrow(ctx); } /* cf. http://bugs.ghostscript.com/show_bug.cgi?id=693517 */ fz_try(ctx) { obj = pdf_dict_getp(dict, "SMask/Matte"); if (pdf_is_array(obj) && image->mask) { assert(!image->usecolorkey); image->usecolorkey = 2; for (i = 0; i < n; i++) image->colorkey[i] = pdf_to_int(pdf_array_get(obj, i)); } } fz_catch(ctx) { fz_drop_image(ctx, image); fz_rethrow(ctx); } return image; }
static void cbz_drop_page(fz_context *ctx, fz_page *page_) { cbz_page *page = (cbz_page*)page_; fz_drop_image(ctx, page->image); }
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 void tiff_drop_page(fz_context *ctx, tiff_page *page) { fz_drop_image(ctx, page->image); }
static pdf_image * pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *cstm, int forcemask) { fz_stream *stm = NULL; pdf_image *image = NULL; pdf_obj *obj, *res; int w, h, bpc, n; int imagemask; int interpolate; int indexed; fz_image *mask = NULL; /* explicit mask/softmask image */ int usecolorkey; int i; fz_context *ctx = xref->ctx; fz_var(stm); fz_var(mask); image = fz_malloc_struct(ctx, pdf_image); /* SumatraPDF: fix memory leak */ FZ_INIT_STORABLE(&image->base, 1, pdf_free_image); fz_try(ctx) { /* special case for JPEG2000 images */ if (pdf_is_jpx_image(ctx, dict)) { pdf_load_jpx(xref, dict, image); /* RJW: "cannot load jpx image" */ if (forcemask) { fz_pixmap *mask_pixmap; if (image->n != 2) fz_throw(ctx, "softmask must be grayscale"); 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")); imagemask = pdf_to_bool(pdf_dict_getsa(dict, "ImageMask", "IM")); interpolate = pdf_to_bool(pdf_dict_getsa(dict, "Interpolate", "I")); indexed = 0; usecolorkey = 0; mask = NULL; if (imagemask) bpc = 1; if (w == 0) fz_throw(ctx, "image width is zero"); if (h == 0) fz_throw(ctx, "image height is zero"); if (bpc == 0) fz_throw(ctx, "image depth is zero"); if (bpc > 16) fz_throw(ctx, "image depth is too large: %d", bpc); if (w > (1 << 16)) fz_throw(ctx, "image is too wide"); if (h > (1 << 16)) fz_throw(ctx, "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; } image->base.colorspace = pdf_load_colorspace(xref, obj); /* RJW: "cannot load image colorspace" */ if (!strcmp(image->base.colorspace->name, "Indexed")) indexed = 1; n = image->base.colorspace->n; } else { n = 1; } obj = pdf_dict_getsa(dict, "Decode", "D"); if (obj) { for (i = 0; i < n * 2; i++) image->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++) image->decode[i] = i & 1 ? maxval : 0; } obj = pdf_dict_getsa(dict, "SMask", "Mask"); if (pdf_is_dict(obj)) { /* Not allowed for inline images */ if (!cstm) { mask = (fz_image *)pdf_load_image_imp(xref, rdb, obj, NULL, 1); /* RJW: "cannot load image mask/softmask" */ } } 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; } image->colorkey[i] = pdf_to_int(pdf_array_get(obj, i)); } } /* Now, do we load a ref, or do we load the actual thing? */ image->params.type = PDF_IMAGE_RAW; FZ_INIT_STORABLE(&image->base, 1, pdf_free_image); image->base.get_pixmap = pdf_image_get_pixmap; image->base.w = w; image->base.h = h; image->n = n; image->bpc = bpc; image->interpolate = interpolate; image->imagemask = imagemask; image->usecolorkey = usecolorkey; image->base.mask = mask; image->params.colorspace = image->base.colorspace; /* Uses the same ref as for the base one */ if (!indexed && !cstm) { /* Just load the compressed image data now and we can * decode it on demand. */ image->buffer = pdf_load_image_stream(xref, pdf_to_num(dict), pdf_to_gen(dict), &image->params); break; /* Out of fz_try */ } /* We need to decompress the image now */ if (cstm) { int stride = (w * image->n * image->bpc + 7) / 8; stm = pdf_open_inline_stream(xref, dict, stride * h, cstm, NULL); } else { stm = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict)); /* RJW: "cannot open image data stream (%d 0 R)", pdf_to_num(dict) */ } image->tile = decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 1, 1); } fz_catch(ctx) { fz_drop_image(ctx, &image->base); fz_rethrow(ctx); } return image; }
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 void img_close_document(fz_context *ctx, img_document *doc) { fz_drop_image(ctx, doc->image); fz_free(ctx, doc); }