Пример #1
0
    def chunk_PLTE(self, pos, len):

        # palette
        s = ImageFile._safe_read(self.fp, len)
        if self.im_mode == "P":
            self.im_palette = "RGB", s
        return s
Пример #2
0
	def chunk_PLTE(self, pos, len):

		# palette
		s = ImageFile._safe_read(self.fp, len)
		if self.im_mode == "P":
			self.im_palette = "RGB", s
		return s
Пример #3
0
def COM(self, marker):
	#
	# Comment marker.  Store these in the APP dictionary.

	n = i16(self.fp.read(2))-2
	s = ImageFile._safe_read(self.fp, n)

	self.app["COM"] = s # compatibility
	self.applist.append(("COM", s))
Пример #4
0
def APP(self, marker):
	#
	# Application marker.  Store these in the APP dictionary.
	# Also look for well-known application markers.

	n = i16(self.fp.read(2))-2
	s = ImageFile._safe_read(self.fp, n)

	app = "APP%d" % (marker&15)

	self.app[app] = s # compatibility
	self.applist.append((app, s))

	if marker == 0xFFE0 and s[:4] == "JFIF":
		# extract JFIF information
		self.info["jfif"] = version = i16(s, 5) # version
		self.info["jfif_version"] = divmod(version, 256)
		# extract JFIF properties
		try:
			jfif_unit = ord(s[7])
			jfif_density = i16(s, 8), i16(s, 10)
		except:
			pass
		else:
			if jfif_unit == 1:
				self.info["dpi"] = jfif_density
			self.info["jfif_unit"] = jfif_unit
			self.info["jfif_density"] = jfif_density
	elif marker == 0xFFE1 and s[:5] == "Exif\0":
		# extract Exif information (incomplete)
		self.info["exif"] = s # FIXME: value will change
	elif marker == 0xFFE2 and s[:5] == "FPXR\0":
		# extract FlashPix information (incomplete)
		self.info["flashpix"] = s # FIXME: value will change
	elif marker == 0xFFE2 and s[:12] == "ICC_PROFILE\0":
		# Since an ICC profile can be larger than the maximum size of
		# a JPEG marker (64K), we need provisions to split it into
		# multiple markers. The format defined by the ICC specifies
		# one or more APP2 markers containing the following data:
		#   Identifying string	  ASCII "ICC_PROFILE\0"  (12 bytes)
		#   Marker sequence number  1, 2, etc (1 byte)
		#   Number of markers	   Total of APP2's used (1 byte)
		#   Profile data			(remainder of APP2 data)
		# Decoders should use the marker sequence numbers to
		# reassemble the profile, rather than assuming that the APP2
		# markers appear in the correct sequence.
		self.icclist.append(s)
	elif marker == 0xFFEE and s[:5] == "Adobe":
		self.info["adobe"] = i16(s, 5)
		# extract Adobe custom properties
		try:
			adobe_transform = ord(s[1])
		except:
			pass
		else:
			self.info["adobe_transform"] = adobe_transform
Пример #5
0
    def load(self, fp):
        # load tag dictionary

        self.reset()

        i16 = self.i16
        i32 = self.i32

        for i in range(i16(fp.read(2))):

            ifd = fp.read(12)

            tag, typ = i16(ifd), i16(ifd, 2)

            if Image.DEBUG:
                import TiffTags
                tagname = TiffTags.TAGS.get(tag, "unknown")
                typname = TiffTags.TYPES.get(typ, "unknown")
                print "tag: %s (%d)" % (tagname, tag),
                print "- type: %s (%d)" % (typname, typ),

            try:
                dispatch = self.load_dispatch[typ]
            except KeyError:
                if Image.DEBUG:
                    print "- unsupported type", typ
                continue  # ignore unsupported type

            size, handler = dispatch

            size = size * i32(ifd, 4)

            # Get and expand tag value
            if size > 4:
                here = fp.tell()
                fp.seek(i32(ifd, 8))
                data = ImageFile._safe_read(fp, size)
                fp.seek(here)
            else:
                data = ifd[8:8 + size]

            if len(data) != size:
                raise IOError, "not enough data"

            self.tagdata[tag] = typ, data
            self.tagtype[tag] = typ

            if Image.DEBUG:
                if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK,
                           ICCPROFILE, XMP):
                    print "- value: <table: %d bytes>" % size
                else:
                    print "- value:", self[tag]

        self.next = i32(fp.read(4))
