2011-12-15 101 views
2

我想在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:enter image description here 2:enter image description here 3:enter image description here 4 :enter image description here

現在,如果我在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 
+0

不是很pythonic,但你可能想用[`shutter`](http://shutter-project.org/):`shutter -s = X,Y,WIDTH,HEIGHT -e` – jcollado 2011-12-15 11:29:40

回答

4

我認爲這是因爲get_pixels,因爲它是存儲在內存中返回你的數據。這裏缺少的是一行可能會有一些填充,因爲性能方面的原因(因爲內存對齊限制)。

查看GdkPixbuf structure:有趣的信息是rowstride,它是行開始和下一行開始之間的字節數。它等於一行中的數據字節數+填充字節數。

當心最後一行沒有填充

+1

你把我在正確的軌道上。緩衝區是窗口的整個大小,但我正在處理它,就好像它與所需子區域的大小相同。由於我不需要分區域以外的任何東西,我通過將緩衝區的大小減小到分區域的大小來解決問題。 – misha 2011-12-22 17:58:43