加速抓取 alphachannel
Speeding up grabbing alphachannel
我不知道是否可以做任何事情来加速我的代码,如果有的话可能不会太多,但我想我会在这里问。
我正在为使用自定义嵌入式 python 解释器的程序编写 python 脚本,因此我只能使用默认库。 Pillow 和 Numpy 等外部库不起作用,因为它们更改了 python dll 的名称,因此预编译库无法与其交互。
此程序不支持从剪贴板粘贴其专有格式以外的透明图像。所以我正在编写一个脚本来涵盖该功能。它使用 ctypes 从剪贴板中获取 CF_DIBv5 格式并检查它是否为 32bpp 以及是否存在 alphamask。
这是慢的部分。然后我需要隔离 alpha 通道并将其保存为自己的单独图像。我可以很容易地做到这一点。只需从字节字符串中获取一个 Long,然后获取 alpha 通道的掩码,然后将其打包回我的新位图字节串。在 300x300 的小图像上,这需要将近 10 秒的时间。这并不可怕。我很乐意接受这一点。但是,我担心它在较大的百万像素图像上会非常慢。
我没有在这里展示完整的代码,因为它是一个可怕的丑陋的混乱,其中大部分只是定义我用于我的位图的结构 class 并让 ctypes 工作。但这里是我循环数据的重要部分。
rowsizemask = calcRowSize(24,bmp.header.bV5Width) #returns bytes per row needed
rowmaskpadding = b'\x00'*(rowsizemask - bmp.header.bV5Width*3) #creates padding bytes
#loop over image data
for y in range(bmp.header.bV5Height):
for x in range(bmp.header.bV5Width):
offset, color = unpack(offset,">L",buff) #calls struct.unpack in custom function
color = color[0] & bmp.header.bV5AlphaMask #gets alpha channel
newbmp.pixels += struct.pack(">3B", color,color,color) #creates 24bpp listing
newbmp.pixels += rowmaskpadding #pad row to meet BMP specs
那你怎么看?我错过了一些明显的东西吗?或者这是否与纯 python 一样好?
好的,所以在进一步挖掘之后。我意识到我可以使用 ctypes.create_string_buffer 创建一个完美大小的二进制字符串,然后使用切片来更改值。
我可以做更多微小的优化和代码清理,但这已经从一个很容易需要几分钟才能在 900x900 像素图像上完成的脚本变成了几秒钟。
这是最好的选择吗?不知道,但它有效。而且它比我想象的要快。请在此处查看编辑后的代码。变化很小。
rowSizeMask = calcRowSize(24,bmp.header.bV5Width) #returns bytes per row needed
paddingLength = (rowSizeMask = bmp.header.bV5Width*3)
rowMaskPadding = b'\x00'*paddingLength #creates padding bytes
writeOffset = 0
#create pixel buffer
#rowsize mask includes padding, multiply by height for total byte count
newBmp.pixels = ctypes.create_string_buffer(bmp.heaer.bV5Height * rowSizeMask)
#loop over image data
for y in range(bmp.header.bV5Height):
for x in range(bmp.header.bV5Width):
offset, color = unpack(offset,">L",buff) #calls struct.unpack in custom function
color = color[0] & bmp.header.bV5AlphaMask #gets alpha channel
newBmp.pixels[writeOffset:writeOffset+3] = struct.pack(">3B", color,color,color) #creates 24bpp listing
writeOffset += 3
newBmp.pixels += rowMaskPadding #pad row to meet BMP specs
writeOffset += paddingLength
我不知道是否可以做任何事情来加速我的代码,如果有的话可能不会太多,但我想我会在这里问。
我正在为使用自定义嵌入式 python 解释器的程序编写 python 脚本,因此我只能使用默认库。 Pillow 和 Numpy 等外部库不起作用,因为它们更改了 python dll 的名称,因此预编译库无法与其交互。
此程序不支持从剪贴板粘贴其专有格式以外的透明图像。所以我正在编写一个脚本来涵盖该功能。它使用 ctypes 从剪贴板中获取 CF_DIBv5 格式并检查它是否为 32bpp 以及是否存在 alphamask。
这是慢的部分。然后我需要隔离 alpha 通道并将其保存为自己的单独图像。我可以很容易地做到这一点。只需从字节字符串中获取一个 Long,然后获取 alpha 通道的掩码,然后将其打包回我的新位图字节串。在 300x300 的小图像上,这需要将近 10 秒的时间。这并不可怕。我很乐意接受这一点。但是,我担心它在较大的百万像素图像上会非常慢。
我没有在这里展示完整的代码,因为它是一个可怕的丑陋的混乱,其中大部分只是定义我用于我的位图的结构 class 并让 ctypes 工作。但这里是我循环数据的重要部分。
rowsizemask = calcRowSize(24,bmp.header.bV5Width) #returns bytes per row needed
rowmaskpadding = b'\x00'*(rowsizemask - bmp.header.bV5Width*3) #creates padding bytes
#loop over image data
for y in range(bmp.header.bV5Height):
for x in range(bmp.header.bV5Width):
offset, color = unpack(offset,">L",buff) #calls struct.unpack in custom function
color = color[0] & bmp.header.bV5AlphaMask #gets alpha channel
newbmp.pixels += struct.pack(">3B", color,color,color) #creates 24bpp listing
newbmp.pixels += rowmaskpadding #pad row to meet BMP specs
那你怎么看?我错过了一些明显的东西吗?或者这是否与纯 python 一样好?
好的,所以在进一步挖掘之后。我意识到我可以使用 ctypes.create_string_buffer 创建一个完美大小的二进制字符串,然后使用切片来更改值。
我可以做更多微小的优化和代码清理,但这已经从一个很容易需要几分钟才能在 900x900 像素图像上完成的脚本变成了几秒钟。
这是最好的选择吗?不知道,但它有效。而且它比我想象的要快。请在此处查看编辑后的代码。变化很小。
rowSizeMask = calcRowSize(24,bmp.header.bV5Width) #returns bytes per row needed
paddingLength = (rowSizeMask = bmp.header.bV5Width*3)
rowMaskPadding = b'\x00'*paddingLength #creates padding bytes
writeOffset = 0
#create pixel buffer
#rowsize mask includes padding, multiply by height for total byte count
newBmp.pixels = ctypes.create_string_buffer(bmp.heaer.bV5Height * rowSizeMask)
#loop over image data
for y in range(bmp.header.bV5Height):
for x in range(bmp.header.bV5Width):
offset, color = unpack(offset,">L",buff) #calls struct.unpack in custom function
color = color[0] & bmp.header.bV5AlphaMask #gets alpha channel
newBmp.pixels[writeOffset:writeOffset+3] = struct.pack(">3B", color,color,color) #creates 24bpp listing
writeOffset += 3
newBmp.pixels += rowMaskPadding #pad row to meet BMP specs
writeOffset += paddingLength