Пример #6
0
	def chunk_tEXt(self, pos, len):

		# text
		s = ImageFile._safe_read(self.fp, len)
		try:
			k, v = string.split(s, "\0", 1)
		except ValueError:
			k = s; v = "" # fallback for broken tEXt tags
		if k:
			self.im_info[k] = self.im_text[k] = v
		return s
Пример #7
0
	def chunk_zTXt(self, pos, len):

		# compressed text
		s = ImageFile._safe_read(self.fp, len)
		k, v = string.split(s, "\0", 1)
		comp_method = ord(v[0])
		if comp_method != 0:
			raise SyntaxError("Unknown compression method %s in zTXt chunk" % comp_method)
		import zlib
		self.im_info[k] = self.im_text[k] = zlib.decompress(v[1:])
		return s
Пример #8
0
	def load(self, fp):
		# load tag dictionary

		self.reset()

		i16 = self.i16
		i32 = self.i32

		for i in range(i16(fp.read(2))):

			ifd = fp.read(12)

			tag, typ = i16(ifd), i16(ifd, 2)

			if Image.DEBUG:
				import TiffTags
				tagname = TiffTags.TAGS.get(tag, "unknown")
				typname = TiffTags.TYPES.get(typ, "unknown")
				print "tag: %s (%d)" % (tagname, tag),
				print "- type: %s (%d)" % (typname, typ),

			try:
				dispatch = self.load_dispatch[typ]
			except KeyError:
				if Image.DEBUG:
					print "- unsupported type", typ
				continue # ignore unsupported type

			size, handler = dispatch

			size = size * i32(ifd, 4)

			# Get and expand tag value
			if size > 4:
				here = fp.tell()
				fp.seek(i32(ifd, 8))
				data = ImageFile._safe_read(fp, size)
				fp.seek(here)
			else:
				data = ifd[8:8+size]

			if len(data) != size:
				raise IOError, "not enough data"

			self.tagdata[tag] = typ, data
			self.tagtype[tag] = typ

			if Image.DEBUG:
				if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, ICCPROFILE, XMP):
					print "- value: <table: %d bytes>" % size
				else:
					print "- value:", self[tag]

		self.next = i32(fp.read(4))
Пример #9
0
	def chunk_pHYs(self, pos, len):

		# pixels per unit
		s = ImageFile._safe_read(self.fp, len)
		px, py = i32(s), i32(s[4:])
		unit = ord(s[8])
		if unit == 1: # meter
			dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5)
			self.im_info["dpi"] = dpi
		elif unit == 0:
			self.im_info["aspect"] = px, py
		return s
Пример #10
0
    def chunk_zTXt(self, pos, len):

        # compressed text
        s = ImageFile._safe_read(self.fp, len)
        k, v = string.split(s, "\0", 1)
        comp_method = ord(v[0])
        if comp_method != 0:
            raise SyntaxError("Unknown compression method %s in zTXt chunk" %
                              comp_method)
        import zlib
        self.im_info[k] = self.im_text[k] = zlib.decompress(v[1:])
        return s
Пример #11
0
    def chunk_tEXt(self, pos, len):

        # text
        s = ImageFile._safe_read(self.fp, len)
        try:
            k, v = string.split(s, "\0", 1)
        except ValueError:
            k = s
            v = ""  # fallback for broken tEXt tags
        if k:
            self.im_info[k] = self.im_text[k] = v
        return s
