summaryrefslogtreecommitdiff
path: root/source/fitz/load-tiff.c
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@gmail.com>2016-09-25 14:52:20 +0800
committerSebastian Rasmussen <sebras@gmail.com>2016-09-26 19:06:35 +0800
commit3059b6908208fbb9547e6876332a5b42a6406d1a (patch)
tree14008e2df606a7d143b48d0e142d38c91c7c224e /source/fitz/load-tiff.c
parentb70ce7de2b8ed37f7bd4fa01bb95b45a79c502e7 (diff)
downloadmupdf-3059b6908208fbb9547e6876332a5b42a6406d1a.tar.xz
tiff: Reorganize code, preparing for tiled image support.
Diffstat (limited to 'source/fitz/load-tiff.c')
-rw-r--r--source/fitz/load-tiff.c394
1 files changed, 207 insertions, 187 deletions
diff --git a/source/fitz/load-tiff.c b/source/fitz/load-tiff.c
index 87e350f0..2ead2e28 100644
--- a/source/fitz/load-tiff.c
+++ b/source/fitz/load-tiff.c
@@ -24,12 +24,11 @@ struct tiff
unsigned rowsperstrip;
unsigned *stripoffsets;
unsigned *stripbytecounts;
+ unsigned stripoffsetslen;
+ unsigned stripbytecountslen;
/* colormap */
unsigned *colormap;
-
- unsigned stripoffsetslen;
- unsigned stripbytecountslen;
unsigned colormaplen;
/* assorted tags */
@@ -368,105 +367,104 @@ fz_expand_tiff_colormap(fz_context *ctx, struct tiff *tiff)
}
static void
-fz_decode_tiff_strips(fz_context *ctx, struct tiff *tiff)
+fz_decode_tiff_chunk(fz_context *ctx, struct tiff *tiff, unsigned char *rp, unsigned int rlen, unsigned char *wp, unsigned int wlen)
{
fz_stream *stm;
+ unsigned i;
+
+ if (rp + rlen > tiff->ep)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "strip extends beyond the end of the file");
+
+ /* the bits are in un-natural order */
+ if (tiff->fillorder == 2)
+ for (i = 0; i < rlen; i++)
+ rp[i] = bitrev[rp[i]];
+
+ /* each decoder will close this */
+ /* FIXME: what if tiff->compression is invalid? what if fz_read() in the strip decoders throws? */
+ stm = fz_open_memory(ctx, rp, rlen);
/* switch on compression to create a filter */
- /* feed each strip to the filter */
- /* read out the data and pack the samples into a pixmap */
+ /* feed each chunk (strip or tile) to the filter */
+ /* read out the data into a buffer */
+ /* the level above packs the chunk's samples into a pixmap */
/* type 32773 / packbits -- nothing special (same row-padding as PDF) */
/* type 2 / ccitt rle -- no EOL, no RTC, rows are byte-aligned */
/* type 3 and 4 / g3 and g4 -- each strip starts new section */
/* type 5 / lzw -- each strip is handled separately */
- unsigned char *wp;
- unsigned row;
- unsigned strip;
- unsigned i;
-
- if (!tiff->rowsperstrip || !tiff->stripoffsets || !tiff->stripbytecounts)
- fz_throw(ctx, FZ_ERROR_GENERIC, "no image data in tiff; maybe it is tiled");
-
- if (tiff->stripoffsetslen < (tiff->imagelength - 1) / tiff->rowsperstrip + 1 ||
- tiff->stripbytecountslen < (tiff->imagelength - 1) / tiff->rowsperstrip + 1)
- fz_throw(ctx, FZ_ERROR_GENERIC, "insufficient strip offset data");
-
- if (tiff->planar != 1)
- fz_throw(ctx, FZ_ERROR_GENERIC, "image data is not in chunky format");
-
- if (tiff->imagelength > UINT_MAX / tiff->imagewidth / (tiff->samplesperpixel + 2) / (tiff->bitspersample / 8 + 1))
- fz_throw(ctx, FZ_ERROR_GENERIC, "image dimensions might overflow");
-
- tiff->stride = (tiff->imagewidth * tiff->samplesperpixel * tiff->bitspersample + 7) / 8;
-
- switch (tiff->photometric)
+ switch (tiff->compression)
{
- case 0: /* WhiteIsZero -- inverted */
- tiff->colorspace = fz_device_gray(ctx);
+ case 1:
+ fz_decode_tiff_uncompressed(ctx, tiff, stm, wp, wlen);
break;
- case 1: /* BlackIsZero */
- tiff->colorspace = fz_device_gray(ctx);
+ case 2:
+ fz_decode_tiff_fax(ctx, tiff, 2, stm, wp, wlen);
break;
- case 2: /* RGB */
- tiff->colorspace = fz_device_rgb(ctx);
+ case 3:
+ fz_decode_tiff_fax(ctx, tiff, 3, stm, wp, wlen);
break;
- case 3: /* RGBPal */
- tiff->colorspace = fz_device_rgb(ctx);
+ case 4:
+ fz_decode_tiff_fax(ctx, tiff, 4, stm, wp, wlen);
break;
- case 5: /* CMYK */
- tiff->colorspace = fz_device_cmyk(ctx);
+ case 5:
+ fz_decode_tiff_lzw(ctx, tiff, stm, wp, wlen, (rp[0] == 0 && rp[1] & 1));
break;
- case 6: /* YCbCr */
- /* it's probably a jpeg ... we let jpeg convert to rgb */
- tiff->colorspace = fz_device_rgb(ctx);
+ case 6:
+ fz_warn(ctx, "deprecated JPEG in TIFF compression not fully supported");
+ /* fall through */
+ case 7:
+ fz_decode_tiff_jpeg(ctx, tiff, stm, wp, wlen);
break;
- case 8: /* 1976 CIE L*a*b* */
- tiff->colorspace = fz_device_lab(ctx);
+ case 8:
+ case 32946:
+ fz_decode_tiff_flate(ctx, tiff, stm, wp, wlen);
break;
- case 32844: /* SGI CIE Log 2 L (16bpp Greyscale) */
- tiff->colorspace = fz_device_gray(ctx);
- tiff->bitspersample = 8;
- tiff->stride >>= 1;
+ case 32773:
+ fz_decode_tiff_packbits(ctx, tiff, stm, wp, wlen);
break;
- case 32845: /* SGI CIE Log 2 L, u, v (24bpp or 32bpp) */
- tiff->colorspace = fz_device_rgb(ctx);
- tiff->bitspersample = 8;
- tiff->stride >>= 1;
+ case 34676:
+ if (tiff->photometric == 32845)
+ fz_decode_tiff_sgilog32(ctx, tiff, stm, wp, wlen, tiff->imagewidth);
+ else
+ fz_decode_tiff_sgilog16(ctx, tiff, stm, wp, wlen, tiff->imagewidth);
break;
- default:
- fz_throw(ctx, FZ_ERROR_GENERIC, "unknown photometric: %d", tiff->photometric);
- }
-
- switch (tiff->resolutionunit)
- {
- case 2:
- /* no unit conversion needed */
+ case 34677:
+ fz_decode_tiff_sgilog24(ctx, tiff, stm, wp, wlen, tiff->imagewidth);
break;
- case 3:
- tiff->xresolution = tiff->xresolution * 254 / 100;
- tiff->yresolution = tiff->yresolution * 254 / 100;
+ case 32809:
+ if (tiff->bitspersample != 4)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "invalid bits per pixel in thunder encoding");
+ fz_decode_tiff_thunder(ctx, tiff, stm, wp, wlen, tiff->imagewidth);
break;
default:
- tiff->xresolution = 96;
- tiff->yresolution = 96;
- break;
+ fz_throw(ctx, FZ_ERROR_GENERIC, "unknown TIFF compression: %d", tiff->compression);
}
- /* Note xres and yres could be 0 even if unit was set. If so default to 96dpi. */
- if (tiff->xresolution == 0 || tiff->yresolution == 0)
- {
- tiff->xresolution = 96;
- tiff->yresolution = 96;
- }
+ /* scramble the bits back into original order */
+ if (tiff->fillorder == 2)
+ for (i = 0; i < rlen; i++)
+ rp[i] = bitrev[rp[i]];
+
+}
+
+static void
+fz_decode_tiff_strips(fz_context *ctx, struct tiff *tiff)
+{
+ unsigned char *wp;
+ unsigned y;
+ unsigned strip;
+ unsigned strips;
+
+ strips = (tiff->imagelength + tiff->rowsperstrip - 1) / tiff->rowsperstrip;
+ if (tiff->stripoffsetslen < strips || tiff->stripbytecountslen < strips)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "insufficient strip metadata");
- tiff->samples = fz_malloc_array(ctx, tiff->imagelength, tiff->stride);
- memset(tiff->samples, 0x55, tiff->imagelength * tiff->stride);
wp = tiff->samples;
strip = 0;
- for (row = 0; row < tiff->imagelength; row += tiff->rowsperstrip)
+ for (y = 0; y < tiff->imagelength; y += tiff->rowsperstrip)
{
unsigned offset = tiff->stripoffsets[strip];
unsigned rlen = tiff->stripbytecounts[strip];
@@ -476,113 +474,12 @@ fz_decode_tiff_strips(fz_context *ctx, struct tiff *tiff)
if (wp + wlen > tiff->samples + (unsigned int)(tiff->stride * tiff->imagelength))
wlen = tiff->samples + (unsigned int)(tiff->stride * tiff->imagelength) - wp;
- if (rp + rlen > tiff->ep)
- fz_throw(ctx, FZ_ERROR_GENERIC, "strip extends beyond the end of the file");
-
- /* the bits are in un-natural order */
- if (tiff->fillorder == 2)
- for (i = 0; i < rlen; i++)
- rp[i] = bitrev[rp[i]];
-
- /* the strip decoders will close this */
- stm = fz_open_memory(ctx, rp, rlen);
-
- switch (tiff->compression)
- {
- case 1:
- fz_decode_tiff_uncompressed(ctx, tiff, stm, wp, wlen);
- break;
- case 2:
- fz_decode_tiff_fax(ctx, tiff, 2, stm, wp, wlen);
- break;
- case 3:
- fz_decode_tiff_fax(ctx, tiff, 3, stm, wp, wlen);
- break;
- case 4:
- fz_decode_tiff_fax(ctx, tiff, 4, stm, wp, wlen);
- break;
- case 5:
- fz_decode_tiff_lzw(ctx, tiff, stm, wp, wlen, (rp[0] == 0 && rp[1] & 1));
- break;
- case 6:
- fz_warn(ctx, "deprecated JPEG in TIFF compression not fully supported");
- /* fall through */
- case 7:
- fz_decode_tiff_jpeg(ctx, tiff, stm, wp, wlen);
- break;
- case 8:
- case 32946:
- fz_decode_tiff_flate(ctx, tiff, stm, wp, wlen);
- break;
- case 32773:
- fz_decode_tiff_packbits(ctx, tiff, stm, wp, wlen);
- break;
- case 34676:
- if (tiff->photometric == 32845)
- fz_decode_tiff_sgilog32(ctx, tiff, stm, wp, wlen, tiff->imagewidth);
- else
- fz_decode_tiff_sgilog16(ctx, tiff, stm, wp, wlen, tiff->imagewidth);
- break;
- case 34677:
- fz_decode_tiff_sgilog24(ctx, tiff, stm, wp, wlen, tiff->imagewidth);
- break;
- case 32809:
- if (tiff->bitspersample != 4)
- fz_throw(ctx, FZ_ERROR_GENERIC, "invalid bits per pixel in thunder encoding");
- fz_decode_tiff_thunder(ctx, tiff, stm, wp, wlen, tiff->imagewidth);
- break;
- default:
- fz_throw(ctx, FZ_ERROR_GENERIC, "unknown TIFF compression: %d", tiff->compression);
- }
-
- /* scramble the bits back into original order */
- if (tiff->fillorder == 2)
- for (i = 0; i < rlen; i++)
- rp[i] = bitrev[rp[i]];
+ fz_decode_tiff_chunk(ctx, tiff, rp, rlen, wp, wlen);
- wp += tiff->stride * tiff->rowsperstrip;
+ wp += wlen;
strip ++;
}
- /* Predictor (only for LZW and Flate) */
- if ((tiff->compression == 5 || tiff->compression == 8 || tiff->compression == 32946) && tiff->predictor == 2)
- {
- unsigned char *p = tiff->samples;
- for (i = 0; i < tiff->imagelength; i++)
- {
- fz_unpredict_tiff(p, tiff->imagewidth, tiff->samplesperpixel, tiff->bitspersample);
- p += tiff->stride;
- }
- }
-
- /* RGBPal */
- if (tiff->photometric == 3 && tiff->colormap)
- fz_expand_tiff_colormap(ctx, tiff);
-
- /* WhiteIsZero .. invert */
- if (tiff->photometric == 0)
- {
- unsigned char *p = tiff->samples;
- for (i = 0; i < tiff->imagelength; i++)
- {
- fz_invert_tiff(p, tiff->imagewidth, tiff->samplesperpixel, tiff->bitspersample, tiff->extrasamples);
- p += tiff->stride;
- }
- }
-
- /* Premultiplied transparency */
- if (tiff->extrasamples == 1)
- {
- /* In GhostXPS we undo the premultiplication here; muxps holds
- * all our images premultiplied by default, so nothing to do.
- */
- }
-
- /* Non-premultiplied transparency */
- if (tiff->extrasamples == 2)
- {
- /* Premultiplied files are corrected for elsewhere */
- }
}
static inline int readbyte(struct tiff *tiff)
@@ -761,6 +658,7 @@ fz_read_tiff_tag(fz_context *ctx, struct tiff *tiff, unsigned offset)
case TileOffsets:
case TileByteCounts:
fz_throw(ctx, FZ_ERROR_GENERIC, "tiled tiffs not supported");
+ break;
default:
/* fz_warn(ctx, "unknown tag: %d t=%d n=%d", tag, type, count); */
@@ -883,6 +781,137 @@ fz_decode_tiff_ifd(fz_context *ctx, struct tiff *tiff)
}
}
+static void
+fz_decode_tiff_samples(fz_context *ctx, struct tiff *tiff)
+{
+ unsigned i;
+
+ if (tiff->imagelength > UINT_MAX / tiff->imagewidth / (tiff->samplesperpixel + 2) / (tiff->bitspersample / 8 + 1))
+ fz_throw(ctx, FZ_ERROR_GENERIC, "image dimensions might overflow");
+
+ if (tiff->planar != 1)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "image data is not in chunky format");
+
+ tiff->stride = (tiff->imagewidth * tiff->samplesperpixel * tiff->bitspersample + 7) / 8;
+
+ switch (tiff->photometric)
+ {
+ case 0: /* WhiteIsZero -- inverted */
+ tiff->colorspace = fz_device_gray(ctx);
+ break;
+ case 1: /* BlackIsZero */
+ tiff->colorspace = fz_device_gray(ctx);
+ break;
+ case 2: /* RGB */
+ tiff->colorspace = fz_device_rgb(ctx);
+ break;
+ case 3: /* RGBPal */
+ tiff->colorspace = fz_device_rgb(ctx);
+ break;
+ case 5: /* CMYK */
+ tiff->colorspace = fz_device_cmyk(ctx);
+ break;
+ case 6: /* YCbCr */
+ /* it's probably a jpeg ... we let jpeg convert to rgb */
+ tiff->colorspace = fz_device_rgb(ctx);
+ break;
+ case 8: /* 1976 CIE L*a*b* */
+ tiff->colorspace = fz_device_lab(ctx);
+ break;
+ case 32844: /* SGI CIE Log 2 L (16bpp Greyscale) */
+ tiff->colorspace = fz_device_gray(ctx);
+ if (tiff->bitspersample != 8)
+ tiff->bitspersample = 8;
+ tiff->stride >>= 1;
+ break;
+ case 32845: /* SGI CIE Log 2 L, u, v (24bpp or 32bpp) */
+ tiff->colorspace = fz_device_rgb(ctx);
+ if (tiff->bitspersample != 8)
+ tiff->bitspersample = 8;
+ tiff->stride >>= 1;
+ break;
+ default:
+ fz_throw(ctx, FZ_ERROR_GENERIC, "unknown photometric: %d", tiff->photometric);
+ }
+
+ switch (tiff->resolutionunit)
+ {
+ case 2:
+ /* no unit conversion needed */
+ break;
+ case 3:
+ tiff->xresolution = tiff->xresolution * 254 / 100;
+ tiff->yresolution = tiff->yresolution * 254 / 100;
+ break;
+ default:
+ tiff->xresolution = 96;
+ tiff->yresolution = 96;
+ break;
+ }
+
+ /* Note xres and yres could be 0 even if unit was set. If so default to 96dpi. */
+ if (tiff->xresolution == 0 || tiff->yresolution == 0)
+ {
+ tiff->xresolution = 96;
+ tiff->yresolution = 96;
+ }
+
+ tiff->samples = fz_malloc_array(ctx, tiff->imagelength, tiff->stride);
+ memset(tiff->samples, 0x55, tiff->imagelength * tiff->stride);
+
+ if (tiff->rowsperstrip > tiff->imagelength)
+ tiff->rowsperstrip = tiff->imagelength;
+
+ if (tiff->rowsperstrip && tiff->stripoffsets && tiff->stripbytecounts)
+ fz_decode_tiff_strips(ctx, tiff);
+ else
+ fz_throw(ctx, FZ_ERROR_GENERIC, "image is missing strip data");
+
+ /* Predictor (only for LZW and Flate) */
+ if ((tiff->compression == 5 || tiff->compression == 8 || tiff->compression == 32946) && tiff->predictor == 2)
+ {
+ unsigned char *p = tiff->samples;
+ for (i = 0; i < tiff->imagelength; i++)
+ {
+ fz_unpredict_tiff(p, tiff->imagewidth, tiff->samplesperpixel, tiff->bitspersample);
+ p += tiff->stride;
+ }
+ }
+
+ /* RGBPal */
+ if (tiff->photometric == 3 && tiff->colormap)
+ fz_expand_tiff_colormap(ctx, tiff);
+
+ /* WhiteIsZero .. invert */
+ if (tiff->photometric == 0)
+ {
+ unsigned char *p = tiff->samples;
+ for (i = 0; i < tiff->imagelength; i++)
+ {
+ fz_invert_tiff(p, tiff->imagewidth, tiff->samplesperpixel, tiff->bitspersample, tiff->extrasamples);
+ p += tiff->stride;
+ }
+ }
+
+ /* Premultiplied transparency */
+ if (tiff->extrasamples == 1)
+ {
+ /* In GhostXPS we undo the premultiplication here; muxps holds
+ * all our images premultiplied by default, so nothing to do.
+ */
+ }
+
+ /* Non-premultiplied transparency */
+ if (tiff->extrasamples == 2)
+ {
+ /* Premultiplied files are corrected for elsewhere */
+ }
+
+ /* Byte swap 16-bit images to big endian if necessary */
+ if (tiff->bitspersample == 16 && tiff->order == TII)
+ fz_swap_tiff_byte_order(tiff->samples, tiff->imagewidth * tiff->imagelength * tiff->samplesperpixel);
+}
+
fz_pixmap *
fz_load_tiff_subimage(fz_context *ctx, unsigned char *buf, size_t len, int subimage)
{
@@ -896,17 +925,8 @@ fz_load_tiff_subimage(fz_context *ctx, unsigned char *buf, size_t len, int subim
fz_seek_ifd(ctx, &tiff, subimage);
fz_decode_tiff_ifd(ctx, &tiff);
- /* Decode the image strips */
-
- if (tiff.rowsperstrip > tiff.imagelength)
- tiff.rowsperstrip = tiff.imagelength;
-
- fz_decode_tiff_strips(ctx, &tiff);
-
- /* Byte swap 16-bit images to big endian if necessary */
- if (tiff.bitspersample == 16)
- if (tiff.order == TII)
- fz_swap_tiff_byte_order(tiff.samples, tiff.imagewidth * tiff.imagelength * tiff.samplesperpixel);
+ /* Decode the image data */
+ fz_decode_tiff_samples(ctx, &tiff);
/* Expand into fz_pixmap struct */
alpha = tiff.extrasamples != 0;