mirror of
https://github.com/SickGear/SickGear.git
synced 2024-11-26 22:53:38 +00:00
85 lines
2.6 KiB
Python
85 lines
2.6 KiB
Python
|
"""
|
||
|
TIFF image parser.
|
||
|
|
||
|
Authors: Victor Stinner, Sebastien Ponce, Robert Xiao
|
||
|
Creation date: 30 september 2006
|
||
|
"""
|
||
|
|
||
|
from hachoir.parser import Parser
|
||
|
from hachoir.field import SeekableFieldSet, RootSeekableFieldSet, Bytes
|
||
|
from hachoir.core.endian import LITTLE_ENDIAN, BIG_ENDIAN
|
||
|
from hachoir.parser.image.exif import TIFF, IFD
|
||
|
|
||
|
|
||
|
def getStrips(ifd):
|
||
|
data = {}
|
||
|
for i, entry in enumerate(ifd.array('entry')):
|
||
|
data[entry['tag'].display] = entry
|
||
|
# image data
|
||
|
if "StripOffsets" in data and "StripByteCounts" in data:
|
||
|
offs = ifd.getEntryValues(data["StripOffsets"])
|
||
|
bytes = ifd.getEntryValues(data["StripByteCounts"])
|
||
|
for off, byte in zip(offs, bytes):
|
||
|
yield off.value, byte.value
|
||
|
|
||
|
# image data
|
||
|
if "TileOffsets" in data and "TileByteCounts" in data:
|
||
|
offs = ifd.getEntryValues(data["TileOffsets"])
|
||
|
bytes = ifd.getEntryValues(data["TileByteCounts"])
|
||
|
for off, byte in zip(offs, bytes):
|
||
|
yield off.value, byte.value
|
||
|
|
||
|
|
||
|
class ImageFile(SeekableFieldSet):
|
||
|
|
||
|
def __init__(self, parent, name, description, ifd):
|
||
|
SeekableFieldSet.__init__(self, parent, name, description, None)
|
||
|
self._ifd = ifd
|
||
|
|
||
|
def createFields(self):
|
||
|
for off, byte in getStrips(self._ifd):
|
||
|
self.seekByte(off, relative=False)
|
||
|
field = Bytes(self, "strip[]", byte)
|
||
|
yield field
|
||
|
|
||
|
|
||
|
class TiffFile(RootSeekableFieldSet, Parser):
|
||
|
PARSER_TAGS = {
|
||
|
"id": "tiff",
|
||
|
"category": "image",
|
||
|
"file_ext": ("tif", "tiff"),
|
||
|
"mime": ("image/tiff",),
|
||
|
"min_size": 8 * 8,
|
||
|
"magic": ((b"II\x2A\0", 0), (b"MM\0\x2A", 0)),
|
||
|
"description": "TIFF picture"
|
||
|
}
|
||
|
|
||
|
# Correct endian is set in constructor
|
||
|
endian = LITTLE_ENDIAN
|
||
|
|
||
|
def __init__(self, stream, **args):
|
||
|
RootSeekableFieldSet.__init__(
|
||
|
self, None, "root", stream, None, stream.askSize(self))
|
||
|
if self.stream.readBytes(0, 2) == b"MM":
|
||
|
self.endian = BIG_ENDIAN
|
||
|
Parser.__init__(self, stream, **args)
|
||
|
|
||
|
def validate(self):
|
||
|
endian = self.stream.readBytes(0, 2)
|
||
|
if endian not in (b"MM", b"II"):
|
||
|
return "Invalid endian (%r)" % endian
|
||
|
if self["version"].value != 42:
|
||
|
return "Unknown TIFF version"
|
||
|
return True
|
||
|
|
||
|
def createFields(self):
|
||
|
yield from TIFF(self)
|
||
|
|
||
|
for ifd in self:
|
||
|
if not isinstance(ifd, IFD):
|
||
|
continue
|
||
|
offs = (off for off, byte in getStrips(ifd))
|
||
|
self.seekByte(min(offs), relative=False)
|
||
|
image = ImageFile(self, "image[]", "Image File", ifd)
|
||
|
yield image
|