Пример #12
0
    def chunk_pHYs(self, pos, len):

        # pixels per unit
        s = ImageFile._safe_read(self.fp, len)
        px, py = i32(s), i32(s[4:])
        unit = ord(s[8])
        if unit == 1:  # meter
            dpi = int(px * 0.0254 + 0.5), int(py * 0.0254 + 0.5)
            self.im_info["dpi"] = dpi
        elif unit == 0:
            self.im_info["aspect"] = px, py
        return s
Пример #13
0
    def chunk_tRNS(self, pos, len):

        # transparency
        s = ImageFile._safe_read(self.fp, len)
        if self.im_mode == "P":
            i = string.find(s, chr(0))
            if i >= 0:
                self.im_info["transparency"] = i
        elif self.im_mode == "L":
            self.im_info["transparency"] = i16(s)
        elif self.im_mode == "RGB":
            self.im_info["transparency"] = i16(s), i16(s[2:]), i16(s[4:])
        return s
Пример #14
0
	def chunk_tRNS(self, pos, len):

		# transparency
		s = ImageFile._safe_read(self.fp, len)
		if self.im_mode == "P":
			i = string.find(s, chr(0))
			if i >= 0:
				self.im_info["transparency"] = i
		elif self.im_mode == "L":
			self.im_info["transparency"] = i16(s)
		elif self.im_mode == "RGB":
			self.im_info["transparency"] = i16(s), i16(s[2:]), i16(s[4:])
		return s
Пример #15
0
	def chunk_IHDR(self, pos, len):

		# image header
		s = ImageFile._safe_read(self.fp, len)
		self.im_size = i32(s), i32(s[4:])
		try:
			self.im_mode, self.im_rawmode = _MODES[(ord(s[8]), ord(s[9]))]
		except:
			pass
		if ord(s[12]):
			self.im_info["interlace"] = 1
		if ord(s[11]):
			raise SyntaxError, "unknown filter category"
		return s
Пример #16
0
    def chunk_IHDR(self, pos, len):

        # image header
        s = ImageFile._safe_read(self.fp, len)
        self.im_size = i32(s), i32(s[4:])
        try:
            self.im_mode, self.im_rawmode = _MODES[(ord(s[8]), ord(s[9]))]
        except:
            pass
        if ord(s[12]):
            self.im_info["interlace"] = 1
        if ord(s[11]):
            raise SyntaxError, "unknown filter category"
        return s
Пример #17
0
	def verify(self, endchunk = "IEND"):

		# Simple approach; just calculate checksum for all remaining
		# blocks.  Must be called directly after open.

		cids = []

		while 1:
			cid, pos, len = self.read()
			if cid == endchunk:
				break
			self.crc(cid, ImageFile._safe_read(self.fp, len))
			cids.append(cid)

		return cids
Пример #18
0
    def verify(self, endchunk="IEND"):

        # Simple approach; just calculate checksum for all remaining
        # blocks.  Must be called directly after open.

        cids = []

        while 1:
            cid, pos, len = self.read()
            if cid == endchunk:
                break
            self.crc(cid, ImageFile._safe_read(self.fp, len))
            cids.append(cid)

        return cids
