用代码转换位图到XPM的总结:

需要注意的内容:

  1. 位图数据的字节序:在某些显示设备上,位图数据的字节序可能与你的代码生成的字节序不同。例如,有些设备可能需要从最高有效位(MSB)开始,而你的代码可能是从最低有效位(LSB)开始的。

  2. 位图数据的行序:位图数据的行序可能与你的显示逻辑不匹配。例如,如果你的显示设备是从上到下读取行的,而你的位图数据是从下到上排列的,那么显示的图像将会是倒置的。

  3. 位图数据的列序:位图数据的列序也可能与你的显示逻辑不匹配。例如,如果你的显示设备是从左到右读取列的,而你的位图数据是从右到左排列的,那么显示的图像将会是镜像的。

  4. 位图数据的填充:如果你的位图数据的宽度不是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()

这个代码生成的位图数据是从最高有效位开始,从上到下,从左到右排列的,这可能与你的显示设备的要求匹配。

效果:

  • 原图: 01
  • 烧录到ESP32-C5后: 01