summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2015-06-26 18:45:26 +0100
committerRobin Watts <robin.watts@artifex.com>2015-06-29 12:15:18 +0100
commit2bb213c70d42e398ef7ea3b6551c8fbb865cf3bd (patch)
tree450c7583241f2236c82fb8ae5bedbb1c0d664ec3
parent051b4932219bed310e17505b2e73029d371a18ce (diff)
downloadmupdf-2bb213c70d42e398ef7ea3b6551c8fbb865cf3bd.tar.xz
Further tweaks to fz_image handling.
Ensure that subsampling and caching happen in the generic image code, not in the specific. Previously, the subsampling happened only for images that were decoded from streams. Images that were loaded direct were never subsampled and hence were always cached at full size. After this change both classes of image are correctly subsampled, and the subsampled version kept in the cache. This produces various image diffs in the cluster, none of which are noticable to the naked eye.
-rw-r--r--include/mupdf/fitz/image.h4
-rw-r--r--source/fitz/compressed-buffer.c23
-rw-r--r--source/fitz/image.c104
-rw-r--r--source/pdf/pdf-stream.c2
4 files changed, 68 insertions, 65 deletions
diff --git a/include/mupdf/fitz/image.h b/include/mupdf/fitz/image.h
index 9c9a9ac4..c788dad3 100644
--- a/include/mupdf/fitz/image.h
+++ b/include/mupdf/fitz/image.h
@@ -58,7 +58,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_pixmap *fz_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h);
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, int native_l2factor);
+fz_pixmap *fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, int indexed, int l2factor);
fz_pixmap *fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src);
struct fz_image_s
@@ -67,7 +67,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 *, int w, int h, int *l2factor);
int colorkey[FZ_MAX_COLORS * 2];
float decode[FZ_MAX_COLORS * 2];
int imagemask;
diff --git a/source/fitz/compressed-buffer.c b/source/fitz/compressed-buffer.c
index d1c73351..2c5dd93f 100644
--- a/source/fitz/compressed-buffer.c
+++ b/source/fitz/compressed-buffer.c
@@ -24,11 +24,11 @@ fz_open_image_decomp_stream_from_buffer(fz_context *ctx, fz_compressed_buffer *b
fz_stream *
fz_open_image_decomp_stream(fz_context *ctx, fz_stream *chain, fz_compression_params *params, int *l2factor)
{
+ int our_l2factor = 0;
+
switch (params->type)
{
case FZ_IMAGE_FAX:
- if (l2factor)
- *l2factor = 0;
return fz_open_faxd(ctx, chain,
params->u.fax.k,
params->u.fax.end_of_line,
@@ -38,30 +38,27 @@ fz_open_image_decomp_stream(fz_context *ctx, fz_stream *chain, fz_compression_pa
params->u.fax.end_of_block,
params->u.fax.black_is_1);
case FZ_IMAGE_JPEG:
- if (l2factor && *l2factor > 3)
- *l2factor = 3;
- return fz_open_dctd(ctx, chain, params->u.jpeg.color_transform, l2factor ? *l2factor : 0, NULL);
- case FZ_IMAGE_RLD:
if (l2factor)
- *l2factor = 0;
+ {
+ our_l2factor = *l2factor;
+ if (our_l2factor > 3)
+ our_l2factor = 3;
+ *l2factor -= our_l2factor;
+ }
+ return fz_open_dctd(ctx, chain, params->u.jpeg.color_transform, our_l2factor, NULL);
+ case FZ_IMAGE_RLD:
return fz_open_rld(ctx, chain);
case FZ_IMAGE_FLATE:
- if (l2factor)
- *l2factor = 0;
chain = fz_open_flated(ctx, chain, 15);
if (params->u.flate.predictor > 1)
chain = fz_open_predict(ctx, chain, params->u.flate.predictor, params->u.flate.columns, params->u.flate.colors, params->u.flate.bpc);
return chain;
case FZ_IMAGE_LZW:
- if (l2factor)
- *l2factor = 0;
chain = fz_open_lzwd(ctx, chain, params->u.lzw.early_change);
if (params->u.lzw.predictor > 1)
chain = fz_open_predict(ctx, chain, params->u.lzw.predictor, params->u.lzw.columns, params->u.lzw.colors, params->u.lzw.bpc);
return chain;
default:
- if (l2factor)
- *l2factor = 0;
break;
}
diff --git a/source/fitz/image.c b/source/fitz/image.c
index 0cf06b33..3c7e7c0e 100644
--- a/source/fitz/image.c
+++ b/source/fitz/image.c
@@ -134,14 +134,14 @@ 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, int native_l2factor)
+fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, int indexed, int l2factor)
{
fz_pixmap *tile = NULL;
int stride, len, i;
unsigned char *samples = NULL;
- int f = 1<<native_l2factor;
- int w = (image->w + f-1) >> native_l2factor;
- int h = (image->h + f-1) >> native_l2factor;
+ int f = 1<<l2factor;
+ int w = (image->w + f-1) >> l2factor;
+ int h = (image->h + f-1) >> l2factor;
fz_var(tile);
fz_var(samples);
@@ -213,14 +213,6 @@ fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, in
fz_rethrow(ctx);
}
- /* Now apply any extra subsampling required */
- if (l2factor - native_l2factor > 0)
- {
- if (l2factor - native_l2factor > 8)
- l2factor = native_l2factor + 8;
- fz_subsample_pixmap(ctx, tile, l2factor - native_l2factor);
- }
-
return tile;
}
@@ -239,12 +231,11 @@ 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, int w, int h, int *l2factor)
{
- fz_stream *stm;
int native_l2factor;
+ fz_stream *stm;
int indexed;
- fz_image_key *keyp;
fz_pixmap *tile;
/* We need to make a new one. */
@@ -280,11 +271,13 @@ standard_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h, int l2
/* fall through */
default:
- native_l2factor = l2factor;
- stm = fz_open_image_decomp_stream_from_buffer(ctx, image->buffer, &native_l2factor);
+ native_l2factor = l2factor ? *l2factor : 0;
+ stm = fz_open_image_decomp_stream_from_buffer(ctx, image->buffer, l2factor);
+ if (l2factor)
+ native_l2factor -= *l2factor;
indexed = fz_colorspace_is_indexed(ctx, image->colorspace);
- tile = fz_decomp_image_from_stream(ctx, stm, image, indexed, l2factor, native_l2factor);
+ tile = fz_decomp_image_from_stream(ctx, stm, image, indexed, native_l2factor);
/* CMYK JPEGs in XPS documents have to be inverted */
if (image->invert_cmyk_jpeg &&
@@ -298,35 +291,6 @@ standard_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h, int l2
break;
}
- /* Now we try to cache the pixmap. Any failure here will just result
- * in us not caching. */
- fz_var(keyp);
- fz_try(ctx)
- {
- fz_pixmap *existing_tile;
-
- keyp = fz_malloc_struct(ctx, fz_image_key);
- keyp->refs = 1;
- keyp->image = fz_keep_image(ctx, image);
- keyp->l2factor = l2factor;
- existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type);
- if (existing_tile)
- {
- /* We already have a tile. This must have been produced by a
- * racing thread. We'll throw away ours and use that one. */
- fz_drop_pixmap(ctx, tile);
- tile = existing_tile;
- }
- }
- fz_always(ctx)
- {
- fz_drop_image_key(ctx, keyp);
- }
- fz_catch(ctx)
- {
- /* Do nothing */
- }
-
return tile;
}
@@ -334,8 +298,9 @@ fz_pixmap *
fz_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h)
{
fz_pixmap *tile;
- int l2factor;
+ int l2factor, l2factor_remaining;
fz_image_key key;
+ fz_image_key *keyp;
/* Check for 'simple' images which are just pixmaps */
if (image->buffer == NULL)
@@ -374,7 +339,48 @@ fz_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h)
}
while (key.l2factor >= 0);
- return image->get_pixmap(ctx, image, w, h, l2factor);
+ /* 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);
+
+ /* l2factor_remaining is updated to the amount of subscaling left to do */
+ assert(l2factor_remaining >= 0 && l2factor_remaining < 8);
+ if (l2factor_remaining)
+ {
+ fz_subsample_pixmap(ctx, tile, l2factor_remaining);
+ }
+
+ /* Now we try to cache the pixmap. Any failure here will just result
+ * in us not caching. */
+ fz_var(keyp);
+ fz_try(ctx)
+ {
+ fz_pixmap *existing_tile;
+
+ keyp = fz_malloc_struct(ctx, fz_image_key);
+ keyp->refs = 1;
+ keyp->image = fz_keep_image(ctx, image);
+ keyp->l2factor = l2factor;
+ existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type);
+ if (existing_tile)
+ {
+ /* We already have a tile. This must have been produced by a
+ * racing thread. We'll throw away ours and use that one. */
+ fz_drop_pixmap(ctx, tile);
+ tile = existing_tile;
+ }
+ }
+ fz_always(ctx)
+ {
+ fz_drop_image_key(ctx, keyp);
+ }
+ fz_catch(ctx)
+ {
+ /* Do nothing */
+ }
+
+ return tile;
}
fz_image *
diff --git a/source/pdf/pdf-stream.c b/source/pdf/pdf-stream.c
index 32440266..4636a1a7 100644
--- a/source/pdf/pdf-stream.c
+++ b/source/pdf/pdf-stream.c
@@ -349,7 +349,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, 0);
+ image->tile = fz_decomp_image_from_stream(ctx, stm, image, indexed, 0);
}
fz_catch(ctx)
{