"""
TIFF image parser.
Author: Victor Stinner
Creation date: 30 september 2006
"""
from hachoir_parser import Parser
from hachoir_core.field import (FieldSet, ParserError,
UInt16, UInt32, String)
from hachoir_core.endian import LITTLE_ENDIAN, BIG_ENDIAN
from hachoir_parser.image.exif import BasicIFDEntry
from hachoir_core.tools import createDict
MAX_COUNT = 250
class IFDEntry(BasicIFDEntry):
static_size = 12*8
TAG_INFO = {
254: ("new_subfile_type", "New subfile type"),
256: ("img_width", "Image width in pixels"),
257: ("img_height", "Image height in pixels"),
258: ("bits_per_sample", "Bits per sample"),
259: ("compression", "Compression method"),
262: ("photo_interpret", "Photometric interpretation"),
263: ("thres", "Thresholding"),
264: ("cell_width", "Cellule width"),
265: ("cell_height", "Cellule height"),
266: ("fill_order", "Fill order"),
269: ("doc_name", "Document name"),
270: ("description", "Image description"),
271: ("make", "Make"),
272: ("model", "Model"),
273: ("strip_ofs", "Strip offsets"),
274: ("orientation", "Orientation"),
277: ("sample_pixel", "Samples per pixel"),
278: ("row_per_strip", "Rows per strip"),
279: ("strip_byte", "Strip byte counts"),
280: ("min_sample_value", "Min sample value"),
281: ("max_sample_value", "Max sample value"),
282: ("xres", "X resolution"),
283: ("yres", "Y resolution"),
284: ("planar_conf", "Planar configuration"),
285: ("page_name", "Page name"),
286: ("xpos", "X position"),
287: ("ypos", "Y position"),
288: ("free_ofs", "Free offsets"),
289: ("free_byte", "Free byte counts"),
290: ("gray_resp_unit", "Gray response unit"),
291: ("gray_resp_curve", "Gray response curve"),
292: ("group3_opt", "Group 3 options"),
293: ("group4_opt", "Group 4 options"),
296: ("res_unit", "Resolution unit"),
297: ("page_nb", "Page number"),
301: ("color_respt_curve", "Color response curves"),
305: ("software", "Software"),
306: ("date_time", "Date time"),
307: ("artist", "Artist"),
308: ("host_computer", "Host computer"),
317: ("predicator", "Predicator"),
318: ("white_pt", "White point"),
319: ("prim_chomat", "Primary chromaticities"),
320: ("color_map", "Color map"),
}
TAG_NAME = createDict(TAG_INFO, 0)
def __init__(self, *args):
FieldSet.__init__(self, *args)
tag = self["tag"].value
if tag in self.TAG_INFO:
self._name, self._description = self.TAG_INFO[tag]
else:
self._parser = None
class IFD(FieldSet):
def __init__(self, *args):
FieldSet.__init__(self, *args)
self._size = 16 + self["count"].value * IFDEntry.static_size
def createFields(self):
yield UInt16(self, "count")
if MAX_COUNT < self["count"].value:
raise ParserError("TIFF IFD: Invalid count (%s)"
% self["count"].value)
for index in xrange(self["count"].value):
yield IFDEntry(self, "entry[]")
class TiffFile(Parser):
PARSER_TAGS = {
"id": "tiff",
"category": "image",
"file_ext": ("tif", "tiff"),
"mime": (u"image/tiff",),
"min_size": 8*8,
# TODO: Re-enable magic
# "magic": (("II\x2A\0", 0), ("MM\0\x2A", 0)),
"description": "TIFF picture"
}
# Correct endian is set in constructor
endian = LITTLE_ENDIAN
# endian = BIG_ENDIAN
def validate(self):
endian = self.stream.readBytes(0, 2)
if endian == "II":
self.endian = LITTLE_ENDIAN
elif endian == "MM":
self.endian = BIG_ENDIAN
else:
return "Invalid endian"
if self["version"].value != 42:
return "Unknown TIFF version"
if self["img_dir_ofs"].value % 2:
return "Invalid first image directory offset"
return True
def createFields(self):
yield String(self, "endian", 2, 'Endian ("II" or "MM")', charset="ASCII")
yield UInt16(self, "version", "TIFF version number")
yield UInt32(self, "img_dir_ofs", "First image directory offset (in bytes from the beginning)")
raw = self.seekByte(self["img_dir_ofs"].value, relative=False)
if raw:
yield raw
yield IFD(self, "ifd")
if self.current_size < self._size:
yield self.seekBit(self._size, "end")
syntax highlighted by Code2HTML, v. 0.9.1