PicoDVI与Adafruit GFX:8位PNG转RGB565格式遇阻求助
8位PNG转RGB565的三种解决方案(适配PicoDVI/Adafruit GFX)
一、修复Python转换代码
原代码因Python版本兼容问题、调色板获取逻辑错误导致报错,以下是适配Python3的稳定版本,专门处理8位索引PNG:
from PIL import Image def png_to_rgb565(input_path, output_path): # 强制转为索引模式,确保能获取调色板 img = Image.open(input_path).convert("P") pal = img.getpalette() if pal is None: raise ValueError("仅支持带调色板的8位索引PNG,当前图像无有效调色板") # 解析调色板为RGB三元组列表 palette = [(pal[i], pal[i+1], pal[i+2]) for i in range(0, len(pal), 3)] width, height = img.size pixels = img.load() with open(output_path, "wb") as f: # 可选:写入宽高信息(根据你的显示需求决定是否保留) f.write(width.to_bytes(2, byteorder="little")) f.write(height.to_bytes(2, byteorder="little")) # 逐像素转换为RGB565并写入 for y in range(height): for x in range(width): r, g, b = palette[pixels[x, y]] # RGB565编码:R取高5位,G取高6位,B取高5位 rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3) f.write(rgb565.to_bytes(2, byteorder="little")) if __name__ == "__main__": # 替换为你的输入输出路径 png_to_rgb565("input.png", "output.rgb565")
说明:
- 强制转
P模式解决了调色板为None的问题,避免灰度模式(L模式)的8位PNG干扰 - 适配Python3语法规范,修复了Python2的语法错误
- 输出的小端字节序符合RP2040的硬件要求
二、用ImageMagick命令行转换
无需编写代码,直接用ImageMagick完成转换,Windows下需先安装ImageMagick并添加到系统PATH:
基础转换命令
magick input.png -resize 320x240! -format "RGBA" -colorspace RGB ^ -channel R -evaluate shift -3 ^ -channel G -evaluate shift -2 ^ -channel B -evaluate shift -3 ^ +channel -type Grayscale -endian little output.rgb565
参数说明:
-resize 320x240!:强制设置输出分辨率(替换为你的目标尺寸)-endian little:生成小端字节序的RGB565数据- 通道移位操作直接完成RGB到565位的截取
简化版命令
如果不需要调整尺寸,可直接用:
magick input.png -define png:color-type=2 -depth 16 -format "%u" ^ -colorspace RGB -channel R -evaluate multiply 32768/255 ^ -channel G -evaluate multiply 65536/255 ^ -channel B -evaluate multiply 32768/255 ^ -combine -endian little output.rgb565
三、用C语言实现转换
适合需要高性能转换或集成到C项目的场景,依赖libpng库(Windows下可通过vcpkg安装):
#include <stdio.h> #include <stdlib.h> #include <png.h> #include <stdint.h> // RGB565结构体定义 typedef union { struct { uint16_t b : 5; uint16_t g : 6; uint16_t r : 5; }; uint16_t value; } RGB565; void png_to_rgb565(const char* input_path, const char* output_path) { FILE* fp = fopen(input_path, "rb"); if (!fp) { perror("无法打开输入文件"); exit(EXIT_FAILURE); } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info_ptr = png_create_info_struct(png_ptr); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); perror("PNG读取错误"); exit(EXIT_FAILURE); } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); int width = png_get_image_width(png_ptr, info_ptr); int height = png_get_image_height(png_ptr, info_ptr); png_byte color_type = png_get_color_type(png_ptr, info_ptr); png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr); // 仅支持8位索引PNG if (color_type != PNG_COLOR_TYPE_PALETTE || bit_depth != 8) { fprintf(stderr, "仅支持带调色板的8位索引PNG\n"); exit(EXIT_FAILURE); } // 获取调色板数据 png_colorp palette; int palette_count; png_get_PLTE(png_ptr, info_ptr, &palette, &palette_count); // 分配行指针并读取图像数据 png_bytep* row_pointers = malloc(sizeof(png_bytep) * height); for (int y = 0; y < height; y++) { row_pointers[y] = malloc(png_get_rowbytes(png_ptr, info_ptr)); } png_read_image(png_ptr, row_pointers); // 写入RGB565文件 FILE* out_fp = fopen(output_path, "wb"); if (!out_fp) { perror("无法打开输出文件"); exit(EXIT_FAILURE); } // 可选:写入宽高信息(小端) int16_t w = width, h = height; fwrite(&w, sizeof(int16_t), 1, out_fp); fwrite(&h, sizeof(int16_t), 1, out_fp); // 逐像素转换 for (int y = 0; y < height; y++) { png_byte* row = row_pointers[y]; for (int x = 0; x < width; x++) { png_color color = palette[row[x]]; RGB565 rgb; rgb.r = color.red >> 3; rgb.g = color.green >> 2; rgb.b = color.blue >> 3; fwrite(&rgb.value, sizeof(uint16_t), 1, out_fp); } } // 清理资源 for (int y = 0; y < height; y++) { free(row_pointers[y]); } free(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); fclose(out_fp); } int main(int argc, char* argv[]) { if (argc != 3) { fprintf(stderr, "用法:%s <输入PNG路径> <输出RGB565路径>\n", argv[0]); return EXIT_FAILURE; } png_to_rgb565(argv[1], argv[2]); return EXIT_SUCCESS; }
编译命令
- GCC编译:
gcc png2rgb565.c -o png2rgb565.exe -lpng -lz
- MSVC编译(需提前配置libpng和zlib的库路径):
cl png2rgb565.c /link libpng.lib zlib.lib
内容的提问来源于stack exchange,提问作者user2249316
相关产品推荐
相关产品推荐