Пример #19
0
def SOF(self, marker):
	#
	# Start of frame marker.  Defines the size and mode of the
	# image.  JPEG is colour blind, so we use some simple
	# heuristics to map the number of layers to an appropriate
	# mode.  Note that this could be made a bit brighter, by
	# looking for JFIF and Adobe APP markers.

	n = i16(self.fp.read(2))-2
	s = ImageFile._safe_read(self.fp, n)
	self.size = i16(s[3:]), i16(s[1:])

	self.bits = ord(s[0])
	if self.bits != 8:
		raise SyntaxError("cannot handle %d-bit layers" % self.bits)

	self.layers = ord(s[5])
	if self.layers == 1:
		self.mode = "L"
	elif self.layers == 3:
		self.mode = "RGB"
	elif self.layers == 4:
		self.mode = "CMYK"
	else:
		raise SyntaxError("cannot handle %d-layer images" % self.layers)

	if marker in [0xFFC2, 0xFFC6, 0xFFCA, 0xFFCE]:
		self.info["progressive"] = self.info["progression"] = 1

	if self.icclist:
		# fixup icc profile
		self.icclist.sort() # sort by sequence number
		if ord(self.icclist[0][13]) == len(self.icclist):
			profile = []
			for p in self.icclist:
				profile.append(p[14:])
			icc_profile = string.join(profile, "")
		else:
			icc_profile = None # wrong number of fragments
		self.info["icc_profile"] = icc_profile
		self.icclist = None

	for i in range(6, len(s), 3):
		t = s[i:i+3]
		# 4-tuples: id, vsamp, hsamp, qtable
		self.layer.append((t[0], ord(t[1])/16, ord(t[1])&15, ord(t[2])))
Пример #20
0
	def _open(self):

		if self.fp.read(8) != _MAGIC:
			raise SyntaxError, "not a PNG file"

		#
		# Parse headers up to the first IDAT chunk

		self.png = PngStream(self.fp)

		while 1:

			#
			# get next chunk

			cid, pos, len = self.png.read()

			try:
				s = self.png.call(cid, pos, len)
			except EOFError:
				break
			except AttributeError:
				if Image.DEBUG:
					print cid, pos, len, "(unknown)"
				s = ImageFile._safe_read(self.fp, len)

			self.png.crc(cid, s)

		#
		# Copy relevant attributes from the PngStream.  An alternative
		# would be to let the PngStream class modify these attributes
		# directly, but that introduces circular references which are
		# difficult to break if things go wrong in the decoder...
		# (believe me, I've tried ;-)

		self.mode = self.png.im_mode
		self.size = self.png.im_size
		self.info = self.png.im_info
		self.text = self.png.im_text # experimental
		self.tile = self.png.im_tile

		if self.png.im_palette:
			rawmode, data = self.png.im_palette
			self.palette = ImagePalette.raw(rawmode, data)

		self.__idat = len # used by load_read()
Пример #21
0
    def _open(self):

        if self.fp.read(8) != _MAGIC:
            raise SyntaxError, "not a PNG file"

        #
        # Parse headers up to the first IDAT chunk

        self.png = PngStream(self.fp)

        while 1:

            #
            # get next chunk

            cid, pos, len = self.png.read()

            try:
                s = self.png.call(cid, pos, len)
            except EOFError:
                break
            except AttributeError:
                if Image.DEBUG:
                    print cid, pos, len, "(unknown)"
                s = ImageFile._safe_read(self.fp, len)

            self.png.crc(cid, s)

        #
        # Copy relevant attributes from the PngStream.  An alternative
        # would be to let the PngStream class modify these attributes
        # directly, but that introduces circular references which are
        # difficult to break if things go wrong in the decoder...
        # (believe me, I've tried ;-)

        self.mode = self.png.im_mode
        self.size = self.png.im_size
        self.info = self.png.im_info
        self.text = self.png.im_text  # experimental
        self.tile = self.png.im_tile

        if self.png.im_palette:
            rawmode, data = self.png.im_palette
            self.palette = ImagePalette.raw(rawmode, data)

        self.__idat = len  # used by load_read()
Пример #22
0
def DQT(self, marker):
	#
	# Define quantization table.  Support baseline 8-bit tables
	# only.  Note that there might be more than one table in
	# each marker.

	# FIXME: The quantization tables can be used to estimate the
	# compression quality.

	n = i16(self.fp.read(2))-2
	s = ImageFile._safe_read(self.fp, n)
	while len(s):
		if len(s) < 65:
			raise SyntaxError("bad quantization table marker")
		v = ord(s[0])
		if v/16 == 0:
			self.quantization[v&15] = array.array("b", s[1:65])
			s = s[65:]
		else:
			return # FIXME: add code to read 16-bit tables!
