原因是線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一個高性能的解決方案。
可能是pygame本身的一個bug。也許報告說他們的問題跟蹤器。 – sloth
我沒有得到pygame Issue Tracker的回覆。 – ragun91