Adding support to reading tiled and YcbCr jpegs tiffs through libtiff

This commit is contained in:
Konstantin Kopachev 2018-07-02 17:15:24 -07:00
parent 4c47628900
commit f0436a4ddc
No known key found for this signature in database
GPG Key ID: CECF757E656F4F62
2 changed files with 157 additions and 110 deletions

View File

@ -257,14 +257,14 @@ OPEN_INFO = {
(II, 5, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0)): ("CMYK", "CMYKXX"),
(MM, 5, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0)): ("CMYK", "CMYKXX"),
(II, 6, (1,), 1, (8, 8, 8), ()): ("YCbCr", "YCbCr"),
(MM, 6, (1,), 1, (8, 8, 8), ()): ("YCbCr", "YCbCr"),
(II, 6, (1,), 1, (8, 8, 8, 8), (0,)): ("YCbCr", "YCbCrX"),
(MM, 6, (1,), 1, (8, 8, 8, 8), (0,)): ("YCbCr", "YCbCrX"),
(II, 6, (1,), 1, (8, 8, 8, 8, 8), (0, 0)): ("YCbCr", "YCbCrXX"),
(MM, 6, (1,), 1, (8, 8, 8, 8, 8), (0, 0)): ("YCbCr", "YCbCrXX"),
(II, 6, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0, 0)): ("YCbCr", "YCbCrXXX"),
(MM, 6, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0, 0)): ("YCbCr", "YCbCrXXX"),
(II, 6, (1,), 1, (8, 8, 8), ()): ("RGB", "RGB"),
(MM, 6, (1,), 1, (8, 8, 8), ()): ("RGB", "RGB"),
(II, 6, (1,), 1, (8, 8, 8, 8), (0,)): ("RGB", "RGBX"),
(MM, 6, (1,), 1, (8, 8, 8, 8), (0,)): ("RGB", "RGBX"),
(II, 6, (1,), 1, (8, 8, 8, 8, 8), (0, 0)): ("RGB", "RGBXX"),
(MM, 6, (1,), 1, (8, 8, 8, 8, 8), (0, 0)): ("RGB", "RGBXX"),
(II, 6, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0, 0)): ("RGB", "RGBXXX"),
(MM, 6, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0, 0)): ("RGB", "RGBXXX"),
(II, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"),
(MM, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"),
@ -1062,6 +1062,8 @@ class TiffImageFile(ImageFile.ImageFile):
compression = self._compression
if compression == "raw":
args = (rawmode, 0, 1)
if compression == "jpeg":
args = ("RGB", "")
elif compression == "packbits":
args = rawmode
@ -1187,6 +1189,7 @@ class TiffImageFile(ImageFile.ImageFile):
print("- photometric_interpretation:", photo)
print("- planar_configuration:", self._planar_configuration)
print("- fill_order:", fillorder)
print("- YCbCr subsampling:", self.tag.get(530))
# size
xsize = self.tag_v2.get(IMAGEWIDTH)
@ -1258,13 +1261,8 @@ class TiffImageFile(ImageFile.ImageFile):
# build tile descriptors
x = y = layer = 0
self.tile = []
self.use_load_libtiff = False
if STRIPOFFSETS in self.tag_v2:
# striped image
offsets = self.tag_v2[STRIPOFFSETS]
h = self.tag_v2.get(ROWSPERSTRIP, ysize)
w = self.size[0]
if READ_LIBTIFF or self._compression != 'raw':
self.use_load_libtiff = self._compression != 'raw'
if self.use_load_libtiff:
# Decoder expects entire file as one tile.
# There's a buffer size limit in load (64k)
# so large g4 images will fail if we use that
@ -1273,8 +1271,6 @@ class TiffImageFile(ImageFile.ImageFile):
# Setup the one tile for the whole image, then
# use the _load_libtiff function.
self.use_load_libtiff = True
# libtiff handles the fillmode for us, so 1;IR should
# actually be 1;I. Including the R double reverses the
# bits, so stripes of the image are reversed. See
@ -1307,38 +1303,29 @@ class TiffImageFile(ImageFile.ImageFile):
a = (rawmode, self._compression, False)
self.tile.append(
(self._compression,
(0, 0, w, ysize),
(0, 0, xsize, ysize),
0, a))
a = None
elif STRIPOFFSETS in self.tag_v2 or TILEOFFSETS in self.tag_v2:
# striped image
if STRIPOFFSETS in self.tag_v2:
offsets = self.tag_v2[STRIPOFFSETS]
h = self.tag_v2.get(ROWSPERSTRIP, ysize)
w = self.size[0]
else:
for i, offset in enumerate(offsets):
a = self._decoder(rawmode, layer, i)
self.tile.append(
(self._compression,
(0, min(y, ysize), w, min(y+h, ysize)),
offset, a))
if DEBUG:
print("tiles: ", self.tile)
y = y + h
if y >= self.size[1]:
x = y = 0
layer += 1
a = None
elif TILEOFFSETS in self.tag_v2:
# tiled image
offsets = self.tag_v2[TILEOFFSETS]
w = self.tag_v2.get(322)
h = self.tag_v2.get(323)
a = None
for o in self.tag_v2[TILEOFFSETS]:
for offset in offsets:
if not a:
a = self._decoder(rawmode, layer)
# FIXME: this doesn't work if the image size
# is not a multiple of the tile size...
self.tile.append(
(self._compression,
(x, y, x+w, y+h),
o, a))
(min(x, xsize), min(y, ysize), min(x+w, xsize), min(y+h, ysize)),
offset, a))
x = x + w
if x >= self.size[0]:
x, y = 0, y + h
@ -1346,6 +1333,7 @@ class TiffImageFile(ImageFile.ImageFile):
x = y = 0
layer += 1
a = None
self.tile_prefix = self.tag_v2.get(JPEGTABLES, b"")
else:
if DEBUG:
print("- unsupported data organization")