Пример #23
0
	def chunk_iCCP(self, pos, len):

		# ICC profile
		s = ImageFile._safe_read(self.fp, len)
		# according to PNG spec, the iCCP chunk contains:
		# Profile name  1-79 bytes (character string)
		# Null separator		1 byte (null character)
		# Compression method	1 byte (0)
		# Compressed profile	n bytes (zlib with deflate compression)
		i = string.find(s, chr(0))
		if Image.DEBUG:
			print "iCCP profile name", s[:i]
			print "Compression method", ord(s[i])
		comp_method = ord(s[i])
		if comp_method != 0:
			raise SyntaxError("Unknown compression method %s in iCCP chunk" % comp_method)
		try:
			icc_profile = zlib.decompress(s[i+2:])
		except zlib.error:
			icc_profile = None # FIXME
		self.im_info["icc_profile"] = icc_profile
		return s
Пример #24
0
    def chunk_iCCP(self, pos, len):

        # ICC profile
        s = ImageFile._safe_read(self.fp, len)
        # according to PNG spec, the iCCP chunk contains:
        # Profile name  1-79 bytes (character string)
        # Null separator		1 byte (null character)
        # Compression method	1 byte (0)
        # Compressed profile	n bytes (zlib with deflate compression)
        i = string.find(s, chr(0))
        if Image.DEBUG:
            print "iCCP profile name", s[:i]
            print "Compression method", ord(s[i])
        comp_method = ord(s[i])
        if comp_method != 0:
            raise SyntaxError("Unknown compression method %s in iCCP chunk" %
                              comp_method)
        try:
            icc_profile = zlib.decompress(s[i + 2:])
        except zlib.error:
            icc_profile = None  # FIXME
        self.im_info["icc_profile"] = icc_profile
        return s
Пример #25
0
	def chunk_gAMA(self, pos, len):

		# gamma setting
		s = ImageFile._safe_read(self.fp, len)
		self.im_info["gamma"] = i32(s) / 100000.0
		return s
Пример #26
0
def Skip(self, marker):
	n = i16(self.fp.read(2))-2
	ImageFile._safe_read(self.fp, n)
Пример #27
0
    def chunk_gAMA(self, pos, len):

        # gamma setting
        s = ImageFile._safe_read(self.fp, len)
        self.im_info["gamma"] = i32(s) / 100000.0
        return s
Пример #28
0
	def _bitmap(self, header = 0, offset = 0):

		if header:
			self.fp.seek(header)

		read = self.fp.read

		# CORE/INFO
		s = read(4)
		s = s + ImageFile._safe_read(self.fp, i32(s)-4)

		if len(s) == 12:

			# OS/2 1.0 CORE
			bits = i16(s[10:])
			self.size = i16(s[4:]), i16(s[6:])
			compression = 0
			lutsize = 3
			colors = 0
			direction = -1

		elif len(s) in [40, 64]:

			# WIN 3.1 or OS/2 2.0 INFO
			bits = i16(s[14:])
			self.size = i32(s[4:]), i32(s[8:])
			compression = i32(s[16:])
			lutsize = 4
			colors = i32(s[32:])
			direction = -1
			if s[11] == '\xff':
				# upside-down storage
				self.size = self.size[0], 2**32 - self.size[1]
				direction = 0

		else:
			raise IOError("Unsupported BMP header type (%d)" % len(s))

		if not colors:
			colors = 1 << bits

		# MODE
		try:
			self.mode, rawmode = BIT2MODE[bits]
		except KeyError:
			raise IOError("Unsupported BMP pixel depth (%d)" % bits)

		if compression == 3:
			# BI_BITFIELDS compression
			mask = i32(read(4)), i32(read(4)), i32(read(4))
			if bits == 32 and mask == (0xff0000, 0x00ff00, 0x0000ff):
				rawmode = "BGRX"
			elif bits == 16 and mask == (0x00f800, 0x0007e0, 0x00001f):
				rawmode = "BGR;16"
			elif bits == 16 and mask == (0x007c00, 0x0003e0, 0x00001f):
				rawmode = "BGR;15"
			else:
				# print bits, map(hex, mask)
				raise IOError("Unsupported BMP bitfields layout")
		elif compression != 0:
			raise IOError("Unsupported BMP compression (%d)" % compression)

		# LUT
		if self.mode == "P":
			palette = []
			greyscale = 1
			if colors == 2:
				indices = (0, 255)
			else:
				indices = range(colors)
			for i in indices:
				rgb = read(lutsize)[:3]
				if rgb != chr(i)*3:
					greyscale = 0
				palette.append(rgb)
			if greyscale:
				if colors == 2:
					self.mode = rawmode = "1"
				else:
					self.mode = rawmode = "L"
			else:
				self.mode = "P"
				self.palette = ImagePalette.raw(
					"BGR", string.join(palette, "")
					)

		if not offset:
			offset = self.fp.tell()

		self.tile = [("raw",
					 (0, 0) + self.size,
					 offset,
					 (rawmode, ((self.size[0]*bits+31)>>3)&(~3), direction))]

		self.info["compression"] = compression
