使用numpy和pil将565(16位颜色)转换为888(24位颜色)
我必须以此为序,事实上我有一个使用 bitshift 和 putpixel 的工作方法,但它非常慢,我希望利用 numpy 来加速这个过程。我相信我已经很接近了,但还没有完全实现。在对我认为应该有效的时间进行计时后,我发现时间提高了 0.3 秒,这就是我的动力。
当前的工作代码:
buff # a binary set of data
im = Image.new("RGBA",(xdim,ydim))
for y in xrange(ydim):
for x in xrange(xdim):
px = buff[x*y]
# the 255 is for the alpha channel which I plan to use later
im.putpixel((x,y),(px&0xF800) >> 8, (px&0x07E0) >> 3, (px&0x001F) <<3, 255))
return im
我试图工作的代码如下所示:
im16 = numpy.fromstring(buff,dtype=numpy.uint16) #read data as shorts
im16 = numpy.array(im16,dtype=numpy.uint32) #now that it's in the correct order, convert to 32 bit so there is room to do shifting
r = numpy.right_shift(8, im16.copy() & 0xF800)
g = numpy.right_shift(3, im16.copy() & 0x07E0)
b = numpy.left_shift( 3, im16 & 0x001F)
pA = numpy.append(r,g)
pB = numpy.append(b,numpy.ones((xdim,ydim),dtype=numpy.uint32) * 0xFF) #this is a black alpha channel
img = numpy.left_shift(img,8) #gives me green channel
im24 = Image.fromstring("RGBA",(xdim,ydim),img)
return im24
所以最后一个问题是通道没有组合,我不相信我应该必须进行最后的位移(请注意,我得到红色通道(如果我不位移 8)。非常感谢有关如何正确组合所有内容的帮助。
解决
import numpy as np
arr = np.fromstring(buff,dtype=np.uint16).astype(np.uint32)
arr = 0xFF000000 + ((arr & 0xF800) >> 8) + ((arr & 0x07E0) << 5) + ((arr & 0x001F) << 19)
return Image.frombuffer('RGBA', (xdim,ydim), arr, 'raw', 'RGBA', 0, 1)
方案的区别在于,您需要将其打包为来自 putpixel 的 MSB(ALPHA,B,G,R)LSB 计数器直觉,但它可以工作,并且工作良好
I must preface this, with the fact that I have a working method using bitshift and putpixel, but it is incredibly slow, and I am looking to leverage numpy to speed up the process. I believe I am close, but not quite there. Having timed what I think should work, I'm seeing a 0.3 second improvement in time, hence my motivation.
The current working code:
buff # a binary set of data
im = Image.new("RGBA",(xdim,ydim))
for y in xrange(ydim):
for x in xrange(xdim):
px = buff[x*y]
# the 255 is for the alpha channel which I plan to use later
im.putpixel((x,y),(px&0xF800) >> 8, (px&0x07E0) >> 3, (px&0x001F) <<3, 255))
return im
The code I'm trying to get work looks like this:
im16 = numpy.fromstring(buff,dtype=numpy.uint16) #read data as shorts
im16 = numpy.array(im16,dtype=numpy.uint32) #now that it's in the correct order, convert to 32 bit so there is room to do shifting
r = numpy.right_shift(8, im16.copy() & 0xF800)
g = numpy.right_shift(3, im16.copy() & 0x07E0)
b = numpy.left_shift( 3, im16 & 0x001F)
pA = numpy.append(r,g)
pB = numpy.append(b,numpy.ones((xdim,ydim),dtype=numpy.uint32) * 0xFF) #this is a black alpha channel
img = numpy.left_shift(img,8) #gives me green channel
im24 = Image.fromstring("RGBA",(xdim,ydim),img)
return im24
so the final problem, is that the channels are not combining and I don't believe I should have to do that final bit shift (note that I get the red channel if I don't bit-shift by 8). Assistance on how to combine everything correctly would be much appreciated.
SOLUTION
import numpy as np
arr = np.fromstring(buff,dtype=np.uint16).astype(np.uint32)
arr = 0xFF000000 + ((arr & 0xF800) >> 8) + ((arr & 0x07E0) << 5) + ((arr & 0x001F) << 19)
return Image.frombuffer('RGBA', (xdim,ydim), arr, 'raw', 'RGBA', 0, 1)
the difference is that you need to pack it as MSB(ALPHA,B,G,R)LSB counter intuitive from putpixel, but it works, and works well
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
警告:以下代码尚未经过检查,但我认为这将实现您想要的功能(如果我正确理解所有内容):
我将所有通道组合在一起,形成执行所有操作的 32 位线路的位移位。最左边的 8 位是红色,接下来的 8 位是绿色,接下来的 8 位是蓝色,最后 8 位是 alpha。移位数字可能看起来有点奇怪,因为我合并了 16 位格式的移位。另外,我使用
frombuffer
因为我们希望利用 Numpy 使用的缓冲区,而不是首先转换为字符串。查看此页面可能会有所帮助。在我看来,这并不是很好,但根据我的经验,PIL 的情况就是这样。该文档确实不太人性化,事实上我经常觉得它令人困惑,但我不打算自愿重写它,因为我不怎么使用 PIL。
Warning: the following code hasn't been checked, but I think that this will do what you want (if I'm understanding everything correctly):
I'm combining all of the channels together into 32-bits on the line that does all of the bit shifting. The leftmost 8-bits are the red, the next 8 are the green, the next 8 blue, and the last 8 alpha. The shifting numbers may seem a little strange because I incorporated the shifts from the 16-bit format. Also, I'm using
frombuffer
because then we want to take advantage of the buffer being used by Numpy rather than converting to a string first.It might help to look at this page. It's not super great in my opinion, but that's how things go with PIL in my experience. The documentation is really not very user-friendly, in fact I often find it confusing, but I'm not about to volunteer to rewrite it because I don't use PIL much.
如果你想适当地进行缩放,这里有一个更接近 PIL 的方法来解决你的问题。
If you want to do the scaling appropriately, here is a more PIL-ish to solve your problem.