summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-02-21 17:09:10 +0000
committerRobin Watts <robin.watts@artifex.com>2012-02-25 08:14:27 -0800
commitf86c02284c259b9034f324dffe76969efa8b2e42 (patch)
tree6e2a0c86ff040ade748d767ecd377282810d0ad4 /pdf
parent7c19fd50ea7ee9dfd253220a0ea2cac4df7d6345 (diff)
downloadmupdf-f86c02284c259b9034f324dffe76969efa8b2e42.tar.xz
Rework image handling for on demand decode
Introduce a new 'fz_image' type; this type contains rudimentary information about images (such as native, size, colorspace etc) and a function to call to get a pixmap of that image (with a size hint). Instead of passing pixmaps through the device interface (and holding pixmaps in the display list) we now pass images instead. The rendering routines therefore call fz_image_to_pixmap to get pixmaps to render, and fz_pixmap_drop those afterwards. The file format handling routines therefore need to produce images rather than pixmaps; xps and cbz currently just wrap pixmaps as images. PDF is more involved. The stream handling routines in PDF have been altered so that they can recognise when the last stream entry in a filter dictionary is an image decoding filter. Rather than applying this filter, they read and store the parameters into a pdf_image_params structure, and stop decoding at that point. This allows us to read the compressed data for an image into memory as a block. We can then restart the image decode process later. pdf_images therefore consist of the compressed image data for images. When a pixmap is requested for such an image, the code checks to see if we have one (of an appropriate size), and if not, decodes it. The size hint is used to determine whether it is possible to subsample the image; currently this is only supported for JPEGs, but we could add generic subsampling code later. In order to handle caching the produced images, various changes have been made to the store and the underlying hash table. Previously the store was indexed purely by fz_obj keys; we don't have an fz_obj key any more, so have extended the store by adding a concept of a key 'type'. A key type is a pointer to a set of functions that keep/drop/compare and make a hashable key from a key pointer. We make a pdf_store.c file that contains functions to offer the existing fz_obj based functions, and add a new 'type' for keys (based on the fz_image handle, and the subsample factor) in the pdf_image.c file. While working on this, a problem became apparent in the existing store codel; fz_obj objects had no protection on their reference counts, hence an interpreter thread could try to alter a ref count at the same time as a malloc caused an eviction from the store. This has been solved by using the alloc lock as protection. This in turn requires some tweaks to the code to make sure we don't try and keep/drop fz_obj's from the store code while the alloc lock is held. A side effect of this work is that when a hash table is created, we inform it what lock should be used to protect its innards (if any). If the alloc lock is used, the insert method knows to drop/retake it to allow it to safely expand the hash table. Callers to the hash functions have the responsibility of taking/dropping the appropriate lock, and ensuring that they cope with the possibility that insert might drop the alloc lock, causing race conditions.
Diffstat (limited to 'pdf')
-rw-r--r--pdf/mupdf.h94
-rw-r--r--pdf/pdf_cmap_load.c4
-rw-r--r--pdf/pdf_colorspace.c4
-rw-r--r--pdf/pdf_font.c4
-rw-r--r--pdf/pdf_function.c4
-rw-r--r--pdf/pdf_image.c474
-rw-r--r--pdf/pdf_interpret.c15
-rw-r--r--pdf/pdf_pattern.c6
-rw-r--r--pdf/pdf_shade.c4
-rw-r--r--pdf/pdf_store.c59
-rw-r--r--pdf/pdf_stream.c130
-rw-r--r--pdf/pdf_xobject.c6
12 files changed, 624 insertions, 180 deletions
diff --git a/pdf/mupdf.h b/pdf/mupdf.h
index 39245177..b233288f 100644
--- a/pdf/mupdf.h
+++ b/pdf/mupdf.h
@@ -5,6 +5,83 @@
#error "fitz.h must be included before mupdf.h"
#endif
+/*
+ * PDF Images
+ */
+
+typedef struct pdf_image_params_s pdf_image_params;
+
+struct pdf_image_params_s
+{
+ int type;
+ fz_colorspace *colorspace;
+ union
+ {
+ struct
+ {
+ int columns;
+ int rows;
+ int k;
+ int eol;
+ int eba;
+ int eob;
+ int bi1;
+ }
+ fax;
+ struct
+ {
+ int ct;
+ }
+ jpeg;
+ struct
+ {
+ int columns;
+ int colors;
+ int predictor;
+ int bpc;
+ }
+ flate;
+ struct
+ {
+ int columns;
+ int colors;
+ int predictor;
+ int bpc;
+ int ec;
+ }
+ lzw;
+ }
+ u;
+};
+
+
+typedef struct pdf_image_s pdf_image;
+
+struct pdf_image_s
+{
+ fz_image base;
+ fz_pixmap *tile;
+ int n, bpc;
+ pdf_image_params params;
+ fz_buffer *buffer;
+ int colorkey[FZ_MAX_COLORS * 2];
+ float decode[FZ_MAX_COLORS * 2];
+ int imagemask;
+ int interpolate;
+ int usecolorkey;
+};
+
+enum
+{
+ PDF_IMAGE_RAW,
+ PDF_IMAGE_FAX,
+ PDF_IMAGE_JPEG,
+ PDF_IMAGE_RLD,
+ PDF_IMAGE_FLATE,
+ PDF_IMAGE_LZW,
+ PDF_IMAGE_JPX
+};
+
typedef struct pdf_document_s pdf_document;
/*
@@ -102,12 +179,15 @@ fz_obj *pdf_load_object(pdf_document *doc, int num, int gen);
void pdf_update_object(pdf_document *doc, int num, int gen, fz_obj *newobj);
int pdf_is_stream(pdf_document *doc, int num, int gen);
-fz_stream *pdf_open_inline_stream(pdf_document *doc, fz_obj *stmobj, int length, fz_stream *chain);
+fz_stream *pdf_open_inline_stream(pdf_document *doc, fz_obj *stmobj, int length, fz_stream *chain, pdf_image_params *params);
fz_buffer *pdf_load_raw_stream(pdf_document *doc, int num, int gen);
fz_buffer *pdf_load_stream(pdf_document *doc, int num, int gen);
+fz_buffer *pdf_load_image_stream(pdf_document *doc, int num, int gen, pdf_image_params *params);
fz_stream *pdf_open_raw_stream(pdf_document *doc, int num, int gen);
+fz_stream *pdf_open_image_stream(pdf_document *doc, int num, int gen, pdf_image_params *params);
fz_stream *pdf_open_stream(pdf_document *doc, int num, int gen);
fz_stream *pdf_open_stream_with_offset(pdf_document *doc, int num, int gen, fz_obj *dict, int stm_ofs);
+fz_stream *pdf_open_image_decomp_stream(fz_context *ctx, fz_buffer *, pdf_image_params *params, int *factor);
pdf_document *pdf_open_document_with_stream(fz_stream *file);
pdf_document *pdf_open_document(fz_context *ctx, const char *filename);
@@ -171,8 +251,8 @@ fz_pixmap *pdf_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src);
fz_shade *pdf_load_shading(pdf_document *doc, fz_obj *obj);
-fz_pixmap *pdf_load_inline_image(pdf_document *doc, fz_obj *rdb, fz_obj *dict, fz_stream *file);
-fz_pixmap *pdf_load_image(pdf_document *doc, fz_obj *obj);
+fz_image *pdf_load_inline_image(pdf_document *doc, fz_obj *rdb, fz_obj *dict, fz_stream *file);
+fz_image *pdf_load_image(pdf_document *doc, fz_obj *obj);
int pdf_is_jpx_image(fz_context *ctx, fz_obj *dict);
/*
@@ -471,4 +551,12 @@ void pdf_run_page_with_usage(pdf_document *doc, pdf_page *page, fz_device *dev,
void pdf_run_page(pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie);
void pdf_run_glyph(pdf_document *doc, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate);
+/*
+ * PDF interface to store
+ */
+
+void pdf_store_item(fz_context *ctx, fz_obj *key, void *val, unsigned int itemsize);
+void *pdf_find_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key);
+void pdf_remove_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key);
+
#endif
diff --git a/pdf/pdf_cmap_load.c b/pdf/pdf_cmap_load.c
index 3257516c..9e6b13ce 100644
--- a/pdf/pdf_cmap_load.c
+++ b/pdf/pdf_cmap_load.c
@@ -31,7 +31,7 @@ pdf_load_embedded_cmap(pdf_document *xref, fz_obj *stmobj)
fz_var(file);
fz_var(cmap);
- if ((cmap = fz_find_item(ctx, pdf_free_cmap_imp, stmobj)))
+ if ((cmap = pdf_find_item(ctx, pdf_free_cmap_imp, stmobj)))
{
return cmap;
}
@@ -63,7 +63,7 @@ pdf_load_embedded_cmap(pdf_document *xref, fz_obj *stmobj)
pdf_drop_cmap(ctx, usecmap);
}
- fz_store_item(ctx, stmobj, cmap, pdf_cmap_size(ctx, cmap));
+ pdf_store_item(ctx, stmobj, cmap, pdf_cmap_size(ctx, cmap));
}
fz_catch(ctx)
{
diff --git a/pdf/pdf_colorspace.c b/pdf/pdf_colorspace.c
index 7a410df8..a6515d42 100644
--- a/pdf/pdf_colorspace.c
+++ b/pdf/pdf_colorspace.c
@@ -395,7 +395,7 @@ pdf_load_colorspace(pdf_document *xref, fz_obj *obj)
fz_context *ctx = xref->ctx;
fz_colorspace *cs;
- if ((cs = fz_find_item(ctx, fz_free_colorspace_imp, obj)))
+ if ((cs = pdf_find_item(ctx, fz_free_colorspace_imp, obj)))
{
return cs;
}
@@ -403,7 +403,7 @@ pdf_load_colorspace(pdf_document *xref, fz_obj *obj)
cs = pdf_load_colorspace_imp(xref, obj);
/* RJW: "cannot load colorspace (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */
- fz_store_item(ctx, obj, cs, cs->size);
+ pdf_store_item(ctx, obj, cs, cs->size);
return cs;
}
diff --git a/pdf/pdf_font.c b/pdf/pdf_font.c
index 3e30c332..fd2afab2 100644
--- a/pdf/pdf_font.c
+++ b/pdf/pdf_font.c
@@ -1081,7 +1081,7 @@ pdf_load_font(pdf_document *xref, fz_obj *rdb, fz_obj *dict)
fz_context *ctx = xref->ctx;
pdf_font_desc *fontdesc;
- if ((fontdesc = fz_find_item(ctx, pdf_free_font_imp, dict)))
+ if ((fontdesc = pdf_find_item(ctx, pdf_free_font_imp, dict)))
{
return fontdesc;
}
@@ -1121,7 +1121,7 @@ pdf_load_font(pdf_document *xref, fz_obj *rdb, fz_obj *dict)
if (fontdesc->font->ft_substitute && !fontdesc->to_ttf_cmap)
pdf_make_width_table(ctx, fontdesc);
- fz_store_item(ctx, dict, fontdesc, fontdesc->size);
+ pdf_store_item(ctx, dict, fontdesc, fontdesc->size);
return fontdesc;
}
diff --git a/pdf/pdf_function.c b/pdf/pdf_function.c
index 23acc4db..4478827c 100644
--- a/pdf/pdf_function.c
+++ b/pdf/pdf_function.c
@@ -1362,7 +1362,7 @@ pdf_load_function(pdf_document *xref, fz_obj *dict)
fz_obj *obj;
int i;
- if ((func = fz_find_item(ctx, pdf_free_function_imp, dict)))
+ if ((func = pdf_find_item(ctx, pdf_free_function_imp, dict)))
{
return func;
}
@@ -1432,7 +1432,7 @@ pdf_load_function(pdf_document *xref, fz_obj *dict)
fz_throw(ctx, "unknown function type (%d %d R)", fz_to_num(dict), fz_to_gen(dict));
}
- fz_store_item(ctx, dict, func, func->size);
+ pdf_store_item(ctx, dict, func, func->size);
}
fz_catch(ctx)
{
diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c
index 3aa26f08..9626d6f0 100644
--- a/pdf/pdf_image.c
+++ b/pdf/pdf_image.c
@@ -1,10 +1,15 @@
#include "fitz.h"
#include "mupdf.h"
-/* TODO: store JPEG compressed samples */
-/* TODO: store flate compressed samples */
+typedef struct pdf_image_key_s pdf_image_key;
-static fz_pixmap *pdf_load_jpx(pdf_document *xref, fz_obj *dict);
+struct pdf_image_key_s {
+ int refs;
+ fz_image *image;
+ int factor;
+};
+
+static void pdf_load_jpx(pdf_document *xref, fz_obj *dict, pdf_image *image);
static void
pdf_mask_color_key(fz_pixmap *pix, int n, int *colorkey)
@@ -25,49 +30,293 @@ pdf_mask_color_key(fz_pixmap *pix, int n, int *colorkey)
}
}
+static int
+pdf_make_hash_image_key(fz_store_hash *hash, void *key_)
+{
+ pdf_image_key *key = (pdf_image_key *)key_;
+
+ hash->u.pi.ptr = key->image;
+ hash->u.pi.i = key->factor;
+ return 1;
+}
+
+static void *
+pdf_keep_image_key(fz_context *ctx, void *key_)
+{
+ pdf_image_key *key = (pdf_image_key *)key_;
+
+ fz_lock(ctx, FZ_LOCK_ALLOC);
+ key->refs++;
+ fz_unlock(ctx, FZ_LOCK_ALLOC);
+
+ return (void *)key;
+}
+
+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 int
+pdf_cmp_image_key(void *k0_, void *k1_)
+{
+ pdf_image_key *k0 = (pdf_image_key *)k0_;
+ pdf_image_key *k1 = (pdf_image_key *)k1_;
+
+ return k0->image == k1->image && k0->factor == k1->factor;
+}
+
+static fz_store_type pdf_image_store_type =
+{
+ pdf_make_hash_image_key,
+ pdf_keep_image_key,
+ pdf_drop_image_key,
+ pdf_cmp_image_key
+};
+
static fz_pixmap *
+decomp_image_from_stream(fz_context *ctx, fz_stream *stm, pdf_image *image, int in_line, int indexed, int factor)
+{
+ fz_pixmap *tile = NULL;
+ fz_pixmap *existing_tile;
+ int stride, len, i;
+ unsigned char *samples = NULL;
+ int w = (image->base.w + (factor-1)) / factor;
+ int h = (image->base.h + (factor-1)) / factor;
+ pdf_image_key *key;
+
+ fz_var(tile);
+ fz_var(samples);
+
+ fz_try(ctx)
+ {
+ tile = fz_new_pixmap(ctx, image->base.colorspace, w, h);
+ tile->mask = fz_image_to_pixmap(ctx, image->base.mask, w, h);
+ tile->interpolate = image->interpolate;
+
+ stride = (w * image->n * image->bpc + 7) / 8;
+
+ samples = fz_malloc_array(ctx, h, stride);
+
+ len = fz_read(stm, samples, h * stride);
+ if (len < 0)
+ {
+ fz_throw(ctx, "cannot read image data");
+ }
+
+ /* Make sure we read the EOF marker (for inline images only) */
+ if (in_line)
+ {
+ unsigned char tbuf[512];
+ fz_try(ctx)
+ {
+ int tlen = fz_read(stm, tbuf, sizeof tbuf);
+ if (tlen > 0)
+ fz_warn(ctx, "ignoring garbage at end of image");
+ }
+ fz_catch(ctx)
+ {
+ fz_warn(ctx, "ignoring error at end of image");
+ }
+ }
+
+ /* Pad truncated images */
+ if (len < stride * h)
+ {
+ fz_warn(ctx, "padding truncated image");
+ memset(samples + len, 0, stride * h - len);
+ }
+
+ /* Invert 1-bit image masks */
+ if (image->imagemask)
+ {
+ /* 0=opaque and 1=transparent so we need to invert */
+ unsigned char *p = samples;
+ len = h * stride;
+ for (i = 0; i < len; i++)
+ p[i] = ~p[i];
+ }
+
+ fz_unpack_tile(tile, samples, image->n, image->bpc, stride, indexed);
+
+ fz_free(ctx, samples);
+ samples = NULL;
+
+ if (image->usecolorkey)
+ pdf_mask_color_key(tile, image->n, image->colorkey);
+
+ if (indexed)
+ {
+ fz_pixmap *conv;
+ fz_decode_indexed_tile(tile, image->decode, (1 << image->bpc) - 1);
+ conv = pdf_expand_indexed_pixmap(ctx, tile);
+ fz_drop_pixmap(ctx, tile);
+ tile = conv;
+ }
+ else
+ {
+ fz_decode_tile(tile, image->decode);
+ }
+ }
+ fz_always(ctx)
+ {
+ fz_close(stm);
+ }
+ fz_catch(ctx)
+ {
+ if (tile)
+ fz_drop_pixmap(ctx, tile);
+ fz_free(ctx, samples);
+
+ fz_rethrow(ctx);
+ }
+
+ /* Now we try to cache the pixmap. Any failure here will just result
+ * in us not caching. */
+ fz_try(ctx)
+ {
+ key = fz_malloc_struct(ctx, pdf_image_key);
+ key->refs = 1;
+ key->image = fz_keep_image(ctx, &image->base);
+ key->factor = factor;
+ existing_tile = fz_store_item(ctx, key, tile, fz_pixmap_size(ctx, tile), &pdf_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);
+ fz_free(ctx, key);
+ tile = existing_tile;
+ }
+ }
+ fz_always(ctx)
+ {
+ pdf_drop_image_key(ctx, key);
+ }
+ fz_catch(ctx)
+ {
+ /* Do nothing */
+ }
+
+ return tile;
+}
+
+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_drop_buffer(ctx, image->buffer);
+ fz_drop_colorspace(ctx, image->base.colorspace);
+ fz_drop_image(ctx, image->base.mask);
+ fz_free(ctx, image);
+}
+
+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 factor;
+ pdf_image_key key;
+
+ /* Check for 'simple' images which are just pixmaps */
+ if (image->buffer == NULL)
+ {
+ tile = image->tile;
+ if (!tile)
+ return NULL;
+ if (image->base.mask)
+ {
+ fz_drop_pixmap(ctx, tile->mask);
+ tile->mask = fz_image_to_pixmap(ctx, image->base.mask, w, h);
+ }
+ 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)
+ factor = 1;
+ else
+ for (factor=1; image->base.w/(2*factor) >= w && image->base.h/(2*factor) >= h && factor < 8; factor *= 2);
+
+ /* Can we find any suitable tiles in the cache? */
+ key.refs = 1;
+ key.image = &image->base;
+ key.factor = factor;
+ do
+ {
+ tile = fz_find_item(ctx, fz_free_pixmap_imp, &key, &pdf_image_store_type);
+ if (tile)
+ return tile;
+ key.factor >>= 1;
+ }
+ while (key.factor > 0);
+
+ /* We need to make a new one. */
+ stm = pdf_open_image_decomp_stream(ctx, image->buffer, &image->params, &factor);
+
+ return decomp_image_from_stream(ctx, stm, image, 0, 0, factor);
+}
+
+static pdf_image *
pdf_load_image_imp(pdf_document *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cstm, int forcemask)
{
fz_stream *stm = NULL;
- fz_pixmap *tile = NULL;
+ pdf_image *image = NULL;
fz_obj *obj, *res;
int w, h, bpc, n;
int imagemask;
int interpolate;
int indexed;
- fz_colorspace *colorspace = NULL;
- fz_pixmap *mask = NULL; /* explicit mask/softmask image */
+ fz_image *mask = NULL; /* explicit mask/softmask image */
int usecolorkey;
- int colorkey[FZ_MAX_COLORS * 2];
- float decode[FZ_MAX_COLORS * 2];
- int stride;
- unsigned char *samples = NULL;
- int i, len;
+ int i;
fz_context *ctx = xref->ctx;
fz_var(stm);
- fz_var(tile);
- fz_var(colorspace);
fz_var(mask);
- fz_var(samples);
+
+ image = fz_malloc_struct(ctx, pdf_image);
fz_try(ctx)
{
/* special case for JPEG2000 images */
if (pdf_is_jpx_image(ctx, dict))
{
- tile = pdf_load_jpx(xref, dict);
+ pdf_load_jpx(xref, dict, image);
/* RJW: "cannot load jpx image" */
if (forcemask)
{
- if (tile->n != 2)
+ fz_pixmap *mask_pixmap;
+ if (image->n != 2)
fz_throw(ctx, "softmask must be grayscale");
- mask = fz_alpha_from_gray(ctx, tile, 1);
- fz_drop_pixmap(ctx, tile);
- tile = mask;
- mask = NULL;
+ 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 */
}
@@ -109,13 +358,13 @@ pdf_load_image_imp(pdf_document *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cst
obj = res;
}
- colorspace = pdf_load_colorspace(xref, obj);
+ image->base.colorspace = pdf_load_colorspace(xref, obj);
/* RJW: "cannot load image colorspace" */
- if (!strcmp(colorspace->name, "Indexed"))
+ if (!strcmp(image->base.colorspace->name, "Indexed"))
indexed = 1;
- n = colorspace->n;
+ n = image->base.colorspace->n;
}
else
{
@@ -126,13 +375,13 @@ pdf_load_image_imp(pdf_document *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cst
if (obj)
{
for (i = 0; i < n * 2; i++)
- decode[i] = fz_to_real(fz_array_get(obj, i));
+ image->decode[i] = fz_to_real(fz_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;
+ image->decode[i] = i & 1 ? maxval : 0;
}
obj = fz_dict_getsa(dict, "SMask", "Mask");
@@ -141,7 +390,7 @@ pdf_load_image_imp(pdf_document *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cst
/* Not allowed for inline images */
if (!cstm)
{
- mask = pdf_load_image_imp(xref, rdb, obj, NULL, 1);
+ mask = (fz_image *)pdf_load_image_imp(xref, rdb, obj, NULL, 1);
/* RJW: "cannot load image mask/softmask" */
}
}
@@ -155,36 +404,36 @@ pdf_load_image_imp(pdf_document *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cst
fz_warn(ctx, "invalid value in color key mask");
usecolorkey = 0;
}
- colorkey[i] = fz_to_int(fz_array_get(obj, i));
+ image->colorkey[i] = fz_to_int(fz_array_get(obj, i));
}
}
- /* Allocate now, to fail early if we run out of memory */
- fz_try(ctx)
- {
- tile = fz_new_pixmap(ctx, colorspace, w, h);
- }
- fz_catch(ctx)
+ /* 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)
{
- fz_drop_colorspace(ctx, colorspace);
- fz_rethrow(ctx);
- }
-
- if (colorspace)
- {
- fz_drop_colorspace(ctx, colorspace);
- colorspace = NULL;
+ /* Just load the compressed image data now and we can
+ * decode it on demand. */
+ image->buffer = pdf_load_image_stream(xref, fz_to_num(dict), fz_to_gen(dict), &image->params);
+ break; /* Out of fz_try */
}
- tile->mask = mask;
- mask = NULL;
- tile->interpolate = interpolate;
-
- stride = (w * n * bpc + 7) / 8;
-
+ /* We need to decompress the image now */
if (cstm)
{
- stm = pdf_open_inline_stream(xref, dict, stride * h, cstm);
+ int stride = (w * image->n * image->bpc + 7) / 8;
+ stm = pdf_open_inline_stream(xref, dict, stride * h, cstm, NULL);
}
else
{
@@ -192,92 +441,20 @@ pdf_load_image_imp(pdf_document *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cst
/* RJW: "cannot open image data stream (%d 0 R)", fz_to_num(dict) */
}
- samples = fz_malloc_array(ctx, h, stride);
-
- len = fz_read(stm, samples, h * stride);
- if (len < 0)
- {
- fz_throw(ctx, "cannot read image data");
- }
-
- /* Make sure we read the EOF marker (for inline images only) */
- if (cstm)
- {
- unsigned char tbuf[512];
- fz_try(ctx)
- {
- int tlen = fz_read(stm, tbuf, sizeof tbuf);
- if (tlen > 0)
- fz_warn(ctx, "ignoring garbage at end of image");
- }
- fz_catch(ctx)
- {
- fz_warn(ctx, "ignoring error at end of image");
- }
- }
-
- fz_close(stm);
- stm = NULL;
-
- /* Pad truncated images */
- if (len < stride * h)
- {
- fz_warn(ctx, "padding truncated image (%d 0 R)", fz_to_num(dict));
- memset(samples + len, 0, stride * h - len);
- }
-
- /* Invert 1-bit image masks */
- if (imagemask)
- {
- /* 0=opaque and 1=transparent so we need to invert */
- unsigned char *p = samples;
- len = h * stride;
- for (i = 0; i < len; i++)
- p[i] = ~p[i];
- }
-
- fz_unpack_tile(tile, samples, n, bpc, stride, indexed);
-
- fz_free(ctx, samples);
- samples = NULL;
-
- if (usecolorkey)
- pdf_mask_color_key(tile, n, colorkey);
-
- if (indexed)
- {
- fz_pixmap *conv;
- fz_decode_indexed_tile(tile, decode, (1 << bpc) - 1);
- conv = pdf_expand_indexed_pixmap(ctx, tile);
- fz_drop_pixmap(ctx, tile);
- tile = conv;
- }
- else
- {
- fz_decode_tile(tile, decode);
- }
+ image->tile = decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 1);
}
fz_catch(ctx)
{
- if (colorspace)
- fz_drop_colorspace(ctx, colorspace);
- if (mask)
- fz_drop_pixmap(ctx, mask);
- if (tile)
- fz_drop_pixmap(ctx, tile);
- fz_close(stm);
- fz_free(ctx, samples);
-
+ fz_drop_image(ctx, &image->base);
fz_rethrow(ctx);
}
-
- return tile;
+ return image;
}
-fz_pixmap *
+fz_image *
pdf_load_inline_image(pdf_document *xref, fz_obj *rdb, fz_obj *dict, fz_stream *file)
{
- return pdf_load_image_imp(xref, rdb, dict, file, 0);
+ return (fz_image *)pdf_load_image_imp(xref, rdb, dict, file, 0);
/* RJW: "cannot load inline image" */
}
@@ -297,8 +474,8 @@ pdf_is_jpx_image(fz_context *ctx, fz_obj *dict)
return 0;
}
-static fz_pixmap *
-pdf_load_jpx(pdf_document *xref, fz_obj *dict)
+static void
+pdf_load_jpx(pdf_document *xref, fz_obj *dict, pdf_image *image)
{
fz_buffer *buf = NULL;
fz_colorspace *colorspace = NULL;
@@ -328,18 +505,13 @@ pdf_load_jpx(pdf_document *xref, fz_obj *dict)
img = fz_load_jpx(ctx, buf->data, buf->len, colorspace);
/* RJW: "cannot load jpx image" */
- if (colorspace)
- {
- fz_drop_colorspace(ctx, colorspace);
- colorspace = NULL;
- }
fz_drop_buffer(ctx, buf);
buf = NULL;
obj = fz_dict_getsa(dict, "SMask", "Mask");
if (fz_is_dict(obj))
{
- img->mask = pdf_load_image_imp(xref, NULL, obj, NULL, 1);
+ image->base.mask = (fz_image *)pdf_load_image_imp(xref, NULL, obj, NULL, 1);
/* RJW: "cannot load image mask/softmask" */
}
@@ -363,24 +535,44 @@ pdf_load_jpx(pdf_document *xref, fz_obj *dict)
fz_drop_pixmap(ctx, img);
fz_rethrow(ctx);
}
- return img;
+ 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 = img->w;
+ image->base.h = img->h;
+ image->base.colorspace = colorspace;
+ image->tile = img;
+ image->n = img->n;
+ image->bpc = 8;
+ image->interpolate = 0;
+ image->imagemask = 0;
+ image->usecolorkey = 0;
+ image->params.colorspace = colorspace; /* Uses the same ref as for the base one */
+}
+
+static int
+pdf_image_size(fz_context *ctx, pdf_image *im)
+{
+ if (im == NULL)
+ return 0;
+ return sizeof(*im) + fz_pixmap_size(ctx, im->tile) + (im->buffer ? im->buffer->cap : 0);
}
-fz_pixmap *
+fz_image *
pdf_load_image(pdf_document *xref, fz_obj *dict)
{
fz_context *ctx = xref->ctx;
- fz_pixmap *pix;
+ pdf_image *image;
- if ((pix = fz_find_item(ctx, fz_free_pixmap_imp, dict)))
+ if ((image = pdf_find_item(ctx, pdf_free_image, dict)))
{
- return pix;
+ return (fz_image *)image;
}
- pix = pdf_load_image_imp(xref, NULL, dict, NULL, 0);
+ image = pdf_load_image_imp(xref, NULL, dict, NULL, 0);
/* RJW: "cannot load image (%d 0 R)", fz_to_num(dict) */
- fz_store_item(ctx, dict, pix, fz_pixmap_size(ctx, pix));
+ pdf_store_item(ctx, dict, image, pdf_image_size(ctx, image));
- return pix;
+ return (fz_image *)image;
}
diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c
index ea7f7692..effea657 100644
--- a/pdf/pdf_interpret.c
+++ b/pdf/pdf_interpret.c
@@ -362,7 +362,7 @@ pdf_show_shade(pdf_csi *csi, fz_shade *shd)
}
static void
-pdf_show_image(pdf_csi *csi, fz_pixmap *image)
+pdf_show_image(pdf_csi *csi, fz_image *image)
{
pdf_gstate *gstate = csi->gstate + csi->gtop;
fz_matrix image_ctm;
@@ -1627,7 +1627,7 @@ static void pdf_run_BI(pdf_csi *csi, fz_obj *rdb, fz_stream *file)
int ch;
char *buf = csi->xref->scratch;
int buflen = sizeof(csi->xref->scratch);
- fz_pixmap *img;
+ fz_image *img;
fz_obj *obj;
obj = pdf_parse_dict(csi->xref, file, buf, buflen);
@@ -1645,7 +1645,7 @@ static void pdf_run_BI(pdf_csi *csi, fz_obj *rdb, fz_stream *file)
pdf_show_image(csi, img);
- fz_drop_pixmap(ctx, img);
+ fz_drop_image(ctx, img);
/* find EI */
ch = fz_read_byte(file);
@@ -1798,19 +1798,20 @@ static void pdf_run_Do(pdf_csi *csi, fz_obj *rdb)
{
if ((csi->dev->hints & FZ_IGNORE_IMAGE) == 0)
{
- fz_pixmap *img;
- img = pdf_load_image(csi->xref, obj);
+ fz_image *img = pdf_load_image(csi->xref, obj);
/* RJW: "cannot load image (%d %d R)", fz_to_num(obj), fz_to_gen(obj) */
fz_try(ctx)
{
pdf_show_image(csi, img);
}
+ fz_always(ctx)
+ {
+ fz_drop_image(ctx, img);
+ }
fz_catch(ctx)
{
- fz_drop_pixmap(ctx, img);
fz_rethrow(ctx);
}
- fz_drop_pixmap(ctx, img);
}
}
diff --git a/pdf/pdf_pattern.c b/pdf/pdf_pattern.c
index 9ffbee02..c1869474 100644
--- a/pdf/pdf_pattern.c
+++ b/pdf/pdf_pattern.c
@@ -40,7 +40,7 @@ pdf_load_pattern(pdf_document *xref, fz_obj *dict)
fz_obj *obj;
fz_context *ctx = xref->ctx;
- if ((pat = fz_find_item(ctx, pdf_free_pattern_imp, dict)))
+ if ((pat = pdf_find_item(ctx, pdf_free_pattern_imp, dict)))
{
return pat;
}
@@ -51,7 +51,7 @@ pdf_load_pattern(pdf_document *xref, fz_obj *dict)
pat->contents = NULL;
/* Store pattern now, to avoid possible recursion if objects refer back to this one */
- fz_store_item(ctx, dict, pat, pdf_pattern_size(pat));
+ pdf_store_item(ctx, dict, pat, pdf_pattern_size(pat));
pat->ismask = fz_to_int(fz_dict_gets(dict, "PaintType")) == 2;
pat->xstep = fz_to_real(fz_dict_gets(dict, "XStep"));
@@ -76,7 +76,7 @@ pdf_load_pattern(pdf_document *xref, fz_obj *dict)
}
fz_catch(ctx)
{
- fz_remove_item(ctx, pdf_free_pattern_imp, dict);
+ pdf_remove_item(ctx, pdf_free_pattern_imp, dict);
pdf_drop_pattern(ctx, pat);
fz_throw(ctx, "cannot load pattern stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict));
}
diff --git a/pdf/pdf_shade.c b/pdf/pdf_shade.c
index fb5dd72c..1be2bb15 100644
--- a/pdf/pdf_shade.c
+++ b/pdf/pdf_shade.c
@@ -1100,7 +1100,7 @@ pdf_load_shading(pdf_document *xref, fz_obj *dict)
fz_context *ctx = xref->ctx;
fz_shade *shade;
- if ((shade = fz_find_item(ctx, fz_free_shade_imp, dict)))
+ if ((shade = pdf_find_item(ctx, fz_free_shade_imp, dict)))
{
return shade;
}
@@ -1138,7 +1138,7 @@ pdf_load_shading(pdf_document *xref, fz_obj *dict)
/* RJW: "cannot load shading dictionary (%d %d R)", fz_to_num(dict), fz_to_gen(dict) */
}
- fz_store_item(ctx, dict, shade, fz_shade_size(shade));
+ pdf_store_item(ctx, dict, shade, fz_shade_size(shade));
return shade;
}
diff --git a/pdf/pdf_store.c b/pdf/pdf_store.c
new file mode 100644
index 00000000..4f51526d
--- /dev/null
+++ b/pdf/pdf_store.c
@@ -0,0 +1,59 @@
+#include "fitz.h"
+#include "mupdf.h"
+
+static int
+pdf_make_hash_key(fz_store_hash *hash, void *key_)
+{
+ fz_obj *key = (fz_obj *)key_;
+
+ if (!fz_is_indirect(key))
+ return 0;
+ hash->u.i.i0 = fz_to_num(key);
+ hash->u.i.i1 = fz_to_gen(key);
+ return 1;
+}
+
+static void *
+pdf_keep_key(fz_context *ctx, void *key)
+{
+ return (void *)fz_keep_obj((fz_obj *)key);
+}
+
+static void
+pdf_drop_key(fz_context *ctx, void *key)
+{
+ fz_drop_obj((fz_obj *)key);
+}
+
+static int
+pdf_cmp_key(void *k0, void *k1)
+{
+ return fz_objcmp((fz_obj *)k0, (fz_obj *)k1);
+}
+
+static fz_store_type pdf_obj_store_type =
+{
+ pdf_make_hash_key,
+ pdf_keep_key,
+ pdf_drop_key,
+ pdf_cmp_key
+};
+
+void
+pdf_store_item(fz_context *ctx, fz_obj *key, void *val, unsigned int itemsize)
+{
+ fz_store_item(ctx, key, val, itemsize, &pdf_obj_store_type);
+}
+
+void *
+pdf_find_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key)
+{
+ return fz_find_item(ctx, free, key, &pdf_obj_store_type);
+}
+
+void
+pdf_remove_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key)
+{
+ fz_remove_item(ctx, free, key, &pdf_obj_store_type);
+}
+
diff --git a/pdf/pdf_stream.c b/pdf/pdf_stream.c
index c66e703e..28fc616f 100644
--- a/pdf/pdf_stream.c
+++ b/pdf/pdf_stream.c
@@ -49,7 +49,7 @@ pdf_stream_has_crypt(fz_context *ctx, fz_obj *stm)
* Create a filter given a name and param dictionary.
*/
static fz_stream *
-build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int num, int gen)
+build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int num, int gen, pdf_image_params *params)
{
fz_context *ctx = chain->ctx;
char *s = fz_to_name(f);
@@ -79,6 +79,19 @@ build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int
fz_obj *rows = fz_dict_gets(p, "Rows");
fz_obj *eob = fz_dict_gets(p, "EndOfBlock");
fz_obj *bi1 = fz_dict_gets(p, "BlackIs1");
+ if (params)
+ {
+ /* We will shortstop here */
+ params->type = PDF_IMAGE_FAX;
+ params->u.fax.k = (k ? fz_to_int(k) : 0);
+ params->u.fax.eol = (eol ? fz_to_bool(eol) : 0);
+ params->u.fax.eba = (eba ? fz_to_bool(eba) : 0);
+ params->u.fax.columns = (columns ? fz_to_int(columns) : 1728);
+ params->u.fax.rows = (rows ? fz_to_int(rows) : 0);
+ params->u.fax.eob = (eob ? fz_to_bool(eob) : 1);
+ params->u.fax.bi1 = (bi1 ? fz_to_bool(bi1) : 0);
+ return chain;
+ }
return fz_open_faxd(chain,
k ? fz_to_int(k) : 0,
eol ? fz_to_bool(eol) : 0,
@@ -92,14 +105,38 @@ build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int
else if (!strcmp(s, "DCTDecode") || !strcmp(s, "DCT"))
{
fz_obj *ct = fz_dict_gets(p, "ColorTransform");
+ if (params)
+ {
+ /* We will shortstop here */
+ params->type = PDF_IMAGE_JPEG;
+ params->u.jpeg.ct = (ct ? fz_to_int(ct) : -1);
+ return chain;
+ }
return fz_open_dctd(chain, ct ? fz_to_int(ct) : -1);
}
else if (!strcmp(s, "RunLengthDecode") || !strcmp(s, "RL"))
+ {
+ if (params)
+ {
+ /* We will shortstop here */
+ params->type = PDF_IMAGE_RLD;
+ return chain;
+ }
return fz_open_rld(chain);
-
+ }
else if (!strcmp(s, "FlateDecode") || !strcmp(s, "Fl"))
{
+ if (params)
+ {
+ /* We will shortstop here */
+ params->type = PDF_IMAGE_FLATE;
+ params->u.flate.predictor = predictor;
+ params->u.flate.columns = columns;
+ params->u.flate.colors = colors;
+ params->u.flate.bpc = bpc;
+ return chain;
+ }
chain = fz_open_flated(chain);
if (predictor > 1)
chain = fz_open_predict(chain, predictor, columns, colors, bpc);
@@ -109,6 +146,17 @@ build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int
else if (!strcmp(s, "LZWDecode") || !strcmp(s, "LZW"))
{
fz_obj *ec = fz_dict_gets(p, "EarlyChange");
+ if (params)
+ {
+ /* We will shortstop here */
+ params->type = PDF_IMAGE_LZW;
+ params->u.lzw.predictor = predictor;
+ params->u.lzw.columns = columns;
+ params->u.lzw.colors = colors;
+ params->u.lzw.bpc = bpc;
+ params->u.lzw.ec = (ec ? fz_to_int(ec) : 1);
+ return chain;
+ }
chain = fz_open_lzwd(chain, ec ? fz_to_int(ec) : 1);
if (predictor > 1)
chain = fz_open_predict(chain, predictor, columns, colors, bpc);
@@ -155,7 +203,7 @@ build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int
* Assume ownership of head.
*/
static fz_stream *
-build_filter_chain(fz_stream *chain, pdf_document *xref, fz_obj *fs, fz_obj *ps, int num, int gen)
+build_filter_chain(fz_stream *chain, pdf_document *xref, fz_obj *fs, fz_obj *ps, int num, int gen, pdf_image_params *params)
{
fz_obj *f;
fz_obj *p;
@@ -166,7 +214,7 @@ build_filter_chain(fz_stream *chain, pdf_document *xref, fz_obj *fs, fz_obj *ps,
{
f = fz_array_get(fs, i);
p = fz_array_get(ps, i);
- chain = build_filter(chain, xref, f, p, num, gen);
+ chain = build_filter(chain, xref, f, p, num, gen, (i == n-1 ? params : NULL));
}
return chain;
@@ -210,7 +258,7 @@ pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, fz_obj *stmobj, int nu
* to stream length and decrypting.
*/
static fz_stream *
-pdf_open_filter(fz_stream *chain, pdf_document *xref, fz_obj *stmobj, int num, int gen)
+pdf_open_filter(fz_stream *chain, pdf_document *xref, fz_obj *stmobj, int num, int gen, pdf_image_params *imparams)
{
fz_obj *filters;
fz_obj *params;
@@ -221,9 +269,9 @@ pdf_open_filter(fz_stream *chain, pdf_document *xref, fz_obj *stmobj, int num, i
chain = pdf_open_raw_filter(chain, xref, stmobj, num, gen);
if (fz_is_name(filters))
- chain = build_filter(chain, xref, filters, params, num, gen);
+ chain = build_filter(chain, xref, filters, params, num, gen, imparams);
else if (fz_array_len(filters) > 0)
- chain = build_filter_chain(chain, xref, filters, params, num, gen);
+ chain = build_filter_chain(chain, xref, filters, params, num, gen, imparams);
fz_lock_stream(chain);
return chain;
@@ -234,7 +282,7 @@ pdf_open_filter(fz_stream *chain, pdf_document *xref, fz_obj *stmobj, int num, i
* constraining to stream length, and without decryption.
*/
fz_stream *
-pdf_open_inline_stream(pdf_document *xref, fz_obj *stmobj, int length, fz_stream *chain)
+pdf_open_inline_stream(pdf_document *xref, fz_obj *stmobj, int length, fz_stream *chain, pdf_image_params *imparams)
{
fz_obj *filters;
fz_obj *params;
@@ -246,9 +294,9 @@ pdf_open_inline_stream(pdf_document *xref, fz_obj *stmobj, int length, fz_stream
fz_keep_stream(chain);
if (fz_is_name(filters))
- return build_filter(chain, xref, filters, params, 0, 0);
+ return build_filter(chain, xref, filters, params, 0, 0, imparams);
if (fz_array_len(filters) > 0)
- return build_filter_chain(chain, xref, filters, params, 0, 0);
+ return build_filter_chain(chain, xref, filters, params, 0, 0, imparams);
return fz_open_null(chain, length);
}
@@ -290,6 +338,12 @@ pdf_open_raw_stream(pdf_document *xref, int num, int gen)
fz_stream *
pdf_open_stream(pdf_document *xref, int num, int gen)
{
+ return pdf_open_image_stream(xref, num, gen, NULL);
+}
+
+fz_stream *
+pdf_open_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *params)
+{
pdf_xref_entry *x;
fz_stream *stm;
@@ -304,12 +358,56 @@ pdf_open_stream(pdf_document *xref, int num, int gen)
if (x->stm_ofs == 0)
fz_throw(xref->ctx, "object is not a stream");
- stm = pdf_open_filter(xref->file, xref, x->obj, num, gen);
+ stm = pdf_open_filter(xref->file, xref, x->obj, num, gen, params);
fz_seek(xref->file, x->stm_ofs, 0);
return stm;
}
fz_stream *
+pdf_open_image_decomp_stream(fz_context *ctx, fz_buffer *buffer, pdf_image_params *params, int *factor)
+{
+ fz_stream *chain = fz_open_buffer(ctx, buffer);
+
+ switch (params->type)
+ {
+ case PDF_IMAGE_FAX:
+ *factor = 1;
+ return fz_open_faxd(chain,
+ params->u.fax.k,
+ params->u.fax.eol,
+ params->u.fax.eba,
+ params->u.fax.columns,
+ params->u.fax.rows,
+ params->u.fax.eob,
+ params->u.fax.bi1);
+ case PDF_IMAGE_JPEG:
+ if (*factor > 8)
+ *factor = 8;
+ return fz_open_resized_dctd(chain, params->u.jpeg.ct, *factor);
+ case PDF_IMAGE_RLD:
+ *factor = 1;
+ return fz_open_rld(chain);
+ case PDF_IMAGE_FLATE:
+ *factor = 1;
+ chain = fz_open_flated(chain);
+ if (params->u.flate.predictor > 1)
+ chain = fz_open_predict(chain, params->u.flate.predictor, params->u.flate.columns, params->u.flate.colors, params->u.flate.bpc);
+ return chain;
+ case PDF_IMAGE_LZW:
+ *factor = 1;
+ chain = fz_open_lzwd(chain, params->u.lzw.ec);
+ if (params->u.lzw.predictor > 1)
+ chain = fz_open_predict(chain, params->u.lzw.predictor, params->u.lzw.columns, params->u.lzw.colors, params->u.lzw.bpc);
+ return chain;
+ default:
+ *factor = 1;
+ break;
+ }
+
+ return chain;
+}
+
+fz_stream *
pdf_open_stream_with_offset(pdf_document *xref, int num, int gen, fz_obj *dict, int stm_ofs)
{
fz_stream *stm;
@@ -317,7 +415,7 @@ pdf_open_stream_with_offset(pdf_document *xref, int num, int gen, fz_obj *dict,
if (stm_ofs == 0)
fz_throw(xref->ctx, "object is not a stream");
- stm = pdf_open_filter(xref->file, xref, dict, num, gen);
+ stm = pdf_open_filter(xref->file, xref, dict, num, gen, NULL);
fz_seek(xref->file, stm_ofs, 0);
return stm;
}
@@ -372,6 +470,12 @@ pdf_guess_filter_length(int len, char *filter)
fz_buffer *
pdf_load_stream(pdf_document *xref, int num, int gen)
{
+ return pdf_load_image_stream(xref, num, gen, NULL);
+}
+
+fz_buffer *
+pdf_load_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *params)
+{
fz_context *ctx = xref->ctx;
fz_stream *stm = NULL;
fz_obj *dict, *obj;
@@ -392,7 +496,7 @@ pdf_load_stream(pdf_document *xref, int num, int gen)
fz_drop_obj(dict);
- stm = pdf_open_stream(xref, num, gen);
+ stm = pdf_open_image_stream(xref, num, gen, params);
/* RJW: "cannot open stream (%d %d R)", num, gen */
fz_try(ctx)
diff --git a/pdf/pdf_xobject.c b/pdf/pdf_xobject.c
index 91bf4db3..9f6d10ce 100644
--- a/pdf/pdf_xobject.c
+++ b/pdf/pdf_xobject.c
@@ -43,7 +43,7 @@ pdf_load_xobject(pdf_document *xref, fz_obj *dict)
fz_obj *obj;
fz_context *ctx = xref->ctx;
- if ((form = fz_find_item(ctx, pdf_free_xobject_imp, dict)))
+ if ((form = pdf_find_item(ctx, pdf_free_xobject_imp, dict)))
{
return form;
}
@@ -56,7 +56,7 @@ pdf_load_xobject(pdf_document *xref, fz_obj *dict)
form->me = NULL;
/* Store item immediately, to avoid possible recursion if objects refer back to this one */
- fz_store_item(ctx, dict, form, pdf_xobject_size(form));
+ pdf_store_item(ctx, dict, form, pdf_xobject_size(form));
obj = fz_dict_gets(dict, "BBox");
form->bbox = pdf_to_rect(ctx, obj);
@@ -102,7 +102,7 @@ pdf_load_xobject(pdf_document *xref, fz_obj *dict)
}
fz_catch(ctx)
{
- fz_remove_item(ctx, pdf_free_xobject_imp, dict);
+ pdf_remove_item(ctx, pdf_free_xobject_imp, dict);
pdf_drop_xobject(ctx, form);
fz_throw(ctx, "cannot load xobject content stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict));
}