2015-08-19 43 views
1

這是我的代碼:的Python Pygame的如何顯示8位圖像

from PIL import ImageGrab 
import pygame 

i = ImageGrab.grab() 
i = i.quantize(256) 
xy = i.getbbox() 
pd = pygame.display.set_mode((xy[2],xy[3])) 
new_img = pygame.image.fromstring(i.tostring(),(xy[2],xy[3]),'P') 
clock = pygame.time.Clock() 
while True: 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      pygame.display.quit() 
    pd.blit(new_img,(0,0)) 
    pygame.display.flip() 
    clock.tick(30) 

我越來越黑屏,請幫忙解決我的issue.thanks地塊。

+0

可能是pygame本身的一個bug。也許報告說他們的問題跟蹤器。 – sloth

+0

我沒有得到pygame Issue Tracker的回覆。 – ragun91

回答

0

原因是線pygame.image.fromstring(..., 'P')其中'P'表示一個8位編碼。該pygame image fromstring documentation指出,「的\」 P \「的格式只創建一個8位的表面,但顏色映射將是全黑的。

我身邊這讓通過跨到pygame的表面手動複製PIL圖像的調色板。代碼片段如下:

img = PIL.Image.open(...) # read an 8-bit image 
surface = pygame.image.fromstring(img.tobytes(), img.size, img.mode) # img.mode is 'P' 

new_palette = [] 
rgb_triplet = [] 
for rgb_value in img.getpalette(): 
    # this loop could be improved, but you get the idea 
    rgb_triplet.append(rgb_value) 

    if len(rgb_triplet) == 3: 
     new_palette.append((rgb_triplet[0], rgb_triplet[1], rgb_triplet[2])) 
     rgb_triplet = [] 

surface.set_palette(new_palette) 

重要:爲了調用surface.set_palette您必須首先調用pygame.init(),否則你會得到一個異常。


另一種選擇:

另一種方式我解決了這個是寫圖像到磁盤,然後將其加載直接進入pygame的表面。這保留了原來的調色板。請注意,這對我來說很有用,因爲我使用的PIL圖像最初不是從磁盤讀取的,而是通過從URL(本例中是來自OpenStreetMap的地圖圖塊)讀取數據在內存中創建的。

代碼舉例如下:

url = "http://a.tile.openstreetmap.org/{0}/{1}/{2}.png" # serves up 8-bit PNGs 
zoom = 10 
tilex = 1 
tiley = 1 

tile_url = url.format(zoom, tilex, tiley) 
imgstr = urllib2.urlopen(tile_url).read() 
tile_img = PIL.Image.open(StringIO.StringIO(imgstr)) 

temp_filename = "%s.%s.%s" % (zoom, tilex, tiley) 
tile_img.save(temp_filename) 

surface = pygame.image.load(temp_filename) 

顯然,這不是由於IO一個高性能的解決方案。