libpng读取PNG8和PNG24的区别

PNG8和PNG24最大的不同就在于透明度,PNG8只有一位存储透明度,PNG24有8位。这也就影响了PNG数据块的数据格式大小。在libpng中提供了检测设置的方法。

// expand any tRNS chunk data into a full alpha channel
if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(pngPtr);
    LOGD("png_set_tRNS_to_alpha");
}

这个检测来自于libpng官方教程,检测透明度如果不够,那么会补齐数据格式。另外libpng还提供了额外的一些检测和设置。

// force palette images to be expanded to 24-bit RGB
// it may include alpha channel
if (colorType == PNG_COLOR_TYPE_PALETTE) {
    png_set_palette_to_rgb(pngPtr);
    LOGD("png_set_palette_to_rgb");
}
 
// low-bit-depth grayscale images are to be expanded to 8 bits
if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) {
    png_set_expand_gray_1_2_4_to_8(pngPtr);
    LOGD("png_set_expand_gray_1_2_4_to_8");
}
 
// expand any tRNS chunk data into a full alpha channel
if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(pngPtr);
    LOGD("png_set_tRNS_to_alpha");
}
 
// reduce images with 16-bit samples to 8 bits
if (bitDepth == 16) {
    png_set_strip_16(pngPtr);
}
 
// expand grayscale images to RGB
if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
    png_set_gray_to_rgb(pngPtr);
    LOGD("png_set_gray_to_rgb");
}

所有的设置,都必须在png_read_update_info函数调用之前,才能起作用。

最后,关于png的一些信息获取,png_get_IHDR是针对32位图片的,那么16位图片就会有问题。我们需要用别的方法调用确保正确性。

/* Note that png_get_IHDR() returns 32-bit data into
 * the application's width and height variables.
 * This is an unsafe situation if these are 16-bit
 * variables
 */
width     = png_get_image_width(pngPtr, infoPtr);
height    = png_get_image_height(pngPtr, infoPtr);
bitDepth  = png_get_bit_depth(pngPtr, infoPtr);
colorType = png_get_color_type(pngPtr, infoPtr);


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用libpng库将png文件解码为bmp数组的步骤如下: 1. 安装libpng库。在Ubuntu上可以使用以下命令安装: ``` sudo apt-get install libpng-dev ``` 2. 编写C代码。下面是一个示例代码,可以将输入的png文件解码为bmp数组,并输出为另一个文件。 ```c #include <stdio.h> #include <stdlib.h> #include <png.h> int main(int argc, char *argv[]) { if (argc != 3) { printf("Usage: %s input_file.png output_file.bmp\n", argv[0]); return 1; } char *input_file = argv[1]; char *output_file = argv[2]; // 打开png文件 FILE *fp = fopen(input_file, "rb"); if (!fp) { printf("Error opening file %s\n", input_file); return 1; } // 读取png文件头信息 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { printf("Error creating read struct\n"); fclose(fp); return 1; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { printf("Error creating info struct\n"); fclose(fp); png_destroy_read_struct(&png_ptr, NULL, NULL); return 1; } if (setjmp(png_jmpbuf(png_ptr))) { printf("Error during setjmp\n"); fclose(fp); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 1; } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); // 获取png文件信息 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); // 将png文件转换为bmp数组 if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); png_read_update_info(png_ptr, info_ptr); png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); for (int y = 0; y < height; y++) { row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr, info_ptr)); } png_read_image(png_ptr, row_pointers); // 将bmp数组输出到文件 FILE *fout = fopen(output_file, "wb"); if (!fout) { printf("Error opening output file %s\n", output_file); fclose(fp); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); for (int y = 0; y < height; y++) free(row_pointers[y]); free(row_pointers); return 1; } fwrite("BM", 1, 2, fout); int bmp_size = width * height * 3; int bmp_offset = 54; int file_size = bmp_offset + bmp_size; fwrite(&file_size, 4, 1, fout); fwrite("\0\0\0\0", 4, 1, fout); fwrite(&bmp_offset, 4, 1, fout); int header_size = 40; int planes = 1; int bits_per_pixel = 24; int compression = 0; int image_size = bmp_size; int x_pixels_per_meter = 2835; int y_pixels_per_meter = 2835; int total_colors = 0; int important_colors = 0; fwrite(&header_size, 4, 1, fout); fwrite(&width, 4, 1, fout); fwrite(&height, 4, 1, fout); fwrite(&planes, 2, 1, fout); fwrite(&bits_per_pixel, 2, 1, fout); fwrite(&compression, 4, 1, fout); fwrite(&image_size, 4, 1, fout); fwrite(&x_pixels_per_meter, 4, 1, fout); fwrite(&y_pixels_per_meter, 4, 1, fout); fwrite(&total_colors, 4, 1, fout); fwrite(&important_colors, 4, 1, fout); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { png_byte *ptr = &row_pointers[y][x * 3]; fwrite(ptr + 2, 1, 1, fout); fwrite(ptr + 1, 1, 1, fout); fwrite(ptr, 1, 1, fout); } } fclose(fout); fclose(fp); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); for (int y = 0; y < height; y++) free(row_pointers[y]); free(row_pointers); return 0; } ``` 在终端中执行以下命令编译代码: ``` gcc png2bmp.c -o png2bmp -lpng ``` 3. 执行程序。在终端中输入以下命令,将png文件转换为bmp数组: ``` ./png2bmp input_file.png output_file.bmp ``` 其中,'input_file.png'为需要转换的png文件名,'output_file.bmp'为输出的bmp文件名。执行成功后,会在当前目录下生成一个bmp文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值