summaryrefslogtreecommitdiff
path: root/pdf/pdf_image.c
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_image.c')
-rw-r--r--pdf/pdf_image.c377
1 files changed, 31 insertions, 346 deletions
diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c
index b6795456..1b6cebaf 100644
--- a/pdf/pdf_image.c
+++ b/pdf/pdf_image.c
@@ -1,313 +1,13 @@
#include "fitz-internal.h"
#include "mupdf-internal.h"
-typedef struct pdf_image_key_s pdf_image_key;
+static fz_image *pdf_load_jpx(pdf_document *xref, pdf_obj *dict, int forcemask);
-struct pdf_image_key_s {
- int refs;
- fz_image *image;
- int l2factor;
-};
-
-static void pdf_load_jpx(pdf_document *xref, pdf_obj *dict, pdf_image *image, int forcemask);
-
-static void
-pdf_mask_color_key(fz_pixmap *pix, int n, int *colorkey)
-{
- unsigned char *p = pix->samples;
- int len = pix->w * pix->h;
- int k, t;
- while (len--)
- {
- t = 1;
- for (k = 0; k < n; k++)
- if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1])
- t = 0;
- if (t)
- for (k = 0; k < pix->n; k++)
- p[k] = 0;
- p += pix->n;
- }
-}
-
-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->l2factor;
- 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->l2factor == k1->l2factor;
-}
-
-#ifndef NDEBUG
-static void
-pdf_debug_image(FILE *out, void *key_)
-{
- pdf_image_key *key = (pdf_image_key *)key_;
-
- fprintf(out, "(image %d x %d sf=%d) ", key->image->w, key->image->h, key->l2factor);
-}
-#endif
-
-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,
-#ifndef NDEBUG
- pdf_debug_image
-#endif
-};
-
-static fz_pixmap *
-decomp_image_from_stream(fz_context *ctx, fz_stream *stm, pdf_image *image, int in_line, int indexed, int l2factor, int native_l2factor, int cache)
-{
- fz_pixmap *tile = NULL;
- fz_pixmap *existing_tile;
- int stride, len, i;
- unsigned char *samples = NULL;
- int f = 1<<native_l2factor;
- int w = (image->base.w + f-1) >> native_l2factor;
- int h = (image->base.h + f-1) >> native_l2factor;
- pdf_image_key *key = NULL;
-
- fz_var(tile);
- fz_var(samples);
- fz_var(key);
-
- fz_try(ctx)
- {
- tile = fz_new_pixmap(ctx, image->base.colorspace, w, h);
- tile->interpolate = image->interpolate;
-
- stride = (w * image->n * image->base.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->base.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->base.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 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);
- }
-
- if (!cache)
- return tile;
-
- /* 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->l2factor = l2factor;
- 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);
- 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_free_compressed_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 l2factor;
- pdf_image_key key;
- int native_l2factor;
- int indexed;
-
- /* Check for 'simple' images which are just pixmaps */
- if (image->buffer == NULL)
- {
- tile = image->tile;
- if (!tile)
- return NULL;
- return fz_keep_pixmap(ctx, tile); /* That's all we can give you! */
- }
-
- /* Ensure our expectations for tile size are reasonable */
- if (w > image->base.w)
- w = image->base.w;
- if (h > image->base.h)
- h = image->base.h;
-
- /* What is our ideal factor? */
- if (w == 0 || h == 0)
- l2factor = 0;
- else
- for (l2factor=0; image->base.w>>(l2factor+1) >= w && image->base.h>>(l2factor+1) >= h && l2factor < 8; l2factor++);
-
- /* Can we find any suitable tiles in the cache? */
- key.refs = 1;
- key.image = &image->base;
- key.l2factor = l2factor;
- do
- {
- tile = fz_find_item(ctx, fz_free_pixmap_imp, &key, &pdf_image_store_type);
- if (tile)
- return tile;
- key.l2factor--;
- }
- while (key.l2factor >= 0);
-
- /* We need to make a new one. */
- native_l2factor = l2factor;
- stm = fz_open_image_decomp_stream(ctx, image->buffer, &native_l2factor);
-
- indexed = fz_colorspace_is_indexed(image->base.colorspace);
- return decomp_image_from_stream(ctx, stm, image, 0, indexed, l2factor, native_l2factor, 1);
-}
-
-static pdf_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;
- pdf_image *image = NULL;
+ fz_image *image = NULL;
pdf_obj *obj, *res;
int w, h, bpc, n;
@@ -315,22 +15,24 @@ pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *c
int interpolate;
int indexed;
fz_image *mask = NULL; /* explicit mask/soft mask image */
- int usecolorkey;
+ 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);
-
- image = fz_malloc_struct(ctx, pdf_image);
+ fz_var(image);
fz_try(ctx)
{
/* special case for JPEG2000 images */
if (pdf_is_jpx_image(ctx, dict))
{
- pdf_load_jpx(xref, dict, image, forcemask);
+ image = pdf_load_jpx(xref, dict, forcemask);
if (forcemask)
{
@@ -383,12 +85,12 @@ pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *c
obj = res;
}
- image->base.colorspace = pdf_load_colorspace(xref, obj);
+ colorspace = pdf_load_colorspace(xref, obj);
- if (!strcmp(image->base.colorspace->name, "Indexed"))
+ if (!strcmp(colorspace->name, "Indexed"))
indexed = 1;
- n = image->base.colorspace->n;
+ n = colorspace->n;
}
else
{
@@ -399,13 +101,13 @@ pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *c
if (obj)
{
for (i = 0; i < n * 2; i++)
- image->decode[i] = pdf_to_real(pdf_array_get(obj, 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++)
- image->decode[i] = i & 1 ? maxval : 0;
+ decode[i] = i & 1 ? maxval : 0;
}
obj = pdf_dict_getsa(dict, "SMask", "Mask");
@@ -429,35 +131,26 @@ pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *c
fz_warn(ctx, "invalid value in color key mask");
usecolorkey = 0;
}
- image->colorkey[i] = pdf_to_int(pdf_array_get(obj, i));
+ colorkey[i] = pdf_to_int(pdf_array_get(obj, i));
}
}
/* Now, do we load a ref, or do we load the actual thing? */
- 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->base.bpc = bpc;
- image->n = n;
- image->interpolate = interpolate;
- image->imagemask = imagemask;
- image->usecolorkey = usecolorkey;
- image->base.mask = mask;
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);
- image->buffer = pdf_load_compressed_stream(xref, num, gen);
+ 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 * image->n * image->base.bpc + 7) / 8;
+ int stride = (w * n * bpc + 7) / 8;
stm = pdf_open_inline_stream(xref, dict, stride * h, cstm, NULL);
}
else
@@ -465,11 +158,12 @@ pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *c
stm = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
}
- image->tile = decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 0, 0, 0);
+ 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)
{
- pdf_free_image(ctx, (fz_storable *) image);
+ fz_drop_image(ctx, image);
fz_rethrow(ctx);
}
return image;
@@ -497,8 +191,8 @@ pdf_is_jpx_image(fz_context *ctx, pdf_obj *dict)
return 0;
}
-static void
-pdf_load_jpx(pdf_document *xref, pdf_obj *dict, pdf_image *image, int forcemask)
+static fz_image *
+pdf_load_jpx(pdf_document *xref, pdf_obj *dict, int forcemask)
{
fz_buffer *buf = NULL;
fz_colorspace *colorspace = NULL;
@@ -506,10 +200,12 @@ pdf_load_jpx(pdf_document *xref, pdf_obj *dict, pdf_image *image, int forcemask)
pdf_obj *obj;
fz_context *ctx = xref->ctx;
int indexed = 0;
+ fz_image *mask = NULL;
fz_var(img);
fz_var(buf);
fz_var(colorspace);
+ fz_var(mask);
buf = pdf_load_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
@@ -537,7 +233,7 @@ pdf_load_jpx(pdf_document *xref, pdf_obj *dict, pdf_image *image, int forcemask)
if (forcemask)
fz_warn(ctx, "Ignoring recursive JPX soft mask");
else
- image->base.mask = (fz_image *)pdf_load_image_imp(xref, NULL, obj, NULL, 1);
+ mask = (fz_image *)pdf_load_image_imp(xref, NULL, obj, NULL, 1);
}
obj = pdf_dict_getsa(dict, "Decode", "D");
@@ -560,22 +256,11 @@ pdf_load_jpx(pdf_document *xref, pdf_obj *dict, pdf_image *image, int forcemask)
fz_drop_pixmap(ctx, img);
fz_rethrow(ctx);
}
- 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.bpc = 8;
- image->base.colorspace = colorspace;
- image->buffer = NULL;
- image->tile = img;
- image->n = img->n;
- image->interpolate = 0;
- image->imagemask = 0;
- image->usecolorkey = 0;
+ return fz_new_image_from_pixmap(ctx, img, mask);
}
static int
-pdf_image_size(fz_context *ctx, pdf_image *im)
+fz_image_size(fz_context *ctx, fz_image *im)
{
if (im == NULL)
return 0;
@@ -586,16 +271,16 @@ fz_image *
pdf_load_image(pdf_document *xref, pdf_obj *dict)
{
fz_context *ctx = xref->ctx;
- pdf_image *image;
+ fz_image *image;
- if ((image = pdf_find_item(ctx, pdf_free_image, dict)))
+ if ((image = pdf_find_item(ctx, fz_free_image, dict)))
{
return (fz_image *)image;
}
image = pdf_load_image_imp(xref, NULL, dict, NULL, 0);
- pdf_store_item(ctx, dict, image, pdf_image_size(ctx, image));
+ pdf_store_item(ctx, dict, image, fz_image_size(ctx, image));
return (fz_image *)image;
}