def setink(self, ink): # compatibility if warnings: warnings.warn( "'setink' is deprecated; use keyword arguments instead", DeprecationWarning, stacklevel=2) if Image.isStringType(ink): ink = ImageColor.getcolor(ink, self.mode) if self.palette and not Image.isNumberType(ink): ink = self.palette.getcolor(ink) self.ink = self.draw.draw_ink(ink, self.mode)
def setink(self, ink): # compatibility if warnings: warnings.warn( "'setink' is deprecated; use keyword arguments instead", DeprecationWarning, stacklevel=2 ) if Image.isStringType(ink): ink = ImageColor.getcolor(ink, self.mode) if self.palette and not Image.isNumberType(ink): ink = self.palette.getcolor(ink) self.ink = self.draw.draw_ink(ink, self.mode)
def load(self, im): im.fp.seek(0) # rewind return Image.fromstring( "RGB", im.size, Image.core.drawwmf(im.fp.read(), im.size, self.bbox), "raw", "BGR", (im.size[0]*3 + 3) & -4, -1 )
def __fixup(self, im1): # convert image to suitable mode if isinstance(im1, _Operand): # argument was an image. if im1.im.mode in ("1", "L"): return im1.im.convert("I") elif im1.im.mode in ("I", "F"): return im1.im else: raise ValueError, "unsupported mode: %s" % im1.im.mode else: # argument was a constant if _isconstant(im1) and self.im.mode in ("1", "L", "I"): return Image.new("I", self.im.size, im1) else: return Image.new("F", self.im.size, im1)
def tostring(self): # experimental: convert palette to string if self.rawmode: raise ValueError("palette contains raw palette data") if Image.isStringType(self.palette): return self.palette return array.array("B", self.palette).tostring()
def grabclipboard(): debug = 0 # temporary interface data = Image.core.grabclipboard(debug) if Image.isStringType(data): import BmpImagePlugin, StringIO return BmpImagePlugin.DibImageFile(StringIO.StringIO(data)) return data
def open(filename): # FIXME: modify to return a WalImageFile instance instead of # plain Image object ? if hasattr(filename, "read"): fp = filename else: import __builtin__ fp = __builtin__.open(filename, "rb") # read header fields header = fp.read(32 + 24 + 32 + 12) size = i32(header, 32), i32(header, 36) offset = i32(header, 40) # load pixel data fp.seek(offset) im = Image.fromstring("P", size, fp.read(size[0] * size[1])) im.putpalette(quake2palette) im.format = "WAL" im.format_description = "Quake2 Texture" # strings are null-terminated im.info["name"] = header[:32].split("\0", 1)[0] next_name = header[56:56 + 32].split("\0", 1)[0] if next_name: im.info["next_name"] = next_name return im
def open(filename): # FIXME: modify to return a WalImageFile instance instead of # plain Image object ? if hasattr(filename, "read"): fp = filename else: import __builtin__ fp = __builtin__.open(filename, "rb") # read header fields header = fp.read(32+24+32+12) size = i32(header, 32), i32(header, 36) offset = i32(header, 40) # load pixel data fp.seek(offset) im = Image.fromstring("P", size, fp.read(size[0] * size[1])) im.putpalette(quake2palette) im.format = "WAL" im.format_description = "Quake2 Texture" # strings are null-terminated im.info["name"] = header[:32].split("\0", 1)[0] next_name = header[56:56+32].split("\0", 1)[0] if next_name: im.info["next_name"] = next_name return im
def __init__(self, im): data = None colortable = None # handle filename, if given instead of image name if hasattr(im, "toUtf8"): # FIXME - is this really the best way to do this? im = unicode(im.toUtf8(), "utf-8") if Image.isStringType(im): im = Image.open(im) if im.mode == "1": format = QImage.Format_Mono elif im.mode == "L": format = QImage.Format_Indexed8 colortable = [] for i in range(256): colortable.append(rgb(i, i, i)) elif im.mode == "P": format = QImage.Format_Indexed8 colortable = [] palette = im.getpalette() for i in range(0, len(palette), 3): colortable.append(rgb(*palette[i:i+3])) elif im.mode == "RGB": data = im.tostring("raw", "BGRX") format = QImage.Format_RGB32 elif im.mode == "RGBA": try: data = im.tostring("raw", "BGRA") except SystemError: # workaround for earlier versions r, g, b, a = im.split() im = Image.merge("RGBA", (b, g, r, a)) format = QImage.Format_ARGB32 else: raise ValueError("unsupported image mode %r" % im.mode) # must keep a reference, or Qt will crash! self.__data = data or im.tostring() QImage.__init__(self, self.__data, im.size[0], im.size[1], format) if colortable: self.setColorTable(colortable)
def __init__(self, im): data = None colortable = None # handle filename, if given instead of image name if hasattr(im, "toUtf8"): # FIXME - is this really the best way to do this? im = unicode(im.toUtf8(), "utf-8") if Image.isStringType(im): im = Image.open(im) if im.mode == "1": format = QImage.Format_Mono elif im.mode == "L": format = QImage.Format_Indexed8 colortable = [] for i in range(256): colortable.append(rgb(i, i, i)) elif im.mode == "P": format = QImage.Format_Indexed8 colortable = [] palette = im.getpalette() for i in range(0, len(palette), 3): colortable.append(rgb(*palette[i:i + 3])) elif im.mode == "RGB": data = im.tostring("raw", "BGRX") format = QImage.Format_RGB32 elif im.mode == "RGBA": try: data = im.tostring("raw", "BGRA") except SystemError: # workaround for earlier versions r, g, b, a = im.split() im = Image.merge("RGBA", (b, g, r, a)) format = QImage.Format_ARGB32 else: raise ValueError("unsupported image mode %r" % im.mode) # must keep a reference, or Qt will crash! self.__data = data or im.tostring() QImage.__init__(self, self.__data, im.size[0], im.size[1], format) if colortable: self.setColorTable(colortable)
def expand(image, border=0, fill=0): "Add border to image" left, top, right, bottom = _border(border) width = left + image.size[0] + right height = top + image.size[1] + bottom out = Image.new(image.mode, (width, height), _color(fill, image.mode)) out.paste(image, (left, top)) return out
def load_path(filename): "Load a font file, searching along the Python path." for dir in sys.path: if Image.isDirectory(dir): try: return load(os.path.join(dir, filename)) except IOError: pass raise IOError("cannot find font file")
def __init__(self, profile): # accepts a string (filename), a file-like object, or a low-level # profile object if Image.isStringType(profile): self._set(core.profile_open(profile), profile) elif hasattr(profile, "read"): self._set(core.profile_fromstring(profile.read())) else: self._set(profile) # assume it's already a profile
def grab(bbox=None): size, data = grabber() im = Image.fromstring( "RGB", size, data, # RGB, 32-bit line padding, origo in lower left corner "raw", "BGR", (size[0]*3 + 3) & -4, -1 ) if bbox: im = im.crop(bbox) return im
def build_prototype_image(): image = Image.new("L", (1,len(_Palm8BitColormapValues),)) image.putdata(range(len(_Palm8BitColormapValues))) palettedata = () for i in range(len(_Palm8BitColormapValues)): palettedata = palettedata + _Palm8BitColormapValues[i] for i in range(256 - len(_Palm8BitColormapValues)): palettedata = palettedata + (0, 0, 0) image.putpalette(palettedata) return image
def _getink(self, ink, fill=None): if ink is None and fill is None: if self.fill: fill = self.ink else: ink = self.ink else: if ink is not None: if Image.isStringType(ink): ink = ImageColor.getcolor(ink, self.mode) if self.palette and not Image.isNumberType(ink): ink = self.palette.getcolor(ink) ink = self.draw.draw_ink(ink, self.mode) if fill is not None: if Image.isStringType(fill): fill = ImageColor.getcolor(fill, self.mode) if self.palette and not Image.isNumberType(fill): fill = self.palette.getcolor(fill) fill = self.draw.draw_ink(fill, self.mode) return ink, fill
def bdf_char(f): # skip to STARTCHAR while 1: s = f.readline() if not s: return None if s[:9] == "STARTCHAR": break id = string.strip(s[9:]) # load symbol properties props = {} while 1: s = f.readline() if not s or s[:6] == "BITMAP": break i = string.find(s, " ") props[s[:i]] = s[i+1:-1] # load bitmap bitmap = [] while 1: s = f.readline() if not s or s[:7] == "ENDCHAR": break bitmap.append(s[:-1]) bitmap = string.join(bitmap, "") [x, y, l, d] = map(int, string.split(props["BBX"])) [dx, dy] = map(int, string.split(props["DWIDTH"])) bbox = (dx, dy), (l, -d-y, x+l, -d), (0, 0, x, y) try: im = Image.fromstring("1", (x, y), bitmap, "hex", "1") except ValueError: # deal with zero-width characters im = Image.new("1", (x, y)) return id, int(props["ENCODING"]), bbox, im
def getcolor(color, mode): # same as getrgb, but converts the result to the given mode color = getrgb(color) if mode == "RGB": return color if mode == "RGBA": r, g, b = color return r, g, b, 255 if Image.getmodebase(mode) == "L": r, g, b = color return (r * 299 + g * 587 + b * 114) / 1000 return color
def getcolor(color, mode): # same as getrgb, but converts the result to the given mode color = getrgb(color) if mode == "RGB": return color if mode == "RGBA": r, g, b = color return r, g, b, 255 if Image.getmodebase(mode) == "L": r, g, b = color return (r*299 + g*587 + b*114)/1000 return color
def _save(im, fp, tile): "Helper to save image based on tile list" im.load() if not hasattr(im, "encoderconfig"): im.encoderconfig = () tile.sort(_tilesort) # FIXME: make MAXBLOCK a configuration parameter bufsize = max(MAXBLOCK, im.size[0] * 4) # see RawEncode.c try: fh = fp.fileno() fp.flush() except AttributeError: # compress to Python file-compatible object for e, b, o, a in tile: e = Image._getencoder(im.mode, e, a, im.encoderconfig) if o > 0: fp.seek(o, 0) e.setimage(im.im, b) while 1: l, s, d = e.encode(bufsize) fp.write(d) if s: break if s < 0: raise IOError("encoder error %d when writing image file" % s) else: # slight speedup: compress to real file object for e, b, o, a in tile: e = Image._getencoder(im.mode, e, a, im.encoderconfig) if o > 0: fp.seek(o, 0) e.setimage(im.im, b) s = e.encode_to_file(fh, bufsize) if s < 0: raise IOError("encoder error %d when writing image file" % s) try: fp.flush() except: pass
def getcolor(self, color): # experimental: given an rgb tuple, allocate palette entry if self.rawmode: raise ValueError("palette contains raw palette data") if Image.isTupleType(color): try: return self.colors[color] except KeyError: # allocate new color slot if Image.isStringType(self.palette): self.palette = map(int, self.palette) index = len(self.colors) if index >= 256: raise ValueError("cannot allocate more than 256 colors") self.colors[color] = index self.palette[index] = color[0] self.palette[index + 256] = color[1] self.palette[index + 512] = color[2] self.dirty = 1 return index else: raise ValueError("unknown color specifier: %r" % color)
def build_prototype_image(): image = Image.new("L", ( 1, len(_Palm8BitColormapValues), )) image.putdata(range(len(_Palm8BitColormapValues))) palettedata = () for i in range(len(_Palm8BitColormapValues)): palettedata = palettedata + _Palm8BitColormapValues[i] for i in range(256 - len(_Palm8BitColormapValues)): palettedata = palettedata + (0, 0, 0) image.putpalette(palettedata) return image
def grab(bbox=None): size, data = grabber() im = Image.fromstring( "RGB", size, data, # RGB, 32-bit line padding, origo in lower left corner "raw", "BGR", (size[0] * 3 + 3) & -4, -1) if bbox: im = im.crop(bbox) return im
def __init__(self, image, size=None): if hasattr(image, "mode") and hasattr(image, "size"): mode = image.mode size = image.size else: mode = image image = None if mode not in ["1", "L", "P", "RGB"]: mode = Image.getmodebase(mode) self.image = Image.core.display(mode, size) self.mode = mode self.size = size if image: self.paste(image)
def apply(self, op, im1, im2=None, mode=None): im1 = self.__fixup(im1) if im2 is None: # unary operation out = Image.new(mode or im1.mode, im1.size, None) im1.load() try: op = getattr(_imagingmath, op + "_" + im1.mode) except AttributeError: raise TypeError, "bad operand type for '%s'" % op _imagingmath.unop(op, out.im.id, im1.im.id) else: # binary operation im2 = self.__fixup(im2) if im1.mode != im2.mode: # convert both arguments to floating point if im1.mode != "F": im1 = im1.convert("F") if im2.mode != "F": im2 = im2.convert("F") if im1.mode != im2.mode: raise ValueError, "mode mismatch" if im1.size != im2.size: # crop both arguments to a common size size = (min(im1.size[0], im2.size[0]), min(im1.size[1], im2.size[1])) if im1.size != size: im1 = im1.crop((0, 0) + size) if im2.size != size: im2 = im2.crop((0, 0) + size) out = Image.new(mode or im1.mode, size, None) else: out = Image.new(mode or im1.mode, im1.size, None) im1.load() im2.load() try: op = getattr(_imagingmath, op + "_" + im1.mode) except AttributeError: raise TypeError, "bad operand type for '%s'" % op _imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id) return _Operand(out)
def show(self, image, **options): # save temporary image to disk if image.mode[:4] == "I;16": # @PIL88 @PIL101 # "I;16" isn't an 'official' mode, but we still want to # provide a simple way to show 16-bit images. base = "L" # FIXME: auto-contrast if max() > 255? else: base = Image.getmodebase(image.mode) if base != image.mode and image.mode != "1": image = image.convert(base) self.show_image(image, **options)
def apply(self, op, im1, im2=None, mode=None): im1 = self.__fixup(im1) if im2 is None: # unary operation out = Image.new(mode or im1.mode, im1.size, None) im1.load() try: op = getattr(_imagingmath, op+"_"+im1.mode) except AttributeError: raise TypeError, "bad operand type for '%s'" % op _imagingmath.unop(op, out.im.id, im1.im.id) else: # binary operation im2 = self.__fixup(im2) if im1.mode != im2.mode: # convert both arguments to floating point if im1.mode != "F": im1 = im1.convert("F") if im2.mode != "F": im2 = im2.convert("F") if im1.mode != im2.mode: raise ValueError, "mode mismatch" if im1.size != im2.size: # crop both arguments to a common size size = (min(im1.size[0], im2.size[0]), min(im1.size[1], im2.size[1])) if im1.size != size: im1 = im1.crop((0, 0) + size) if im2.size != size: im2 = im2.crop((0, 0) + size) out = Image.new(mode or im1.mode, size, None) else: out = Image.new(mode or im1.mode, im1.size, None) im1.load(); im2.load() try: op = getattr(_imagingmath, op+"_"+im1.mode) except AttributeError: raise TypeError, "bad operand type for '%s'" % op _imagingmath.binop(op, out.im.id, im1.im.id, im2.im.id) return _Operand(out)
def compile(self): "Create metrics and bitmap" if self.bitmap: return # create bitmap large enough to hold all data h = w = maxwidth = 0 lines = 1 for glyph in self: if glyph: d, dst, src, im = glyph h = max(h, src[3] - src[1]) w = w + (src[2] - src[0]) if w > WIDTH: lines = lines + 1 w = (src[2] - src[0]) maxwidth = max(maxwidth, w) xsize = maxwidth ysize = lines * h if xsize == 0 and ysize == 0: return "" self.ysize = h # paste glyphs into bitmap self.bitmap = Image.new("1", (xsize, ysize)) self.metrics = [None] * 256 x = y = 0 for i in range(256): glyph = self[i] if glyph: d, dst, src, im = glyph xx, yy = src[2] - src[0], src[3] - src[1] x0, y0 = x, y x = x + xx if x > WIDTH: x, y = 0, y + h x0, y0 = x, y x = xx s = src[0] + x0, src[1] + y0, src[2] + x0, src[3] + y0 self.bitmap.paste(im.crop(src), s) # print chr(i), dst, s self.metrics[i] = d, dst, s
def _load_bitmaps(self, metrics): # # bitmap data bitmaps = [] fp, format, i16, i32 = self._getformat(PCF_BITMAPS) nbitmaps = i32(fp.read(4)) if nbitmaps != len(metrics): raise IOError, "Wrong number of bitmaps" offsets = [] for i in range(nbitmaps): offsets.append(i32(fp.read(4))) bitmapSizes = [] for i in range(4): bitmapSizes.append(i32(fp.read(4))) byteorder = format & 4 # non-zero => MSB bitorder = format & 8 # non-zero => MSB padindex = format & 3 bitmapsize = bitmapSizes[padindex] offsets.append(bitmapsize) data = fp.read(bitmapsize) pad = BYTES_PER_ROW[padindex] mode = "1;R" if bitorder: mode = "1" for i in range(nbitmaps): x, y, l, r, w, a, d, f = metrics[i] b, e = offsets[i], offsets[i+1] bitmaps.append( Image.fromstring("1", (x, y), data[b:e], "raw", mode, pad(x)) ) return bitmaps
def _load_pilfont(self, filename): file = open(filename, "rb") for ext in (".png", ".gif", ".pbm"): try: fullname = os.path.splitext(filename)[0] + ext image = Image.open(fullname) except: pass else: if image and image.mode in ("1", "L"): break else: raise IOError("cannot find glyph data file") self.file = fullname return self._load_pilfont_data(file, image)
def _load_bitmaps(self, metrics): # # bitmap data bitmaps = [] fp, format, i16, i32 = self._getformat(PCF_BITMAPS) nbitmaps = i32(fp.read(4)) if nbitmaps != len(metrics): raise IOError, "Wrong number of bitmaps" offsets = [] for i in range(nbitmaps): offsets.append(i32(fp.read(4))) bitmapSizes = [] for i in range(4): bitmapSizes.append(i32(fp.read(4))) byteorder = format & 4 # non-zero => MSB bitorder = format & 8 # non-zero => MSB padindex = format & 3 bitmapsize = bitmapSizes[padindex] offsets.append(bitmapsize) data = fp.read(bitmapsize) pad = BYTES_PER_ROW[padindex] mode = "1;R" if bitorder: mode = "1" for i in range(nbitmaps): x, y, l, r, w, a, d, f = metrics[i] b, e = offsets[i], offsets[i + 1] bitmaps.append( Image.fromstring("1", (x, y), data[b:e], "raw", mode, pad(x))) return bitmaps
def loadImageSeries(filelist=None): " create a list of Image.images for use in montage " if filelist == None or len(filelist) < 1: return imglist = [] for img in filelist: if not os.path.exists(img): print "unable to find %s" % img continue try: im = Image.open(img).convert2byte() except: if not isSpiderImage(img): print img + " is not a Spider image file" continue im.info['filename'] = img imglist.append(im) return imglist
def load(self): if len(self.tile) != 1 or self.tile[0][0] != "iptc": return ImageFile.ImageFile.load(self) type, tile, box = self.tile[0] encoding, offset = tile self.fp.seek(offset) # Copy image data to temporary file outfile = tempfile.mktemp() o = open(outfile, "wb") if encoding == "raw": # To simplify access to the extracted file, # prepend a PPM header o.write("P5\n%d %d\n255\n" % self.size) while 1: type, size = self.field() if type != (8, 10): break while size > 0: s = self.fp.read(min(size, 8192)) if not s: break o.write(s) size = size - len(s) o.close() try: try: # fast self.im = Image.core.open_ppm(outfile) except: # slightly slower im = Image.open(outfile) im.load() self.im = im.im finally: try: os.unlink(outfile) except: pass
def close(self): # finish decoding if self.decoder: # get rid of what's left in the buffers self.feed("") self.data = self.decoder = None if not self.finished: raise IOError("image was incomplete") if not self.image: raise IOError("cannot parse this image") if self.data: # incremental parsing not possible; reopen the file # not that we have all data try: fp = _ParserFile(self.data) self.image = Image.open(fp) finally: self.image.load() fp.close() # explicitly close the virtual file return self.image
def __init__(self, fp=None, filename=None): Image.Image.__init__(self) self.tile = None self.readonly = 1 # until we know better self.decoderconfig = () self.decodermaxblock = MAXBLOCK if Image.isStringType(fp): # filename self.fp = open(fp, "rb") self.filename = fp else: # stream self.fp = fp self.filename = filename try: self._open() except IndexError, v: # end of data if Image.DEBUG > 1: traceback.print_exc() raise SyntaxError, v
raise SyntaxError("Not an HDF file") self.fp.seek(offset) # make something up self.mode = "F" self.size = 1, 1 loader = self._load() if loader: loader.open(self) def _load(self): return _handler def _save(im, fp, filename): if _handler is None or not hasattr("_handler", "save"): raise IOError("HDF5 save handler not installed") _handler.save(im, fp, filename) # -------------------------------------------------------------------- # Registry Image.register_open(HDF5StubImageFile.format, HDF5StubImageFile, _accept) Image.register_save(HDF5StubImageFile.format, _save) Image.register_extension(HDF5StubImageFile.format, ".h5") Image.register_extension(HDF5StubImageFile.format, ".hdf")
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))]) # ALTERNATIVE: save via builtin debug function # im._dump(filename) # # -------------------------------------------------------------------- Image.register_open("PPM", PpmImageFile, _accept) Image.register_save("PPM", _save) Image.register_extension("PPM", ".pbm") Image.register_extension("PPM", ".pgm") Image.register_extension("PPM", ".ppm")
self.mode = "P" self.palette = ImagePalette.raw("RGB", string.join(palette, "")) self.tile = [("raw", (0, 0)+self.size, self.fp.tell(), ("P", 0, 1))] def load_read(self, bytes): # # load all image data in one chunk xsize, ysize = self.size s = [None] * ysize for i in range(ysize): s[i] = string.ljust(self.fp.readline()[1:xsize+1], xsize) self.fp = None return string.join(s, "") # # Registry Image.register_open("XPM", XpmImageFile, _accept) Image.register_extension("XPM", ".xpm") Image.register_mime("XPM", "image/xpm")
elif compression == 1: # # packbits compression i = 0 tile = [] bytecount = read(channels * ysize * 2) offset = file.tell() for channel in range(channels): layer = mode[channel] if mode == "CMYK": layer = layer + ";I" tile.append(("packbits", bbox, offset, layer)) for y in range(ysize): offset = offset + i16(bytecount[i:i + 2]) i = i + 2 file.seek(offset) if offset & 1: read(1) # padding return tile # -------------------------------------------------------------------- # registry Image.register_open("PSD", PsdImageFile, _accept) Image.register_extension("PSD", ".psd")
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))]) # # -------------------------------------------------------------------- # Registry Image.register_open("TGA", TgaImageFile, _accept) Image.register_save("TGA", _save) Image.register_extension("TGA", ".tga")
if width <= 0 or height <= 0 or bytes != 1: raise SyntaxError, "not a GIMP brush" comment = self.fp.read(header_size - 20)[:-1] self.mode = "L" self.size = width, height self.info["comment"] = comment # Since the brush is so small, we read the data immediately self.data = self.fp.read(width * height) def load(self): if not self.data: return # create an image out of the brush data block self.im = Image.core.new(self.mode, self.size) self.im.fromstring(self.data) self.data = "" # # registry Image.register_open("GBR", GbrImageFile, _accept) Image.register_extension("GBR", ".gbr")
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_cjpeg(im, fp, filename): # ALTERNATIVE: handle JPEGs via the IJG command line utilities. import os file = im._dump() os.system("cjpeg %s >%s" % (file, filename)) try: os.unlink(file) except: pass # -------------------------------------------------------------------q- # Registry stuff Image.register_open("JPEG", JpegImageFile, _accept) Image.register_save("JPEG", _save) Image.register_extension("JPEG", ".jfif") Image.register_extension("JPEG", ".jpe") Image.register_extension("JPEG", ".jpg") Image.register_extension("JPEG", ".jpeg") Image.register_mime("JPEG", "image/jpeg")
if not _accept(self.fp.read(8)): raise SyntaxError("Not a GRIB file") self.fp.seek(offset) # make something up self.mode = "F" self.size = 1, 1 loader = self._load() if loader: loader.open(self) def _load(self): return _handler def _save(im, fp, filename): if _handler is None or not hasattr("_handler", "save"): raise IOError("GRIB save handler not installed") _handler.save(im, fp, filename) # -------------------------------------------------------------------- # Registry Image.register_open(GribStubImageFile.format, GribStubImageFile, _accept) Image.register_save(GribStubImageFile.format, _save) Image.register_extension(GribStubImageFile.format, ".grib")
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()
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() # # -------------------------------------------------------------------- Image.register_save("PDF", _save) Image.register_extension("PDF", ".pdf") Image.register_mime("PDF", "application/pdf")