PIL 学习笔记(3)
图片序列(Image Sequences,也叫动画格式, animation formats)
PIL 对图片序列有一些基础的支持。支持 FLI/FLC, GIP 和其他一些格式,TIFF 文件也可以包含多个帧。
打开文件时,PIL 自动加载第一帧,可以用 seek 和 tell 方法来在帧之间切换。下列代码是枚举图片序列的每一帧的一个写法:
注意当前的实现中只允许访问下一帧,如果要重头访问,则需要重新 open 图片文件。
用 iterator 类包装后,我们可以用 for 语句来枚举每一个帧:
Postscript Printing
PIL 包含在 Postscript 打印机上打印图片,文字和图形的函数。例子:
关于读取图片的更多话题
前面说过一般用 Image.open(图片文件名) 的方法打开图片,其实不一定要传递图片文件名,也可以是一个实现了 read, seek, tell 方法的对象。该对象将被以二进制模式打开。
可以从字符串中读取图片,用 StringIO 类:
注意,PIL 库在读取图片头信息时,会重新回到文件开头(用 seek(0) 方法)。在读取图片数据时(load()) 也是如此。如果图片文件比较大,比如在 tar 文件中,可以用 ContainerIO 或 TarIO 模块来访问它。
例子:从 tar 压缩包中读取:
控制解码器
有些解码器允许一边从文件中读取,一边操作图片。这通常用于在创建缩略图时加速解码操作(速度比图片质量更重要),或者在向单色激光打印机打印的时候(仅需要图片的灰度信息)。
例子:用草稿(draft)模式读取
这样会输出类似下面的结果:
注意,草稿模式打开的结果图片不一定符合指定的模式和尺寸。如果要确保图片不大于指定尺寸,使用 thumbnail 方法。
PIL 对图片序列有一些基础的支持。支持 FLI/FLC, GIP 和其他一些格式,TIFF 文件也可以包含多个帧。
打开文件时,PIL 自动加载第一帧,可以用 seek 和 tell 方法来在帧之间切换。下列代码是枚举图片序列的每一帧的一个写法:
import Image
im = Image.open(r"c:/testimg/ani1.gif")
try:
while 1:
im.seek(im.tell() + 1)
# do something to im
print "x"
except EOFError:
pass
im = Image.open(r"c:/testimg/ani1.gif")
try:
while 1:
im.seek(im.tell() + 1)
# do something to im
print "x"
except EOFError:
pass
注意当前的实现中只允许访问下一帧,如果要重头访问,则需要重新 open 图片文件。
用 iterator 类包装后,我们可以用 for 语句来枚举每一个帧:
class ImageSequence:
def __init__(self, im):
self.im = im
def __getitem__(self, ix):
try:
if ix:
self.im.seek(ix)
return self.im
except EOFError:
raise IndexError
for frame in ImageSequence(im):
print "test"
def __init__(self, im):
self.im = im
def __getitem__(self, ix):
try:
if ix:
self.im.seek(ix)
return self.im
except EOFError:
raise IndexError
for frame in ImageSequence(im):
print "test"
Postscript Printing
PIL 包含在 Postscript 打印机上打印图片,文字和图形的函数。例子:
import Image
import PSDraw
im = Image.open("lena.ppm")
title = "lena"
box = (1*72, 2*72, 7*72, 10*72) # in points
ps = PSDraw.PSDraw() # 默认是 sys.stdout
ps.begin_document(title)
# draw the image (75 dpi)
ps.image(box, im, 75)
# draw centered title
ps.setfont("HelveticaNarrow-Bold", 36)
w, h, b = ps.textsize(title)
ps.text((4*72-w/2, 1*72-h), title)
ps.end_document()
import PSDraw
im = Image.open("lena.ppm")
title = "lena"
box = (1*72, 2*72, 7*72, 10*72) # in points
ps = PSDraw.PSDraw() # 默认是 sys.stdout
ps.begin_document(title)
# draw the image (75 dpi)
ps.image(box, im, 75)
# draw centered title
ps.setfont("HelveticaNarrow-Bold", 36)
w, h, b = ps.textsize(title)
ps.text((4*72-w/2, 1*72-h), title)
ps.end_document()
关于读取图片的更多话题
前面说过一般用 Image.open(图片文件名) 的方法打开图片,其实不一定要传递图片文件名,也可以是一个实现了 read, seek, tell 方法的对象。该对象将被以二进制模式打开。
可以从字符串中读取图片,用 StringIO 类:
import StringIO
im = Image.open(StringIO.StringIO(buffer))
im = Image.open(StringIO.StringIO(buffer))
注意,PIL 库在读取图片头信息时,会重新回到文件开头(用 seek(0) 方法)。在读取图片数据时(load()) 也是如此。如果图片文件比较大,比如在 tar 文件中,可以用 ContainerIO 或 TarIO 模块来访问它。
例子:从 tar 压缩包中读取:
import TarIO
fp = TarIO.TarIO("Imaging.tar", "Imaging/test/lena.ppm")
im = Image.open(fp)
fp = TarIO.TarIO("Imaging.tar", "Imaging/test/lena.ppm")
im = Image.open(fp)
控制解码器
有些解码器允许一边从文件中读取,一边操作图片。这通常用于在创建缩略图时加速解码操作(速度比图片质量更重要),或者在向单色激光打印机打印的时候(仅需要图片的灰度信息)。
例子:用草稿(draft)模式读取
im = Image.open(file)
print "original =", im.mode, im.size
im.draft("L", (100,100))
print "draft =", im.mode, im.size
print "original =", im.mode, im.size
im.draft("L", (100,100))
print "draft =", im.mode, im.size
这样会输出类似下面的结果:
origial = RGB (512, 512)
draft = L (128, 128)
draft = L (128, 128)
注意,草稿模式打开的结果图片不一定符合指定的模式和尺寸。如果要确保图片不大于指定尺寸,使用 thumbnail 方法。