You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 04:00:47