View File

@ -173,7 +173,6 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, int
char *filename = "tempfile.tif";
char *mode = "r";
TIFF *tiff;
tsize_t size;
/* buffer is the encoded file, bytes is the length of the encoded file */
@ -235,8 +234,67 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, int
}
}
TIFFSetField(tiff, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
if (TIFFIsTiled(tiff)) {
state->bytes = TIFFTileSize(tiff);
/* overflow check for malloc */
if (state->bytes > INT_MAX - 1) {
state->errcode = IMAGING_CODEC_MEMORY;
TIFFClose(tiff);
return -1;
}
/* realloc to fit whole tile */
UINT8 *new = realloc (state->buffer, state->bytes);
if (!new) {
state->errcode = IMAGING_CODEC_MEMORY;
TIFFClose(tiff);
return -1;
}
state->buffer = new;
TRACE(("TIFFTileSize: %d\n", state->bytes));
uint32 x, y, tile_y;
uint32 tileWidth, tileLength;
TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth);
TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength);
for (y = state->yoff; y < state->ysize; y += tileLength) {
for (x = state->xoff; x < state->xsize; x += tileWidth) {
if (TIFFReadTile(tiff, (tdata_t)state->buffer, x, y, 0, 0) == -1) {
TRACE(("Decode Error, Tile at %dx%d\n", x, y));
state->errcode = IMAGING_CODEC_BROKEN;
TIFFClose(tiff);
return -1;
}
TRACE(("Read tile at %dx%d; \n\n", x, y));
// iterate over each line in the tile and stuff data into image
for (tile_y = 0; tile_y < min(tileLength, state->ysize - y); tile_y++) {
TRACE(("Writing tile data at %dx%d using tilwWidth: %d; \n", tile_y + y, x, min(tileWidth, state->xsize - x)));
// UINT8 * bbb = state->buffer + tile_y * (state->bytes / tileLength);
// TRACE(("chars: %x%x%x%x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3]));
state->shuffle((UINT8*) im->image[tile_y + y] + x * im->pixelsize,
state->buffer + tile_y * (state->bytes / tileLength),
min(tileWidth, state->xsize - x)
);
}
}
}
} else {
tsize_t size;
size = TIFFScanlineSize(tiff);
TRACE(("ScanlineSize: %d \n", size));
TRACE(("ScanlineSize: %lu \n", size));
if (size > state->bytes) {
TRACE(("Error, scanline size > buffer size\n"));
state->errcode = IMAGING_CODEC_BROKEN;
@ -265,6 +323,7 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, int
state->y++;
}
}
TIFFClose(tiff);
TRACE(("Done Decoding, Returning \n"));