summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/fitz/image.h24
-rw-r--r--include/mupdf/fitz/math.h15
-rw-r--r--include/mupdf/fitz/output-png.h2
-rw-r--r--include/mupdf/fitz/store.h6
-rw-r--r--include/mupdf/fitz/stream.h11
-rw-r--r--source/fitz/draw-device.c88
-rw-r--r--source/fitz/geometry.c12
-rw-r--r--source/fitz/image.c209
-rw-r--r--source/fitz/pixmap.c4
-rw-r--r--source/fitz/stext-output.c2
-rw-r--r--source/fitz/stream-read.c20
-rw-r--r--source/fitz/svg-device.c6
-rw-r--r--source/fitz/test-device.c2
-rw-r--r--source/gprf/gprf-doc.c10
-rw-r--r--source/pdf/pdf-image.c2
-rw-r--r--source/pdf/pdf-resources.c2
-rw-r--r--source/pdf/pdf-stream.c2
-rw-r--r--source/tools/murun.c4
-rw-r--r--source/tools/pdfextract.c2
19 files changed, 369 insertions, 54 deletions
diff --git a/include/mupdf/fitz/image.h b/include/mupdf/fitz/image.h
index 3355748c..5b9db325 100644
--- a/include/mupdf/fitz/image.h
+++ b/include/mupdf/fitz/image.h
@@ -24,17 +24,23 @@ typedef struct fz_image_s fz_image;
image: The image to retrieve a pixmap from.
- w: The desired width (in pixels). This may be completely ignored, but
- may serve as an indication of a suitable subsample factor to use for
- image types that support this.
+ subarea: The subarea of the image that we actually care about (or NULL
+ to indicate the whole image).
- h: The desired height (in pixels). This may be completely ignored, but
- may serve as an indication of a suitable subsample factor to use for
- image types that support this.
+ trans: Optional, unless subarea is given. If given, then on entry this is
+ the transform that will be applied to the complete image. It should be
+ updated on exit to the transform to apply to the given subarea of the
+ image. This is used to calculate the desired width/height for subsampling.
+
+ w: If non-NULL, a pointer to an int to be updated on exit to the
+ width (in pixels) that the scaled output will cover.
+
+ h: If non-NULL, a pointer to an int to be updated on exit to the
+ height (in pixels) that the scaled output will cover.
Returns a non NULL pixmap pointer. May throw exceptions.
*/
-fz_pixmap *fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, int w, int h);
+fz_pixmap *fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, const fz_irect *subarea, fz_matrix *trans, int *w, int *h);
/*
fz_drop_image: Drop a reference to an image.
@@ -58,7 +64,7 @@ fz_image *fz_new_image_from_data(fz_context *ctx, unsigned char *data, int len);
fz_image *fz_new_image_from_buffer(fz_context *ctx, fz_buffer *buffer);
fz_image *fz_new_image_from_file(fz_context *ctx, const char *path);
void fz_drop_image_imp(fz_context *ctx, fz_storable *image);
-fz_pixmap *fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, int indexed, int l2factor);
+fz_pixmap *fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, fz_irect *subarea, int indexed, int l2factor);
fz_pixmap *fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src);
struct fz_image_s
@@ -67,7 +73,7 @@ struct fz_image_s
int w, h, n, bpc;
fz_image *mask;
fz_colorspace *colorspace;
- fz_pixmap *(*get_pixmap)(fz_context *, fz_image *, int w, int h, int *l2factor);
+ fz_pixmap *(*get_pixmap)(fz_context *, fz_image *, fz_irect *subarea, int w, int h, int *l2factor);
int colorkey[FZ_MAX_COLORS * 2];
float decode[FZ_MAX_COLORS * 2];
int imagemask;
diff --git a/include/mupdf/fitz/math.h b/include/mupdf/fitz/math.h
index f16b3627..b7baede8 100644
--- a/include/mupdf/fitz/math.h
+++ b/include/mupdf/fitz/math.h
@@ -294,6 +294,21 @@ fz_matrix *fz_scale(fz_matrix *m, float sx, float sy);
fz_matrix *fz_pre_scale(fz_matrix *m, float sx, float sy);
/*
+ fz_post_scale: Scale a matrix by postmultiplication.
+
+ m: Pointer to the matrix to scale
+
+ sx, sy: Scaling factors along the X- and Y-axes. A scaling
+ factor of 1.0 will not cause any scaling along the relevant
+ axis.
+
+ Returns m (updated).
+
+ Does not throw exceptions.
+*/
+fz_matrix *fz_post_scale(fz_matrix *m, float sx, float sy);
+
+/*
fz_shear: Create a shearing matrix.
The returned matrix is of the form [ 1 sy sx 1 0 0 ].
diff --git a/include/mupdf/fitz/output-png.h b/include/mupdf/fitz/output-png.h
index 34af799a..c77f9e5f 100644
--- a/include/mupdf/fitz/output-png.h
+++ b/include/mupdf/fitz/output-png.h
@@ -29,7 +29,7 @@ void fz_write_png_trailer(fz_context *ctx, fz_output *out, fz_png_output_context
/*
Create a new buffer containing the image/pixmap in PNG format.
*/
-fz_buffer *fz_new_buffer_from_image_as_png(fz_context *ctx, fz_image *image, int w, int h);
+fz_buffer *fz_new_buffer_from_image_as_png(fz_context *ctx, fz_image *image);
fz_buffer *fz_new_buffer_from_pixmap_as_png(fz_context *ctx, fz_pixmap *pixmap);
#endif
diff --git a/include/mupdf/fitz/store.h b/include/mupdf/fitz/store.h
index e98e2394..5dbf5538 100644
--- a/include/mupdf/fitz/store.h
+++ b/include/mupdf/fitz/store.h
@@ -78,6 +78,12 @@ struct fz_store_hash_s
} pi;
struct
{
+ const void *ptr;
+ int i;
+ fz_irect r;
+ } pir;
+ struct
+ {
int id;
float m[4];
} im;
diff --git a/include/mupdf/fitz/stream.h b/include/mupdf/fitz/stream.h
index 233e2b06..90b5ec22 100644
--- a/include/mupdf/fitz/stream.h
+++ b/include/mupdf/fitz/stream.h
@@ -136,6 +136,17 @@ void fz_seek(fz_context *ctx, fz_stream *stm, fz_off_t offset, int whence);
int fz_read(fz_context *ctx, fz_stream *stm, unsigned char *data, int len);
/*
+ fz_skip: Read from a stream discarding data.
+
+ stm: The stream to read from.
+
+ len: The number of bytes to read.
+
+ Returns the number of bytes read. May throw exceptions.
+*/
+int fz_skip(fz_context *ctx, fz_stream *stm, int len);
+
+/*
fz_read_all: Read all of a stream into a buffer.
stm: The stream to read from
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index b9db1558..4108cf09 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -1106,6 +1106,8 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
fz_colorspace *model = state->dest->colorspace;
fz_irect clip;
fz_matrix local_ctm = *ctm;
+ fz_matrix inverse;
+ fz_irect src_area;
fz_intersect_irect(fz_pixmap_bbox(ctx, state->dest, &clip), &state->scissor);
@@ -1120,10 +1122,42 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
if (image->w == 0 || image->h == 0)
return;
- dx = sqrtf(local_ctm.a * local_ctm.a + local_ctm.b * local_ctm.b);
- dy = sqrtf(local_ctm.c * local_ctm.c + local_ctm.d * local_ctm.d);
-
- pixmap = fz_get_pixmap_from_image(ctx, image, dx, dy);
+ /* ctm maps the image (expressed as the unit square) onto the
+ * destination device. Reverse that to get a mapping from
+ * the destination device to the source pixels. */
+ if (fz_try_invert_matrix(&inverse, &local_ctm))
+ {
+ /* Not invertible. Could just bale? Use the whole image
+ * for now. */
+ src_area.x0 = 0;
+ src_area.x1 = image->w;
+ src_area.y0 = 0;
+ src_area.y1 = image->h;
+ }
+ else
+ {
+ float exp;
+ fz_rect rect;
+ fz_irect sane;
+ /* We want to scale from image coords, not from unit square */
+ fz_post_scale(&inverse, image->w, image->h);
+ /* Are we scaling up or down? exp < 1 means scaling down. */
+ exp = fz_matrix_max_expansion(&inverse);
+ fz_rect_from_irect(&rect, &clip);
+ fz_transform_rect(&rect, &inverse);
+ /* Allow for support requirements for scalers. */
+ fz_expand_rect(&rect, fz_max(exp, 1) * 4);
+ fz_irect_from_rect(&src_area, &rect);
+ sane.x0 = 0;
+ sane.y0 = 0;
+ sane.x1 = image->w;
+ sane.y1 = image->h;
+ fz_intersect_irect(&src_area, &sane);
+ if (fz_is_empty_irect(&src_area))
+ return;
+ }
+
+ pixmap = fz_get_pixmap_from_image(ctx, image, &src_area, &local_ctm, &dx, &dy);
orig_pixmap = pixmap;
/* convert images with more components (cmyk->rgb) before scaling */
@@ -1214,6 +1248,8 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_colorspace *model = state->dest->colorspace;
fz_irect clip;
fz_matrix local_ctm = *ctm;
+ fz_matrix inverse;
+ fz_irect src_area;
fz_pixmap_bbox(ctx, state->dest, &clip);
fz_intersect_irect(&clip, &state->scissor);
@@ -1221,9 +1257,42 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
if (image->w == 0 || image->h == 0)
return;
- dx = sqrtf(local_ctm.a * local_ctm.a + local_ctm.b * local_ctm.b);
- dy = sqrtf(local_ctm.c * local_ctm.c + local_ctm.d * local_ctm.d);
- pixmap = fz_get_pixmap_from_image(ctx, image, dx, dy);
+ /* ctm maps the image (expressed as the unit square) onto the
+ * destination device. Reverse that to get a mapping from
+ * the destination device to the source pixels. */
+ if (fz_try_invert_matrix(&inverse, &local_ctm))
+ {
+ /* Not invertible. Could just bale? Use the whole image
+ * for now. */
+ src_area.x0 = 0;
+ src_area.x1 = image->w;
+ src_area.y0 = 0;
+ src_area.y1 = image->h;
+ }
+ else
+ {
+ float exp;
+ fz_rect rect;
+ fz_irect sane;
+ /* We want to scale from image coords, not from unit square */
+ fz_post_scale(&inverse, image->w, image->h);
+ /* Are we scaling up or down? exp < 1 means scaling down. */
+ exp = fz_matrix_max_expansion(&inverse);
+ fz_rect_from_irect(&rect, &clip);
+ fz_transform_rect(&rect, &inverse);
+ /* Allow for support requirements for scalers. */
+ fz_expand_rect(&rect, fz_max(exp, 1) * 4);
+ fz_irect_from_rect(&src_area, &rect);
+ sane.x0 = 0;
+ sane.y0 = 0;
+ sane.x1 = image->w;
+ sane.y1 = image->h;
+ fz_intersect_irect(&src_area, &sane);
+ if (fz_is_empty_irect(&src_area))
+ return;
+ }
+
+ pixmap = fz_get_pixmap_from_image(ctx, image, &src_area, &local_ctm, &dx, &dy);
orig_pixmap = pixmap;
fz_try(ctx)
@@ -1321,12 +1390,9 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_intersect_irect(&bbox, fz_irect_from_rect(&bbox2, scissor));
}
- dx = sqrtf(local_ctm.a * local_ctm.a + local_ctm.b * local_ctm.b);
- dy = sqrtf(local_ctm.c * local_ctm.c + local_ctm.d * local_ctm.d);
-
fz_try(ctx)
{
- pixmap = fz_get_pixmap_from_image(ctx, image, dx, dy);
+ pixmap = fz_get_pixmap_from_image(ctx, image, NULL, &local_ctm, &dx, &dy);
orig_pixmap = pixmap;
state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
diff --git a/source/fitz/geometry.c b/source/fitz/geometry.c
index 073536ff..f7a92816 100644
--- a/source/fitz/geometry.c
+++ b/source/fitz/geometry.c
@@ -59,6 +59,18 @@ fz_pre_scale(fz_matrix *mat, float sx, float sy)
}
fz_matrix *
+fz_post_scale(fz_matrix *mat, float sx, float sy)
+{
+ mat->a *= sx;
+ mat->b *= sy;
+ mat->c *= sx;
+ mat->d *= sy;
+ mat->e *= sx;
+ mat->f *= sy;
+ return mat;
+}
+
+fz_matrix *
fz_shear(fz_matrix *mat, float h, float v)
{
mat->a = 1; mat->b = v;
diff --git a/source/fitz/image.c b/source/fitz/image.c
index 9c66176f..36026a19 100644
--- a/source/fitz/image.c
+++ b/source/fitz/image.c
@@ -21,14 +21,16 @@ struct fz_image_key_s {
int refs;
fz_image *image;
int l2factor;
+ fz_irect rect;
};
static int
fz_make_hash_image_key(fz_context *ctx, fz_store_hash *hash, void *key_)
{
fz_image_key *key = (fz_image_key *)key_;
- hash->u.pi.ptr = key->image;
- hash->u.pi.i = key->l2factor;
+ hash->u.pir.ptr = key->image;
+ hash->u.pir.i = key->l2factor;
+ hash->u.pir.r = key->rect;
return 1;
}
@@ -55,7 +57,7 @@ fz_cmp_image_key(fz_context *ctx, void *k0_, void *k1_)
{
fz_image_key *k0 = (fz_image_key *)k0_;
fz_image_key *k1 = (fz_image_key *)k1_;
- return k0->image == k1->image && k0->l2factor == k1->l2factor;
+ return k0->image == k1->image && k0->l2factor == k1->l2factor && k0->rect.x0 == k1->rect.x0 && k0->rect.y0 == k1->rect.y0 && k0->rect.x1 == k1->rect.x1 && k0->rect.y1 == k1->rect.y1;
}
static void
@@ -96,7 +98,7 @@ fz_mask_color_key(fz_pixmap *pix, int n, const int *colorkey)
static void
fz_unblend_masked_tile(fz_context *ctx, fz_pixmap *tile, fz_image *image)
{
- fz_pixmap *mask = fz_get_pixmap_from_image(ctx, image->mask, tile->w, tile->h);
+ fz_pixmap *mask = fz_get_pixmap_from_image(ctx, image->mask, NULL, NULL, NULL, NULL);
unsigned char *s = mask->samples, *end = s + mask->w * mask->h;
unsigned char *d = tile->samples;
int k;
@@ -122,14 +124,39 @@ fz_unblend_masked_tile(fz_context *ctx, fz_pixmap *tile, fz_image *image)
}
fz_pixmap *
-fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, int indexed, int l2factor)
+fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, fz_irect *subarea, int indexed, int l2factor)
{
fz_pixmap *tile = NULL;
int stride, len, i;
unsigned char *samples = NULL;
int f = 1<<l2factor;
- int w = (image->w + f-1) >> l2factor;
- int h = (image->h + f-1) >> l2factor;
+ int w = image->w;
+ int h = image->h;
+
+ if (subarea)
+ {
+ int bpp = image->bpc * image->n;
+ int mask;
+ switch (bpp)
+ {
+ case 1: mask = 8*f; break;
+ case 2: mask = 4*f; break;
+ case 4: mask = 2*f; break;
+ default: mask = f; break;
+ }
+ subarea->x0 &= ~(mask - 1);
+ subarea->y0 &= ~(f - 1);
+ subarea->x1 = (subarea->x1 + mask - 1) & ~(mask - 1);
+ if (subarea->x1 > image->w)
+ subarea->x1 = image->w;
+ subarea->y1 = (subarea->y1 + f - 1) & ~(f - 1);
+ if (subarea->y1 > image->h)
+ subarea->y1 = image->h;
+ w = (subarea->x1 - subarea->x0);
+ h = (subarea->y1 - subarea->y0);
+ }
+ w = (w + f - 1) >> l2factor;
+ h = (h + f - 1) >> l2factor;
fz_var(tile);
fz_var(samples);
@@ -143,7 +170,46 @@ fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, in
samples = fz_malloc_array(ctx, h, stride);
- len = fz_read(ctx, stm, samples, h * stride);
+ if (subarea)
+ {
+ int hh;
+ unsigned char *s = samples;
+ int stream_w = (image->w + f - 1)>>l2factor;
+ int stream_stride = (stream_w * image->n * image->bpc + 7) / 8;
+ int l_margin = subarea->x0 >> l2factor;
+ int t_margin = subarea->y0 >> l2factor;
+ int r_margin = (image->w + f - 1 - subarea->x1) >> l2factor;
+ int b_margin = (image->h + f - 1 - subarea->y1) >> l2factor;
+ int l_skip = (l_margin * image->n * image->bpc)/8;
+ int r_skip = (r_margin * image->n * image->bpc)/8;
+ int t_skip = t_margin * stream_stride + l_skip;
+ int b_skip = b_margin * stream_stride + r_skip;
+ int l = fz_skip(ctx, stm, t_skip);
+ len = 0;
+ if (l == t_skip)
+ {
+ hh = h;
+ do
+ {
+ l = fz_read(ctx, stm, s, stride);
+ s += l;
+ len += l;
+ if (l < stride)
+ break;
+ if (--hh == 0)
+ break;
+ l = fz_skip(ctx, stm, r_skip + l_skip);
+ if (l < r_skip + l_skip)
+ break;
+ }
+ while (1);
+ (void)fz_skip(ctx, stm, r_skip + b_skip);
+ }
+ }
+ else
+ {
+ len = fz_read(ctx, stm, samples, h * stride);
+ }
/* Pad truncated images */
if (len < stride * h)
@@ -219,12 +285,13 @@ fz_drop_image_imp(fz_context *ctx, fz_storable *image_)
}
static fz_pixmap *
-standard_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h, int *l2factor)
+standard_image_get_pixmap(fz_context *ctx, fz_image *image, fz_irect *subarea, int w, int h, int *l2factor)
{
int native_l2factor;
fz_stream *stm;
int indexed;
fz_pixmap *tile;
+ int can_sub = 0;
/* We need to make a new one. */
/* First check for ones that we can't decode using streams */
@@ -271,7 +338,8 @@ standard_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h, int *l
native_l2factor -= *l2factor;
indexed = fz_colorspace_is_indexed(ctx, image->colorspace);
- tile = fz_decomp_image_from_stream(ctx, stm, image, indexed, native_l2factor);
+ can_sub = 1;
+ tile = fz_decomp_image_from_stream(ctx, stm, image, subarea, indexed, native_l2factor);
/* CMYK JPEGs in XPS documents have to be inverted */
if (image->invert_cmyk_jpeg &&
@@ -285,20 +353,63 @@ standard_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h, int *l
break;
}
+ if (can_sub == 0 && subarea != NULL)
+ {
+ subarea->x0 = 0;
+ subarea->y0 = 0;
+ subarea->x1 = image->w;
+ subarea->y1 = image->h;
+ }
+
return tile;
}
+static void
+update_ctm_for_subarea(fz_matrix *ctm, const fz_irect *subarea, int w, int h)
+{
+ fz_matrix m;
+
+ if (subarea->x0 == 0 && subarea->y0 == 0 && subarea->x1 == w && subarea->y1 == h)
+ return;
+
+ m.a = (subarea->x1 - subarea->x0) / (float)w;
+ m.b = 0;
+ m.c = 0;
+ m.d = (subarea->y1 - subarea->y0) / (float)h;
+ m.e = subarea->x0 / (float)w;
+ m.f = subarea->y0 / (float)h;
+ fz_concat(ctm, &m, ctm);
+}
+
fz_pixmap *
-fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, int w, int h)
+fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, const fz_irect *subarea, fz_matrix *ctm, int *dw, int *dh)
{
fz_pixmap *tile;
int l2factor, l2factor_remaining;
fz_image_key key;
fz_image_key *keyp;
+ int w;
+ int h;
if (!image)
return NULL;
+ /* Figure out the extent. */
+ if (ctm)
+ {
+ w = sqrtf(ctm->a * ctm->a + ctm->b * ctm->b);
+ if (w > image->w)
+ w = image->w;
+ h = sqrtf(ctm->c * ctm->c + ctm->d * ctm->d);
+ if (h > image->h)
+ w = image->h;
+ }
+ else
+ {
+ w = image->w;
+ h = image->h;
+ }
+
/* 'Simple' images created direct from pixmaps will have no buffer
* of compressed data. We cannot do any better than just returning
* a pointer to the original 'tile'.
@@ -307,13 +418,13 @@ fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, int w, int h)
* with masks applied, so we need both parts of the following test.
*/
if (image->buffer == NULL && image->tile != NULL)
+ {
+ if (dw)
+ *dw = w;
+ if (dh)
+ *dh = h;
return fz_keep_pixmap(ctx, image->tile); /* That's all we can give you! */
-
- /* Ensure our expectations for tile size are reasonable */
- if (w < 0 || w > image->w)
- w = image->w;
- if (h < 0 || h > image->h)
- h = image->h;
+ }
/* What is our ideal factor? We search for the largest factor where
* we can subdivide and stay larger than the required size. We add
@@ -324,6 +435,61 @@ fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, int w, int h)
else
for (l2factor=0; image->w>>(l2factor+1) >= w+2 && image->h>>(l2factor+1) >= h+2 && l2factor < 6; l2factor++);
+ /* Now figure out if we want to decode just a subarea */
+ if (subarea == NULL || (subarea->x1-subarea->x0)*(subarea->y1-subarea->y0) >= (image->w*image->h/10)*9)
+ {
+ /* Either no subarea specified, or a subarea 90% or more of the
+ * whole area specified. Use the whole image. */
+ key.rect.x0 = 0;
+ key.rect.y0 = 0;
+ key.rect.x1 = image->w;
+ key.rect.y1 = image->h;
+ }
+ else
+ {
+ /* Clip to the edges if they are within 1% */
+ key.rect = *subarea;
+ if (key.rect.x0 <= image->w/100)
+ key.rect.x0 = 0;
+ if (key.rect.y0 <= image->h/100)
+ key.rect.y0 = 0;
+ if (key.rect.x1 >= image->w*99/100)
+ key.rect.x1 = image->w;
+ if (key.rect.y1 >= image->h*99/100)
+ key.rect.y1 = image->h;
+ }
+
+ if (ctm)
+ {
+ float frac_w = (key.rect.x1 - key.rect.x0) / (float)image->w;
+ float frac_h = (key.rect.y1 - key.rect.y0) / (float)image->h;
+ float a = ctm->a * frac_w;
+ float b = ctm->b * frac_h;
+ float c = ctm->c * frac_w;
+ float d = ctm->d * frac_h;
+
+ w = sqrtf(a * a + b * b);
+ h = sqrtf(c * c + d * d);
+ }
+ else
+ {
+ w = image->w;
+ h = image->h;
+ }
+
+ /* Return the true sizes to the caller */
+ if (dw)
+ *dw = w;
+ if (dh)
+ *dh = h;
+ if (w > image->w)
+ w = image->w;
+ if (h > image->h)
+ h = image->h;
+
+ if (w == 0 || h == 0)
+ l2factor = 0;
+
/* Can we find any suitable tiles in the cache? */
key.refs = 1;
key.image = image;
@@ -332,7 +498,10 @@ fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, int w, int h)
{
tile = fz_find_item(ctx, fz_drop_pixmap_imp, &key, &fz_image_store_type);
if (tile)
+ {
+ update_ctm_for_subarea(ctm, &key.rect, image->w, image->h);
return tile;
+ }
key.l2factor--;
}
while (key.l2factor >= 0);
@@ -340,7 +509,10 @@ fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, int w, int h)
/* We'll have to decode the image; request the correct amount of
* downscaling. */
l2factor_remaining = l2factor;
- tile = image->get_pixmap(ctx, image, w, h, &l2factor_remaining);
+ tile = image->get_pixmap(ctx, image, &key.rect, w, h, &l2factor_remaining);
+
+ /* Update the ctm to allow for subareas. */
+ update_ctm_for_subarea(ctm, &key.rect, image->w, image->h);
/* l2factor_remaining is updated to the amount of subscaling left to do */
assert(l2factor_remaining >= 0 && l2factor_remaining <= 6);
@@ -360,6 +532,7 @@ fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, int w, int h)
keyp->refs = 1;
keyp->image = fz_keep_image(ctx, image);
keyp->l2factor = l2factor;
+ keyp->rect = key.rect;
existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type);
if (existing_tile)
{
diff --git a/source/fitz/pixmap.c b/source/fitz/pixmap.c
index 88e16d9d..fca6f733 100644
--- a/source/fitz/pixmap.c
+++ b/source/fitz/pixmap.c
@@ -1123,9 +1123,9 @@ png_from_pixmap(fz_context *ctx, fz_pixmap *pix, int drop)
}
fz_buffer *
-fz_new_buffer_from_image_as_png(fz_context *ctx, fz_image *image, int w, int h)
+fz_new_buffer_from_image_as_png(fz_context *ctx, fz_image *image)
{
- return png_from_pixmap(ctx, fz_get_pixmap_from_image(ctx, image, image->w, image->h), 1);
+ return png_from_pixmap(ctx, fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL), 1);
}
fz_buffer *
diff --git a/source/fitz/stext-output.c b/source/fitz/stext-output.c
index 1ba9fe51..70b0bf7e 100644
--- a/source/fitz/stext-output.c
+++ b/source/fitz/stext-output.c
@@ -258,7 +258,7 @@ fz_print_stext_page_html(fz_context *ctx, fz_output *out, fz_stext_page *page)
break;
default:
{
- fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, image->image, image->image->w, image->image->h);
+ fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, image->image);
fz_printf(ctx, out, "image/png;base64,");
send_data_base64(ctx, out, buf);
fz_drop_buffer(ctx, buf);
diff --git a/source/fitz/stream-read.c b/source/fitz/stream-read.c
index 2ebd5ad6..2ace7b1f 100644
--- a/source/fitz/stream-read.c
+++ b/source/fitz/stream-read.c
@@ -27,6 +27,26 @@ fz_read(fz_context *ctx, fz_stream *stm, unsigned char *buf, int len)
return count;
}
+static unsigned char skip_buf[4096];
+
+int fz_skip(fz_context *ctx, fz_stream *stm, int len)
+{
+ int count, l, total = 0;
+
+ while (len)
+ {
+ l = len;
+ if (l > sizeof(skip_buf))
+ l = sizeof(skip_buf);
+ count = fz_read(ctx, stm, skip_buf, l);
+ total += count;
+ if (count < l)
+ break;
+ len -= count;
+ }
+ return total;
+}
+
fz_buffer *
fz_read_all(fz_context *ctx, fz_stream *stm, int initial)
{
diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c
index d36a5872..5f60cf75 100644
--- a/source/fitz/svg-device.c
+++ b/source/fitz/svg-device.c
@@ -743,7 +743,7 @@ svg_dev_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
break;
default:
{
- fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, image, image->w, image->h);
+ fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, image);
fz_printf(ctx, out, "image/png;base64,");
send_data_base64(ctx, out, buf);
fz_drop_buffer(ctx, buf);
@@ -830,7 +830,7 @@ svg_dev_fill_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const
break;
default:
{
- fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, image, image->w, image->h);
+ fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, image);
fz_printf(ctx, out, "image/png;base64,");
send_data_base64(ctx, out, buf);
fz_drop_buffer(ctx, buf);
@@ -874,7 +874,7 @@ svg_dev_clip_image_mask(fz_context *ctx, fz_device *dev, fz_image *image, const
break;
default:
{
- fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, image, image->w, image->h);
+ fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, image);
fz_printf(ctx, out, "image/png;base64,");
send_data_base64(ctx, out, buf);
fz_drop_buffer(ctx, buf);
diff --git a/source/fitz/test-device.c b/source/fitz/test-device.c
index 64c7804f..6a4e0127 100644
--- a/source/fitz/test-device.c
+++ b/source/fitz/test-device.c
@@ -184,7 +184,7 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
return;
}
- pix = fz_get_pixmap_from_image(ctx, image, 0, 0);
+ pix = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0);
if (pix == NULL) /* Should never happen really, but... */
return;
diff --git a/source/gprf/gprf-doc.c b/source/gprf/gprf-doc.c
index d56501ba..d1dc4aa3 100644
--- a/source/gprf/gprf-doc.c
+++ b/source/gprf/gprf-doc.c
@@ -314,7 +314,7 @@ unsigned char undelta(unsigned char delta, unsigned char *ptr, int len)
}
static fz_pixmap *
-gprf_get_pixmap(fz_context *ctx, fz_image *image_, int w, int h, int *l2factor)
+gprf_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *area, int w, int h, int *l2factor)
{
/* The file contains RGB + up to FZ_MAX_SEPARATIONS. Hence the
* "3 + FZ_MAX_SEPARATIONS" usage in all the arrays below. */
@@ -332,6 +332,14 @@ gprf_get_pixmap(fz_context *ctx, fz_image *image_, int w, int h, int *l2factor)
fz_var(file);
+ if (area)
+ {
+ area->x0 = 0;
+ area->y0 = 0;
+ area->x1 = image->base.w;
+ area->y1 = image->base.h;
+ }
+
fz_try(ctx)
{
/* First off, figure out if we are doing RGB or separations
diff --git a/source/pdf/pdf-image.c b/source/pdf/pdf-image.c
index 04e1c1f0..e0da7ad9 100644
--- a/source/pdf/pdf-image.c
+++ b/source/pdf/pdf-image.c
@@ -330,7 +330,7 @@ pdf_add_image(fz_context *ctx, pdf_document *doc, fz_image *image, int mask)
/* Currently, set to maintain resolution; should we consider
* subsampling here according to desired output res? */
- pixmap = fz_get_pixmap_from_image(ctx, image, image->w, image->h);
+ pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL);
colorspace = pixmap->colorspace; /* May be different to image->colorspace! */
n = (pixmap->n == 1 ? 1 : pixmap->n - 1);
size = image->w * image->h * n;
diff --git a/source/pdf/pdf-resources.c b/source/pdf/pdf-resources.c
index 4fae6c87..212c57df 100644
--- a/source/pdf/pdf-resources.c
+++ b/source/pdf/pdf-resources.c
@@ -28,7 +28,7 @@ res_image_get_md5(fz_context *ctx, fz_image *image, unsigned char *digest)
fz_pixmap *pixmap;
fz_md5 state;
- pixmap = fz_get_pixmap_from_image(ctx, image, 0, 0);
+ pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0);
fz_md5_init(&state);
fz_md5_update(&state, pixmap->samples, pixmap->w * pixmap->h * pixmap->n);
fz_md5_final(&state, digest);
diff --git a/source/pdf/pdf-stream.c b/source/pdf/pdf-stream.c
index 1743a22c..3c275d2d 100644
--- a/source/pdf/pdf-stream.c
+++ b/source/pdf/pdf-stream.c
@@ -357,7 +357,7 @@ pdf_load_compressed_inline_image(fz_context *ctx, pdf_document *doc, pdf_obj *di
stm = fz_open_leecher(ctx, stm, bc->buffer);
stm = fz_open_image_decomp_stream(ctx, stm, &bc->params, &dummy_l2factor);
- image->tile = fz_decomp_image_from_stream(ctx, stm, image, indexed, 0);
+ image->tile = fz_decomp_image_from_stream(ctx, stm, image, NULL, indexed, 0);
}
fz_catch(ctx)
{
diff --git a/source/tools/murun.c b/source/tools/murun.c
index c2a9f0bc..6e6e2719 100644
--- a/source/tools/murun.c
+++ b/source/tools/murun.c
@@ -1881,12 +1881,10 @@ static void ffi_Image_toPixmap(js_State *J)
{
fz_context *ctx = js_getcontext(J);
fz_image *image = js_touserdata(J, 0, "fz_image");
- int w = js_isnumber(J, 1) ? js_tonumber(J, 1) : image->w;
- int h = js_isnumber(J, 2) ? js_tonumber(J, 2) : image->h;
fz_pixmap *pixmap = NULL;
fz_try(ctx)
- pixmap = fz_get_pixmap_from_image(ctx, image, w, h);
+ pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL);
fz_catch(ctx)
rethrow(J);
diff --git a/source/tools/pdfextract.c b/source/tools/pdfextract.c
index 74b3654e..3f79137a 100644
--- a/source/tools/pdfextract.c
+++ b/source/tools/pdfextract.c
@@ -72,7 +72,7 @@ static void saveimage(int num)
/* TODO: detect DCTD and save as jpeg */
image = pdf_load_image(ctx, doc, ref);
- pix = fz_get_pixmap_from_image(ctx, image, 0, 0);
+ pix = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0);
fz_drop_image(ctx, image);
snprintf(buf, sizeof(buf), "img-%04d", num);