def _save(im, fp, filename): if im.mode != "1": raise IOError, "cannot write mode %s as MSP" % im.mode # create MSP header header = [0] * 16 header[0], header[1] = i16("Da"), i16("nM") # version 1 header[2], header[3] = im.size header[4], header[5] = 1, 1 header[6], header[7] = 1, 1 header[8], header[9] = im.size sum = 0 for h in header: sum = sum ^ h header[12] = sum # FIXME: is this the right field? # header for h in header: fp.write(o16(h)) # image body ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 32, ("1", 0, 1))])
def getdata(im, offset = (0, 0), **params): """Return a list of strings representing this image. The first string is a local image header, the rest contains encoded image data.""" class collector: data = [] def write(self, data): self.data.append(data) im.load() # make sure raster data is available fp = collector() try: im.encoderinfo = params # local image header fp.write("," + o16(offset[0]) + # offset o16(offset[1]) + o16(im.size[0]) + # size o16(im.size[1]) + chr(0) + # flags chr(8)) # bits ImageFile._save(im, fp, [("gif", (0,0)+im.size, 0, RAWMODE[im.mode])]) fp.write("\0") # end of image data finally: del im.encoderinfo return fp.data
def _save(im, fp, filename, check=0): try: rawmode, bits, colormaptype, imagetype = SAVE[im.mode] except KeyError: raise IOError("cannot write mode %s as TGA" % im.mode) if check: return check if colormaptype: colormapfirst, colormaplength, colormapentry = 0, 256, 24 else: colormapfirst, colormaplength, colormapentry = 0, 0, 0 if im.mode == "RGBA": flags = 8 else: flags = 0 orientation = im.info.get("orientation", -1) if orientation > 0: flags = flags | 0x20 fp.write("\000" + chr(colormaptype) + chr(imagetype) + o16(colormapfirst) + o16(colormaplength) + chr(colormapentry) + o16(0) + o16(0) + o16(im.size[0]) + o16(im.size[1]) + chr(bits) + chr(flags)) if colormaptype: fp.write(im.im.getpalette("RGB", "BGR")) ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, 0, orientation))])
def _save(im, fp, filename, check=0): try: type, rawmode = SAVE[im.mode] except KeyError: raise ValueError, "Cannot save %s images as IM" % im.mode try: frames = im.encoderinfo["frames"] except KeyError: frames = 1 if check: return check fp.write("Image type: %s image\r\n" % type) if filename: fp.write("Name: %s\r\n" % filename) fp.write("Image size (x*y): %d*%d\r\n" % im.size) fp.write("File size (no of images): %d\r\n" % frames) if im.mode == "P": fp.write("Lut: 1\r\n") fp.write("\000" * (511 - fp.tell()) + "\032") if im.mode == "P": fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, 0, -1))])
def _save(im, fp, filename): try: rawmode = RAWMODE[im.mode] except KeyError: raise IOError("cannot write mode %s as JPEG" % im.mode) info = im.encoderinfo dpi = info.get("dpi", (0, 0)) subsampling = info.get("subsampling", -1) if subsampling == "4:4:4": subsampling = 0 elif subsampling == "4:2:2": subsampling = 1 elif subsampling == "4:1:1": subsampling = 2 extra = "" icc_profile = info.get("icc_profile") if icc_profile: ICC_OVERHEAD_LEN = 14 MAX_BYTES_IN_MARKER = 65533 MAX_DATA_BYTES_IN_MARKER = MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN markers = [] while icc_profile: markers.append(icc_profile[:MAX_DATA_BYTES_IN_MARKER]) icc_profile = icc_profile[MAX_DATA_BYTES_IN_MARKER:] i = 1 for marker in markers: size = struct.pack(">H", 2 + ICC_OVERHEAD_LEN + len(marker)) extra = extra + ("\xFF\xE2" + size + "ICC_PROFILE\0" + chr(i) + chr(len(markers)) + marker) i = i + 1 # get keyword arguments im.encoderconfig = ( info.get("quality", 0), # "progressive" is the official name, but older documentation # says "progression" # FIXME: issue a warning if the wrong form is used (post-1.1.7) info.has_key("progressive") or info.has_key("progression"), info.get("smooth", 0), info.has_key("optimize"), info.get("streamtype", 0), dpi[0], dpi[1], subsampling, extra, ) ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
def _save(im, fp, filename): if im.mode == "1": rawmode, head = "1;I", "P4" elif im.mode == "L": rawmode, head = "L", "P5" elif im.mode == "RGB": rawmode, head = "RGB", "P6" elif im.mode == "RGBA": rawmode, head = "RGB", "P6" else: raise IOError, "cannot write mode %s as PPM" % im.mode fp.write(head + "\n%d %d\n" % im.size) if head != "P4": fp.write("255\n") ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, 1))])
def _save(im, fp, filename): if im.mode == "1": rawmode, head = "1;I", "P4" elif im.mode == "L": rawmode, head = "L", "P5" elif im.mode == "RGB": rawmode, head = "RGB", "P6" elif im.mode == "RGBA": rawmode, head = "RGB", "P6" else: raise IOError, "cannot write mode %s as PPM" % im.mode fp.write(head + "\n%d %d\n" % im.size) if head != "P4": fp.write("255\n") ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, 0, 1))])
def _save(im, fp, filename, check=0): try: rawmode, bits, colors = SAVE[im.mode] except KeyError: raise IOError("cannot write mode %s as BMP" % im.mode) if check: return check stride = ((im.size[0] * bits + 7) / 8 + 3) & (~3) header = 40 # or 64 for OS/2 version 2 offset = 14 + header + colors * 4 image = stride * im.size[1] # bitmap header fp.write("BM" + # file type (magic) o32(offset + image) + # file size o32(0) + # reserved o32(offset)) # image data offset # bitmap info header fp.write( o32(header) + # info header size o32(im.size[0]) + # width o32(im.size[1]) + # height o16(1) + # planes o16(bits) + # depth o32(0) + # compression (0=uncompressed) o32(image) + # size of bitmap o32(1) + o32(1) + # resolution o32(colors) + # colors used o32(colors)) # colors important fp.write("\000" * (header - 40)) # padding (for OS/2 format) if im.mode == "1": for i in (0, 255): fp.write(chr(i) * 4) elif im.mode == "L": for i in range(256): fp.write(chr(i) * 4) elif im.mode == "P": fp.write(im.im.getpalette("RGB", "BGRX")) ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, stride, -1))])
def _save(im, fp, filename, check=0): try: rawmode, bits, colors = SAVE[im.mode] except KeyError: raise IOError("cannot write mode %s as BMP" % im.mode) if check: return check stride = ((im.size[0]*bits+7)/8+3)&(~3) header = 40 # or 64 for OS/2 version 2 offset = 14 + header + colors * 4 image = stride * im.size[1] # bitmap header fp.write("BM" + # file type (magic) o32(offset+image) + # file size o32(0) + # reserved o32(offset)) # image data offset # bitmap info header fp.write(o32(header) + # info header size o32(im.size[0]) + # width o32(im.size[1]) + # height o16(1) + # planes o16(bits) + # depth o32(0) + # compression (0=uncompressed) o32(image) + # size of bitmap o32(1) + o32(1) + # resolution o32(colors) + # colors used o32(colors)) # colors important fp.write("\000" * (header - 40)) # padding (for OS/2 format) if im.mode == "1": for i in (0, 255): fp.write(chr(i) * 4) elif im.mode == "L": for i in range(256): fp.write(chr(i) * 4) elif im.mode == "P": fp.write(im.im.getpalette("RGB", "BGRX")) ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))])
def _save(im, fp, filename): if im.mode != "1": raise IOError, "cannot write mode %s as XBM" % im.mode fp.write("#define im_width %d\n" % im.size[0]) fp.write("#define im_height %d\n" % im.size[1]) hotspot = im.encoderinfo.get("hotspot") if hotspot: fp.write("#define im_x_hot %d\n" % hotspot[0]) fp.write("#define im_y_hot %d\n" % hotspot[1]) fp.write("static char im_bits[] = {\n") ImageFile._save(im, fp, [("xbm", (0,0)+im.size, 0, None)]) fp.write("};\n")
def _save(im, fp, filename): if im.mode != "1": raise IOError, "cannot write mode %s as XBM" % im.mode fp.write("#define im_width %d\n" % im.size[0]) fp.write("#define im_height %d\n" % im.size[1]) hotspot = im.encoderinfo.get("hotspot") if hotspot: fp.write("#define im_x_hot %d\n" % hotspot[0]) fp.write("#define im_y_hot %d\n" % hotspot[1]) fp.write("static char im_bits[] = {\n") ImageFile._save(im, fp, [("xbm", (0, 0) + im.size, 0, None)]) fp.write("};\n")
def _save(im, fp, filename): if im.mode[0] != "F": im = im.convert('F') hdr = makeSpiderHeader(im) if len(hdr) < 256: raise IOError, "Error creating Spider header" # write the SPIDER header try: fp = open(filename, 'wb') except: raise IOError, "Unable to open %s for writing" % filename fp.writelines(hdr) rawmode = "F;32NF" #32-bit native floating point ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, 0, 1))]) fp.close()
def _save(im, fp, filename): if im.mode[0] != "F": im = im.convert('F') hdr = makeSpiderHeader(im) if len(hdr) < 256: raise IOError, "Error creating Spider header" # write the SPIDER header try: fp = open(filename, 'wb') except: raise IOError, "Unable to open %s for writing" % filename fp.writelines(hdr) rawmode = "F;32NF" #32-bit native floating point ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode,0,1))]) fp.close()
def _save(im, fp, filename, check=0): try: version, bits, planes, rawmode = SAVE[im.mode] except KeyError: raise ValueError, "Cannot save %s images as PCX" % im.mode if check: return check # bytes per plane stride = (im.size[0] * bits + 7) / 8 # under windows, we could determine the current screen size with # "Image.core.display_mode()[1]", but I think that's overkill... screen = im.size dpi = 100, 100 # PCX header fp.write( chr(10) + chr(version) + chr(1) + chr(bits) + o16(0) + o16(0) + o16(im.size[0]-1) + o16(im.size[1]-1) + o16(dpi[0]) + o16(dpi[1]) + chr(0)*24 + chr(255)*24 + chr(0) + chr(planes) + o16(stride) + o16(1) + o16(screen[0]) + o16(screen[1]) + chr(0)*54 ) assert fp.tell() == 128 ImageFile._save(im, fp, [("pcx", (0,0)+im.size, 0, (rawmode, bits*planes))]) if im.mode == "P": # colour palette fp.write(chr(12)) fp.write(im.im.getpalette("RGB", "RGB")) # 768 bytes elif im.mode == "L": # greyscale palette fp.write(chr(12)) for i in range(256): fp.write(chr(i)*3)
def _save(im, fp, filename, check=0): try: rawmode, bits, colormaptype, imagetype = SAVE[im.mode] except KeyError: raise IOError("cannot write mode %s as TGA" % im.mode) if check: return check if colormaptype: colormapfirst, colormaplength, colormapentry = 0, 256, 24 else: colormapfirst, colormaplength, colormapentry = 0, 0, 0 if im.mode == "RGBA": flags = 8 else: flags = 0 orientation = im.info.get("orientation", -1) if orientation > 0: flags = flags | 0x20 fp.write("\000" + chr(colormaptype) + chr(imagetype) + o16(colormapfirst) + o16(colormaplength) + chr(colormapentry) + o16(0) + o16(0) + o16(im.size[0]) + o16(im.size[1]) + chr(bits) + chr(flags)) if colormaptype: fp.write(im.im.getpalette("RGB", "BGR")) ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, orientation))])
def _save(im, fp, filename, check=0): try: version, bits, planes, rawmode = SAVE[im.mode] except KeyError: raise ValueError, "Cannot save %s images as PCX" % im.mode if check: return check # bytes per plane stride = (im.size[0] * bits + 7) / 8 # under windows, we could determine the current screen size with # "Image.core.display_mode()[1]", but I think that's overkill... screen = im.size dpi = 100, 100 # PCX header fp.write( chr(10) + chr(version) + chr(1) + chr(bits) + o16(0) + o16(0) + o16(im.size[0] - 1) + o16(im.size[1] - 1) + o16(dpi[0]) + o16(dpi[1]) + chr(0) * 24 + chr(255) * 24 + chr(0) + chr(planes) + o16(stride) + o16(1) + o16(screen[0]) + o16(screen[1]) + chr(0) * 54) assert fp.tell() == 128 ImageFile._save(im, fp, [("pcx", (0, 0) + im.size, 0, (rawmode, bits * planes))]) if im.mode == "P": # colour palette fp.write(chr(12)) fp.write(im.im.getpalette("RGB", "RGB")) # 768 bytes elif im.mode == "L": # greyscale palette fp.write(chr(12)) for i in range(256): fp.write(chr(i) * 3)
def _save(im, fp, filename): try: rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode] except KeyError: raise IOError, "cannot write mode %s as TIFF" % im.mode ifd = ImageFileDirectory(prefix) # -- multi-page -- skip TIFF header on subsequent pages if fp.tell() == 0: # tiff header (write via IFD to get everything right) # PIL always starts the first IFD at offset 8 fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8)) ifd[IMAGEWIDTH] = im.size[0] ifd[IMAGELENGTH] = im.size[1] # additions written by Greg Couch, [email protected] # inspired by image-sig posting from Kevin Cazabon, [email protected] if hasattr(im, 'tag'): # preserve tags from original TIFF image file for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION): if im.tag.tagdata.has_key(key): ifd[key] = im.tag.tagdata.get(key) # preserve some more tags from original TIFF image file # -- 2008-06-06 Florian Hoech ifd.tagtype = im.tag.tagtype for key in (IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, XMP): if im.tag.has_key(key): ifd[key] = im.tag[key] # preserve ICC profile (should also work when saving other formats # which support profiles as TIFF) -- 2008-06-06 Florian Hoech if im.info.has_key("icc_profile"): ifd[ICCPROFILE] = im.info["icc_profile"] if im.encoderinfo.has_key("description"): ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"] if im.encoderinfo.has_key("resolution"): ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] \ = _cvt_res(im.encoderinfo["resolution"]) if im.encoderinfo.has_key("x resolution"): ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo["x resolution"]) if im.encoderinfo.has_key("y resolution"): ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo["y resolution"]) if im.encoderinfo.has_key("resolution unit"): unit = im.encoderinfo["resolution unit"] if unit == "inch": ifd[RESOLUTION_UNIT] = 2 elif unit == "cm" or unit == "centimeter": ifd[RESOLUTION_UNIT] = 3 else: ifd[RESOLUTION_UNIT] = 1 if im.encoderinfo.has_key("software"): ifd[SOFTWARE] = im.encoderinfo["software"] if im.encoderinfo.has_key("date time"): ifd[DATE_TIME] = im.encoderinfo["date time"] if im.encoderinfo.has_key("artist"): ifd[ARTIST] = im.encoderinfo["artist"] if im.encoderinfo.has_key("copyright"): ifd[COPYRIGHT] = im.encoderinfo["copyright"] dpi = im.encoderinfo.get("dpi") if dpi: ifd[RESOLUTION_UNIT] = 2 ifd[X_RESOLUTION] = _cvt_res(dpi[0]) ifd[Y_RESOLUTION] = _cvt_res(dpi[1]) if bits != (1, ): ifd[BITSPERSAMPLE] = bits if len(bits) != 1: ifd[SAMPLESPERPIXEL] = len(bits) if extra is not None: ifd[EXTRASAMPLES] = extra if format != 1: ifd[SAMPLEFORMAT] = format ifd[PHOTOMETRIC_INTERPRETATION] = photo if im.mode == "P": lut = im.im.getpalette("RGB", "RGB;L") ifd[COLORMAP] = tuple(map(lambda v: ord(v) * 256, lut)) # data orientation stride = len(bits) * ((im.size[0] * bits[0] + 7) / 8) ifd[ROWSPERSTRIP] = im.size[1] ifd[STRIPBYTECOUNTS] = stride * im.size[1] ifd[STRIPOFFSETS] = 0 # this is adjusted by IFD writer ifd[COMPRESSION] = 1 # no compression offset = ifd.save(fp) ImageFile._save(im, fp, [("raw", (0, 0) + im.size, offset, (rawmode, stride, 1))]) # -- helper for multi-page save -- if im.encoderinfo.has_key("_debug_multipage"): #just to access o32 and o16 (using correct byte order) im._debug_multipage = ifd
def _save(im, fp, filename): resolution = im.encoderinfo.get("resolution", 72.0) # # make sure image data is available im.load() xref = [0]*(5+1) # placeholders fp.write("%PDF-1.2\n") fp.write("% created by PIL PDF driver " + __version__ + "\n") # # Get image characteristics width, height = im.size # FIXME: Should replace ASCIIHexDecode with RunLengthDecode (packbits) # or LZWDecode (tiff/lzw compression). Note that PDF 1.2 also supports # Flatedecode (zip compression). bits = 8 params = None if im.mode == "1": filter = "/ASCIIHexDecode" colorspace = "/DeviceGray" procset = "/ImageB" # grayscale bits = 1 elif im.mode == "L": filter = "/DCTDecode" # params = "<< /Predictor 15 /Columns %d >>" % (width-2) colorspace = "/DeviceGray" procset = "/ImageB" # grayscale elif im.mode == "P": filter = "/ASCIIHexDecode" colorspace = "[ /Indexed /DeviceRGB 255 <" palette = im.im.getpalette("RGB") for i in range(256): r = ord(palette[i*3]) g = ord(palette[i*3+1]) b = ord(palette[i*3+2]) colorspace = colorspace + "%02x%02x%02x " % (r, g, b) colorspace = colorspace + "> ]" procset = "/ImageI" # indexed color elif im.mode == "RGB": filter = "/DCTDecode" colorspace = "/DeviceRGB" procset = "/ImageC" # color images elif im.mode == "CMYK": filter = "/DCTDecode" colorspace = "/DeviceCMYK" procset = "/ImageC" # color images else: raise ValueError("cannot save mode %s" % im.mode) # # catalogue xref[1] = fp.tell() _obj(fp, 1, Type = "/Catalog", Pages = "2 0 R") _endobj(fp) # # pages xref[2] = fp.tell() _obj(fp, 2, Type = "/Pages", Count = 1, Kids = "[4 0 R]") _endobj(fp) # # image op = StringIO.StringIO() if filter == "/ASCIIHexDecode": if bits == 1: # FIXME: the hex encoder doesn't support packed 1-bit # images; do things the hard way... data = im.tostring("raw", "1") im = Image.new("L", (len(data), 1), None) im.putdata(data) ImageFile._save(im, op, [("hex", (0,0)+im.size, 0, im.mode)]) elif filter == "/DCTDecode": ImageFile._save(im, op, [("jpeg", (0,0)+im.size, 0, im.mode)]) elif filter == "/FlateDecode": ImageFile._save(im, op, [("zip", (0,0)+im.size, 0, im.mode)]) elif filter == "/RunLengthDecode": ImageFile._save(im, op, [("packbits", (0,0)+im.size, 0, im.mode)]) else: raise ValueError("unsupported PDF filter (%s)" % filter) xref[3] = fp.tell() _obj(fp, 3, Type = "/XObject", Subtype = "/Image", Width = width, # * 72.0 / resolution, Height = height, # * 72.0 / resolution, Length = len(op.getvalue()), Filter = filter, BitsPerComponent = bits, DecodeParams = params, ColorSpace = colorspace) fp.write("stream\n") fp.write(op.getvalue()) fp.write("\nendstream\n") _endobj(fp) # # page xref[4] = fp.tell() _obj(fp, 4) fp.write("<<\n/Type /Page\n/Parent 2 0 R\n"\ "/Resources <<\n/ProcSet [ /PDF %s ]\n"\ "/XObject << /image 3 0 R >>\n>>\n"\ "/MediaBox [ 0 0 %d %d ]\n/Contents 5 0 R\n>>\n" %\ (procset, int(width * 72.0 /resolution) , int(height * 72.0 / resolution))) _endobj(fp) # # page contents op = StringIO.StringIO() op.write("q %d 0 0 %d 0 0 cm /image Do Q\n" % (int(width * 72.0 / resolution), int(height * 72.0 / resolution))) xref[5] = fp.tell() _obj(fp, 5, Length = len(op.getvalue())) fp.write("stream\n") fp.write(op.getvalue()) fp.write("\nendstream\n") _endobj(fp) # # trailer startxref = fp.tell() fp.write("xref\n0 %d\n0000000000 65535 f \n" % len(xref)) for x in xref[1:]: fp.write("%010d 00000 n \n" % x) fp.write("trailer\n<<\n/Size %d\n/Root 1 0 R\n>>\n" % len(xref)) fp.write("startxref\n%d\n%%%%EOF\n" % startxref) fp.flush()
def _save(im, fp, filename): try: rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode] except KeyError: raise IOError, "cannot write mode %s as TIFF" % im.mode ifd = ImageFileDirectory(prefix) # -- multi-page -- skip TIFF header on subsequent pages if fp.tell() == 0: # tiff header (write via IFD to get everything right) # PIL always starts the first IFD at offset 8 fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8)) ifd[IMAGEWIDTH] = im.size[0] ifd[IMAGELENGTH] = im.size[1] # additions written by Greg Couch, [email protected] # inspired by image-sig posting from Kevin Cazabon, [email protected] if hasattr(im, 'tag'): # preserve tags from original TIFF image file for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION): if im.tag.tagdata.has_key(key): ifd[key] = im.tag.tagdata.get(key) # preserve some more tags from original TIFF image file # -- 2008-06-06 Florian Hoech ifd.tagtype = im.tag.tagtype for key in (IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, XMP): if im.tag.has_key(key): ifd[key] = im.tag[key] # preserve ICC profile (should also work when saving other formats # which support profiles as TIFF) -- 2008-06-06 Florian Hoech if im.info.has_key("icc_profile"): ifd[ICCPROFILE] = im.info["icc_profile"] if im.encoderinfo.has_key("description"): ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"] if im.encoderinfo.has_key("resolution"): ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] \ = _cvt_res(im.encoderinfo["resolution"]) if im.encoderinfo.has_key("x resolution"): ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo["x resolution"]) if im.encoderinfo.has_key("y resolution"): ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo["y resolution"]) if im.encoderinfo.has_key("resolution unit"): unit = im.encoderinfo["resolution unit"] if unit == "inch": ifd[RESOLUTION_UNIT] = 2 elif unit == "cm" or unit == "centimeter": ifd[RESOLUTION_UNIT] = 3 else: ifd[RESOLUTION_UNIT] = 1 if im.encoderinfo.has_key("software"): ifd[SOFTWARE] = im.encoderinfo["software"] if im.encoderinfo.has_key("date time"): ifd[DATE_TIME] = im.encoderinfo["date time"] if im.encoderinfo.has_key("artist"): ifd[ARTIST] = im.encoderinfo["artist"] if im.encoderinfo.has_key("copyright"): ifd[COPYRIGHT] = im.encoderinfo["copyright"] dpi = im.encoderinfo.get("dpi") if dpi: ifd[RESOLUTION_UNIT] = 2 ifd[X_RESOLUTION] = _cvt_res(dpi[0]) ifd[Y_RESOLUTION] = _cvt_res(dpi[1]) if bits != (1,): ifd[BITSPERSAMPLE] = bits if len(bits) != 1: ifd[SAMPLESPERPIXEL] = len(bits) if extra is not None: ifd[EXTRASAMPLES] = extra if format != 1: ifd[SAMPLEFORMAT] = format ifd[PHOTOMETRIC_INTERPRETATION] = photo if im.mode == "P": lut = im.im.getpalette("RGB", "RGB;L") ifd[COLORMAP] = tuple(map(lambda v: ord(v) * 256, lut)) # data orientation stride = len(bits) * ((im.size[0]*bits[0]+7)/8) ifd[ROWSPERSTRIP] = im.size[1] ifd[STRIPBYTECOUNTS] = stride * im.size[1] ifd[STRIPOFFSETS] = 0 # this is adjusted by IFD writer ifd[COMPRESSION] = 1 # no compression offset = ifd.save(fp) ImageFile._save(im, fp, [ ("raw", (0,0)+im.size, offset, (rawmode, stride, 1)) ]) # -- helper for multi-page save -- if im.encoderinfo.has_key("_debug_multipage"): #just to access o32 and o16 (using correct byte order) im._debug_multipage = ifd
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 _save(im, fp, filename, check=0): if im.mode == "P": # we assume this is a color Palm image with the standard colormap, # unless the "info" dict has a "custom-colormap" field rawmode = "P" bpp = 8 version = 1 elif im.mode == "L" and im.encoderinfo.has_key( "bpp") and im.encoderinfo["bpp"] in (1, 2, 4): # this is 8-bit grayscale, so we shift it to get the high-order bits, and invert it because # Palm does greyscale from white (0) to black (1) bpp = im.encoderinfo["bpp"] im = im.point(lambda x, shift=8 - bpp, maxval=(1 << bpp) - 1: maxval - (x >> shift)) # we ignore the palette here im.mode = "P" rawmode = "P;" + str(bpp) version = 1 elif im.mode == "L" and im.info.has_key("bpp") and im.info["bpp"] in (1, 2, 4): # here we assume that even though the inherent mode is 8-bit grayscale, only # the lower bpp bits are significant. We invert them to match the Palm. bpp = im.info["bpp"] im = im.point(lambda x, maxval=(1 << bpp) - 1: maxval - (x & maxval)) # we ignore the palette here im.mode = "P" rawmode = "P;" + str(bpp) version = 1 elif im.mode == "1": # monochrome -- write it inverted, as is the Palm standard rawmode = "1;I" bpp = 1 version = 0 else: raise IOError, "cannot write mode %s as Palm" % im.mode if check: return check # # make sure image data is available im.load() # write header cols = im.size[0] rows = im.size[1] rowbytes = ((cols + (16 / bpp - 1)) / (16 / bpp)) * 2 transparent_index = 0 compression_type = _COMPRESSION_TYPES["none"] flags = 0 if im.mode == "P" and im.info.has_key("custom-colormap"): flags = flags & _FLAGS["custom-colormap"] colormapsize = 4 * 256 + 2 colormapmode = im.palette.mode colormap = im.getdata().getpalette() else: colormapsize = 0 if im.info.has_key("offset"): offset = (rowbytes * rows + 16 + 3 + colormapsize) / 4 else: offset = 0 fp.write(o16b(cols) + o16b(rows) + o16b(rowbytes) + o16b(flags)) fp.write(chr(bpp)) fp.write(chr(version)) fp.write(o16b(offset)) fp.write(chr(transparent_index)) fp.write(chr(compression_type)) fp.write(o16b(0)) # reserved by Palm # now write colormap if necessary if colormapsize > 0: fp.write(o16b(256)) for i in range(256): fp.write(chr(i)) if colormapmode == 'RGB': fp.write( chr(colormap[3 * i]) + chr(colormap[3 * i + 1]) + chr(colormap[3 * i + 2])) elif colormapmode == 'RGBA': fp.write( chr(colormap[4 * i]) + chr(colormap[4 * i + 1]) + chr(colormap[4 * i + 2])) # now convert data to raw form ImageFile._save(im, fp, [("raw", (0, 0) + im.size, 0, (rawmode, rowbytes, 1))]) fp.flush()
def _save(im, fp, filename, check=0): if im.mode == "P": # we assume this is a color Palm image with the standard colormap, # unless the "info" dict has a "custom-colormap" field rawmode = "P" bpp = 8 version = 1 elif im.mode == "L" and im.encoderinfo.has_key("bpp") and im.encoderinfo["bpp"] in (1, 2, 4): # this is 8-bit grayscale, so we shift it to get the high-order bits, and invert it because # Palm does greyscale from white (0) to black (1) bpp = im.encoderinfo["bpp"] im = im.point(lambda x, shift=8-bpp, maxval=(1 << bpp)-1: maxval - (x >> shift)) # we ignore the palette here im.mode = "P" rawmode = "P;" + str(bpp) version = 1 elif im.mode == "L" and im.info.has_key("bpp") and im.info["bpp"] in (1, 2, 4): # here we assume that even though the inherent mode is 8-bit grayscale, only # the lower bpp bits are significant. We invert them to match the Palm. bpp = im.info["bpp"] im = im.point(lambda x, maxval=(1 << bpp)-1: maxval - (x & maxval)) # we ignore the palette here im.mode = "P" rawmode = "P;" + str(bpp) version = 1 elif im.mode == "1": # monochrome -- write it inverted, as is the Palm standard rawmode = "1;I" bpp = 1 version = 0 else: raise IOError, "cannot write mode %s as Palm" % im.mode if check: return check # # make sure image data is available im.load() # write header cols = im.size[0] rows = im.size[1] rowbytes = ((cols + (16/bpp - 1)) / (16 / bpp)) * 2; transparent_index = 0 compression_type = _COMPRESSION_TYPES["none"] flags = 0; if im.mode == "P" and im.info.has_key("custom-colormap"): flags = flags & _FLAGS["custom-colormap"] colormapsize = 4 * 256 + 2; colormapmode = im.palette.mode colormap = im.getdata().getpalette() else: colormapsize = 0 if im.info.has_key("offset"): offset = (rowbytes * rows + 16 + 3 + colormapsize) / 4; else: offset = 0 fp.write(o16b(cols) + o16b(rows) + o16b(rowbytes) + o16b(flags)) fp.write(chr(bpp)) fp.write(chr(version)) fp.write(o16b(offset)) fp.write(chr(transparent_index)) fp.write(chr(compression_type)) fp.write(o16b(0)) # reserved by Palm # now write colormap if necessary if colormapsize > 0: fp.write(o16b(256)) for i in range(256): fp.write(chr(i)) if colormapmode == 'RGB': fp.write(chr(colormap[3 * i]) + chr(colormap[3 * i + 1]) + chr(colormap[3 * i + 2])) elif colormapmode == 'RGBA': fp.write(chr(colormap[4 * i]) + chr(colormap[4 * i + 1]) + chr(colormap[4 * i + 2])) # now convert data to raw form ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, rowbytes, 1))]) fp.flush()
def _save(im, fp, filename): if _imaging_gif: # call external driver try: _imaging_gif.save(im, fp, filename) return except IOError: pass # write uncompressed file try: rawmode = RAWMODE[im.mode] imOut = im except KeyError: # convert on the fly (EXPERIMENTAL -- I'm not sure PIL # should automatically convert images on save...) if Image.getmodebase(im.mode) == "RGB": imOut = im.convert("P") rawmode = "P" else: imOut = im.convert("L") rawmode = "L" # header for s in getheader(imOut, im.encoderinfo): fp.write(s) flags = 0 try: interlace = im.encoderinfo["interlace"] except KeyError: interlace = 1 # workaround for @PIL153 if min(im.size) < 16: interlace = 0 if interlace: flags = flags | 64 try: transparency = im.encoderinfo["transparency"] except KeyError: pass else: # transparency extension block fp.write("!" + chr(249) + # extension intro chr(4) + # length chr(1) + # transparency info present o16(0) + # duration chr(int(transparency)) # transparency index + chr(0)) # local image header fp.write("," + o16(0) + o16(0) + # bounding box o16(im.size[0]) + # size o16(im.size[1]) + chr(flags) + # flags chr(8)) # bits imOut.encoderconfig = (8, interlace) ImageFile._save(imOut, fp, [("gif", (0,0)+im.size, 0, rawmode)]) fp.write("\0") # end of image data fp.write(";") # end of file try: fp.flush() except: pass
def _save(im, fp, filename): resolution = im.encoderinfo.get("resolution", 72.0) # # make sure image data is available im.load() xref = [0] * (5 + 1) # placeholders fp.write("%PDF-1.2\n") fp.write("% created by PIL PDF driver " + __version__ + "\n") # # Get image characteristics width, height = im.size # FIXME: Should replace ASCIIHexDecode with RunLengthDecode (packbits) # or LZWDecode (tiff/lzw compression). Note that PDF 1.2 also supports # Flatedecode (zip compression). bits = 8 params = None if im.mode == "1": filter = "/ASCIIHexDecode" colorspace = "/DeviceGray" procset = "/ImageB" # grayscale bits = 1 elif im.mode == "L": filter = "/DCTDecode" # params = "<< /Predictor 15 /Columns %d >>" % (width-2) colorspace = "/DeviceGray" procset = "/ImageB" # grayscale elif im.mode == "P": filter = "/ASCIIHexDecode" colorspace = "[ /Indexed /DeviceRGB 255 <" palette = im.im.getpalette("RGB") for i in range(256): r = ord(palette[i * 3]) g = ord(palette[i * 3 + 1]) b = ord(palette[i * 3 + 2]) colorspace = colorspace + "%02x%02x%02x " % (r, g, b) colorspace = colorspace + "> ]" procset = "/ImageI" # indexed color elif im.mode == "RGB": filter = "/DCTDecode" colorspace = "/DeviceRGB" procset = "/ImageC" # color images elif im.mode == "CMYK": filter = "/DCTDecode" colorspace = "/DeviceCMYK" procset = "/ImageC" # color images else: raise ValueError("cannot save mode %s" % im.mode) # # catalogue xref[1] = fp.tell() _obj(fp, 1, Type="/Catalog", Pages="2 0 R") _endobj(fp) # # pages xref[2] = fp.tell() _obj(fp, 2, Type="/Pages", Count=1, Kids="[4 0 R]") _endobj(fp) # # image op = StringIO.StringIO() if filter == "/ASCIIHexDecode": if bits == 1: # FIXME: the hex encoder doesn't support packed 1-bit # images; do things the hard way... data = im.tostring("raw", "1") im = Image.new("L", (len(data), 1), None) im.putdata(data) ImageFile._save(im, op, [("hex", (0, 0) + im.size, 0, im.mode)]) elif filter == "/DCTDecode": ImageFile._save(im, op, [("jpeg", (0, 0) + im.size, 0, im.mode)]) elif filter == "/FlateDecode": ImageFile._save(im, op, [("zip", (0, 0) + im.size, 0, im.mode)]) elif filter == "/RunLengthDecode": ImageFile._save(im, op, [("packbits", (0, 0) + im.size, 0, im.mode)]) else: raise ValueError("unsupported PDF filter (%s)" % filter) xref[3] = fp.tell() _obj( fp, 3, Type="/XObject", Subtype="/Image", Width=width, # * 72.0 / resolution, Height=height, # * 72.0 / resolution, Length=len(op.getvalue()), Filter=filter, BitsPerComponent=bits, DecodeParams=params, ColorSpace=colorspace) fp.write("stream\n") fp.write(op.getvalue()) fp.write("\nendstream\n") _endobj(fp) # # page xref[4] = fp.tell() _obj(fp, 4) fp.write("<<\n/Type /Page\n/Parent 2 0 R\n"\ "/Resources <<\n/ProcSet [ /PDF %s ]\n"\ "/XObject << /image 3 0 R >>\n>>\n"\ "/MediaBox [ 0 0 %d %d ]\n/Contents 5 0 R\n>>\n" %\ (procset, int(width * 72.0 /resolution) , int(height * 72.0 / resolution))) _endobj(fp) # # page contents op = StringIO.StringIO() op.write("q %d 0 0 %d 0 0 cm /image Do Q\n" % (int(width * 72.0 / resolution), int(height * 72.0 / resolution))) xref[5] = fp.tell() _obj(fp, 5, Length=len(op.getvalue())) fp.write("stream\n") fp.write(op.getvalue()) fp.write("\nendstream\n") _endobj(fp) # # trailer startxref = fp.tell() fp.write("xref\n0 %d\n0000000000 65535 f \n" % len(xref)) for x in xref[1:]: fp.write("%010d 00000 n \n" % x) fp.write("trailer\n<<\n/Size %d\n/Root 1 0 R\n>>\n" % len(xref)) fp.write("startxref\n%d\n%%%%EOF\n" % startxref) fp.flush()