diff options
author | Robin Watts <robin.watts@artifex.com> | 2014-02-10 16:29:44 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2014-02-10 16:58:29 +0000 |
commit | 9b9438fa4210b29023f85bb98c73f8f58a7760d5 (patch) | |
tree | fe99bd7f35ff42cbdf416c5d576c3d23379f3cc8 /source/fitz/load-tiff.c | |
parent | addbdd3bc39e3ed07259706e896f275a9f35ae9e (diff) | |
download | mupdf-9b9438fa4210b29023f85bb98c73f8f58a7760d5.tar.xz |
Bug 695022: Add support for multuple image tiff files.
Patch from Thomas Fach-Pedersen. Many Thanks.
Diffstat (limited to 'source/fitz/load-tiff.c')
-rw-r--r-- | source/fitz/load-tiff.c | 103 |
1 files changed, 93 insertions, 10 deletions
diff --git a/source/fitz/load-tiff.c b/source/fitz/load-tiff.c index 2850e278..a9325f18 100644 --- a/source/fitz/load-tiff.c +++ b/source/fitz/load-tiff.c @@ -19,6 +19,9 @@ struct tiff /* byte order */ unsigned order; + /* offset of first ifd */ + unsigned ifd_offset; + /* where we can find the strips of image data */ unsigned rowsperstrip; unsigned *stripoffsets; @@ -696,7 +699,7 @@ fz_read_tiff_tag(struct tiff *tiff, unsigned offset) fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "tiled tiffs not supported"); default: - /* printf("unknown tag: %d t=%d n=%d\n", tag, type, count); */ + /* fz_warn(tiff->ctx, "unknown tag: %d t=%d n=%d", tag, type, count); */ break; } } @@ -717,9 +720,6 @@ static void fz_decode_tiff_header(fz_context *ctx, struct tiff *tiff, unsigned char *buf, int len) { unsigned version; - unsigned offset; - unsigned count; - unsigned i; memset(tiff, 0, sizeof(struct tiff)); tiff->ctx = ctx; @@ -756,16 +756,57 @@ fz_decode_tiff_header(fz_context *ctx, struct tiff *tiff, unsigned char *buf, in fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "not a TIFF file, wrong version marker"); /* get offset of IFD */ + tiff->ifd_offset = readlong(tiff); +} + +static unsigned +fz_next_ifd(fz_context *ctx, struct tiff *tiff, unsigned offset) +{ + unsigned count; + + tiff->rp = tiff->bp + offset; + + if (tiff->rp <= tiff->bp || tiff->rp > tiff->ep) + fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "invalid IFD offset %u", offset); + + count = readshort(tiff); + + if (count * 12 > (unsigned)(tiff->ep - tiff->rp)) + fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "overlarge IFD entry count %u", count); + + tiff->rp += count * 12; offset = readlong(tiff); - /* - * Read IFD - */ + return offset; +} + +static void +fz_seek_ifd(fz_context *ctx, struct tiff *tiff, int subimage) +{ + unsigned offset = tiff->ifd_offset; + + while (subimage--) + { + offset = fz_next_ifd(ctx, tiff, offset); + + if (offset == 0) + fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "subimage index %i out of range", subimage); + } tiff->rp = tiff->bp + offset; if (tiff->rp < tiff->bp || tiff->rp > tiff->ep) - fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "invalid IFD offset %u", offset); + fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "invalid IFD offset %u", tiff->ifd_offset); +} + +static void +fz_decode_tiff_ifd(fz_context *ctx, struct tiff *tiff) +{ + unsigned offset; + unsigned count; + unsigned i; + + offset = tiff->rp - tiff->bp; count = readshort(tiff); @@ -781,7 +822,7 @@ fz_decode_tiff_header(fz_context *ctx, struct tiff *tiff, unsigned char *buf, in } fz_pixmap * -fz_load_tiff(fz_context *ctx, unsigned char *buf, int len) +fz_load_tiff_subimage(fz_context *ctx, unsigned char *buf, int len, int subimage) { fz_pixmap *image; struct tiff tiff = { 0 }; @@ -789,6 +830,8 @@ fz_load_tiff(fz_context *ctx, unsigned char *buf, int len) fz_try(ctx) { fz_decode_tiff_header(ctx, &tiff, buf, len); + fz_seek_ifd(ctx, &tiff, subimage); + fz_decode_tiff_ifd(ctx, &tiff); /* Decode the image strips */ @@ -842,14 +885,22 @@ fz_load_tiff(fz_context *ctx, unsigned char *buf, int len) return image; } +fz_pixmap * +fz_load_tiff(fz_context *ctx, unsigned char *buf, int len) +{ + return fz_load_tiff_subimage(ctx, buf, len, 0); +} + void -fz_load_tiff_info(fz_context *ctx, unsigned char *buf, int len, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep) +fz_load_tiff_info_subimage(fz_context *ctx, unsigned char *buf, int len, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep, int subimage) { struct tiff tiff = { 0 }; fz_try(ctx) { fz_decode_tiff_header(ctx, &tiff, buf, len); + fz_seek_ifd(ctx, &tiff, subimage); + fz_decode_tiff_ifd(ctx, &tiff); *wp = tiff.imagewidth; *hp = tiff.imagelength; @@ -871,3 +922,35 @@ fz_load_tiff_info(fz_context *ctx, unsigned char *buf, int len, int *wp, int *hp fz_rethrow_message(ctx, "out of memory loading tiff"); } } + +void +fz_load_tiff_info(fz_context *ctx, unsigned char *buf, int len, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep) +{ + fz_load_tiff_info_subimage(ctx, buf, len, wp, hp, xresp, yresp, cspacep, 0); +} + +int +fz_load_tiff_subimage_count(fz_context *ctx, unsigned char *buf, int len) +{ + unsigned offset; + unsigned subimage_count = 0; + struct tiff tiff = { 0 }; + + fz_try(ctx) + { + fz_decode_tiff_header(ctx, &tiff, buf, len); + + offset = tiff.ifd_offset; + + do { + subimage_count++; + offset = fz_next_ifd(ctx, &tiff, offset); + } while (offset != 0); + } + fz_catch(ctx) + { + fz_rethrow_message(ctx, "error while counting subimages in tiff"); + } + + return subimage_count; +} |