Пример #29
0
    def _bitmap(self, header=0, offset=0):

        if header:
            self.fp.seek(header)

        read = self.fp.read

        # CORE/INFO
        s = read(4)
        s = s + ImageFile._safe_read(self.fp, i32(s) - 4)

        if len(s) == 12:

            # OS/2 1.0 CORE
            bits = i16(s[10:])
            self.size = i16(s[4:]), i16(s[6:])
            compression = 0
            lutsize = 3
            colors = 0
            direction = -1

        elif len(s) in [40, 64]:

            # WIN 3.1 or OS/2 2.0 INFO
            bits = i16(s[14:])
            self.size = i32(s[4:]), i32(s[8:])
            compression = i32(s[16:])
            lutsize = 4
            colors = i32(s[32:])
            direction = -1
            if s[11] == '\xff':
                # upside-down storage
                self.size = self.size[0], 2**32 - self.size[1]
                direction = 0

        else:
            raise IOError("Unsupported BMP header type (%d)" % len(s))

        if not colors:
            colors = 1 << bits

        # MODE
        try:
            self.mode, rawmode = BIT2MODE[bits]
        except KeyError:
            raise IOError("Unsupported BMP pixel depth (%d)" % bits)

        if compression == 3:
            # BI_BITFIELDS compression
            mask = i32(read(4)), i32(read(4)), i32(read(4))
            if bits == 32 and mask == (0xff0000, 0x00ff00, 0x0000ff):
                rawmode = "BGRX"
            elif bits == 16 and mask == (0x00f800, 0x0007e0, 0x00001f):
                rawmode = "BGR;16"
            elif bits == 16 and mask == (0x007c00, 0x0003e0, 0x00001f):
                rawmode = "BGR;15"
            else:
                # print bits, map(hex, mask)
                raise IOError("Unsupported BMP bitfields layout")
        elif compression != 0:
            raise IOError("Unsupported BMP compression (%d)" % compression)

        # LUT
        if self.mode == "P":
            palette = []
            greyscale = 1
            if colors == 2:
                indices = (0, 255)
            else:
                indices = range(colors)
            for i in indices:
                rgb = read(lutsize)[:3]
                if rgb != chr(i) * 3:
                    greyscale = 0
                palette.append(rgb)
            if greyscale:
                if colors == 2:
                    self.mode = rawmode = "1"
                else:
                    self.mode = rawmode = "L"
            else:
                self.mode = "P"
                self.palette = ImagePalette.raw("BGR",
                                                string.join(palette, ""))

        if not offset:
            offset = self.fp.tell()

        self.tile = [("raw", (0, 0) + self.size, offset,
                      (rawmode, ((self.size[0] * bits + 31) >> 3) & (~3),
                       direction))]

        self.info["compression"] = compression