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

如何使用libpng库读取16位深度灰度图像的正确像素值

问题根源

你遇到的问题是类型使用错误导致只读取了16位像素的8位数值:

  • png_bytepp 本质是 unsigned char** 类型,每个元素只能存储8位数据,16位灰度图每个像素占连续2字节的存储空间,你用rows[h][w]索引时只会取到第一个字节的数值,范围自然只能到255。
  • 额外的潜在问题:Windows平台下读取二进制文件需要用rb模式打开,否则可能因换行符转换导致文件读取异常;原代码缺少必要的错误判断逻辑,遇到异常文件会直接崩溃。

修复方案

你需要将行指针转换为16位无符号整数类型指针,正确读取2字节的像素值,同时补充必要的校验逻辑,修复后的代码如下:

#include <stdio.h>
#include <png.h>
#include <stdint.h>

int main(void) {
    // 二进制模式打开文件,兼容Windows平台
    FILE *fp = fopen("sample.png", "rb");
    if (!fp) {
        printf("文件打开失败\n");
        return 1;
    }

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        fclose(fp);
        return 1;
    }
    png_infop png_info = png_create_info_struct(png_ptr);
    if (!png_info) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        fclose(fp);
        return 1;
    }

    // libpng错误跳转处理,读取失败时不会直接崩溃
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &png_info, NULL);
        fclose(fp);
        return 1;
    }

    png_init_io(png_ptr, fp);
    png_read_png(png_ptr, png_info, PNG_TRANSFORM_IDENTITY, NULL);

    int WIDTH = png_get_image_width(png_ptr, png_info);
    int HEIGHT = png_get_image_height(png_ptr, png_info);
    int bit_depth = png_get_bit_depth(png_ptr, png_info);
    int color_type = png_get_color_type(png_ptr, png_info);

    // 校验图像格式是否为16位灰度图
    if (color_type != PNG_COLOR_TYPE_GRAY || bit_depth != 16) {
        printf("图像不是16位灰度图\n");
        png_destroy_read_struct(&png_ptr, &png_info, NULL);
        fclose(fp);
        return 1;
    }

    // 将行指针转换为16位无符号整数类型
    png_uint_16pp rows = (png_uint_16pp)png_get_rows(png_ptr, png_info);

    for (int h = 0; h < HEIGHT; h++) {
        for (int w = 0; w < WIDTH; w++) {
            // 打印16位像素值,范围0~65535
            printf("%u ", rows[h][w]);
        }
        printf("\n");
    }

    // 释放资源
    png_destroy_read_struct(&png_ptr, &png_info, NULL);
    fclose(fp);
    return 0;
}

注意:libpng返回的16位像素值默认是大端字节序,如果你运行的平台是小端字节序(比如x86、x86_64架构),可以在png_read_png的转换参数中加入PNG_TRANSFORM_SWAP_ENDIAN宏,自动转换为本地字节序,避免数值错误。

内容的提问来源于stack exchange,提问作者Phan Chính Quân

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 19:15:10