summaryrefslogtreecommitdiff
path: root/source/fitz/load-tiff.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2014-02-10 16:29:44 +0000
committerRobin Watts <robin.watts@artifex.com>2014-02-10 16:58:29 +0000
commit9b9438fa4210b29023f85bb98c73f8f58a7760d5 (patch)
treefe99bd7f35ff42cbdf416c5d576c3d23379f3cc8 /source/fitz/load-tiff.c
parentaddbdd3bc39e3ed07259706e896f275a9f35ae9e (diff)
downloadmupdf-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.c103
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;
+}