我目前正在使用python 3.5脚本将bmp图像(或任何像素数组)转换为gif图像。我想不使用诸如numpy或枕头之类的笨重的python模块来执行此操作,我正在使用准纯python。 为了达到这个目的,我需要将颜色数量减少到256种,并对像素进行抖动处理。 我已经有一个可以正常运行的脚本,但是它非常慢(570x370图像大约需要3s,1900x1100图像大约需要30s),这是不可接受的:-)
这是我编写的代码。 “ px”是这样创建的[高度] x [宽度] x [3种颜色]的数组
px = []
for i in range(height):
px.append([[0,0,0]]*width)
并用bmp值填充(例如px [10] [12] = [101,203,255])
减色和抖动处理是通过以下代码完成的(使用Sierra Lite抖动处理http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/):
data=bytearray(height*width) # Output data array
i = 0
for ligne in range(height):
for col in range(width):
[R,G,B] = px[ligne][col] # Get colors of pixel
Idx = GetColorIdx(R,G,B) # Get table index of nearest color
data[i] = Idx # Store index
i += 1
[Rnew,Gnew,Bnew] = GetIdxColor(Idx) # Get colors of table index
e = (R+G+B)/3-(Rnew+Gnew+Bnew)/3 # error between colors
# Error diffusion on nearest pixels if available
if col < width-1:
[R,G,B] = px[ligne][col+1]
px[ligne][col+1] = [clip(R+e/2),clip(G+e/2),clip(B+e/2)]
if ligne < height-1:
if col > 0:
[R,G,B] = px[ligne+1][col-1]
px[ligne+1][col-1] = [clip(R+e/4),clip(G+e/4),clip(B+e/4)]
[R,G,B] = px[ligne+1][col]
px[ligne+1][col] = [clip(R+e/4),clip(G+e/4),clip(B+e/4)]
以下是辅助功能:
# 256 8-8-4 color palette inspired from
# https://en.wikipedia.org/wiki/List_of_software_palettes#8-8-4_levels_RGB
def GetColorIdx(R,G,B): # Get color index from RGB colors
return round(R/36.5)+round(G/36.5)*8+round(B/85)*64
def GetIdxColor(Idx): # Get RGB colors from table index
R=int(Idx%8*36.5)
G=int(Idx//8%8*36.5)
B=int(Idx//64*85)
return [R,G,B]
def clip(n): # Trim n between 0 and 255
if n<0: return 0
elif n>255: return 255
return round(n)
非常慢的部分是围绕宽度和高度的双倍for循环。 您是否对如何在纯python下改善这一点有任何想法? 我已经尝试了几种方法,例如使用dict而不是list,将颜色编码为3个字节而不是3个值,但这没有实际效果...
这部分之后是gif编码和书写部分。我认为这也可以改善,但这将是下一步^^
谢谢!!