def _save(im, fp, filename, chunk=putchunk, check=0): # save an image to disk (called by the save method) mode = im.mode if mode == "P": # # attempt to minimize storage requirements for palette images if im.encoderinfo.has_key("bits"): # number of bits specified by user n = 1 << im.encoderinfo["bits"] else: # check palette contents n = 256 # FIXME if n <= 2: bits = 1 elif n <= 4: bits = 2 elif n <= 16: bits = 4 else: bits = 8 if bits != 8: mode = "%s;%d" % (mode, bits) # encoder options if im.encoderinfo.has_key("dictionary"): dictionary = im.encoderinfo["dictionary"] else: dictionary = "" im.encoderconfig = (im.encoderinfo.has_key("optimize"), dictionary) # get the corresponding PNG mode try: rawmode, mode = _OUTMODES[mode] except KeyError: raise IOError, "cannot write mode %s as PNG" % mode if check: return check # # write minimal PNG file fp.write(_MAGIC) chunk(fp, "IHDR", o32(im.size[0]), o32(im.size[1]), # 0: size mode, # 8: depth/type chr(0), # 10: compression chr(0), # 11: filter category chr(0)) # 12: interlace flag if im.mode == "P": chunk(fp, "PLTE", im.im.getpalette("RGB")) if im.encoderinfo.has_key("transparency"): if im.mode == "P": transparency = max(0, min(255, im.encoderinfo["transparency"])) chunk(fp, "tRNS", chr(255) * transparency + chr(0)) elif im.mode == "L": transparency = max(0, min(65535, im.encoderinfo["transparency"])) chunk(fp, "tRNS", o16(transparency)) elif im.mode == "RGB": red, green, blue = im.encoderinfo["transparency"] chunk(fp, "tRNS", o16(red) + o16(green) + o16(blue)) else: raise IOError("cannot use transparency for this mode") if 0: # FIXME: to be supported some day chunk(fp, "gAMA", o32(int(gamma * 100000.0))) dpi = im.encoderinfo.get("dpi") if dpi: chunk(fp, "pHYs", o32(int(dpi[0] / 0.0254 + 0.5)), o32(int(dpi[1] / 0.0254 + 0.5)), chr(1)) info = im.encoderinfo.get("pnginfo") if info: for cid, data in info.chunks: chunk(fp, cid, data) # ICC profile writing support -- 2008-06-06 Florian Hoech if im.info.has_key("icc_profile"): # ICC profile # 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) try: import ICCProfile p = ICCProfile.ICCProfile(im.info["icc_profile"]) name = p.tags.desc.get("ASCII", p.tags.desc.get("Unicode", p.tags.desc.get("Macintosh", p.tags.desc.get("en", {}).get("US", "ICC Profile")))).encode("latin1", "replace")[:79] except ImportError: name = "ICC Profile" data = name + "\0\0" + zlib.compress(im.info["icc_profile"]) chunk(fp, "iCCP", data) ImageFile._save(im, _idat(fp, chunk), [("zip", (0,0)+im.size, 0, rawmode)]) chunk(fp, "IEND", "") try: fp.flush() except: pass
def _save(im, fp, filename, chunk=putchunk, check=0): # save an image to disk (called by the save method) mode = im.mode if mode == "P": # # attempt to minimize storage requirements for palette images if im.encoderinfo.has_key("bits"): # number of bits specified by user n = 1 << im.encoderinfo["bits"] else: # check palette contents n = 256 # FIXME if n <= 2: bits = 1 elif n <= 4: bits = 2 elif n <= 16: bits = 4 else: bits = 8 if bits != 8: mode = "%s;%d" % (mode, bits) # encoder options if im.encoderinfo.has_key("dictionary"): dictionary = im.encoderinfo["dictionary"] else: dictionary = "" im.encoderconfig = (im.encoderinfo.has_key("optimize"), dictionary) # get the corresponding PNG mode try: rawmode, mode = _OUTMODES[mode] except KeyError: raise IOError, "cannot write mode %s as PNG" % mode if check: return check # # write minimal PNG file fp.write(_MAGIC) chunk( fp, "IHDR", o32(im.size[0]), o32(im.size[1]), # 0: size mode, # 8: depth/type chr(0), # 10: compression chr(0), # 11: filter category chr(0)) # 12: interlace flag if im.mode == "P": chunk(fp, "PLTE", im.im.getpalette("RGB")) if im.encoderinfo.has_key("transparency"): if im.mode == "P": transparency = max(0, min(255, im.encoderinfo["transparency"])) chunk(fp, "tRNS", chr(255) * transparency + chr(0)) elif im.mode == "L": transparency = max(0, min(65535, im.encoderinfo["transparency"])) chunk(fp, "tRNS", o16(transparency)) elif im.mode == "RGB": red, green, blue = im.encoderinfo["transparency"] chunk(fp, "tRNS", o16(red) + o16(green) + o16(blue)) else: raise IOError("cannot use transparency for this mode") if 0: # FIXME: to be supported some day chunk(fp, "gAMA", o32(int(gamma * 100000.0))) dpi = im.encoderinfo.get("dpi") if dpi: chunk(fp, "pHYs", o32(int(dpi[0] / 0.0254 + 0.5)), o32(int(dpi[1] / 0.0254 + 0.5)), chr(1)) info = im.encoderinfo.get("pnginfo") if info: for cid, data in info.chunks: chunk(fp, cid, data) # ICC profile writing support -- 2008-06-06 Florian Hoech if im.info.has_key("icc_profile"): # ICC profile # 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) try: import ICCProfile p = ICCProfile.ICCProfile(im.info["icc_profile"]) name = p.tags.desc.get( "ASCII", p.tags.desc.get( "Unicode", p.tags.desc.get( "Macintosh", p.tags.desc.get("en", {}).get("US", "ICC Profile")))).encode( "latin1", "replace")[:79] except ImportError: name = "ICC Profile" data = name + "\0\0" + zlib.compress(im.info["icc_profile"]) chunk(fp, "iCCP", data) ImageFile._save(im, _idat(fp, chunk), [("zip", (0, 0) + im.size, 0, rawmode)]) chunk(fp, "IEND", "") try: fp.flush() except: pass
def add_text(self, key, value, zip=0): if zip: import zlib self.add("zTXt", key + "\0\0" + zlib.compress(value)) else: self.add("tEXt", key + "\0" + value)