使用GTK的屏幕分区的屏幕截图
我想在Ubuntu 10.04下使用Python只屏幕的一部分屏幕截图。使用GTK的屏幕分区的屏幕截图
这里是我的代码(假设IMAGE_GRAB
为false):
def screenshot_roi(regions):
if IMAGE_GRAB:
return map(ImageGrab.grab, regions)
else:
w = gtk.gdk.get_default_root_window()
sz = w.get_size()
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
src = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
results = []
for roi in regions:
if not roi:
results.append(None)
continue
x,y,width,height = roi
dst = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,width,height)
src.copy_area(x,y,width,height,dst,0,0)
im = PIL.Image.fromstring("RGB", (width, height), dst.get_pixels())
results.append(im)
return results
没有什么,看中这里。将整个drawable捕获到像素缓冲区中,然后继续裁剪每个像素缓冲区,然后将其转换为所需的PIL对象。
这是主线:
def main():
regions = [(845, 219, 248, 82), (1101, 243, 109, 59),
(1213, 245, 66, 57), (1281, 245, 74, 58)]
images = screenshot_roi(regions)
for i,roi in enumerate(images):
if roi:
roi.save('%d.png' % i)
if __name__ == '__main__':
main()
所产生的图像(所有除了第一个)具有步幅的问题,虽然:
1: 2:
3:
4 :
现在,如果我在PIL中进行修剪,一切正常:
def screenshot_roi(regions):
if IMAGE_GRAB:
return map(ImageGrab.grab, regions)
else:
w = gtk.gdk.get_default_root_window()
sz = w.get_size()
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
src = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
entire_im = PIL.Image.fromstring("RGB", sz, src.get_pixels())
results = []
for roi in regions:
if not roi:
results.append(None)
continue
x,y,width,height = roi
crop = entire_im.crop((x,y,x+width,y+height))
crop.load()
results.append(crop)
return results
我不想这样做,认为,因为从GTK到PIL的转换非常昂贵。这是一种浪费,因为我正在转换整个图像,以便从中获取较小的子区域。
任何人都可以提出为什么GTK版本有步幅错误?
编辑
工作来源:
x,y,w,h = region
win = gtk.gdk.get_default_root_window()
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,w,h)
src = pb.get_from_drawable(win,win.get_colormap(),x,y,0,0,w,h)
im = PIL.Image.frombuffer('RGB', (w,h), src.get_pixels(), 'raw',
'RGB', src.get_rowstride(), 1)
return im
我认为这是因为get_pixels,因为它是存储在内存中返回你的数据。这里缺少的是一行可能会有一些填充,因为性能方面的原因(因为内存对齐限制)。
查看GdkPixbuf structure:有趣的信息是rowstride,它是行开始和下一行开始之间的字节数。它等于一行中的数据字节数+填充字节数。
当心最后一行没有填充。
你把我在正确的轨道上。缓冲区是窗口的整个大小,但我正在处理它,就好像它与所需子区域的大小相同。由于我不需要分区域以外的任何东西,我通过将缓冲区的大小减小到分区域的大小来解决问题。 – misha 2011-12-22 17:58:43
不是很pythonic,但你可能想用[`shutter`](http://shutter-project.org/):`shutter -s = X,Y,WIDTH,HEIGHT -e` – jcollado 2011-12-15 11:29:40