mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-24 17:06:16 +03:00
flake8
This commit is contained in:
parent
5d9107ee4c
commit
8de95676e0
|
@ -26,12 +26,12 @@ from PIL import FontFile
|
|||
# --------------------------------------------------------------------
|
||||
|
||||
bdf_slant = {
|
||||
"R": "Roman",
|
||||
"I": "Italic",
|
||||
"O": "Oblique",
|
||||
"RI": "Reverse Italic",
|
||||
"RO": "Reverse Oblique",
|
||||
"OT": "Other"
|
||||
"R": "Roman",
|
||||
"I": "Italic",
|
||||
"O": "Oblique",
|
||||
"RI": "Reverse Italic",
|
||||
"RO": "Reverse Oblique",
|
||||
"OT": "Other"
|
||||
}
|
||||
|
||||
bdf_spacing = {
|
||||
|
@ -40,8 +40,8 @@ bdf_spacing = {
|
|||
"C": "Cell"
|
||||
}
|
||||
|
||||
def bdf_char(f):
|
||||
|
||||
def bdf_char(f):
|
||||
# skip to STARTCHAR
|
||||
while True:
|
||||
s = f.readline()
|
||||
|
@ -82,6 +82,7 @@ def bdf_char(f):
|
|||
|
||||
return id, int(props["ENCODING"]), bbox, im
|
||||
|
||||
|
||||
##
|
||||
# Font file plugin for the X11 BDF format.
|
||||
|
||||
|
@ -113,10 +114,10 @@ class BdfFontFile(FontFile.FontFile):
|
|||
font[4] = bdf_slant[font[4].upper()]
|
||||
font[11] = bdf_spacing[font[11].upper()]
|
||||
|
||||
ascent = int(props["FONT_ASCENT"])
|
||||
descent = int(props["FONT_DESCENT"])
|
||||
# ascent = int(props["FONT_ASCENT"])
|
||||
# descent = int(props["FONT_DESCENT"])
|
||||
|
||||
fontname = ";".join(font[1:])
|
||||
# fontname = ";".join(font[1:])
|
||||
|
||||
# print "#", fontname
|
||||
# for i in comments:
|
||||
|
|
|
@ -51,9 +51,11 @@ BIT2MODE = {
|
|||
32: ("RGB", "BGRX")
|
||||
}
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:2] == b"BM"
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for the Windows BMP format.
|
||||
|
||||
|
@ -62,8 +64,7 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
format = "BMP"
|
||||
format_description = "Windows Bitmap"
|
||||
|
||||
def _bitmap(self, header = 0, offset = 0):
|
||||
|
||||
def _bitmap(self, header=0, offset=0):
|
||||
if header:
|
||||
self.fp.seek(header)
|
||||
|
||||
|
@ -97,8 +98,9 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
# upside-down storage
|
||||
self.size = self.size[0], 2**32 - self.size[1]
|
||||
direction = 0
|
||||
|
||||
self.info["dpi"] = tuple(map(lambda x: math.ceil(x / 39.3701), pxperm))
|
||||
|
||||
self.info["dpi"] = tuple(map(lambda x: math.ceil(x / 39.3701),
|
||||
pxperm))
|
||||
|
||||
else:
|
||||
raise IOError("Unsupported BMP header type (%d)" % len(s))
|
||||
|
@ -137,7 +139,7 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
greyscale = 1
|
||||
if colors == 2:
|
||||
indices = (0, 255)
|
||||
elif colors > 2**16 or colors <=0: #We're reading a i32.
|
||||
elif colors > 2**16 or colors <= 0: # We're reading a i32.
|
||||
raise IOError("Unsupported BMP Palette size (%d)" % colors)
|
||||
else:
|
||||
indices = list(range(colors))
|
||||
|
@ -163,7 +165,8 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
self.tile = [("raw",
|
||||
(0, 0) + self.size,
|
||||
offset,
|
||||
(rawmode, ((self.size[0]*bits+31)>>3)&(~3), direction))]
|
||||
(rawmode, ((self.size[0]*bits+31) >> 3) & (~3),
|
||||
direction))]
|
||||
|
||||
self.info["compression"] = compression
|
||||
|
||||
|
@ -197,8 +200,8 @@ SAVE = {
|
|||
"RGB": ("BGR", 24, 0),
|
||||
}
|
||||
|
||||
def _save(im, fp, filename, check=0):
|
||||
|
||||
def _save(im, fp, filename, check=0):
|
||||
try:
|
||||
rawmode, bits, colors = SAVE[im.mode]
|
||||
except KeyError:
|
||||
|
@ -214,10 +217,10 @@ def _save(im, fp, filename, check=0):
|
|||
# 1 meter == 39.3701 inches
|
||||
ppm = tuple(map(lambda x: int(x * 39.3701), dpi))
|
||||
|
||||
stride = ((im.size[0]*bits+7)//8+3)&(~3)
|
||||
header = 40 # or 64 for OS/2 version 2
|
||||
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]
|
||||
image = stride * im.size[1]
|
||||
|
||||
# bitmap header
|
||||
fp.write(b"BM" + # file type (magic)
|
||||
|
@ -248,7 +251,8 @@ def _save(im, fp, filename, check=0):
|
|||
elif im.mode == "P":
|
||||
fp.write(im.im.getpalette("RGB", "BGRX"))
|
||||
|
||||
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))])
|
||||
ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 0,
|
||||
(rawmode, stride, -1))])
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
|
|
@ -13,6 +13,7 @@ from PIL import Image, ImageFile
|
|||
|
||||
_handler = None
|
||||
|
||||
|
||||
##
|
||||
# Install application-specific BUFR image handler.
|
||||
#
|
||||
|
@ -22,12 +23,14 @@ def register_handler(handler):
|
|||
global _handler
|
||||
_handler = handler
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Image adapter
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] == b"BUFR" or prefix[:4] == b"ZCZC"
|
||||
|
||||
|
||||
class BufrStubImageFile(ImageFile.StubImageFile):
|
||||
|
||||
format = "BUFR"
|
||||
|
@ -53,6 +56,7 @@ class BufrStubImageFile(ImageFile.StubImageFile):
|
|||
def _load(self):
|
||||
return _handler
|
||||
|
||||
|
||||
def _save(im, fp, filename):
|
||||
if _handler is None or not hasattr("_handler", "save"):
|
||||
raise IOError("BUFR save handler not installed")
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
# A file object that provides read access to a part of an existing
|
||||
# file (for example a TAR file).
|
||||
|
||||
|
||||
class ContainerIO:
|
||||
|
||||
##
|
||||
|
@ -48,7 +49,7 @@ class ContainerIO:
|
|||
# for current offset, and 2 for end of region. You cannot move
|
||||
# the pointer outside the defined region.
|
||||
|
||||
def seek(self, offset, mode = 0):
|
||||
def seek(self, offset, mode=0):
|
||||
if mode == 1:
|
||||
self.pos = self.pos + offset
|
||||
elif mode == 2:
|
||||
|
@ -75,12 +76,12 @@ class ContainerIO:
|
|||
# read until end of region.
|
||||
# @return An 8-bit string.
|
||||
|
||||
def read(self, n = 0):
|
||||
def read(self, n=0):
|
||||
if n:
|
||||
n = min(n, self.length - self.pos)
|
||||
else:
|
||||
n = self.length - self.pos
|
||||
if not n: # EOF
|
||||
if not n: # EOF
|
||||
return ""
|
||||
self.pos = self.pos + n
|
||||
return self.fh.read(n)
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
# 1996-08-23 fl Handle files from Macintosh (0.3)
|
||||
# 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.4)
|
||||
# 2003-09-07 fl Check gs.close status (from Federico Di Gregorio) (0.5)
|
||||
# 2014-05-07 e Handling of EPS with binary preview and fixed resolution resizing
|
||||
# 2014-05-07 e Handling of EPS with binary preview and fixed resolution
|
||||
# resizing
|
||||
#
|
||||
# Copyright (c) 1997-2003 by Secret Labs AB.
|
||||
# Copyright (c) 1995-2003 by Fredrik Lundh
|
||||
|
@ -51,20 +52,21 @@ if sys.platform.startswith('win'):
|
|||
else:
|
||||
gs_windows_binary = False
|
||||
|
||||
|
||||
def has_ghostscript():
|
||||
if gs_windows_binary:
|
||||
return True
|
||||
if not sys.platform.startswith('win'):
|
||||
import subprocess
|
||||
try:
|
||||
gs = subprocess.Popen(['gs','--version'], stdout=subprocess.PIPE)
|
||||
gs = subprocess.Popen(['gs', '--version'], stdout=subprocess.PIPE)
|
||||
gs.stdout.read()
|
||||
return True
|
||||
except OSError:
|
||||
# no ghostscript
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def Ghostscript(tile, size, fp, scale=1):
|
||||
"""Render an image using Ghostscript"""
|
||||
|
@ -72,25 +74,28 @@ def Ghostscript(tile, size, fp, scale=1):
|
|||
# Unpack decoder tile
|
||||
decoder, tile, offset, data = tile[0]
|
||||
length, bbox = data
|
||||
|
||||
#Hack to support hi-res rendering
|
||||
scale = int(scale) or 1
|
||||
orig_size = size
|
||||
orig_bbox = bbox
|
||||
size = (size[0] * scale, size[1] * scale)
|
||||
# resolution is dependend on bbox and size
|
||||
res = ( float((72.0 * size[0]) / (bbox[2]-bbox[0])), float((72.0 * size[1]) / (bbox[3]-bbox[1])) )
|
||||
#print("Ghostscript", scale, size, orig_size, bbox, orig_bbox, res)
|
||||
|
||||
import tempfile, os, subprocess
|
||||
# Hack to support hi-res rendering
|
||||
scale = int(scale) or 1
|
||||
# orig_size = size
|
||||
# orig_bbox = bbox
|
||||
size = (size[0] * scale, size[1] * scale)
|
||||
# resolution is dependent on bbox and size
|
||||
res = (float((72.0 * size[0]) / (bbox[2]-bbox[0])),
|
||||
float((72.0 * size[1]) / (bbox[3]-bbox[1])))
|
||||
# print("Ghostscript", scale, size, orig_size, bbox, orig_bbox, res)
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
out_fd, outfile = tempfile.mkstemp()
|
||||
os.close(out_fd)
|
||||
in_fd, infile = tempfile.mkstemp()
|
||||
os.close(in_fd)
|
||||
|
||||
|
||||
# ignore length and offset!
|
||||
# ghostscript can read it
|
||||
# ghostscript can read it
|
||||
# copy whole file to read in ghostscript
|
||||
with open(infile, 'wb') as f:
|
||||
# fetch length of fp
|
||||
|
@ -109,17 +114,17 @@ def Ghostscript(tile, size, fp, scale=1):
|
|||
|
||||
# Build ghostscript command
|
||||
command = ["gs",
|
||||
"-q", # quiet mode
|
||||
"-g%dx%d" % size, # set output geometry (pixels)
|
||||
"-r%fx%f" % res, # set input DPI (dots per inch)
|
||||
"-dNOPAUSE -dSAFER", # don't pause between pages, safe mode
|
||||
"-sDEVICE=ppmraw", # ppm driver
|
||||
"-sOutputFile=%s" % outfile, # output file
|
||||
"-q", # quiet mode
|
||||
"-g%dx%d" % size, # set output geometry (pixels)
|
||||
"-r%fx%f" % res, # set input DPI (dots per inch)
|
||||
"-dNOPAUSE -dSAFER", # don't pause between pages, safe mode
|
||||
"-sDEVICE=ppmraw", # ppm driver
|
||||
"-sOutputFile=%s" % outfile, # output file
|
||||
"-c", "%d %d translate" % (-bbox[0], -bbox[1]),
|
||||
# adjust for image origin
|
||||
"-f", infile, # input file
|
||||
]
|
||||
|
||||
# adjust for image origin
|
||||
"-f", infile, # input file
|
||||
]
|
||||
|
||||
if gs_windows_binary is not None:
|
||||
if not gs_windows_binary:
|
||||
raise WindowsError('Unable to locate Ghostscript on paths')
|
||||
|
@ -127,7 +132,8 @@ def Ghostscript(tile, size, fp, scale=1):
|
|||
|
||||
# push data through ghostscript
|
||||
try:
|
||||
gs = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
gs = subprocess.Popen(command, stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE)
|
||||
gs.stdin.close()
|
||||
status = gs.wait()
|
||||
if status:
|
||||
|
@ -137,8 +143,9 @@ def Ghostscript(tile, size, fp, scale=1):
|
|||
try:
|
||||
os.unlink(outfile)
|
||||
os.unlink(infile)
|
||||
except: pass
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
return im
|
||||
|
||||
|
||||
|
@ -147,22 +154,28 @@ class PSFile:
|
|||
def __init__(self, fp):
|
||||
self.fp = fp
|
||||
self.char = None
|
||||
|
||||
def __getattr__(self, id):
|
||||
v = getattr(self.fp, id)
|
||||
setattr(self, id, v)
|
||||
return v
|
||||
|
||||
def seek(self, offset, whence=0):
|
||||
self.char = None
|
||||
self.fp.seek(offset, whence)
|
||||
|
||||
def read(self, count):
|
||||
return self.fp.read(count).decode('latin-1')
|
||||
|
||||
def readbinary(self, count):
|
||||
return self.fp.read(count)
|
||||
|
||||
def tell(self):
|
||||
pos = self.fp.tell()
|
||||
if self.char:
|
||||
pos -= 1
|
||||
return pos
|
||||
|
||||
def readline(self):
|
||||
s = b""
|
||||
if self.char:
|
||||
|
@ -187,6 +200,7 @@ def _accept(prefix):
|
|||
# Image plugin for Encapsulated Postscript. This plugin supports only
|
||||
# a few variants of this format.
|
||||
|
||||
|
||||
class EpsImageFile(ImageFile.ImageFile):
|
||||
"""EPS File Parser for the Python Imaging Library"""
|
||||
|
||||
|
@ -197,13 +211,14 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
|
||||
fp = PSFile(self.fp)
|
||||
|
||||
# FIX for: Some EPS file not handled correctly / issue #302
|
||||
# FIX for: Some EPS file not handled correctly / issue #302
|
||||
# EPS can contain binary data
|
||||
# or start directly with latin coding
|
||||
# read header in both ways to handle both
|
||||
# file types
|
||||
# more info see http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf
|
||||
|
||||
# more info see:
|
||||
# http://partners.adobe.com/public/developer/en/ps/5002.EPSF_Spec.pdf
|
||||
|
||||
# for HEAD without binary preview
|
||||
s = fp.read(4)
|
||||
# for HEAD with binary preview
|
||||
|
@ -220,19 +235,19 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
else:
|
||||
raise SyntaxError("not an EPS file")
|
||||
|
||||
# go to offset - start of "%!PS"
|
||||
# go to offset - start of "%!PS"
|
||||
fp.seek(offset)
|
||||
|
||||
|
||||
box = None
|
||||
|
||||
self.mode = "RGB"
|
||||
self.size = 1, 1 # FIXME: huh?
|
||||
self.size = 1, 1 # FIXME: huh?
|
||||
|
||||
#
|
||||
# Load EPS header
|
||||
|
||||
s = fp.readline()
|
||||
|
||||
|
||||
while s:
|
||||
|
||||
if len(s) > 255:
|
||||
|
@ -258,7 +273,7 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
# put floating point values there anyway.
|
||||
box = [int(float(s)) for s in v.split()]
|
||||
self.size = box[2] - box[0], box[3] - box[1]
|
||||
self.tile = [("eps", (0,0) + self.size, offset,
|
||||
self.tile = [("eps", (0, 0) + self.size, offset,
|
||||
(length, box))]
|
||||
except:
|
||||
pass
|
||||
|
@ -288,7 +303,6 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
if s[:1] != "%":
|
||||
break
|
||||
|
||||
|
||||
#
|
||||
# Scan for an "ImageData" descriptor
|
||||
|
||||
|
@ -307,7 +321,8 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
[x, y, bi, mo, z3, z4, en, id] =\
|
||||
s[11:].split(None, 7)
|
||||
|
||||
x = int(x); y = int(y)
|
||||
x = int(x)
|
||||
y = int(y)
|
||||
|
||||
bi = int(bi)
|
||||
mo = int(mo)
|
||||
|
@ -363,11 +378,12 @@ class EpsImageFile(ImageFile.ImageFile):
|
|||
self.size = self.im.size
|
||||
self.tile = []
|
||||
|
||||
def load_seek(self,*args,**kwargs):
|
||||
def load_seek(self, *args, **kwargs):
|
||||
# we can't incrementally load, so force ImageFile.parser to
|
||||
# use our custom load method by defining this method.
|
||||
# use our custom load method by defining this method.
|
||||
pass
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
|
@ -392,8 +408,10 @@ def _save(im, fp, filename, eps=1):
|
|||
class NoCloseStream:
|
||||
def __init__(self, fp):
|
||||
self.fp = fp
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.fp, name)
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
|
@ -407,7 +425,7 @@ def _save(im, fp, filename, eps=1):
|
|||
# write EPS header
|
||||
fp.write("%!PS-Adobe-3.0 EPSF-3.0\n")
|
||||
fp.write("%%Creator: PIL 0.1 EpsEncode\n")
|
||||
#fp.write("%%CreationDate: %s"...)
|
||||
# fp.write("%%CreationDate: %s"...)
|
||||
fp.write("%%%%BoundingBox: 0 0 %d %d\n" % im.size)
|
||||
fp.write("%%Pages: 1\n")
|
||||
fp.write("%%EndComments\n")
|
||||
|
@ -421,13 +439,13 @@ def _save(im, fp, filename, eps=1):
|
|||
fp.write("10 dict begin\n")
|
||||
fp.write("/buf %d string def\n" % (im.size[0] * operator[1]))
|
||||
fp.write("%d %d scale\n" % im.size)
|
||||
fp.write("%d %d 8\n" % im.size) # <= bits
|
||||
fp.write("%d %d 8\n" % im.size) # <= bits
|
||||
fp.write("[%d 0 0 -%d 0 %d]\n" % (im.size[0], im.size[1], im.size[1]))
|
||||
fp.write("{ currentfile buf readhexstring pop } bind\n")
|
||||
fp.write(operator[2] + "\n")
|
||||
fp.flush()
|
||||
|
||||
ImageFile._save(im, base_fp, [("eps", (0,0)+im.size, 0, None)])
|
||||
ImageFile._save(im, base_fp, [("eps", (0, 0)+im.size, 0, None)])
|
||||
|
||||
fp.write("\n%%%%EndBinary\n")
|
||||
fp.write("grestore end\n")
|
||||
|
|
|
@ -34,16 +34,18 @@ MODES = {
|
|||
(0x00020000, 0x00020001, 0x00020002): ("RGB", "YCC;P"),
|
||||
(0x00028000, 0x00028001, 0x00028002, 0x00027ffe): ("RGBA", "YCCA;P"),
|
||||
# standard RGB (NIFRGB)
|
||||
(0x00030000, 0x00030001, 0x00030002): ("RGB","RGB"),
|
||||
(0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA","RGBA"),
|
||||
(0x00030000, 0x00030001, 0x00030002): ("RGB", "RGB"),
|
||||
(0x00038000, 0x00038001, 0x00038002, 0x00037ffe): ("RGBA", "RGBA"),
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:8] == MAGIC
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for the FlashPix images.
|
||||
|
||||
|
@ -67,7 +69,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
|
||||
self._open_index(1)
|
||||
|
||||
def _open_index(self, index = 1):
|
||||
def _open_index(self, index=1):
|
||||
#
|
||||
# get the Image Contents Property Set
|
||||
|
||||
|
@ -95,7 +97,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
|
||||
id = self.maxid << 16
|
||||
|
||||
s = prop[0x2000002|id]
|
||||
s = prop[0x2000002 | id]
|
||||
|
||||
colors = []
|
||||
for i in range(i32(s, 4)):
|
||||
|
@ -107,7 +109,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
# load JPEG tables, if any
|
||||
self.jpeg = {}
|
||||
for i in range(256):
|
||||
id = 0x3000001|(i << 16)
|
||||
id = 0x3000001 | (i << 16)
|
||||
if id in prop:
|
||||
self.jpeg[i] = prop[id]
|
||||
|
||||
|
@ -115,7 +117,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
|
||||
self._open_subimage(1, self.maxid)
|
||||
|
||||
def _open_subimage(self, index = 1, subimage = 0):
|
||||
def _open_subimage(self, index=1, subimage=0):
|
||||
#
|
||||
# setup tile descriptors for a given subimage
|
||||
|
||||
|
@ -159,14 +161,14 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
compression = i32(s, i+8)
|
||||
|
||||
if compression == 0:
|
||||
self.tile.append(("raw", (x,y,x+xtile,y+ytile),
|
||||
i32(s, i) + 28, (self.rawmode)))
|
||||
self.tile.append(("raw", (x, y, x+xtile, y+ytile),
|
||||
i32(s, i) + 28, (self.rawmode)))
|
||||
|
||||
elif compression == 1:
|
||||
|
||||
# FIXME: the fill decoder is not implemented
|
||||
self.tile.append(("fill", (x,y,x+xtile,y+ytile),
|
||||
i32(s, i) + 28, (self.rawmode, s[12:16])))
|
||||
self.tile.append(("fill", (x, y, x+xtile, y+ytile),
|
||||
i32(s, i) + 28, (self.rawmode, s[12:16])))
|
||||
|
||||
elif compression == 2:
|
||||
|
||||
|
@ -182,14 +184,14 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
# this problem :
|
||||
jpegmode, rawmode = "YCbCrK", "CMYK"
|
||||
else:
|
||||
jpegmode = None # let the decoder decide
|
||||
jpegmode = None # let the decoder decide
|
||||
|
||||
else:
|
||||
# The image is stored as defined by rawmode
|
||||
jpegmode = rawmode
|
||||
|
||||
self.tile.append(("jpeg", (x,y,x+xtile,y+ytile),
|
||||
i32(s, i) + 28, (rawmode, jpegmode)))
|
||||
self.tile.append(("jpeg", (x, y, x+xtile, y+ytile),
|
||||
i32(s, i) + 28, (rawmode, jpegmode)))
|
||||
|
||||
# FIXME: jpeg tables are tile dependent; the prefix
|
||||
# data must be placed in the tile descriptor itself!
|
||||
|
@ -204,7 +206,7 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
if x >= xsize:
|
||||
x, y = 0, y + ytile
|
||||
if y >= ysize:
|
||||
break # isn't really required
|
||||
break # isn't really required
|
||||
|
||||
self.stream = stream
|
||||
self.fp = None
|
||||
|
@ -212,7 +214,8 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||
def load(self):
|
||||
|
||||
if not self.fp:
|
||||
self.fp = self.ole.openstream(self.stream[:2] + ["Subimage 0000 Data"])
|
||||
self.fp = self.ole.openstream(self.stream[:2] +
|
||||
["Subimage 0000 Data"])
|
||||
|
||||
ImageFile.ImageFile.load(self)
|
||||
|
||||
|
|
|
@ -17,9 +17,11 @@ from PIL import Image, ImageFile, _binary
|
|||
|
||||
i32 = _binary.i32be
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return i32(prefix) >= 20 and i32(prefix[4:8]) == 1
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for the GIMP brush format.
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ except ImportError:
|
|||
|
||||
i16 = _binary.i16be
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for the GD uncompressed format. Note that this format
|
||||
# is not supported by the standard <b>Image.open</b> function. To use
|
||||
|
@ -52,7 +53,7 @@ class GdImageFile(ImageFile.ImageFile):
|
|||
# Header
|
||||
s = self.fp.read(775)
|
||||
|
||||
self.mode = "L" # FIXME: "P"
|
||||
self.mode = "L" # FIXME: "P"
|
||||
self.size = i16(s[0:2]), i16(s[2:4])
|
||||
|
||||
# transparency index
|
||||
|
@ -62,7 +63,8 @@ class GdImageFile(ImageFile.ImageFile):
|
|||
|
||||
self.palette = ImagePalette.raw("RGB", s[7:])
|
||||
|
||||
self.tile = [("raw", (0,0)+self.size, 775, ("L", 0, -1))]
|
||||
self.tile = [("raw", (0, 0)+self.size, 775, ("L", 0, -1))]
|
||||
|
||||
|
||||
##
|
||||
# Load texture from a GD image file.
|
||||
|
@ -73,7 +75,7 @@ class GdImageFile(ImageFile.ImageFile):
|
|||
# @return An image instance.
|
||||
# @exception IOError If the image could not be read.
|
||||
|
||||
def open(fp, mode = "r"):
|
||||
def open(fp, mode="r"):
|
||||
|
||||
if mode != "r":
|
||||
raise ValueError("bad mode")
|
||||
|
|
|
@ -46,6 +46,7 @@ o16 = _binary.o16le
|
|||
def _accept(prefix):
|
||||
return prefix[:6] in [b"GIF87a", b"GIF89a"]
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for GIF images. This plugin supports both GIF87 and
|
||||
# GIF89 images.
|
||||
|
@ -79,16 +80,16 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
# get global palette
|
||||
self.info["background"] = i8(s[11])
|
||||
# check if palette contains colour indices
|
||||
p = self.fp.read(3<<bits)
|
||||
p = self.fp.read(3 << bits)
|
||||
for i in range(0, len(p), 3):
|
||||
if not (i//3 == i8(p[i]) == i8(p[i+1]) == i8(p[i+2])):
|
||||
p = ImagePalette.raw("RGB", p)
|
||||
self.global_palette = self.palette = p
|
||||
break
|
||||
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self.__rewind = self.fp.tell()
|
||||
self.seek(0) # get ready to read first frame
|
||||
self.seek(0) # get ready to read first frame
|
||||
|
||||
def seek(self, frame):
|
||||
|
||||
|
@ -96,7 +97,7 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
# rewind
|
||||
self.__offset = 0
|
||||
self.dispose = None
|
||||
self.dispose_extent = [0, 0, 0, 0] #x0, y0, x1, y1
|
||||
self.dispose_extent = [0, 0, 0, 0] # x0, y0, x1, y1
|
||||
self.__frame = -1
|
||||
self.__fp.seek(self.__rewind)
|
||||
self._prev_im = None
|
||||
|
@ -185,7 +186,7 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
if flags & 128:
|
||||
bits = (flags & 7) + 1
|
||||
self.palette =\
|
||||
ImagePalette.raw("RGB", self.fp.read(3<<bits))
|
||||
ImagePalette.raw("RGB", self.fp.read(3 << bits))
|
||||
|
||||
# image data
|
||||
bits = i8(self.fp.read(1))
|
||||
|
@ -219,7 +220,6 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
except (AttributeError, KeyError):
|
||||
pass
|
||||
|
||||
|
||||
if not self.tile:
|
||||
# self.__fp = None
|
||||
raise EOFError("no more images in GIF file")
|
||||
|
@ -240,7 +240,8 @@ class GifImageFile(ImageFile.ImageFile):
|
|||
# we do this by pasting the updated area onto the previous
|
||||
# frame which we then use as the current image content
|
||||
updated = self.im.crop(self.dispose_extent)
|
||||
self._prev_im.paste(updated, self.dispose_extent, updated.convert('RGBA'))
|
||||
self._prev_im.paste(updated, self.dispose_extent,
|
||||
updated.convert('RGBA'))
|
||||
self.im = self._prev_im
|
||||
self._prev_im = self.im.copy()
|
||||
|
||||
|
@ -258,6 +259,7 @@ RAWMODE = {
|
|||
"P": "P",
|
||||
}
|
||||
|
||||
|
||||
def _save(im, fp, filename):
|
||||
|
||||
if _imaging_gif:
|
||||
|
@ -266,7 +268,7 @@ def _save(im, fp, filename):
|
|||
_imaging_gif.save(im, fp, filename)
|
||||
return
|
||||
except IOError:
|
||||
pass # write uncompressed file
|
||||
pass # write uncompressed file
|
||||
|
||||
if im.mode in RAWMODE:
|
||||
imOut = im
|
||||
|
@ -343,15 +345,17 @@ def _save(im, fp, filename):
|
|||
o8(8)) # bits
|
||||
|
||||
imOut.encoderconfig = (8, interlace)
|
||||
ImageFile._save(imOut, fp, [("gif", (0,0)+im.size, 0, RAWMODE[imOut.mode])])
|
||||
ImageFile._save(imOut, fp, [("gif", (0, 0)+im.size, 0,
|
||||
RAWMODE[imOut.mode])])
|
||||
|
||||
fp.write(b"\0") # end of image data
|
||||
fp.write(b"\0") # end of image data
|
||||
|
||||
fp.write(b";") # end of file
|
||||
fp.write(b";") # end of file
|
||||
|
||||
try:
|
||||
fp.flush()
|
||||
except: pass
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def _save_netpbm(im, fp, filename):
|
||||
|
@ -363,7 +367,7 @@ def _save_netpbm(im, fp, filename):
|
|||
|
||||
import os
|
||||
from subprocess import Popen, check_call, PIPE, CalledProcessError
|
||||
import tempfile
|
||||
import tempfile
|
||||
file = im._dump()
|
||||
|
||||
if im.mode != "RGB":
|
||||
|
@ -380,8 +384,9 @@ def _save_netpbm(im, fp, filename):
|
|||
stderr = tempfile.TemporaryFile()
|
||||
quant_proc = Popen(quant_cmd, stdout=PIPE, stderr=stderr)
|
||||
stderr = tempfile.TemporaryFile()
|
||||
togif_proc = Popen(togif_cmd, stdin=quant_proc.stdout, stdout=f, stderr=stderr)
|
||||
|
||||
togif_proc = Popen(togif_cmd, stdin=quant_proc.stdout, stdout=f,
|
||||
stderr=stderr)
|
||||
|
||||
# Allow ppmquant to receive SIGPIPE if ppmtogif exits
|
||||
quant_proc.stdout.close()
|
||||
|
||||
|
@ -420,7 +425,7 @@ def getheader(im, palette=None, info=None):
|
|||
sourcePalette = palette[:768]
|
||||
else:
|
||||
sourcePalette = im.im.getpalette("RGB")[:768]
|
||||
else: # L-mode
|
||||
else: # L-mode
|
||||
if palette and isinstance(palette, bytes):
|
||||
sourcePalette = palette[:768]
|
||||
else:
|
||||
|
@ -455,9 +460,11 @@ def getheader(im, palette=None, info=None):
|
|||
for i in range(len(imageBytes)):
|
||||
imageBytes[i] = newPositions[imageBytes[i]]
|
||||
im.frombytes(bytes(imageBytes))
|
||||
newPaletteBytes = paletteBytes + (768 - len(paletteBytes)) * b'\x00'
|
||||
im.putpalette(newPaletteBytes)
|
||||
im.palette = ImagePalette.ImagePalette("RGB", palette = paletteBytes, size = len(paletteBytes))
|
||||
newPaletteBytes = (paletteBytes +
|
||||
(768 - len(paletteBytes)) * b'\x00')
|
||||
im.putpalette(newPaletteBytes)
|
||||
im.palette = ImagePalette.ImagePalette("RGB", palette=paletteBytes,
|
||||
size=len(paletteBytes))
|
||||
|
||||
if not paletteBytes:
|
||||
paletteBytes = sourcePalette
|
||||
|
@ -466,7 +473,8 @@ def getheader(im, palette=None, info=None):
|
|||
# calculate the palette size for the header
|
||||
import math
|
||||
colorTableSize = int(math.ceil(math.log(len(paletteBytes)//3, 2)))-1
|
||||
if colorTableSize < 0: colorTableSize = 0
|
||||
if colorTableSize < 0:
|
||||
colorTableSize = 0
|
||||
# size of global color table + global color table flag
|
||||
header.append(o8(colorTableSize + 128))
|
||||
# background + reserved/aspect
|
||||
|
@ -475,7 +483,7 @@ def getheader(im, palette=None, info=None):
|
|||
|
||||
# add the missing amount of bytes
|
||||
# the palette has to be 2<<n in size
|
||||
actualTargetSizeDiff = (2<<colorTableSize) - len(paletteBytes)//3
|
||||
actualTargetSizeDiff = (2 << colorTableSize) - len(paletteBytes)//3
|
||||
if actualTargetSizeDiff > 0:
|
||||
paletteBytes += o8(0) * 3 * actualTargetSizeDiff
|
||||
|
||||
|
@ -484,17 +492,18 @@ def getheader(im, palette=None, info=None):
|
|||
return header, usedPaletteColors
|
||||
|
||||
|
||||
def getdata(im, offset = (0, 0), **params):
|
||||
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
|
||||
im.load() # make sure raster data is available
|
||||
|
||||
fp = collector()
|
||||
|
||||
|
@ -510,9 +519,9 @@ def getdata(im, offset = (0, 0), **params):
|
|||
o8(0) + # flags
|
||||
o8(8)) # bits
|
||||
|
||||
ImageFile._save(im, fp, [("gif", (0,0)+im.size, 0, RAWMODE[im.mode])])
|
||||
ImageFile._save(im, fp, [("gif", (0, 0)+im.size, 0, RAWMODE[im.mode])])
|
||||
|
||||
fp.write(b"\0") # end of image data
|
||||
fp.write(b"\0") # end of image data
|
||||
|
||||
finally:
|
||||
del im.encoderinfo
|
||||
|
|
|
@ -13,6 +13,7 @@ from PIL import Image, ImageFile
|
|||
|
||||
_handler = None
|
||||
|
||||
|
||||
##
|
||||
# Install application-specific GRIB image handler.
|
||||
#
|
||||
|
@ -22,12 +23,14 @@ def register_handler(handler):
|
|||
global _handler
|
||||
_handler = handler
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Image adapter
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[0:4] == b"GRIB" and prefix[7] == b'\x01'
|
||||
|
||||
|
||||
class GribStubImageFile(ImageFile.StubImageFile):
|
||||
|
||||
format = "GRIB"
|
||||
|
@ -53,6 +56,7 @@ class GribStubImageFile(ImageFile.StubImageFile):
|
|||
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")
|
||||
|
|
|
@ -13,6 +13,7 @@ from PIL import Image, ImageFile
|
|||
|
||||
_handler = None
|
||||
|
||||
|
||||
##
|
||||
# Install application-specific HDF5 image handler.
|
||||
#
|
||||
|
@ -22,12 +23,14 @@ def register_handler(handler):
|
|||
global _handler
|
||||
_handler = handler
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Image adapter
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:8] == b"\x89HDF\r\n\x1a\n"
|
||||
|
||||
|
||||
class HDF5StubImageFile(ImageFile.StubImageFile):
|
||||
|
||||
format = "HDF5"
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
#
|
||||
|
||||
from PIL import Image, ImageFile, PngImagePlugin, _binary
|
||||
import struct, io
|
||||
import io
|
||||
import struct
|
||||
|
||||
enable_jpeg2k = hasattr(Image.core, 'jp2klib_version')
|
||||
if enable_jpeg2k:
|
||||
|
@ -26,9 +27,11 @@ i8 = _binary.i8
|
|||
|
||||
HEADERSIZE = 8
|
||||
|
||||
|
||||
def nextheader(fobj):
|
||||
return struct.unpack('>4sI', fobj.read(HEADERSIZE))
|
||||
|
||||
|
||||
def read_32t(fobj, start_length, size):
|
||||
# The 128x128 icon seems to have an extra header for some reason.
|
||||
(start, length) = start_length
|
||||
|
@ -38,6 +41,7 @@ def read_32t(fobj, start_length, size):
|
|||
raise SyntaxError('Unknown signature, expecting 0x00000000')
|
||||
return read_32(fobj, (start + 4, length - 4), size)
|
||||
|
||||
|
||||
def read_32(fobj, start_length, size):
|
||||
"""
|
||||
Read a 32bit RGB icon resource. Seems to be either uncompressed or
|
||||
|
@ -83,6 +87,7 @@ def read_32(fobj, start_length, size):
|
|||
im.im.putband(band.im, band_ix)
|
||||
return {"RGB": im}
|
||||
|
||||
|
||||
def read_mk(fobj, start_length, size):
|
||||
# Alpha masks seem to be uncompressed
|
||||
(start, length) = start_length
|
||||
|
@ -94,6 +99,7 @@ def read_mk(fobj, start_length, size):
|
|||
)
|
||||
return {"A": band}
|
||||
|
||||
|
||||
def read_png_or_jpeg2000(fobj, start_length, size):
|
||||
(start, length) = start_length
|
||||
fobj.seek(start)
|
||||
|
@ -103,10 +109,11 @@ def read_png_or_jpeg2000(fobj, start_length, size):
|
|||
im = PngImagePlugin.PngImageFile(fobj)
|
||||
return {"RGBA": im}
|
||||
elif sig[:4] == b'\xff\x4f\xff\x51' \
|
||||
or sig[:4] == b'\x0d\x0a\x87\x0a' \
|
||||
or sig == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a':
|
||||
or sig[:4] == b'\x0d\x0a\x87\x0a' \
|
||||
or sig == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a':
|
||||
if not enable_jpeg2k:
|
||||
raise ValueError('Unsupported icon subimage format (rebuild PIL with JPEG 2000 support to fix this)')
|
||||
raise ValueError('Unsupported icon subimage format (rebuild PIL '
|
||||
'with JPEG 2000 support to fix this)')
|
||||
# j2k, jpc or j2c
|
||||
fobj.seek(start)
|
||||
jp2kstream = fobj.read(length)
|
||||
|
@ -118,6 +125,7 @@ def read_png_or_jpeg2000(fobj, start_length, size):
|
|||
else:
|
||||
raise ValueError('Unsupported icon subimage format')
|
||||
|
||||
|
||||
class IcnsFile:
|
||||
|
||||
SIZES = {
|
||||
|
@ -225,7 +233,7 @@ class IcnsFile:
|
|||
im = channels.get('RGBA', None)
|
||||
if im:
|
||||
return im
|
||||
|
||||
|
||||
im = channels.get("RGB").copy()
|
||||
try:
|
||||
im.putalpha(channels["A"])
|
||||
|
@ -233,6 +241,7 @@ class IcnsFile:
|
|||
pass
|
||||
return im
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for Mac OS icons.
|
||||
|
||||
|
@ -275,7 +284,7 @@ class IcnsImageFile(ImageFile.ImageFile):
|
|||
|
||||
# If this is a PNG or JPEG 2000, it won't be loaded yet
|
||||
im.load()
|
||||
|
||||
|
||||
self.im = im.im
|
||||
self.mode = im.mode
|
||||
self.size = im.size
|
||||
|
@ -288,7 +297,8 @@ Image.register_open("ICNS", IcnsImageFile, lambda x: x[:4] == b'icns')
|
|||
Image.register_extension("ICNS", '.icns')
|
||||
|
||||
if __name__ == '__main__':
|
||||
import os, sys
|
||||
import os
|
||||
import sys
|
||||
imf = IcnsImageFile(open(sys.argv[1], 'rb'))
|
||||
for size in imf.info['sizes']:
|
||||
imf.size = size
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
# This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis <casadebender@gmail.com>.
|
||||
# This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis
|
||||
# <casadebender@gmail.com>.
|
||||
# https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin
|
||||
#
|
||||
# Icon format references:
|
||||
|
@ -35,6 +36,7 @@ i32 = _binary.i32le
|
|||
|
||||
_MAGIC = b"\0\0\1\0"
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] == _MAGIC
|
||||
|
||||
|
@ -63,7 +65,7 @@ class IcoFile:
|
|||
icon_header = {
|
||||
'width': i8(s[0]),
|
||||
'height': i8(s[1]),
|
||||
'nb_color': i8(s[2]), # Number of colors in image (0 if >=8bpp)
|
||||
'nb_color': i8(s[2]), # No. of colors in image (0 if >=8bpp)
|
||||
'reserved': i8(s[3]),
|
||||
'planes': i16(s[4:]),
|
||||
'bpp': i16(s[6:]),
|
||||
|
@ -78,10 +80,14 @@ class IcoFile:
|
|||
|
||||
# See Wikipedia notes about color depth.
|
||||
# We need this just to differ images with equal sizes
|
||||
icon_header['color_depth'] = (icon_header['bpp'] or (icon_header['nb_color'] != 0 and ceil(log(icon_header['nb_color'],2))) or 256)
|
||||
icon_header['color_depth'] = (icon_header['bpp'] or
|
||||
(icon_header['nb_color'] != 0 and
|
||||
ceil(log(icon_header['nb_color'],
|
||||
2))) or 256)
|
||||
|
||||
icon_header['dim'] = (icon_header['width'], icon_header['height'])
|
||||
icon_header['square'] = icon_header['width'] * icon_header['height']
|
||||
icon_header['square'] = (icon_header['width'] *
|
||||
icon_header['height'])
|
||||
|
||||
self.entry.append(icon_header)
|
||||
|
||||
|
@ -102,7 +108,7 @@ class IcoFile:
|
|||
Get an image from the icon
|
||||
"""
|
||||
for (i, h) in enumerate(self.entry):
|
||||
if size == h['dim'] and (bpp == False or bpp == h['color_depth']):
|
||||
if size == h['dim'] and (bpp is False or bpp == h['color_depth']):
|
||||
return self.frame(i)
|
||||
return self.frame(0)
|
||||
|
||||
|
@ -127,7 +133,7 @@ class IcoFile:
|
|||
# change tile dimension to only encompass XOR image
|
||||
im.size = (im.size[0], int(im.size[1] / 2))
|
||||
d, e, o, a = im.tile[0]
|
||||
im.tile[0] = d, (0,0) + im.size, o, a
|
||||
im.tile[0] = d, (0, 0) + im.size, o, a
|
||||
|
||||
# figure out where AND mask image starts
|
||||
mode = a[0]
|
||||
|
@ -139,8 +145,9 @@ class IcoFile:
|
|||
|
||||
if 32 == bpp:
|
||||
# 32-bit color depth icon image allows semitransparent areas
|
||||
# PIL's DIB format ignores transparency bits, recover them
|
||||
# The DIB is packed in BGRX byte order where X is the alpha channel
|
||||
# PIL's DIB format ignores transparency bits, recover them.
|
||||
# The DIB is packed in BGRX byte order where X is the alpha
|
||||
# channel.
|
||||
|
||||
# Back up to start of bmp data
|
||||
self.buf.seek(o)
|
||||
|
@ -162,9 +169,11 @@ class IcoFile:
|
|||
# bitmap row data is aligned to word boundaries
|
||||
w += 32 - (im.size[0] % 32)
|
||||
|
||||
# the total mask data is padded row size * height / bits per char
|
||||
# the total mask data is
|
||||
# padded row size * height / bits per char
|
||||
|
||||
and_mask_offset = o + int(im.size[0] * im.size[1] * (bpp / 8.0))
|
||||
and_mask_offset = o + int(im.size[0] * im.size[1] *
|
||||
(bpp / 8.0))
|
||||
total_bytes = int((w * im.size[1]) / 8)
|
||||
|
||||
self.buf.seek(and_mask_offset)
|
||||
|
@ -187,6 +196,7 @@ class IcoFile:
|
|||
|
||||
return im
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for Windows Icon files.
|
||||
|
||||
|
@ -194,15 +204,16 @@ class IcoImageFile(ImageFile.ImageFile):
|
|||
"""
|
||||
PIL read-only image support for Microsoft Windows .ico files.
|
||||
|
||||
By default the largest resolution image in the file will be loaded. This can
|
||||
be changed by altering the 'size' attribute before calling 'load'.
|
||||
By default the largest resolution image in the file will be loaded. This
|
||||
can be changed by altering the 'size' attribute before calling 'load'.
|
||||
|
||||
The info dictionary has a key 'sizes' that is a list of the sizes available
|
||||
in the icon file.
|
||||
|
||||
Handles classic, XP and Vista icon formats.
|
||||
|
||||
This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis <casadebender@gmail.com>.
|
||||
This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis
|
||||
<casadebender@gmail.com>.
|
||||
https://code.google.com/p/casadebender/wiki/Win32IconImagePlugin
|
||||
"""
|
||||
format = "ICO"
|
||||
|
@ -222,9 +233,9 @@ class IcoImageFile(ImageFile.ImageFile):
|
|||
self.mode = im.mode
|
||||
self.size = im.size
|
||||
|
||||
|
||||
def load_seek(self):
|
||||
# Flage the ImageFile.Parser so that it just does all the decode at the end.
|
||||
# Flage the ImageFile.Parser so that it
|
||||
# just does all the decode at the end.
|
||||
pass
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
|
|
@ -30,7 +30,7 @@ __version__ = "0.7"
|
|||
|
||||
import re
|
||||
from PIL import Image, ImageFile, ImagePalette
|
||||
from PIL._binary import i8, o8
|
||||
from PIL._binary import i8
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
@ -46,8 +46,8 @@ SCALE = "Scale (x,y)"
|
|||
SIZE = "Image size (x*y)"
|
||||
MODE = "Image type"
|
||||
|
||||
TAGS = { COMMENT:0, DATE:0, EQUIPMENT:0, FRAMES:0, LUT:0, NAME:0,
|
||||
SCALE:0, SIZE:0, MODE:0 }
|
||||
TAGS = {COMMENT: 0, DATE: 0, EQUIPMENT: 0, FRAMES: 0, LUT: 0, NAME: 0,
|
||||
SCALE: 0, SIZE: 0, MODE: 0}
|
||||
|
||||
OPEN = {
|
||||
# ifunc93/p3cfunc formats
|
||||
|
@ -94,12 +94,14 @@ for i in range(2, 33):
|
|||
|
||||
split = re.compile(br"^([A-Za-z][^:]*):[ \t]*(.*)[ \t]*$")
|
||||
|
||||
|
||||
def number(s):
|
||||
try:
|
||||
return int(s)
|
||||
except ValueError:
|
||||
return float(s)
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for the IFUNC IM file format.
|
||||
|
||||
|
@ -113,7 +115,7 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
# Quick rejection: if there's not an LF among the first
|
||||
# 100 bytes, this is (probably) not a text header.
|
||||
|
||||
if not b"\n" in self.fp.read(100):
|
||||
if b"\n" not in self.fp.read(100):
|
||||
raise SyntaxError("not an IM file")
|
||||
self.fp.seek(0)
|
||||
|
||||
|
@ -155,7 +157,7 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
|
||||
if m:
|
||||
|
||||
k, v = m.group(1,2)
|
||||
k, v = m.group(1, 2)
|
||||
|
||||
# Don't know if this is the correct encoding, but a decent guess
|
||||
# (I guess)
|
||||
|
@ -186,7 +188,8 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
|
||||
else:
|
||||
|
||||
raise SyntaxError("Syntax error in IM header: " + s.decode('ascii', 'replace'))
|
||||
raise SyntaxError("Syntax error in IM header: " +
|
||||
s.decode('ascii', 'replace'))
|
||||
|
||||
if not n:
|
||||
raise SyntaxError("Not an IM file")
|
||||
|
@ -204,8 +207,8 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
if LUT in self.info:
|
||||
# convert lookup table to palette or lut attribute
|
||||
palette = self.fp.read(768)
|
||||
greyscale = 1 # greyscale palette
|
||||
linear = 1 # linear greyscale palette
|
||||
greyscale = 1 # greyscale palette
|
||||
linear = 1 # linear greyscale palette
|
||||
for i in range(256):
|
||||
if palette[i] == palette[i+256] == palette[i+512]:
|
||||
if i8(palette[i]) != i:
|
||||
|
@ -230,7 +233,7 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
|
||||
self.__offset = offs = self.fp.tell()
|
||||
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
|
||||
if self.rawmode[:2] == "F;":
|
||||
|
||||
|
@ -239,7 +242,7 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
# use bit decoder (if necessary)
|
||||
bits = int(self.rawmode[2:])
|
||||
if bits not in [8, 16, 32]:
|
||||
self.tile = [("bit", (0,0)+self.size, offs,
|
||||
self.tile = [("bit", (0, 0)+self.size, offs,
|
||||
(bits, 8, 3, 0, -1))]
|
||||
return
|
||||
except ValueError:
|
||||
|
@ -249,12 +252,13 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
# Old LabEye/3PC files. Would be very surprised if anyone
|
||||
# ever stumbled upon such a file ;-)
|
||||
size = self.size[0] * self.size[1]
|
||||
self.tile = [("raw", (0,0)+self.size, offs, ("G", 0, -1)),
|
||||
("raw", (0,0)+self.size, offs+size, ("R", 0, -1)),
|
||||
("raw", (0,0)+self.size, offs+2*size, ("B", 0, -1))]
|
||||
self.tile = [("raw", (0, 0)+self.size, offs, ("G", 0, -1)),
|
||||
("raw", (0, 0)+self.size, offs+size, ("R", 0, -1)),
|
||||
("raw", (0, 0)+self.size, offs+2*size, ("B", 0, -1))]
|
||||
else:
|
||||
# LabEye/IFUNC files
|
||||
self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
|
||||
self.tile = [("raw", (0, 0)+self.size, offs,
|
||||
(self.rawmode, 0, -1))]
|
||||
|
||||
def seek(self, frame):
|
||||
|
||||
|
@ -276,7 +280,7 @@ class ImImageFile(ImageFile.ImageFile):
|
|||
|
||||
self.fp = self.__fp
|
||||
|
||||
self.tile = [("raw", (0,0)+self.size, offs, (self.rawmode, 0, -1))]
|
||||
self.tile = [("raw", (0, 0)+self.size, offs, (self.rawmode, 0, -1))]
|
||||
|
||||
def tell(self):
|
||||
|
||||
|
@ -305,6 +309,7 @@ SAVE = {
|
|||
"YCbCr": ("YCC", "YCbCr;L")
|
||||
}
|
||||
|
||||
|
||||
def _save(im, fp, filename, check=0):
|
||||
|
||||
try:
|
||||
|
@ -329,8 +334,8 @@ def _save(im, fp, filename, check=0):
|
|||
fp.write(b"Lut: 1\r\n")
|
||||
fp.write(b"\000" * (511-fp.tell()) + b"\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))])
|
||||
fp.write(im.im.getpalette("RGB", "RGB;L")) # 768 bytes
|
||||
ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 0, (rawmode, 0, -1))])
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
from PIL import Image
|
||||
import re
|
||||
|
||||
|
||||
def getrgb(color):
|
||||
"""
|
||||
Convert a color string to an RGB tuple. If the string cannot be parsed,
|
||||
|
@ -86,7 +87,8 @@ def getrgb(color):
|
|||
int(rgb[1] * 255 + 0.5),
|
||||
int(rgb[2] * 255 + 0.5)
|
||||
)
|
||||
m = re.match("rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$", color)
|
||||
m = re.match("rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$",
|
||||
color)
|
||||
if m:
|
||||
return (
|
||||
int(m.group(1)),
|
||||
|
@ -96,6 +98,7 @@ def getrgb(color):
|
|||
)
|
||||
raise ValueError("unknown color specifier: %r" % color)
|
||||
|
||||
|
||||
def getcolor(color, mode):
|
||||
"""
|
||||
Same as :py:func:`~PIL.ImageColor.getrgb`, but converts the RGB value to a
|
||||
|
|
|
@ -61,7 +61,7 @@ class ImageDraw:
|
|||
def __init__(self, im, mode=None):
|
||||
im.load()
|
||||
if im.readonly:
|
||||
im._copy() # make it writable
|
||||
im._copy() # make it writeable
|
||||
blend = 0
|
||||
if mode is None:
|
||||
mode = im.mode
|
||||
|
@ -85,7 +85,7 @@ class ImageDraw:
|
|||
# FIXME: fix Fill2 to properly support matte for I+F images
|
||||
self.fontmode = "1"
|
||||
else:
|
||||
self.fontmode = "L" # aliasing is okay for other modes
|
||||
self.fontmode = "L" # aliasing is okay for other modes
|
||||
self.fill = 0
|
||||
self.font = None
|
||||
|
||||
|
@ -280,6 +280,7 @@ class ImageDraw:
|
|||
font = self.getfont()
|
||||
return font.getsize(text)
|
||||
|
||||
|
||||
##
|
||||
# A simple 2D drawing interface for PIL images.
|
||||
#
|
||||
|
@ -302,6 +303,7 @@ try:
|
|||
except:
|
||||
Outline = None
|
||||
|
||||
|
||||
##
|
||||
# (Experimental) A more advanced 2D drawing interface for PIL images,
|
||||
# based on the WCK interface.
|
||||
|
@ -325,6 +327,7 @@ def getdraw(im=None, hints=None):
|
|||
im = handler.Draw(im)
|
||||
return im, handler
|
||||
|
||||
|
||||
##
|
||||
# (experimental) Fills a bounded region with a given color.
|
||||
#
|
||||
|
@ -344,10 +347,10 @@ def floodfill(image, xy, value, border=None):
|
|||
try:
|
||||
background = pixel[x, y]
|
||||
if background == value:
|
||||
return # seed point already has fill color
|
||||
return # seed point already has fill color
|
||||
pixel[x, y] = value
|
||||
except IndexError:
|
||||
return # seed point outside image
|
||||
return # seed point outside image
|
||||
edge = [(x, y)]
|
||||
if border is None:
|
||||
while edge:
|
||||
|
|
|
@ -18,21 +18,25 @@
|
|||
|
||||
from PIL import Image, ImageColor, ImageDraw, ImageFont, ImagePath
|
||||
|
||||
|
||||
class Pen:
|
||||
def __init__(self, color, width=1, opacity=255):
|
||||
self.color = ImageColor.getrgb(color)
|
||||
self.width = width
|
||||
|
||||
|
||||
class Brush:
|
||||
def __init__(self, color, opacity=255):
|
||||
self.color = ImageColor.getrgb(color)
|
||||
|
||||
|
||||
class Font:
|
||||
def __init__(self, color, file, size=12):
|
||||
# FIXME: add support for bitmap fonts
|
||||
self.color = ImageColor.getrgb(color)
|
||||
self.font = ImageFont.truetype(file, size)
|
||||
|
||||
|
||||
class Draw:
|
||||
|
||||
def __init__(self, image, size=None, color=None):
|
||||
|
@ -47,7 +51,8 @@ class Draw:
|
|||
|
||||
def render(self, op, xy, pen, brush=None):
|
||||
# handle color arguments
|
||||
outline = fill = None; width = 1
|
||||
outline = fill = None
|
||||
width = 1
|
||||
if isinstance(pen, Pen):
|
||||
outline = pen.color
|
||||
width = pen.width
|
||||
|
|
|
@ -29,8 +29,10 @@
|
|||
|
||||
from PIL import Image
|
||||
from PIL._util import isPath
|
||||
import traceback, os, sys
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
MAXBLOCK = 65536
|
||||
|
||||
|
@ -46,6 +48,7 @@ ERRORS = {
|
|||
-9: "out of memory error"
|
||||
}
|
||||
|
||||
|
||||
def raise_ioerror(error):
|
||||
try:
|
||||
message = Image.core.getcodecstatus(error)
|
||||
|
@ -55,6 +58,7 @@ def raise_ioerror(error):
|
|||
message = "decoder error %d" % error
|
||||
raise IOError(message + " when reading image file")
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Helpers
|
||||
|
@ -63,6 +67,7 @@ def _tilesort(t):
|
|||
# sort on offset
|
||||
return t[2]
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# ImageFile base class
|
||||
|
@ -74,7 +79,7 @@ class ImageFile(Image.Image):
|
|||
Image.Image.__init__(self)
|
||||
|
||||
self.tile = None
|
||||
self.readonly = 1 # until we know better
|
||||
self.readonly = 1 # until we know better
|
||||
|
||||
self.decoderconfig = ()
|
||||
self.decodermaxblock = MAXBLOCK
|
||||
|
@ -90,19 +95,19 @@ class ImageFile(Image.Image):
|
|||
|
||||
try:
|
||||
self._open()
|
||||
except IndexError as v: # end of data
|
||||
except IndexError as v: # end of data
|
||||
if Image.DEBUG > 1:
|
||||
traceback.print_exc()
|
||||
raise SyntaxError(v)
|
||||
except TypeError as v: # end of data (ord)
|
||||
except TypeError as v: # end of data (ord)
|
||||
if Image.DEBUG > 1:
|
||||
traceback.print_exc()
|
||||
raise SyntaxError(v)
|
||||
except KeyError as v: # unsupported mode
|
||||
except KeyError as v: # unsupported mode
|
||||
if Image.DEBUG > 1:
|
||||
traceback.print_exc()
|
||||
raise SyntaxError(v)
|
||||
except EOFError as v: # got header but not the first frame
|
||||
except EOFError as v: # got header but not the first frame
|
||||
if Image.DEBUG > 1:
|
||||
traceback.print_exc()
|
||||
raise SyntaxError(v)
|
||||
|
@ -135,8 +140,8 @@ class ImageFile(Image.Image):
|
|||
self.map = None
|
||||
use_mmap = self.filename and len(self.tile) == 1
|
||||
# As of pypy 2.1.0, memory mapping was failing here.
|
||||
use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')
|
||||
|
||||
use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info')
|
||||
|
||||
readonly = 0
|
||||
|
||||
# look for read/seek overrides
|
||||
|
@ -203,23 +208,25 @@ class ImageFile(Image.Image):
|
|||
while True:
|
||||
try:
|
||||
s = read(self.decodermaxblock)
|
||||
except IndexError as ie: # truncated png/gif
|
||||
except IndexError as ie: # truncated png/gif
|
||||
if LOAD_TRUNCATED_IMAGES:
|
||||
break
|
||||
else:
|
||||
raise IndexError(ie)
|
||||
|
||||
if not s and not d.handles_eof: # truncated jpeg
|
||||
if not s and not d.handles_eof: # truncated jpeg
|
||||
self.tile = []
|
||||
|
||||
# JpegDecode needs to clean things up here either way
|
||||
# If we don't destroy the decompressor, we have a memory leak.
|
||||
# If we don't destroy the decompressor,
|
||||
# we have a memory leak.
|
||||
d.cleanup()
|
||||
|
||||
if LOAD_TRUNCATED_IMAGES:
|
||||
break
|
||||
else:
|
||||
raise IOError("image file is truncated (%d bytes not processed)" % len(b))
|
||||
raise IOError("image file is truncated "
|
||||
"(%d bytes not processed)" % len(b))
|
||||
|
||||
b = b + s
|
||||
n, e = d.decode(b)
|
||||
|
@ -231,7 +238,7 @@ class ImageFile(Image.Image):
|
|||
self.tile = []
|
||||
self.readonly = readonly
|
||||
|
||||
self.fp = None # might be shared
|
||||
self.fp = None # might be shared
|
||||
|
||||
if not self.map and (not LOAD_TRUNCATED_IMAGES or t == 0) and e < 0:
|
||||
# still raised if decoder fails to return anything
|
||||
|
@ -378,10 +385,10 @@ class Parser:
|
|||
fp = io.BytesIO(self.data)
|
||||
im = Image.open(fp)
|
||||
finally:
|
||||
fp.close() # explicitly close the virtual file
|
||||
fp.close() # explicitly close the virtual file
|
||||
except IOError:
|
||||
# traceback.print_exc()
|
||||
pass # not enough data
|
||||
pass # not enough data
|
||||
else:
|
||||
flag = hasattr(im, "load_seek") or hasattr(im, "load_read")
|
||||
if flag or len(im.tile) != 1:
|
||||
|
@ -431,9 +438,10 @@ class Parser:
|
|||
self.image = Image.open(fp)
|
||||
finally:
|
||||
self.image.load()
|
||||
fp.close() # explicitly close the virtual file
|
||||
fp.close() # explicitly close the virtual file
|
||||
return self.image
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
def _save(im, fp, tile, bufsize=0):
|
||||
|
@ -450,10 +458,10 @@ def _save(im, fp, tile, bufsize=0):
|
|||
im.encoderconfig = ()
|
||||
tile.sort(key=_tilesort)
|
||||
# FIXME: make MAXBLOCK a configuration parameter
|
||||
# It would be great if we could have the encoder specifiy what it needs
|
||||
# It would be great if we could have the encoder specify what it needs
|
||||
# But, it would need at least the image size in most cases. RawEncode is
|
||||
# a tricky case.
|
||||
bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4) # see RawEncode.c
|
||||
bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4) # see RawEncode.c
|
||||
try:
|
||||
fh = fp.fileno()
|
||||
fp.flush()
|
||||
|
@ -483,7 +491,8 @@ def _save(im, fp, tile, bufsize=0):
|
|||
raise IOError("encoder error %d when writing image file" % s)
|
||||
try:
|
||||
fp.flush()
|
||||
except: pass
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def _safe_read(fp, size):
|
||||
|
|
|
@ -43,7 +43,7 @@ class Kernel(Filter):
|
|||
def __init__(self, size, kernel, scale=None, offset=0):
|
||||
if scale is None:
|
||||
# default scale is sum of kernel
|
||||
scale = reduce(lambda a,b: a+b, kernel)
|
||||
scale = reduce(lambda a, b: a+b, kernel)
|
||||
if size[0] * size[1] != len(kernel):
|
||||
raise ValueError("not enough coefficients in kernel")
|
||||
self.filterargs = size, scale, offset, kernel
|
||||
|
|
|
@ -40,7 +40,7 @@ def grab(bbox=None):
|
|||
|
||||
|
||||
def grabclipboard():
|
||||
debug = 0 # temporary interface
|
||||
debug = 0 # temporary interface
|
||||
data = Image.core.grabclipboard(debug)
|
||||
if isinstance(data, bytes):
|
||||
from PIL import BmpImagePlugin
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
# mode descriptor cache
|
||||
_modes = {}
|
||||
|
||||
|
||||
##
|
||||
# Wrapper for mode strings.
|
||||
|
||||
|
@ -30,6 +31,7 @@ class ModeDescriptor:
|
|||
def __str__(self):
|
||||
return self.mode
|
||||
|
||||
|
||||
##
|
||||
# Gets a mode descriptor for the given mode.
|
||||
|
||||
|
|
|
@ -35,14 +35,14 @@ class LutBuilder:
|
|||
returned if no other match is found.
|
||||
|
||||
Operations:
|
||||
|
||||
|
||||
- 4 - 4 way rotation
|
||||
- N - Negate
|
||||
- 1 - Dummy op for no other operation (an op must always be given)
|
||||
- M - Mirroring
|
||||
|
||||
Example::
|
||||
|
||||
|
||||
lb = LutBuilder(patterns = ["4:(... .1. 111)->1"])
|
||||
lut = lb.build_lut()
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ from PIL._util import isStringType
|
|||
import operator
|
||||
from functools import reduce
|
||||
|
||||
|
||||
#
|
||||
# helpers
|
||||
|
||||
|
@ -35,12 +36,14 @@ def _border(border):
|
|||
left = top = right = bottom = border
|
||||
return left, top, right, bottom
|
||||
|
||||
|
||||
def _color(color, mode):
|
||||
if isStringType(color):
|
||||
from PIL import ImageColor
|
||||
color = ImageColor.getcolor(color, mode)
|
||||
return color
|
||||
|
||||
|
||||
def _lut(image, lut):
|
||||
if image.mode == "P":
|
||||
# FIXME: apply to lookup table, not image data
|
||||
|
@ -147,7 +150,9 @@ def colorize(image, black, white):
|
|||
assert image.mode == "L"
|
||||
black = _color(black, "RGB")
|
||||
white = _color(white, "RGB")
|
||||
red = []; green = []; blue = []
|
||||
red = []
|
||||
green = []
|
||||
blue = []
|
||||
for i in range(256):
|
||||
red.append(black[0]+i*(white[0]-black[0])//255)
|
||||
green.append(black[1]+i*(white[1]-black[1])//255)
|
||||
|
@ -273,7 +278,7 @@ def fit(image, size, method=Image.NEAREST, bleed=0.0, centering=(0.5, 0.5)):
|
|||
centering = [centering[0], centering[1]]
|
||||
|
||||
if centering[0] > 1.0 or centering[0] < 0.0:
|
||||
centering [0] = 0.50
|
||||
centering[0] = 0.50
|
||||
if centering[1] > 1.0 or centering[1] < 0.0:
|
||||
centering[1] = 0.50
|
||||
|
||||
|
@ -404,6 +409,7 @@ def solarize(image, threshold=128):
|
|||
lut.append(255-i)
|
||||
return _lut(image, lut)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PIL USM components, from Kevin Cazabon.
|
||||
|
||||
|
@ -419,6 +425,7 @@ def gaussian_blur(im, radius=None):
|
|||
|
||||
gblur = gaussian_blur
|
||||
|
||||
|
||||
def unsharp_mask(im, radius=None, percent=None, threshold=None):
|
||||
""" PIL_usm.usm(im, [radius, percent, threshold])"""
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
##
|
||||
|
||||
|
||||
class Iterator:
|
||||
"""
|
||||
This class implements an iterator object that can be used to loop
|
||||
|
@ -38,4 +39,4 @@ class Iterator:
|
|||
self.im.seek(ix)
|
||||
return self.im
|
||||
except EOFError:
|
||||
raise IndexError # end of sequence
|
||||
raise IndexError # end of sequence
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
from __future__ import print_function
|
||||
|
||||
from PIL import Image
|
||||
import os, sys
|
||||
import os
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (3, 3):
|
||||
from shlex import quote
|
||||
|
@ -24,17 +25,19 @@ else:
|
|||
|
||||
_viewers = []
|
||||
|
||||
|
||||
def register(viewer, order=1):
|
||||
try:
|
||||
if issubclass(viewer, Viewer):
|
||||
viewer = viewer()
|
||||
except TypeError:
|
||||
pass # raised if viewer wasn't a class
|
||||
pass # raised if viewer wasn't a class
|
||||
if order > 0:
|
||||
_viewers.append(viewer)
|
||||
elif order < 0:
|
||||
_viewers.insert(0, viewer)
|
||||
|
||||
|
||||
##
|
||||
# Displays a given image.
|
||||
#
|
||||
|
@ -49,6 +52,7 @@ def show(image, title=None, **options):
|
|||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
##
|
||||
# Base class for viewers.
|
||||
|
||||
|
@ -102,6 +106,7 @@ if sys.platform == "win32":
|
|||
|
||||
class WindowsViewer(Viewer):
|
||||
format = "BMP"
|
||||
|
||||
def get_command(self, file, **options):
|
||||
return ('start "Pillow" /WAIT "%s" '
|
||||
'&& ping -n 2 127.0.0.1 >NUL '
|
||||
|
@ -113,11 +118,13 @@ elif sys.platform == "darwin":
|
|||
|
||||
class MacViewer(Viewer):
|
||||
format = "BMP"
|
||||
|
||||
def get_command(self, file, **options):
|
||||
# on darwin open returns immediately resulting in the temp
|
||||
# file removal while app is opening
|
||||
command = "open -a /Applications/Preview.app"
|
||||
command = "(%s %s; sleep 20; rm -f %s)&" % (command, quote(file), quote(file))
|
||||
command = "(%s %s; sleep 20; rm -f %s)&" % (command, quote(file),
|
||||
quote(file))
|
||||
return command
|
||||
|
||||
register(MacViewer)
|
||||
|
@ -140,7 +147,8 @@ else:
|
|||
class UnixViewer(Viewer):
|
||||
def show_file(self, file, **options):
|
||||
command, executable = self.get_command_ex(file, **options)
|
||||
command = "(%s %s; rm -f %s)&" % (command, quote(file), quote(file))
|
||||
command = "(%s %s; rm -f %s)&" % (command, quote(file),
|
||||
quote(file))
|
||||
os.system(command)
|
||||
return 1
|
||||
|
||||
|
|
|
@ -21,20 +21,21 @@
|
|||
# See the README file for information on usage and redistribution.
|
||||
#
|
||||
|
||||
import operator, math
|
||||
import math
|
||||
import operator
|
||||
from functools import reduce
|
||||
|
||||
|
||||
class Stat:
|
||||
|
||||
def __init__(self, image_or_list, mask = None):
|
||||
def __init__(self, image_or_list, mask=None):
|
||||
try:
|
||||
if mask:
|
||||
self.h = image_or_list.histogram(mask)
|
||||
else:
|
||||
self.h = image_or_list.histogram()
|
||||
except AttributeError:
|
||||
self.h = image_or_list # assume it to be a histogram list
|
||||
self.h = image_or_list # assume it to be a histogram list
|
||||
if not isinstance(self.h, list):
|
||||
raise TypeError("first argument must be image or list")
|
||||
self.bands = list(range(len(self.h) // 256))
|
||||
|
@ -58,7 +59,7 @@ class Stat:
|
|||
if histogram[i]:
|
||||
n = min(n, i)
|
||||
x = max(x, i)
|
||||
return n, x # returns (255, 0) if there's no data in the histogram
|
||||
return n, x # returns (255, 0) if there's no data in the histogram
|
||||
|
||||
v = []
|
||||
for i in range(0, len(self.h), 256):
|
||||
|
@ -126,7 +127,6 @@ class Stat:
|
|||
v.append(math.sqrt(self.sum2[i] / self.count[i]))
|
||||
return v
|
||||
|
||||
|
||||
def _getvar(self):
|
||||
"Get variance for each layer"
|
||||
|
||||
|
@ -144,4 +144,4 @@ class Stat:
|
|||
v.append(math.sqrt(self.var[i]))
|
||||
return v
|
||||
|
||||
Global = Stat # compatibility
|
||||
Global = Stat # compatibility
|
||||
|
|
|
@ -40,17 +40,19 @@ from PIL import Image
|
|||
|
||||
_pilbitmap_ok = None
|
||||
|
||||
|
||||
def _pilbitmap_check():
|
||||
global _pilbitmap_ok
|
||||
if _pilbitmap_ok is None:
|
||||
try:
|
||||
im = Image.new("1", (1,1))
|
||||
im = Image.new("1", (1, 1))
|
||||
tkinter.BitmapImage(data="PIL:%d" % im.im.id)
|
||||
_pilbitmap_ok = 1
|
||||
except tkinter.TclError:
|
||||
_pilbitmap_ok = 0
|
||||
return _pilbitmap_ok
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PhotoImage
|
||||
|
||||
|
@ -95,7 +97,7 @@ class PhotoImage:
|
|||
try:
|
||||
mode = image.palette.mode
|
||||
except AttributeError:
|
||||
mode = "RGB" # default
|
||||
mode = "RGB" # default
|
||||
size = image.size
|
||||
kw["width"], kw["height"] = size
|
||||
else:
|
||||
|
@ -118,8 +120,7 @@ class PhotoImage:
|
|||
try:
|
||||
self.__photo.tk.call("image", "delete", name)
|
||||
except:
|
||||
pass # ignore internal errors
|
||||
|
||||
pass # ignore internal errors
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
|
@ -131,7 +132,6 @@ class PhotoImage:
|
|||
"""
|
||||
return str(self.__photo)
|
||||
|
||||
|
||||
def width(self):
|
||||
"""
|
||||
Get the width of the image.
|
||||
|
@ -140,7 +140,6 @@ class PhotoImage:
|
|||
"""
|
||||
return self.__size[0]
|
||||
|
||||
|
||||
def height(self):
|
||||
"""
|
||||
Get the height of the image.
|
||||
|
@ -149,7 +148,6 @@ class PhotoImage:
|
|||
"""
|
||||
return self.__size[1]
|
||||
|
||||
|
||||
def paste(self, im, box=None):
|
||||
"""
|
||||
Paste a PIL image into the photo image. Note that this can
|
||||
|
@ -170,13 +168,13 @@ class PhotoImage:
|
|||
block = image
|
||||
else:
|
||||
block = image.new_block(self.__mode, im.size)
|
||||
image.convert2(block, image) # convert directly between buffers
|
||||
image.convert2(block, image) # convert directly between buffers
|
||||
|
||||
tk = self.__photo.tk
|
||||
|
||||
try:
|
||||
tk.call("PyImagingPhoto", self.__photo, block.id)
|
||||
except tkinter.TclError as v:
|
||||
except tkinter.TclError:
|
||||
# activate Tkinter hook
|
||||
try:
|
||||
from PIL import _imagingtk
|
||||
|
@ -186,7 +184,7 @@ class PhotoImage:
|
|||
_imagingtk.tkinit(id(tk), 0)
|
||||
tk.call("PyImagingPhoto", self.__photo, block.id)
|
||||
except (ImportError, AttributeError, tkinter.TclError):
|
||||
raise # configuration problem; cannot attach to Tkinter
|
||||
raise # configuration problem; cannot attach to Tkinter
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# BitmapImage
|
||||
|
@ -226,7 +224,7 @@ class BitmapImage:
|
|||
# fast way (requires the pilbitmap booster patch)
|
||||
image.load()
|
||||
kw["data"] = "PIL:%d" % image.im.id
|
||||
self.__im = image # must keep a reference
|
||||
self.__im = image # must keep a reference
|
||||
else:
|
||||
# slow but safe way
|
||||
kw["data"] = image.tobitmap()
|
||||
|
@ -238,8 +236,7 @@ class BitmapImage:
|
|||
try:
|
||||
self.__photo.tk.call("image", "delete", name)
|
||||
except:
|
||||
pass # ignore internal errors
|
||||
|
||||
pass # ignore internal errors
|
||||
|
||||
def width(self):
|
||||
"""
|
||||
|
@ -249,7 +246,6 @@ class BitmapImage:
|
|||
"""
|
||||
return self.__size[0]
|
||||
|
||||
|
||||
def height(self):
|
||||
"""
|
||||
Get the height of the image.
|
||||
|
@ -258,7 +254,6 @@ class BitmapImage:
|
|||
"""
|
||||
return self.__size[1]
|
||||
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Get the Tkinter bitmap image identifier. This method is automatically
|
||||
|
@ -274,6 +269,7 @@ def getimage(photo):
|
|||
"""Copies the contents of a PhotoImage to a PIL image memory."""
|
||||
photo.tk.call("PyImagingPhotoGet", photo)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Helper for the Image.show method.
|
||||
|
||||
|
@ -286,7 +282,7 @@ def _show(image, title):
|
|||
else:
|
||||
self.image = PhotoImage(im, master=master)
|
||||
tkinter.Label.__init__(self, master, image=self.image,
|
||||
bg="black", bd=0)
|
||||
bg="black", bd=0)
|
||||
|
||||
if not tkinter._default_root:
|
||||
raise IOError("tkinter not initialized")
|
||||
|
|
|
@ -15,16 +15,20 @@
|
|||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
class Transform(Image.ImageTransformHandler):
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
def getdata(self):
|
||||
return self.method, self.data
|
||||
|
||||
def transform(self, size, image, **options):
|
||||
# can be overridden
|
||||
method, data = self.getdata()
|
||||
return image.transform(size, method, data, **options)
|
||||
|
||||
|
||||
##
|
||||
# Define an affine image transform.
|
||||
# <p>
|
||||
|
@ -43,9 +47,11 @@ class Transform(Image.ImageTransformHandler):
|
|||
# the first two rows from an affine transform matrix.
|
||||
# @see Image#Image.transform
|
||||
|
||||
|
||||
class AffineTransform(Transform):
|
||||
method = Image.AFFINE
|
||||
|
||||
|
||||
##
|
||||
# Define a transform to extract a subregion from an image.
|
||||
# <p>
|
||||
|
@ -68,6 +74,7 @@ class AffineTransform(Transform):
|
|||
class ExtentTransform(Transform):
|
||||
method = Image.EXTENT
|
||||
|
||||
|
||||
##
|
||||
# Define an quad image transform.
|
||||
# <p>
|
||||
|
@ -83,6 +90,7 @@ class ExtentTransform(Transform):
|
|||
class QuadTransform(Transform):
|
||||
method = Image.QUAD
|
||||
|
||||
|
||||
##
|
||||
# Define an mesh image transform. A mesh transform consists of one
|
||||
# or more individual quad transforms.
|
||||
|
|
|
@ -29,9 +29,11 @@ class HDC:
|
|||
"""
|
||||
def __init__(self, dc):
|
||||
self.dc = dc
|
||||
|
||||
def __int__(self):
|
||||
return self.dc
|
||||
|
||||
|
||||
class HWND:
|
||||
"""
|
||||
Wraps a HWND integer. The resulting object can be passed to the
|
||||
|
@ -40,6 +42,7 @@ class HWND:
|
|||
"""
|
||||
def __init__(self, wnd):
|
||||
self.wnd = wnd
|
||||
|
||||
def __int__(self):
|
||||
return self.wnd
|
||||
|
||||
|
@ -79,7 +82,6 @@ class Dib:
|
|||
if image:
|
||||
self.paste(image)
|
||||
|
||||
|
||||
def expose(self, handle):
|
||||
"""
|
||||
Copy the bitmap contents to a device context.
|
||||
|
@ -109,7 +111,7 @@ class Dib:
|
|||
necessary.
|
||||
"""
|
||||
if not src:
|
||||
src = (0,0) + self.size
|
||||
src = (0, 0) + self.size
|
||||
if isinstance(handle, HWND):
|
||||
dc = self.image.getdc(handle)
|
||||
try:
|
||||
|
@ -120,7 +122,6 @@ class Dib:
|
|||
result = self.image.draw(handle, dst, src)
|
||||
return result
|
||||
|
||||
|
||||
def query_palette(self, handle):
|
||||
"""
|
||||
Installs the palette associated with the image in the given device
|
||||
|
@ -146,7 +147,6 @@ class Dib:
|
|||
result = self.image.query_palette(handle)
|
||||
return result
|
||||
|
||||
|
||||
def paste(self, im, box=None):
|
||||
"""
|
||||
Paste a PIL image into the bitmap image.
|
||||
|
@ -166,7 +166,6 @@ class Dib:
|
|||
else:
|
||||
self.image.paste(im.im)
|
||||
|
||||
|
||||
def frombytes(self, buffer):
|
||||
"""
|
||||
Load display memory contents from byte data.
|
||||
|
@ -176,7 +175,6 @@ class Dib:
|
|||
"""
|
||||
return self.image.frombytes(buffer)
|
||||
|
||||
|
||||
def tobytes(self):
|
||||
"""
|
||||
Copy display memory contents to bytes object.
|
||||
|
@ -204,6 +202,7 @@ class Dib:
|
|||
)
|
||||
return self.tobytes()
|
||||
|
||||
|
||||
##
|
||||
# Create a Window with the given title size.
|
||||
|
||||
|
@ -235,6 +234,7 @@ class Window:
|
|||
def mainloop(self):
|
||||
Image.core.eventloop()
|
||||
|
||||
|
||||
##
|
||||
# Create an image window which displays the given image.
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ def _parse_jp2_header(fp):
|
|||
|
||||
if lbox < hlen:
|
||||
raise SyntaxError('Invalid JP2 header length')
|
||||
|
||||
|
||||
if tbox == b'jp2h':
|
||||
header = fp.read(lbox - hlen)
|
||||
break
|
||||
|
|
|
@ -21,9 +21,11 @@ __version__ = "0.2"
|
|||
import struct
|
||||
from PIL import Image, ImageFile
|
||||
|
||||
|
||||
def _accept(s):
|
||||
return s[:8] == b"\x00\x00\x00\x00\x00\x00\x00\x04"
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for McIdas area images.
|
||||
|
||||
|
@ -47,10 +49,12 @@ class McIdasImageFile(ImageFile.ImageFile):
|
|||
mode = rawmode = "L"
|
||||
elif w[11] == 2:
|
||||
# FIXME: add memory map support
|
||||
mode = "I"; rawmode = "I;16B"
|
||||
mode = "I"
|
||||
rawmode = "I;16B"
|
||||
elif w[11] == 4:
|
||||
# FIXME: add memory map support
|
||||
mode = "I"; rawmode = "I;32B"
|
||||
mode = "I"
|
||||
rawmode = "I;32B"
|
||||
else:
|
||||
raise SyntaxError("unsupported McIdas format")
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ from PIL.OleFileIO import *
|
|||
def _accept(prefix):
|
||||
return prefix[:8] == MAGIC
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for Microsoft's Image Composer file format.
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ __version__ = "0.1"
|
|||
from PIL import Image, ImageFile
|
||||
from PIL._binary import i8
|
||||
|
||||
|
||||
#
|
||||
# Bitstream parser
|
||||
|
||||
|
@ -52,6 +53,7 @@ class BitStream:
|
|||
self.bits = self.bits - bits
|
||||
return v
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for MPEG streams. This plugin can identify a stream,
|
||||
# but it cannot read it.
|
||||
|
|
|
@ -22,13 +22,16 @@ __version__ = "0.1"
|
|||
|
||||
from PIL import Image, JpegImagePlugin
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return JpegImagePlugin._accept(prefix)
|
||||
|
||||
|
||||
def _save(im, fp, filename):
|
||||
# Note that we can only save the current frame at present
|
||||
return JpegImagePlugin._save(im, fp, filename)
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for MPO images.
|
||||
|
||||
|
@ -38,19 +41,19 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
|||
format_description = "MPO (CIPA DC-007)"
|
||||
|
||||
def _open(self):
|
||||
self.fp.seek(0) # prep the fp in order to pass the JPEG test
|
||||
self.fp.seek(0) # prep the fp in order to pass the JPEG test
|
||||
JpegImagePlugin.JpegImageFile._open(self)
|
||||
self.mpinfo = self._getmp()
|
||||
self.__framecount = self.mpinfo[0xB001]
|
||||
self.__mpoffsets = [mpent['DataOffset'] + self.info['mpoffset'] \
|
||||
self.__mpoffsets = [mpent['DataOffset'] + self.info['mpoffset']
|
||||
for mpent in self.mpinfo[0xB002]]
|
||||
self.__mpoffsets[0] = 0
|
||||
# Note that the following assertion will only be invalid if something
|
||||
# gets broken within JpegImagePlugin.
|
||||
assert self.__framecount == len(self.__mpoffsets)
|
||||
del self.info['mpoffset'] # no longer needed
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self.__fp.seek(self.__mpoffsets[0]) # get ready to read first frame
|
||||
del self.info['mpoffset'] # no longer needed
|
||||
self.__fp = self.fp # FIXME: hack
|
||||
self.__fp.seek(self.__mpoffsets[0]) # get ready to read first frame
|
||||
self.__frame = 0
|
||||
self.offset = 0
|
||||
# for now we can only handle reading and individual frame extraction
|
||||
|
@ -79,7 +82,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
|||
|
||||
# Note that since MPO shares a factory with JPEG, we do not need to do a
|
||||
# separate registration for it here.
|
||||
#Image.register_open("MPO", JpegImagePlugin.jpeg_factory, _accept)
|
||||
# Image.register_open("MPO", JpegImagePlugin.jpeg_factory, _accept)
|
||||
Image.register_save("MPO", _save)
|
||||
|
||||
Image.register_extension("MPO", ".mpo")
|
||||
|
|
|
@ -27,9 +27,11 @@ from PIL import Image, ImageFile, _binary
|
|||
|
||||
i16 = _binary.i16le
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] in [b"DanM", b"LinS"]
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for Windows MSP images. This plugin supports both
|
||||
# uncompressed (Windows 1.0).
|
||||
|
@ -57,15 +59,16 @@ class MspImageFile(ImageFile.ImageFile):
|
|||
self.size = i16(s[4:]), i16(s[6:])
|
||||
|
||||
if s[:4] == b"DanM":
|
||||
self.tile = [("raw", (0,0)+self.size, 32, ("1", 0, 1))]
|
||||
self.tile = [("raw", (0, 0)+self.size, 32, ("1", 0, 1))]
|
||||
else:
|
||||
self.tile = [("msp", (0,0)+self.size, 32+2*self.size[1], None)]
|
||||
self.tile = [("msp", (0, 0)+self.size, 32+2*self.size[1], None)]
|
||||
|
||||
#
|
||||
# write MSP files (uncompressed only)
|
||||
|
||||
o16 = _binary.o16le
|
||||
|
||||
|
||||
def _save(im, fp, filename):
|
||||
|
||||
if im.mode != "1":
|
||||
|
@ -74,7 +77,7 @@ def _save(im, fp, filename):
|
|||
# create MSP header
|
||||
header = [0] * 16
|
||||
|
||||
header[0], header[1] = i16(b"Da"), i16(b"nM") # version 1
|
||||
header[0], header[1] = i16(b"Da"), i16(b"nM") # version 1
|
||||
header[2], header[3] = im.size
|
||||
header[4], header[5] = 1, 1
|
||||
header[6], header[7] = 1, 1
|
||||
|
@ -83,14 +86,14 @@ def _save(im, fp, filename):
|
|||
sum = 0
|
||||
for h in header:
|
||||
sum = sum ^ h
|
||||
header[12] = sum # FIXME: is this the right field?
|
||||
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))])
|
||||
ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 32, ("1", 0, 1))])
|
||||
|
||||
#
|
||||
# registry
|
||||
|
|
|
@ -19,6 +19,7 @@ from __future__ import print_function
|
|||
|
||||
from PIL import EpsImagePlugin
|
||||
|
||||
|
||||
##
|
||||
# Simple Postscript graphics interface.
|
||||
|
||||
|
@ -34,7 +35,7 @@ class PSDraw:
|
|||
fp = sys.stdout
|
||||
self.fp = fp
|
||||
|
||||
def begin_document(self, id = None):
|
||||
def begin_document(self, id=None):
|
||||
"""Set up printing of a document. (Write Postscript DSC header.)"""
|
||||
# FIXME: incomplete
|
||||
self.fp.write("%!PS-Adobe-3.0\n"
|
||||
|
@ -42,7 +43,7 @@ class PSDraw:
|
|||
"/showpage { } def\n"
|
||||
"%%EndComments\n"
|
||||
"%%BeginDocument\n")
|
||||
#self.fp.write(ERROR_PS) # debugging!
|
||||
# self.fp.write(ERROR_PS) # debugging!
|
||||
self.fp.write(EDROFF_PS)
|
||||
self.fp.write(VDI_PS)
|
||||
self.fp.write("%%EndProlog\n")
|
||||
|
@ -65,7 +66,7 @@ class PSDraw:
|
|||
"""
|
||||
if font not in self.isofont:
|
||||
# reencode font
|
||||
self.fp.write("/PSDraw-%s ISOLatin1Encoding /%s E\n" %\
|
||||
self.fp.write("/PSDraw-%s ISOLatin1Encoding /%s E\n" %
|
||||
(font, font))
|
||||
self.isofont[font] = 1
|
||||
# rough
|
||||
|
@ -73,7 +74,8 @@ class PSDraw:
|
|||
|
||||
def setink(self, ink):
|
||||
"""
|
||||
.. warning:: This has been in the PIL API for ages but was never implemented.
|
||||
.. warning:: This has been in the PIL API for ages but was never
|
||||
implemented.
|
||||
|
||||
"""
|
||||
print("*** NOT YET IMPLEMENTED ***")
|
||||
|
@ -112,14 +114,14 @@ class PSDraw:
|
|||
xy = xy + (text,)
|
||||
self.fp.write("%d %d M (%s) S\n" % xy)
|
||||
|
||||
def image(self, box, im, dpi = None):
|
||||
def image(self, box, im, dpi=None):
|
||||
"""Draw a PIL image, centered in the given box."""
|
||||
# default resolution depends on mode
|
||||
if not dpi:
|
||||
if im.mode == "1":
|
||||
dpi = 200 # fax
|
||||
dpi = 200 # fax
|
||||
else:
|
||||
dpi = 100 # greyscale
|
||||
dpi = 100 # greyscale
|
||||
# image size (on paper)
|
||||
x = float(im.size[0] * 72) / dpi
|
||||
y = float(im.size[1] * 72) / dpi
|
||||
|
@ -127,9 +129,11 @@ class PSDraw:
|
|||
xmax = float(box[2] - box[0])
|
||||
ymax = float(box[3] - box[1])
|
||||
if x > xmax:
|
||||
y = y * xmax / x; x = xmax
|
||||
y = y * xmax / x
|
||||
x = xmax
|
||||
if y > ymax:
|
||||
x = x * ymax / y; y = ymax
|
||||
x = x * ymax / y
|
||||
y = ymax
|
||||
dx = (xmax - x) / 2 + box[0]
|
||||
dy = (ymax - y) / 2 + box[1]
|
||||
self.fp.write("gsave\n%f %f translate\n" % (dx, dy))
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
from PIL._binary import o8
|
||||
|
||||
|
||||
##
|
||||
# File handler for Teragon-style palette files.
|
||||
|
||||
|
@ -49,7 +50,6 @@ class PaletteFile:
|
|||
|
||||
self.palette = b"".join(self.palette)
|
||||
|
||||
|
||||
def getpalette(self):
|
||||
|
||||
return self.palette, self.rawmode
|
||||
|
|
|
@ -22,6 +22,7 @@ from PIL import Image, ImageFile, _binary
|
|||
|
||||
i8 = _binary.i8
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for PhotoCD images. This plugin only reads the 768x512
|
||||
# image from the file; higher resolutions are encoded in a proprietary
|
||||
|
@ -43,13 +44,13 @@ class PcdImageFile(ImageFile.ImageFile):
|
|||
|
||||
orientation = i8(s[1538]) & 3
|
||||
if orientation == 1:
|
||||
self.tile_post_rotate = 90 # hack
|
||||
self.tile_post_rotate = 90 # hack
|
||||
elif orientation == 3:
|
||||
self.tile_post_rotate = -90
|
||||
|
||||
self.mode = "RGB"
|
||||
self.size = 768, 512 # FIXME: not correct for rotated images!
|
||||
self.tile = [("pcd", (0,0)+self.size, 96*2048, None)]
|
||||
self.size = 768, 512 # FIXME: not correct for rotated images!
|
||||
self.tile = [("pcd", (0, 0)+self.size, 96*2048, None)]
|
||||
|
||||
def draft(self, mode, size):
|
||||
|
||||
|
@ -60,7 +61,7 @@ class PcdImageFile(ImageFile.ImageFile):
|
|||
|
||||
if size:
|
||||
scale = max(self.size[0] / size[0], self.size[1] / size[1])
|
||||
for s, o in [(4,0*2048), (2,0*2048), (1,96*2048)]:
|
||||
for s, o in [(4, 0*2048), (2, 0*2048), (1, 96*2048)]:
|
||||
if scale >= s:
|
||||
break
|
||||
# e = e[0], e[1], (e[2]-e[0]+s-1)/s+e[0], (e[3]-e[1]+s-1)/s+e[1]
|
||||
|
|
|
@ -23,20 +23,20 @@ from PIL import _binary
|
|||
# --------------------------------------------------------------------
|
||||
# declarations
|
||||
|
||||
PCF_MAGIC = 0x70636601 # "\x01fcp"
|
||||
PCF_MAGIC = 0x70636601 # "\x01fcp"
|
||||
|
||||
PCF_PROPERTIES = (1<<0)
|
||||
PCF_ACCELERATORS = (1<<1)
|
||||
PCF_METRICS = (1<<2)
|
||||
PCF_BITMAPS = (1<<3)
|
||||
PCF_INK_METRICS = (1<<4)
|
||||
PCF_BDF_ENCODINGS = (1<<5)
|
||||
PCF_SWIDTHS = (1<<6)
|
||||
PCF_GLYPH_NAMES = (1<<7)
|
||||
PCF_BDF_ACCELERATORS = (1<<8)
|
||||
PCF_PROPERTIES = (1 << 0)
|
||||
PCF_ACCELERATORS = (1 << 1)
|
||||
PCF_METRICS = (1 << 2)
|
||||
PCF_BITMAPS = (1 << 3)
|
||||
PCF_INK_METRICS = (1 << 4)
|
||||
PCF_BDF_ENCODINGS = (1 << 5)
|
||||
PCF_SWIDTHS = (1 << 6)
|
||||
PCF_GLYPH_NAMES = (1 << 7)
|
||||
PCF_BDF_ACCELERATORS = (1 << 8)
|
||||
|
||||
BYTES_PER_ROW = [
|
||||
lambda bits: ((bits+7) >> 3),
|
||||
lambda bits: ((bits+7) >> 3),
|
||||
lambda bits: ((bits+15) >> 3) & ~1,
|
||||
lambda bits: ((bits+31) >> 3) & ~3,
|
||||
lambda bits: ((bits+63) >> 3) & ~7,
|
||||
|
@ -48,9 +48,11 @@ l32 = _binary.i32le
|
|||
b16 = _binary.i16be
|
||||
b32 = _binary.i32be
|
||||
|
||||
|
||||
def sz(s, o):
|
||||
return s[o:s.index(b"\0", o)]
|
||||
|
||||
|
||||
##
|
||||
# Font file plugin for the X11 PCF format.
|
||||
|
||||
|
@ -122,7 +124,7 @@ class PcfFontFile(FontFile.FontFile):
|
|||
for i in range(nprops):
|
||||
p.append((i32(fp.read(4)), i8(fp.read(1)), i32(fp.read(4))))
|
||||
if nprops & 3:
|
||||
fp.seek(4 - (nprops & 3), 1) # pad
|
||||
fp.seek(4 - (nprops & 3), 1) # pad
|
||||
|
||||
data = fp.read(i32(fp.read(4)))
|
||||
|
||||
|
@ -202,16 +204,16 @@ class PcfFontFile(FontFile.FontFile):
|
|||
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
|
||||
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]
|
||||
pad = BYTES_PER_ROW[padindex]
|
||||
mode = "1;R"
|
||||
if bitorder:
|
||||
mode = "1"
|
||||
|
@ -245,6 +247,6 @@ class PcfFontFile(FontFile.FontFile):
|
|||
try:
|
||||
encoding[i+firstCol] = encodingOffset
|
||||
except IndexError:
|
||||
break # only load ISO-8859-1 glyphs
|
||||
break # only load ISO-8859-1 glyphs
|
||||
|
||||
return encoding
|
||||
|
|
|
@ -33,9 +33,11 @@ i8 = _binary.i8
|
|||
i16 = _binary.i16le
|
||||
o8 = _binary.o8
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return i8(prefix[0]) == 10 and i8(prefix[1]) in [0, 2, 3, 5]
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for Paintbrush images.
|
||||
|
||||
|
@ -52,23 +54,22 @@ class PcxImageFile(ImageFile.ImageFile):
|
|||
raise SyntaxError("not a PCX file")
|
||||
|
||||
# image
|
||||
bbox = i16(s,4), i16(s,6), i16(s,8)+1, i16(s,10)+1
|
||||
bbox = i16(s, 4), i16(s, 6), i16(s, 8)+1, i16(s, 10)+1
|
||||
if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]:
|
||||
raise SyntaxError("bad PCX image size")
|
||||
if Image.DEBUG:
|
||||
print ("BBox: %s %s %s %s" % bbox)
|
||||
|
||||
|
||||
# format
|
||||
version = i8(s[1])
|
||||
bits = i8(s[3])
|
||||
planes = i8(s[65])
|
||||
stride = i16(s,66)
|
||||
stride = i16(s, 66)
|
||||
if Image.DEBUG:
|
||||
print ("PCX version %s, bits %s, planes %s, stride %s" %
|
||||
(version, bits, planes, stride))
|
||||
|
||||
self.info["dpi"] = i16(s,12), i16(s,14)
|
||||
self.info["dpi"] = i16(s, 12), i16(s, 14)
|
||||
|
||||
if bits == 1 and planes == 1:
|
||||
mode = rawmode = "1"
|
||||
|
@ -106,7 +107,7 @@ class PcxImageFile(ImageFile.ImageFile):
|
|||
bbox = (0, 0) + self.size
|
||||
if Image.DEBUG:
|
||||
print ("size: %sx%s" % self.size)
|
||||
|
||||
|
||||
self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))]
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
@ -122,6 +123,7 @@ SAVE = {
|
|||
|
||||
o16 = _binary.o16le
|
||||
|
||||
|
||||
def _save(im, fp, filename, check=0):
|
||||
|
||||
try:
|
||||
|
@ -138,8 +140,7 @@ def _save(im, fp, filename, check=0):
|
|||
stride += stride % 2
|
||||
# Stride needs to be kept in sync with the PcxEncode.c version.
|
||||
# Ideally it should be passed in in the state, but the bytes value
|
||||
# gets overwritten.
|
||||
|
||||
# gets overwritten.
|
||||
|
||||
if Image.DEBUG:
|
||||
print ("PcxImagePlugin._save: xwidth: %d, bits: %d, stride: %d" % (
|
||||
|
@ -163,13 +164,13 @@ def _save(im, fp, filename, check=0):
|
|||
|
||||
assert fp.tell() == 128
|
||||
|
||||
ImageFile._save(im, fp, [("pcx", (0,0)+im.size, 0,
|
||||
ImageFile._save(im, fp, [("pcx", (0, 0)+im.size, 0,
|
||||
(rawmode, bits*planes))])
|
||||
|
||||
if im.mode == "P":
|
||||
# colour palette
|
||||
fp.write(o8(12))
|
||||
fp.write(im.im.getpalette("RGB", "RGB")) # 768 bytes
|
||||
fp.write(im.im.getpalette("RGB", "RGB")) # 768 bytes
|
||||
elif im.mode == "L":
|
||||
# greyscale palette
|
||||
fp.write(o8(12))
|
||||
|
|
|
@ -29,6 +29,7 @@ from PIL import Image, ImageFile, _binary
|
|||
i16 = _binary.i16le
|
||||
i32 = _binary.i32le
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for PIXAR raster images.
|
||||
|
||||
|
@ -57,7 +58,7 @@ class PixarImageFile(ImageFile.ImageFile):
|
|||
# FIXME: to be continued...
|
||||
|
||||
# create tile descriptor (assuming "dumped")
|
||||
self.tile = [("raw", (0,0)+self.size, 1024, (self.mode, 0, 1))]
|
||||
self.tile = [("raw", (0, 0)+self.size, 1024, (self.mode, 0, 1))]
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
|
|
@ -52,26 +52,27 @@ _MAGIC = b"\211PNG\r\n\032\n"
|
|||
|
||||
_MODES = {
|
||||
# supported bits/color combinations, and corresponding modes/rawmodes
|
||||
(1, 0): ("1", "1"),
|
||||
(2, 0): ("L", "L;2"),
|
||||
(4, 0): ("L", "L;4"),
|
||||
(8, 0): ("L", "L"),
|
||||
(16,0): ("I", "I;16B"),
|
||||
(8, 2): ("RGB", "RGB"),
|
||||
(16,2): ("RGB", "RGB;16B"),
|
||||
(1, 3): ("P", "P;1"),
|
||||
(2, 3): ("P", "P;2"),
|
||||
(4, 3): ("P", "P;4"),
|
||||
(8, 3): ("P", "P"),
|
||||
(8, 4): ("LA", "LA"),
|
||||
(16,4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available
|
||||
(8, 6): ("RGBA", "RGBA"),
|
||||
(16,6): ("RGBA", "RGBA;16B"),
|
||||
(1, 0): ("1", "1"),
|
||||
(2, 0): ("L", "L;2"),
|
||||
(4, 0): ("L", "L;4"),
|
||||
(8, 0): ("L", "L"),
|
||||
(16, 0): ("I", "I;16B"),
|
||||
(8, 2): ("RGB", "RGB"),
|
||||
(16, 2): ("RGB", "RGB;16B"),
|
||||
(1, 3): ("P", "P;1"),
|
||||
(2, 3): ("P", "P;2"),
|
||||
(4, 3): ("P", "P;4"),
|
||||
(8, 3): ("P", "P"),
|
||||
(8, 4): ("LA", "LA"),
|
||||
(16, 4): ("RGBA", "LA;16B"), # LA;16B->LA not yet available
|
||||
(8, 6): ("RGBA", "RGBA"),
|
||||
(16, 6): ("RGBA", "RGBA;16B"),
|
||||
}
|
||||
|
||||
|
||||
_simple_palette = re.compile(b'^\xff+\x00\xff*$')
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Support classes. Suitable for PNG and related formats like MNG etc.
|
||||
|
||||
|
@ -123,15 +124,15 @@ class ChunkStream:
|
|||
crc1 = Image.core.crc32(data, Image.core.crc32(cid))
|
||||
crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))
|
||||
if crc1 != crc2:
|
||||
raise SyntaxError("broken PNG file"\
|
||||
"(bad header checksum in %s)" % cid)
|
||||
raise SyntaxError("broken PNG file"
|
||||
"(bad header checksum in %s)" % cid)
|
||||
|
||||
def crc_skip(self, cid, data):
|
||||
"Read checksum. Used if the C module is not present"
|
||||
|
||||
self.fp.read(4)
|
||||
|
||||
def verify(self, endchunk = b"IEND"):
|
||||
def verify(self, endchunk=b"IEND"):
|
||||
|
||||
# Simple approach; just calculate checksum for all remaining
|
||||
# blocks. Must be called directly after open.
|
||||
|
@ -147,6 +148,7 @@ class ChunkStream:
|
|||
|
||||
return cids
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Subclass of string to allow iTXt chunks to look like strings while
|
||||
# keeping their extra information
|
||||
|
@ -159,6 +161,7 @@ class iTXt(str):
|
|||
self.tkey = tkey
|
||||
return self
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PNG chunk container (for use with save(pnginfo=))
|
||||
|
||||
|
@ -182,9 +185,11 @@ class PngInfo:
|
|||
|
||||
if zip:
|
||||
import zlib
|
||||
self.add(b"iTXt", key + b"\0\x01\0" + lang + b"\0" + tkey + b"\0" + zlib.compress(value))
|
||||
self.add(b"iTXt", key + b"\0\x01\0" + lang + b"\0" + tkey + b"\0" +
|
||||
zlib.compress(value))
|
||||
else:
|
||||
self.add(b"iTXt", key + b"\0\0\0" + lang + b"\0" + tkey + b"\0" + value)
|
||||
self.add(b"iTXt", key + b"\0\0\0" + lang + b"\0" + tkey + b"\0" +
|
||||
value)
|
||||
|
||||
def add_text(self, key, value, zip=0):
|
||||
if isinstance(value, iTXt):
|
||||
|
@ -206,6 +211,7 @@ class PngInfo:
|
|||
else:
|
||||
self.add(b"tEXt", key + b"\0" + value)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PNG image stream (IHDR/IEND)
|
||||
|
||||
|
@ -218,7 +224,7 @@ class PngStream(ChunkStream):
|
|||
# local copies of Image attributes
|
||||
self.im_info = {}
|
||||
self.im_text = {}
|
||||
self.im_size = (0,0)
|
||||
self.im_size = (0, 0)
|
||||
self.im_mode = None
|
||||
self.im_tile = None
|
||||
self.im_palette = None
|
||||
|
@ -238,11 +244,12 @@ class PngStream(ChunkStream):
|
|||
print("Compression method", i8(s[i]))
|
||||
comp_method = i8(s[i])
|
||||
if comp_method != 0:
|
||||
raise SyntaxError("Unknown compression method %s in iCCP chunk" % comp_method)
|
||||
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
|
||||
icc_profile = None # FIXME
|
||||
self.im_info["icc_profile"] = icc_profile
|
||||
return s
|
||||
|
||||
|
@ -264,7 +271,7 @@ class PngStream(ChunkStream):
|
|||
def chunk_IDAT(self, pos, length):
|
||||
|
||||
# image data
|
||||
self.im_tile = [("zip", (0,0)+self.im_size, pos, self.im_rawmode)]
|
||||
self.im_tile = [("zip", (0, 0)+self.im_size, pos, self.im_rawmode)]
|
||||
self.im_idat = length
|
||||
raise EOFError
|
||||
|
||||
|
@ -311,7 +318,7 @@ class PngStream(ChunkStream):
|
|||
s = ImageFile._safe_read(self.fp, length)
|
||||
px, py = i32(s), i32(s[4:])
|
||||
unit = i8(s[8])
|
||||
if unit == 1: # meter
|
||||
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:
|
||||
|
@ -325,7 +332,9 @@ class PngStream(ChunkStream):
|
|||
try:
|
||||
k, v = s.split(b"\0", 1)
|
||||
except ValueError:
|
||||
k = s; v = b"" # fallback for broken tEXt tags
|
||||
# fallback for broken tEXt tags
|
||||
k = s
|
||||
v = b""
|
||||
if k:
|
||||
if bytes is not str:
|
||||
k = k.decode('latin-1', 'strict')
|
||||
|
@ -341,13 +350,15 @@ class PngStream(ChunkStream):
|
|||
try:
|
||||
k, v = s.split(b"\0", 1)
|
||||
except ValueError:
|
||||
k = s; v = b""
|
||||
k = s
|
||||
v = b""
|
||||
if v:
|
||||
comp_method = i8(v[0])
|
||||
else:
|
||||
comp_method = 0
|
||||
if comp_method != 0:
|
||||
raise SyntaxError("Unknown compression method %s in zTXt chunk" % comp_method)
|
||||
raise SyntaxError("Unknown compression method %s in zTXt chunk" %
|
||||
comp_method)
|
||||
import zlib
|
||||
try:
|
||||
v = zlib.decompress(v[1:])
|
||||
|
@ -396,15 +407,17 @@ class PngStream(ChunkStream):
|
|||
return s
|
||||
|
||||
self.im_info[k] = self.im_text[k] = iTXt(v, lang, tk)
|
||||
|
||||
|
||||
return s
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# PNG reader
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:8] == _MAGIC
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for PNG images.
|
||||
|
||||
|
@ -451,7 +464,7 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
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.text = self.png.im_text # experimental
|
||||
self.tile = self.png.im_tile
|
||||
|
||||
if self.png.im_palette:
|
||||
|
@ -460,7 +473,6 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
|
||||
self.__idat = length # used by load_read()
|
||||
|
||||
|
||||
def verify(self):
|
||||
"Verify PNG file"
|
||||
|
||||
|
@ -489,7 +501,7 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
while self.__idat == 0:
|
||||
# end of chunk, skip forward to next one
|
||||
|
||||
self.fp.read(4) # CRC
|
||||
self.fp.read(4) # CRC
|
||||
|
||||
cid, pos, length = self.png.read()
|
||||
|
||||
|
@ -509,7 +521,6 @@ class PngImageFile(ImageFile.ImageFile):
|
|||
|
||||
return self.fp.read(read_bytes)
|
||||
|
||||
|
||||
def load_end(self):
|
||||
"internal: finished reading image data"
|
||||
|
||||
|
@ -526,21 +537,22 @@ o32 = _binary.o32be
|
|||
|
||||
_OUTMODES = {
|
||||
# supported PIL modes, and corresponding rawmodes/bits/color combinations
|
||||
"1": ("1", b'\x01\x00'),
|
||||
"L;1": ("L;1", b'\x01\x00'),
|
||||
"L;2": ("L;2", b'\x02\x00'),
|
||||
"L;4": ("L;4", b'\x04\x00'),
|
||||
"L": ("L", b'\x08\x00'),
|
||||
"LA": ("LA", b'\x08\x04'),
|
||||
"I": ("I;16B", b'\x10\x00'),
|
||||
"P;1": ("P;1", b'\x01\x03'),
|
||||
"P;2": ("P;2", b'\x02\x03'),
|
||||
"P;4": ("P;4", b'\x04\x03'),
|
||||
"P": ("P", b'\x08\x03'),
|
||||
"RGB": ("RGB", b'\x08\x02'),
|
||||
"RGBA":("RGBA", b'\x08\x06'),
|
||||
"1": ("1", b'\x01\x00'),
|
||||
"L;1": ("L;1", b'\x01\x00'),
|
||||
"L;2": ("L;2", b'\x02\x00'),
|
||||
"L;4": ("L;4", b'\x04\x00'),
|
||||
"L": ("L", b'\x08\x00'),
|
||||
"LA": ("LA", b'\x08\x04'),
|
||||
"I": ("I;16B", b'\x10\x00'),
|
||||
"P;1": ("P;1", b'\x01\x03'),
|
||||
"P;2": ("P;2", b'\x02\x03'),
|
||||
"P;4": ("P;4", b'\x04\x03'),
|
||||
"P": ("P", b'\x08\x03'),
|
||||
"RGB": ("RGB", b'\x08\x02'),
|
||||
"RGBA": ("RGBA", b'\x08\x06'),
|
||||
}
|
||||
|
||||
|
||||
def putchunk(fp, cid, *data):
|
||||
"Write a PNG chunk (including CRC field)"
|
||||
|
||||
|
@ -551,15 +563,18 @@ def putchunk(fp, cid, *data):
|
|||
hi, lo = Image.core.crc32(data, Image.core.crc32(cid))
|
||||
fp.write(o16(hi) + o16(lo))
|
||||
|
||||
|
||||
class _idat:
|
||||
# wrap output from the encoder in IDAT chunks
|
||||
|
||||
def __init__(self, fp, chunk):
|
||||
self.fp = fp
|
||||
self.chunk = chunk
|
||||
|
||||
def write(self, data):
|
||||
self.chunk(self.fp, b"IDAT", data)
|
||||
|
||||
|
||||
def _save(im, fp, filename, chunk=putchunk, check=0):
|
||||
# save an image to disk (called by the save method)
|
||||
|
||||
|
@ -597,9 +612,9 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
|
|||
dictionary = b""
|
||||
|
||||
im.encoderconfig = ("optimize" in im.encoderinfo,
|
||||
im.encoderinfo.get("compress_level", -1),
|
||||
im.encoderinfo.get("compress_type", -1),
|
||||
dictionary)
|
||||
im.encoderinfo.get("compress_level", -1),
|
||||
im.encoderinfo.get("compress_type", -1),
|
||||
dictionary)
|
||||
|
||||
# get the corresponding PNG mode
|
||||
try:
|
||||
|
@ -616,8 +631,8 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
|
|||
fp.write(_MAGIC)
|
||||
|
||||
chunk(fp, b"IHDR",
|
||||
o32(im.size[0]), o32(im.size[1]), # 0: size
|
||||
mode, # 8: depth/type
|
||||
o32(im.size[0]), o32(im.size[1]), # 0: size
|
||||
mode, # 8: depth/type
|
||||
b'\0', # 10: compression
|
||||
b'\0', # 11: filter category
|
||||
b'\0') # 12: interlace flag
|
||||
|
@ -629,7 +644,8 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
|
|||
palette_bytes += b'\0'
|
||||
chunk(fp, b"PLTE", palette_bytes)
|
||||
|
||||
transparency = im.encoderinfo.get('transparency',im.info.get('transparency', None))
|
||||
transparency = im.encoderinfo.get('transparency',
|
||||
im.info.get('transparency', None))
|
||||
|
||||
if transparency or transparency == 0:
|
||||
if im.mode == "P":
|
||||
|
@ -686,7 +702,8 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
|
|||
data = name + b"\0\0" + zlib.compress(im.info["icc_profile"])
|
||||
chunk(fp, b"iCCP", data)
|
||||
|
||||
ImageFile._save(im, _idat(fp, chunk), [("zip", (0,0)+im.size, 0, rawmode)])
|
||||
ImageFile._save(im, _idat(fp, chunk),
|
||||
[("zip", (0, 0)+im.size, 0, rawmode)])
|
||||
|
||||
chunk(fp, b"IEND", b"")
|
||||
|
||||
|
@ -704,8 +721,10 @@ def getchunks(im, **params):
|
|||
|
||||
class collector:
|
||||
data = []
|
||||
|
||||
def write(self, data):
|
||||
pass
|
||||
|
||||
def append(self, chunk):
|
||||
self.data.append(chunk)
|
||||
|
||||
|
|
|
@ -27,12 +27,13 @@ from PIL import Image, ImageFile
|
|||
b_whitespace = string.whitespace
|
||||
try:
|
||||
import locale
|
||||
locale_lang,locale_enc = locale.getlocale()
|
||||
locale_lang, locale_enc = locale.getlocale()
|
||||
if locale_enc is None:
|
||||
locale_lang,locale_enc = locale.getdefaultlocale()
|
||||
locale_lang, locale_enc = locale.getdefaultlocale()
|
||||
b_whitespace = b_whitespace.decode(locale_enc)
|
||||
except: pass
|
||||
b_whitespace = b_whitespace.encode('ascii','ignore')
|
||||
except:
|
||||
pass
|
||||
b_whitespace = b_whitespace.encode('ascii', 'ignore')
|
||||
|
||||
MODES = {
|
||||
# standard
|
||||
|
@ -47,9 +48,11 @@ MODES = {
|
|||
b"PyCMYK": "CMYK"
|
||||
}
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[0:1] == b"P" and prefix[1] in b"0456y"
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for PBM, PGM, and PPM images.
|
||||
|
||||
|
@ -58,8 +61,8 @@ class PpmImageFile(ImageFile.ImageFile):
|
|||
format = "PPM"
|
||||
format_description = "Pbmplus image"
|
||||
|
||||
def _token(self, s = b""):
|
||||
while True: # read until next whitespace
|
||||
def _token(self, s=b""):
|
||||
while True: # read until next whitespace
|
||||
c = self.fp.read(1)
|
||||
if not c or c in b_whitespace:
|
||||
break
|
||||
|
@ -104,14 +107,14 @@ class PpmImageFile(ImageFile.ImageFile):
|
|||
# maxgrey
|
||||
if s > 255:
|
||||
if not mode == 'L':
|
||||
raise ValueError("Too many colors for band: %s" %s)
|
||||
raise ValueError("Too many colors for band: %s" % s)
|
||||
if s < 2**16:
|
||||
self.mode = 'I'
|
||||
rawmode = 'I;16B'
|
||||
else:
|
||||
self.mode = 'I';
|
||||
self.mode = 'I'
|
||||
rawmode = 'I;32B'
|
||||
|
||||
|
||||
self.size = xsize, ysize
|
||||
self.tile = [("raw",
|
||||
(0, 0, xsize, ysize),
|
||||
|
@ -123,6 +126,7 @@ class PpmImageFile(ImageFile.ImageFile):
|
|||
# self.mode = self.im.mode
|
||||
# self.size = self.im.size
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
|
@ -152,7 +156,7 @@ def _save(im, fp, filename):
|
|||
fp.write(b"65535\n")
|
||||
elif rawmode == "I;32B":
|
||||
fp.write(b"2147483648\n")
|
||||
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, 0, 1))])
|
||||
ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 0, (rawmode, 0, 1))])
|
||||
|
||||
# ALTERNATIVE: save via builtin debug function
|
||||
# im._dump(filename)
|
||||
|
|
|
@ -28,8 +28,8 @@ MODES = {
|
|||
(2, 8): ("P", 1),
|
||||
(3, 8): ("RGB", 3),
|
||||
(4, 8): ("CMYK", 4),
|
||||
(7, 8): ("L", 1), # FIXME: multilayer
|
||||
(8, 8): ("L", 1), # duotone
|
||||
(7, 8): ("L", 1), # FIXME: multilayer
|
||||
(8, 8): ("L", 1), # duotone
|
||||
(9, 8): ("LAB", 3)
|
||||
}
|
||||
|
||||
|
@ -40,12 +40,14 @@ i8 = _binary.i8
|
|||
i16 = _binary.i16be
|
||||
i32 = _binary.i32be
|
||||
|
||||
|
||||
# --------------------------------------------------------------------.
|
||||
# read PSD images
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] == b"8BPS"
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for Photoshop images.
|
||||
|
||||
|
@ -100,12 +102,12 @@ class PsdImageFile(ImageFile.ImageFile):
|
|||
id = i16(read(2))
|
||||
name = read(i8(read(1)))
|
||||
if not (len(name) & 1):
|
||||
read(1) # padding
|
||||
read(1) # padding
|
||||
data = read(i32(read(4)))
|
||||
if (len(data) & 1):
|
||||
read(1) # padding
|
||||
read(1) # padding
|
||||
self.resources.append((id, name, data))
|
||||
if id == 1039: # ICC profile
|
||||
if id == 1039: # ICC profile
|
||||
self.info["icc_profile"] = data
|
||||
|
||||
#
|
||||
|
@ -159,6 +161,7 @@ class PsdImageFile(ImageFile.ImageFile):
|
|||
if self.mode == "P":
|
||||
Image.Image.load(self)
|
||||
|
||||
|
||||
def _layerinfo(file):
|
||||
# read layerinfo block
|
||||
layers = []
|
||||
|
@ -166,8 +169,10 @@ def _layerinfo(file):
|
|||
for i in range(abs(i16(read(2)))):
|
||||
|
||||
# bounding box
|
||||
y0 = i32(read(4)); x0 = i32(read(4))
|
||||
y1 = i32(read(4)); x1 = i32(read(4))
|
||||
y0 = i32(read(4))
|
||||
x0 = i32(read(4))
|
||||
y1 = i32(read(4))
|
||||
x1 = i32(read(4))
|
||||
|
||||
# image info
|
||||
info = []
|
||||
|
@ -197,7 +202,7 @@ def _layerinfo(file):
|
|||
elif mode == ["A", "B", "G", "R"]:
|
||||
mode = "RGBA"
|
||||
else:
|
||||
mode = None # unknown
|
||||
mode = None # unknown
|
||||
|
||||
# skip over blend flags and extra information
|
||||
filler = read(12)
|
||||
|
@ -207,8 +212,10 @@ def _layerinfo(file):
|
|||
if size:
|
||||
length = i32(read(4))
|
||||
if length:
|
||||
mask_y = i32(read(4)); mask_x = i32(read(4))
|
||||
mask_h = i32(read(4)) - mask_y; mask_w = i32(read(4)) - mask_x
|
||||
mask_y = i32(read(4))
|
||||
mask_x = i32(read(4))
|
||||
mask_h = i32(read(4)) - mask_y
|
||||
mask_w = i32(read(4)) - mask_x
|
||||
file.seek(length - 16, 1)
|
||||
combined += length + 4
|
||||
|
||||
|
@ -219,7 +226,8 @@ def _layerinfo(file):
|
|||
|
||||
length = i8(read(1))
|
||||
if length:
|
||||
# Don't know the proper encoding, Latin-1 should be a good guess
|
||||
# Don't know the proper encoding,
|
||||
# Latin-1 should be a good guess
|
||||
name = read(length).decode('latin-1', 'replace')
|
||||
combined += length + 1
|
||||
|
||||
|
@ -239,6 +247,7 @@ def _layerinfo(file):
|
|||
|
||||
return layers
|
||||
|
||||
|
||||
def _maketile(file, mode, bbox, channels):
|
||||
|
||||
tile = None
|
||||
|
@ -283,7 +292,7 @@ def _maketile(file, mode, bbox, channels):
|
|||
file.seek(offset)
|
||||
|
||||
if offset & 1:
|
||||
read(1) # padding
|
||||
read(1) # padding
|
||||
|
||||
return tile
|
||||
|
||||
|
|
139
PIL/PyAccess.py
139
PIL/PyAccess.py
|
@ -16,7 +16,8 @@
|
|||
# * Implements the pixel access object following Access.
|
||||
# * Does not implement the line functions, as they don't appear to be used
|
||||
# * Taking only the tuple form, which is used from python.
|
||||
# * Fill.c uses the integer form, but it's still going to use the old Access.c implementation.
|
||||
# * Fill.c uses the integer form, but it's still going to use the old
|
||||
# Access.c implementation.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
|
@ -25,7 +26,7 @@ from cffi import FFI
|
|||
import sys
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
|
||||
defs = """
|
||||
struct Pixel_RGBA {
|
||||
unsigned char r,g,b,a;
|
||||
|
@ -39,8 +40,8 @@ ffi.cdef(defs)
|
|||
|
||||
|
||||
class PyAccess(object):
|
||||
|
||||
def __init__(self, img, readonly = False):
|
||||
|
||||
def __init__(self, img, readonly=False):
|
||||
vals = dict(img.im.unsafe_ptrs)
|
||||
self.readonly = readonly
|
||||
self.image8 = ffi.cast('unsigned char **', vals['image8'])
|
||||
|
@ -48,13 +49,14 @@ class PyAccess(object):
|
|||
self.image = ffi.cast('unsigned char **', vals['image'])
|
||||
self.xsize = vals['xsize']
|
||||
self.ysize = vals['ysize']
|
||||
|
||||
|
||||
if DEBUG:
|
||||
print (vals)
|
||||
self._post_init()
|
||||
|
||||
def _post_init(): pass
|
||||
|
||||
def _post_init():
|
||||
pass
|
||||
|
||||
def __setitem__(self, xy, color):
|
||||
"""
|
||||
Modifies the pixel at x,y. The color is given as a single
|
||||
|
@ -62,11 +64,12 @@ class PyAccess(object):
|
|||
multi-band images
|
||||
|
||||
:param xy: The pixel coordinate, given as (x, y).
|
||||
:param value: The pixel value.
|
||||
:param value: The pixel value.
|
||||
"""
|
||||
if self.readonly: raise ValueError('Attempt to putpixel a read only image')
|
||||
(x,y) = self.check_xy(xy)
|
||||
return self.set_pixel(x,y,color)
|
||||
if self.readonly:
|
||||
raise ValueError('Attempt to putpixel a read only image')
|
||||
(x, y) = self.check_xy(xy)
|
||||
return self.set_pixel(x, y, color)
|
||||
|
||||
def __getitem__(self, xy):
|
||||
"""
|
||||
|
@ -76,94 +79,98 @@ class PyAccess(object):
|
|||
|
||||
:param xy: The pixel coordinate, given as (x, y).
|
||||
"""
|
||||
|
||||
(x,y) = self.check_xy(xy)
|
||||
return self.get_pixel(x,y)
|
||||
|
||||
(x, y) = self.check_xy(xy)
|
||||
return self.get_pixel(x, y)
|
||||
|
||||
putpixel = __setitem__
|
||||
getpixel = __getitem__
|
||||
|
||||
def check_xy(self, xy):
|
||||
(x,y) = xy
|
||||
(x, y) = xy
|
||||
if not (0 <= x < self.xsize and 0 <= y < self.ysize):
|
||||
raise ValueError('pixel location out of range')
|
||||
return xy
|
||||
|
||||
|
||||
class _PyAccess32_2(PyAccess):
|
||||
""" PA, LA, stored in first and last bytes of a 32 bit word """
|
||||
def _post_init(self, *args, **kwargs):
|
||||
self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
|
||||
|
||||
def get_pixel(self, x,y):
|
||||
|
||||
def get_pixel(self, x, y):
|
||||
pixel = self.pixels[y][x]
|
||||
return (pixel.r, pixel.a)
|
||||
|
||||
def set_pixel(self, x,y, color):
|
||||
def set_pixel(self, x, y, color):
|
||||
pixel = self.pixels[y][x]
|
||||
# tuple
|
||||
pixel.r = min(color[0],255)
|
||||
pixel.a = min(color[1],255)
|
||||
|
||||
pixel.r = min(color[0], 255)
|
||||
pixel.a = min(color[1], 255)
|
||||
|
||||
|
||||
class _PyAccess32_3(PyAccess):
|
||||
""" RGB and friends, stored in the first three bytes of a 32 bit word """
|
||||
|
||||
|
||||
def _post_init(self, *args, **kwargs):
|
||||
self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
|
||||
|
||||
def get_pixel(self, x,y):
|
||||
|
||||
def get_pixel(self, x, y):
|
||||
pixel = self.pixels[y][x]
|
||||
return (pixel.r, pixel.g, pixel.b)
|
||||
|
||||
def set_pixel(self, x,y, color):
|
||||
def set_pixel(self, x, y, color):
|
||||
pixel = self.pixels[y][x]
|
||||
# tuple
|
||||
pixel.r = min(color[0],255)
|
||||
pixel.g = min(color[1],255)
|
||||
pixel.b = min(color[2],255)
|
||||
pixel.r = min(color[0], 255)
|
||||
pixel.g = min(color[1], 255)
|
||||
pixel.b = min(color[2], 255)
|
||||
|
||||
|
||||
class _PyAccess32_4(PyAccess):
|
||||
""" RGBA etc, all 4 bytes of a 32 bit word """
|
||||
def _post_init(self, *args, **kwargs):
|
||||
self.pixels = ffi.cast("struct Pixel_RGBA **", self.image32)
|
||||
|
||||
def get_pixel(self, x,y):
|
||||
|
||||
def get_pixel(self, x, y):
|
||||
pixel = self.pixels[y][x]
|
||||
return (pixel.r, pixel.g, pixel.b, pixel.a)
|
||||
|
||||
def set_pixel(self, x,y, color):
|
||||
def set_pixel(self, x, y, color):
|
||||
pixel = self.pixels[y][x]
|
||||
# tuple
|
||||
pixel.r = min(color[0],255)
|
||||
pixel.g = min(color[1],255)
|
||||
pixel.b = min(color[2],255)
|
||||
pixel.a = min(color[3],255)
|
||||
pixel.r = min(color[0], 255)
|
||||
pixel.g = min(color[1], 255)
|
||||
pixel.b = min(color[2], 255)
|
||||
pixel.a = min(color[3], 255)
|
||||
|
||||
|
||||
|
||||
class _PyAccess8(PyAccess):
|
||||
""" 1, L, P, 8 bit images stored as uint8 """
|
||||
def _post_init(self, *args, **kwargs):
|
||||
self.pixels = self.image8
|
||||
|
||||
def get_pixel(self, x,y):
|
||||
|
||||
def get_pixel(self, x, y):
|
||||
return self.pixels[y][x]
|
||||
|
||||
def set_pixel(self, x,y, color):
|
||||
def set_pixel(self, x, y, color):
|
||||
try:
|
||||
# integer
|
||||
self.pixels[y][x] = min(color,255)
|
||||
self.pixels[y][x] = min(color, 255)
|
||||
except:
|
||||
# tuple
|
||||
self.pixels[y][x] = min(color[0],255)
|
||||
self.pixels[y][x] = min(color[0], 255)
|
||||
|
||||
|
||||
class _PyAccessI16_N(PyAccess):
|
||||
""" I;16 access, native bitendian without conversion """
|
||||
def _post_init(self, *args, **kwargs):
|
||||
self.pixels = ffi.cast('unsigned short **', self.image)
|
||||
|
||||
def get_pixel(self, x,y):
|
||||
def get_pixel(self, x, y):
|
||||
return self.pixels[y][x]
|
||||
|
||||
def set_pixel(self, x,y, color):
|
||||
def set_pixel(self, x, y, color):
|
||||
try:
|
||||
# integer
|
||||
self.pixels[y][x] = min(color, 65535)
|
||||
|
@ -171,16 +178,17 @@ class _PyAccessI16_N(PyAccess):
|
|||
# tuple
|
||||
self.pixels[y][x] = min(color[0], 65535)
|
||||
|
||||
|
||||
class _PyAccessI16_L(PyAccess):
|
||||
""" I;16L access, with conversion """
|
||||
def _post_init(self, *args, **kwargs):
|
||||
self.pixels = ffi.cast('struct Pixel_I16 **', self.image)
|
||||
|
||||
def get_pixel(self, x,y):
|
||||
def get_pixel(self, x, y):
|
||||
pixel = self.pixels[y][x]
|
||||
return pixel.l + pixel.r * 256
|
||||
|
||||
def set_pixel(self, x,y, color):
|
||||
def set_pixel(self, x, y, color):
|
||||
pixel = self.pixels[y][x]
|
||||
try:
|
||||
color = min(color, 65535)
|
||||
|
@ -190,16 +198,17 @@ class _PyAccessI16_L(PyAccess):
|
|||
pixel.l = color & 0xFF
|
||||
pixel.r = color >> 8
|
||||
|
||||
|
||||
class _PyAccessI16_B(PyAccess):
|
||||
""" I;16B access, with conversion """
|
||||
def _post_init(self, *args, **kwargs):
|
||||
self.pixels = ffi.cast('struct Pixel_I16 **', self.image)
|
||||
|
||||
def get_pixel(self, x,y):
|
||||
def get_pixel(self, x, y):
|
||||
pixel = self.pixels[y][x]
|
||||
return pixel.l *256 + pixel.r
|
||||
return pixel.l * 256 + pixel.r
|
||||
|
||||
def set_pixel(self, x,y, color):
|
||||
def set_pixel(self, x, y, color):
|
||||
pixel = self.pixels[y][x]
|
||||
try:
|
||||
color = min(color, 65535)
|
||||
|
@ -209,17 +218,19 @@ class _PyAccessI16_B(PyAccess):
|
|||
pixel.l = color >> 8
|
||||
pixel.r = color & 0xFF
|
||||
|
||||
|
||||
class _PyAccessI32_N(PyAccess):
|
||||
""" Signed Int32 access, native endian """
|
||||
def _post_init(self, *args, **kwargs):
|
||||
self.pixels = self.image32
|
||||
|
||||
def get_pixel(self, x,y):
|
||||
def get_pixel(self, x, y):
|
||||
return self.pixels[y][x]
|
||||
|
||||
def set_pixel(self, x,y, color):
|
||||
def set_pixel(self, x, y, color):
|
||||
self.pixels[y][x] = color
|
||||
|
||||
|
||||
class _PyAccessI32_Swap(PyAccess):
|
||||
""" I;32L/B access, with byteswapping conversion """
|
||||
def _post_init(self, *args, **kwargs):
|
||||
|
@ -228,24 +239,26 @@ class _PyAccessI32_Swap(PyAccess):
|
|||
def reverse(self, i):
|
||||
orig = ffi.new('int *', i)
|
||||
chars = ffi.cast('unsigned char *', orig)
|
||||
chars[0],chars[1],chars[2],chars[3] = chars[3], chars[2],chars[1],chars[0]
|
||||
chars[0], chars[1], chars[2], chars[3] = chars[3], chars[2], \
|
||||
chars[1], chars[0]
|
||||
return ffi.cast('int *', chars)[0]
|
||||
|
||||
def get_pixel(self, x,y):
|
||||
|
||||
def get_pixel(self, x, y):
|
||||
return self.reverse(self.pixels[y][x])
|
||||
|
||||
def set_pixel(self, x,y, color):
|
||||
def set_pixel(self, x, y, color):
|
||||
self.pixels[y][x] = self.reverse(color)
|
||||
|
||||
|
||||
class _PyAccessF(PyAccess):
|
||||
""" 32 bit float access """
|
||||
def _post_init(self, *args, **kwargs):
|
||||
self.pixels = ffi.cast('float **', self.image32)
|
||||
|
||||
def get_pixel(self, x,y):
|
||||
def get_pixel(self, x, y):
|
||||
return self.pixels[y][x]
|
||||
|
||||
def set_pixel(self, x,y, color):
|
||||
def set_pixel(self, x, y, color):
|
||||
try:
|
||||
# not a tuple
|
||||
self.pixels[y][x] = color
|
||||
|
@ -275,7 +288,7 @@ if sys.byteorder == 'little':
|
|||
mode_map['I;16'] = _PyAccessI16_N
|
||||
mode_map['I;16L'] = _PyAccessI16_N
|
||||
mode_map['I;16B'] = _PyAccessI16_B
|
||||
|
||||
|
||||
mode_map['I;32L'] = _PyAccessI32_N
|
||||
mode_map['I;32B'] = _PyAccessI32_Swap
|
||||
else:
|
||||
|
@ -285,14 +298,16 @@ else:
|
|||
|
||||
mode_map['I;32L'] = _PyAccessI32_Swap
|
||||
mode_map['I;32B'] = _PyAccessI32_N
|
||||
|
||||
def new(img, readonly=False):
|
||||
|
||||
|
||||
def new(img, readonly=False):
|
||||
access_type = mode_map.get(img.mode, None)
|
||||
if not access_type:
|
||||
if DEBUG: print ("PyAccess Not Implemented: %s" % img.mode)
|
||||
if DEBUG:
|
||||
print("PyAccess Not Implemented: %s" % img.mode)
|
||||
return None
|
||||
if DEBUG: print ("New PyAccess: %s" % img.mode)
|
||||
if DEBUG:
|
||||
print("New PyAccess: %s" % img.mode)
|
||||
return access_type(img, readonly)
|
||||
|
||||
|
||||
# End of file
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
from PIL import ContainerIO
|
||||
|
||||
|
||||
##
|
||||
# A file object that provides read access to a given member of a TAR
|
||||
# file.
|
||||
|
|
|
@ -33,6 +33,7 @@ except ImportError:
|
|||
|
||||
i32 = _binary.i32le
|
||||
|
||||
|
||||
##
|
||||
# Load texture from a Quake2 WAL texture file.
|
||||
# <p>
|
||||
|
|
|
@ -12,7 +12,7 @@ _VALID_WEBP_MODES = {
|
|||
_VP8_MODES_BY_IDENTIFIER = {
|
||||
b"VP8 ": "RGB",
|
||||
b"VP8X": "RGBA",
|
||||
b"VP8L": "RGBA", # lossless
|
||||
b"VP8L": "RGBA", # lossless
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,7 +30,8 @@ class WebPImageFile(ImageFile.ImageFile):
|
|||
format_description = "WebP image"
|
||||
|
||||
def _open(self):
|
||||
data, width, height, self.mode, icc_profile, exif = _webp.WebPDecode(self.fp.read())
|
||||
data, width, height, self.mode, icc_profile, exif = \
|
||||
_webp.WebPDecode(self.fp.read())
|
||||
|
||||
if icc_profile:
|
||||
self.info["icc_profile"] = icc_profile
|
||||
|
|
|
@ -24,6 +24,7 @@ _handler = None
|
|||
if str != bytes:
|
||||
long = int
|
||||
|
||||
|
||||
##
|
||||
# Install application-specific WMF image handler.
|
||||
#
|
||||
|
@ -43,7 +44,7 @@ if hasattr(Image.core, "drawwmf"):
|
|||
self.bbox = im.info["wmf_bbox"]
|
||||
|
||||
def load(self, im):
|
||||
im.fp.seek(0) # rewind
|
||||
im.fp.seek(0) # rewind
|
||||
return Image.frombytes(
|
||||
"RGB", im.size,
|
||||
Image.core.drawwmf(im.fp.read(), im.size, self.bbox),
|
||||
|
@ -56,6 +57,7 @@ if hasattr(Image.core, "drawwmf"):
|
|||
|
||||
word = _binary.i16le
|
||||
|
||||
|
||||
def short(c, o=0):
|
||||
v = word(c, o)
|
||||
if v >= 32768:
|
||||
|
@ -64,6 +66,7 @@ def short(c, o=0):
|
|||
|
||||
dword = _binary.i32le
|
||||
|
||||
|
||||
#
|
||||
# --------------------------------------------------------------------
|
||||
# Read WMF file
|
||||
|
@ -74,6 +77,7 @@ def _accept(prefix):
|
|||
prefix[:4] == b"\x01\x00\x00\x00"
|
||||
)
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for Windows metafiles.
|
||||
|
||||
|
@ -95,8 +99,10 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
|||
inch = word(s, 14)
|
||||
|
||||
# get bounding box
|
||||
x0 = short(s, 6); y0 = short(s, 8)
|
||||
x1 = short(s, 10); y1 = short(s, 12)
|
||||
x0 = short(s, 6)
|
||||
y0 = short(s, 8)
|
||||
x1 = short(s, 10)
|
||||
y1 = short(s, 12)
|
||||
|
||||
# normalize size to 72 dots per inch
|
||||
size = (x1 - x0) * 72 // inch, (y1 - y0) * 72 // inch
|
||||
|
@ -115,8 +121,10 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
|||
# enhanced metafile
|
||||
|
||||
# get bounding box
|
||||
x0 = dword(s, 8); y0 = dword(s, 12)
|
||||
x1 = dword(s, 16); y1 = dword(s, 20)
|
||||
x0 = dword(s, 8)
|
||||
y0 = dword(s, 12)
|
||||
x1 = dword(s, 16)
|
||||
y1 = dword(s, 20)
|
||||
|
||||
# get frame (in 0.01 millimeter units)
|
||||
frame = dword(s, 24), dword(s, 28), dword(s, 32), dword(s, 36)
|
||||
|
|
|
@ -35,9 +35,11 @@ xbm_head = re.compile(
|
|||
b"[\\000-\\377]*_bits\\[\\]"
|
||||
)
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix.lstrip()[:7] == b"#define"
|
||||
|
||||
|
||||
##
|
||||
# Image plugin for X11 bitmaps.
|
||||
|
||||
|
@ -81,7 +83,7 @@ def _save(im, fp, filename):
|
|||
|
||||
fp.write(b"static char im_bits[] = {\n")
|
||||
|
||||
ImageFile._save(im, fp, [("xbm", (0,0)+im.size, 0, None)])
|
||||
ImageFile._save(im, fp, [("xbm", (0, 0)+im.size, 0, None)])
|
||||
|
||||
fp.write(b"};\n")
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# ;-)
|
||||
|
||||
VERSION = '1.1.7' # PIL version
|
||||
PILLOW_VERSION = '2.5.3' # Pillow
|
||||
PILLOW_VERSION = '2.5.3' # Pillow
|
||||
|
||||
_plugins = ['BmpImagePlugin',
|
||||
'BufrStubImagePlugin',
|
||||
|
|
|
@ -16,16 +16,17 @@ if bytes is str:
|
|||
return ord(c)
|
||||
|
||||
def o8(i):
|
||||
return chr(i&255)
|
||||
return chr(i & 255)
|
||||
else:
|
||||
def i8(c):
|
||||
return c if c.__class__ is int else c[0]
|
||||
|
||||
def o8(i):
|
||||
return bytes((i&255,))
|
||||
return bytes((i & 255,))
|
||||
|
||||
|
||||
# Input, le = little endian, be = big endian
|
||||
#TODO: replace with more readable struct.unpack equivalent
|
||||
# TODO: replace with more readable struct.unpack equivalent
|
||||
def i16le(c, o=0):
|
||||
"""
|
||||
Converts a 2-bytes (16 bits) string to an integer.
|
||||
|
@ -33,7 +34,8 @@ def i16le(c, o=0):
|
|||
c: string containing bytes to convert
|
||||
o: offset of bytes to convert in string
|
||||
"""
|
||||
return i8(c[o]) | (i8(c[o+1])<<8)
|
||||
return i8(c[o]) | (i8(c[o+1]) << 8)
|
||||
|
||||
|
||||
def i32le(c, o=0):
|
||||
"""
|
||||
|
@ -42,24 +44,33 @@ def i32le(c, o=0):
|
|||
c: string containing bytes to convert
|
||||
o: offset of bytes to convert in string
|
||||
"""
|
||||
return i8(c[o]) | (i8(c[o+1])<<8) | (i8(c[o+2])<<16) | (i8(c[o+3])<<24)
|
||||
return (i8(c[o]) | (i8(c[o+1]) << 8) | (i8(c[o+2]) << 16) |
|
||||
(i8(c[o+3]) << 24))
|
||||
|
||||
|
||||
def i16be(c, o=0):
|
||||
return (i8(c[o])<<8) | i8(c[o+1])
|
||||
return (i8(c[o]) << 8) | i8(c[o+1])
|
||||
|
||||
|
||||
def i32be(c, o=0):
|
||||
return (i8(c[o])<<24) | (i8(c[o+1])<<16) | (i8(c[o+2])<<8) | i8(c[o+3])
|
||||
return ((i8(c[o]) << 24) | (i8(c[o+1]) << 16) |
|
||||
(i8(c[o+2]) << 8) | i8(c[o+3]))
|
||||
|
||||
|
||||
# Output, le = little endian, be = big endian
|
||||
def o16le(i):
|
||||
return o8(i) + o8(i>>8)
|
||||
return o8(i) + o8(i >> 8)
|
||||
|
||||
|
||||
def o32le(i):
|
||||
return o8(i) + o8(i>>8) + o8(i>>16) + o8(i>>24)
|
||||
return o8(i) + o8(i >> 8) + o8(i >> 16) + o8(i >> 24)
|
||||
|
||||
|
||||
def o16be(i):
|
||||
return o8(i>>8) + o8(i)
|
||||
return o8(i >> 8) + o8(i)
|
||||
|
||||
|
||||
def o32be(i):
|
||||
return o8(i>>24) + o8(i>>16) + o8(i>>8) + o8(i)
|
||||
return o8(i >> 24) + o8(i >> 16) + o8(i >> 8) + o8(i)
|
||||
|
||||
# End of file
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from __future__ import print_function
|
||||
import sys
|
||||
sys.path.insert(0, ".")
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ class TestFileGif(PillowTestCase):
|
|||
try:
|
||||
while True:
|
||||
framecount += 1
|
||||
img.seek(img.tell() +1)
|
||||
img.seek(img.tell() + 1)
|
||||
except EOFError:
|
||||
self.assertEqual(framecount, 5)
|
||||
|
||||
|
@ -128,7 +128,7 @@ class TestFileGif(PillowTestCase):
|
|||
img = Image.open("Tests/images/dispose_none.gif")
|
||||
try:
|
||||
while True:
|
||||
img.seek(img.tell() +1)
|
||||
img.seek(img.tell() + 1)
|
||||
self.assertEqual(img.disposal_method, 1)
|
||||
except EOFError:
|
||||
pass
|
||||
|
@ -137,7 +137,7 @@ class TestFileGif(PillowTestCase):
|
|||
img = Image.open("Tests/images/dispose_bgnd.gif")
|
||||
try:
|
||||
while True:
|
||||
img.seek(img.tell() +1)
|
||||
img.seek(img.tell() + 1)
|
||||
self.assertEqual(img.disposal_method, 2)
|
||||
except EOFError:
|
||||
pass
|
||||
|
@ -146,7 +146,7 @@ class TestFileGif(PillowTestCase):
|
|||
img = Image.open("Tests/images/dispose_prev.gif")
|
||||
try:
|
||||
while True:
|
||||
img.seek(img.tell() +1)
|
||||
img.seek(img.tell() + 1)
|
||||
self.assertEqual(img.disposal_method, 3)
|
||||
except EOFError:
|
||||
pass
|
||||
|
@ -154,8 +154,9 @@ class TestFileGif(PillowTestCase):
|
|||
def test_iss634(self):
|
||||
img = Image.open("Tests/images/iss634.gif")
|
||||
# seek to the second frame
|
||||
img.seek(img.tell() +1)
|
||||
# all transparent pixels should be replaced with the color from the first frame
|
||||
img.seek(img.tell() + 1)
|
||||
# all transparent pixels should be replaced with the color from the
|
||||
# first frame
|
||||
self.assertEqual(img.histogram()[img.info['transparency']], 0)
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from helper import unittest, PillowTestCase, lena
|
||||
from helper import unittest, PillowTestCase
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from helper import *
|
||||
from helper import unittest, PillowTestCase
|
||||
|
||||
try:
|
||||
import pyroma
|
||||
|
|
Loading…
Reference in New Issue
Block a user