用代码转换位图到XPM的总结:
需要注意的内容:
-
位图数据的字节序:在某些显示设备上,位图数据的字节序可能与你的代码生成的字节序不同。例如,有些设备可能需要从最高有效位(MSB)开始,而你的代码可能是从最低有效位(LSB)开始的。
-
位图数据的行序:位图数据的行序可能与你的显示逻辑不匹配。例如,如果你的显示设备是从上到下读取行的,而你的位图数据是从下到上排列的,那么显示的图像将会是倒置的。
-
位图数据的列序:位图数据的列序也可能与你的显示逻辑不匹配。例如,如果你的显示设备是从左到右读取列的,而你的位图数据是从右到左排列的,那么显示的图像将会是镜像的。
-
位图数据的填充:如果你的位图数据的宽度不是8的倍数,那么你可能需要在每行的末尾添加一些填充位。如果你没有正确地添加这些填充位,那么显示的图像可能会有一些问题。
为了解决这些问题,可以尝试以下方法:
-
检查位图数据的字节序:你可以检查你的位图数据的字节序是否与你的显示设备的要求匹配。如果不匹配,你可能需要修改你的代码来生成正确的字节序。
-
检查位图数据的行序:你可以检查你的位图数据的行序是否与你的显示逻辑匹配。如果不匹配,你可能需要修改你的代码来生成正确的行序。
-
检查位图数据的列序:你可以检查你的位图数据的列序是否与你的显示逻辑匹配。如果不匹配,你可能需要修改你的代码来生成正确的列序。
-
检查位图数据的填充:你可以检查你的位图数据的填充是否正确。如果不正确,你可能需要修改你的代码来正确地添加填充位。
以下是一个我修改后的代码,它生成的位图数据是从最高有效位开始,从上到下,从左到右排列的:
from PIL import Image
import argparse
def image_to_xbm(image_path, output_width=None, output_height=None):
img = Image.open(image_path).convert("L")
if output_width and output_height:
img = img.resize((output_width,output_height))
img = img.point(lambda p: p > 128 and 1)
width, height = img.size
print(f"Image size: {width}x{height}")
xbm_data = []
for y in range(height):
row = 0
for x in range(width):
if img.getpixel((x,y)) == 1:
row |= (1 << (x % 8))
if (x+1) % 8 == 0:
xbm_data.append(row)
row = 0
if width % 8 != 0:
row <<= (8 - width % 8)
xbm_data.append(row)
return xbm_data, width, height
def write_to_header_file(xbm_data, width, height, output_file):
with open(output_file, "w") as f:
f.write(f"// Generated from image, size: {width}x{height}\n")
f.write(f"const uint8_t bitmap[{len(xbm_data)}] PROGMEM = {{\n")
for i in range(0, len(xbm_data), 16):
f.write(" " + ", ".join(f"0x{byte:02X}" for byte in xbm_data[i:i+16]) + ",\n")
f.write("};\n")
def main():
parser = argparse.ArgumentParser(description="convert an image to XBM forma and write it to a header file.")
parser.add_argument("image_path", type=str, help="Path to the input image file")
parser.add_argument("output_width", type=int, help="Output width of the image")
parser.add_argument("output_height", type=int, help="Output height of the image")
parser.add_argument("output_file", type=str, help="Output header file of the image")
args = parser.parse_args()
xbm_data, width, height = image_to_xbm(args.image_path, args.output_width, args.output_height)
write_to_header_file(xbm_data, width, height, args.output_file)
print(f"write to {args.output_file} finished!\n")
if __name__ == "__main__":
main()
这个代码生成的位图数据是从最高有效位开始,从上到下,从左到右排列的,这可能与你的显示设备的要求匹配。
效果:
- 原图:

- 烧录到ESP32-C5后:
