Python图片位数转换
一般购买嵌入式的屏幕,商家都会提供软件,可以将bmp文件转换成对应的C数组。
我们只需要提前转换好后放入代码中并烧录进单片机。
其实商家提供的软件只是做了简单的一件事,就是扫描并将图像位数进行转换。
我们常规使用的png图像是32位的,有4个通道,RGB三个通道以及一个透明通道。
我们常规使用的jpeg以及bmp图像是24位的,只有RGB三个通道。
而我们使用的屏幕是16位的,所以需要进行位数的转换。
具体来说,24位bmp图像是RGB888
我们需要转换成16位的RGB565
举个例子 比如24位的像素RGB888是11010110 11010100 11101010(高位在前)
转换成16位的像素RGB565则只需要取R的高五位,G的高六位,B的高五位,如下图:
以python实现为例,假设输入的是一个24位的数,转换实现如下:
def rgb888_to_rgb565(rgb888):
# 获得rgb各自对应的八位
r = (rgb888 & 0xff0000) >> 16
g = (rgb888 & 0x00ff00) >> 8
b = rgb888 & 0x0000ff
# 888 -> 565
r >>= 3
g >>= 2
b >>= 3
return r << 11 | g << 5 | b
而python用opencv读取图像,是一个numpy数组,RGB通道各自的值是分离的。
假设我们模拟软件,将一个bmp图像转换成对应的16位c数组,python实现如下:
import numpy as np
import cv2 as cv
def img_rgb888_to_rgb565(img888):
# 这里img是8位的 需要转类型到16位 不修改后续左移会溢出
img888 = img888.astype(np.uint16)
# opencv 是 BGR
b = img888[:, :, 0]
g = img888[:, :, 1]
r = img888[:, :, 2]
# 888 -> 565
r >>= 3
g >>= 2
b >>= 3
return r << 11 | g << 5 | b
def bit16_to_two_bit8(bit16):
#高八位和低八位
high_bit8 = (bit16 & 0xff00) >> 8
low_bit8 = bit16 & 0x00ff
return high_bit8, low_bit8
def write_list_to_c_file(data, save_path, array_type, array_name):
with open(save_path, "w") as f:
# 第一行 写类型和数组名
f.write(array_type + " " + array_name + "[" + str(len(data)) + "]" + " = {")
f.write('\n')
# 循环写数据
for i in range(len(data)):
f.write(data[i])
f.write(",")
if i % 16 == 15:
f.write("\n")
# 尾行
f.write("};")
f.write("\n")
if __name__ == "__main__":
img = cv.imread(r"./1.bmp")
rgb565 = img_rgb888_to_rgb565(img)
high, low = bit16_to_two_bit8(rgb565)
bit16_array = np.concatenate((np.expand_dims(high, 2), np.expand_dims(low, 2)), axis=2) # 高位在前
data_list = list(map(lambda x: ("0X%02X" % x), bit16_array.flatten().tolist())) #flatten实现了横向扫描 要纵向扫描可以先转置
write_list_to_c_file(data=data_list, save_path="./test.c", array_type="const unsigned char", array_name="gImage_1")
实现起来比较容易,但是有挺多需要注意的地方,我写在了注释
参考:https://bbs.csdn.net/topics/360140415
参考:https://blog.csdn.net/baidu_26678247/article/details/65629447