LIBPNG读写PNG文件

本文分享了使用libpng库读取和生成PNG图片的代码示例。详细介绍了如何通过C语言实现对PNG图片的解码和编码过程,并提供了完整的源代码供读者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分享一下我使用的代码,以下是读取png图片文件的代码:

 
   
#include <stdio.h>
#include <png.h> 
#include <stdlib.h>
/******************************图片数据*********************************/
typedef struct _pic_data pic_data;
struct _pic_data
{
int width, height; /* 尺寸 */
int bit_depth; /* 位深 */
int flag; /* 一个标志,表示是否有alpha通道 */


unsigned char **rgba; /* 图片数组 */
};
/**********************************************************************/
#define PNG_BYTES_TO_CHECK 4
#define HAVE_ALPHA 1
#define NO_ALPHA 0


/* 用于解码png图片 */
int detect_png(char *filepath, pic_data *out){
FILE *pic_fp;
pic_fp = fopen(filepath, "rb");
/* 文件打开失败 */
if(pic_fp == NULL) 
return -1;
/* 初始化各种结构 */
png_structp png_ptr;
png_infop   info_ptr;
char buf[PNG_BYTES_TO_CHECK];
int temp;
png_ptr  = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
info_ptr = png_create_info_struct(png_ptr);setjmp(png_jmpbuf(png_ptr));

temp = fread(buf,1,PNG_BYTES_TO_CHECK,pic_fp);
temp = png_sig_cmp((void*)buf, (png_size_t)0, PNG_BYTES_TO_CHECK);
/*检测是否为png文件*/
if (temp!=0) return 1;
rewind(pic_fp);
/*开始读文件*/
png_init_io(png_ptr, pic_fp);
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);
int color_type,channels;
/*获取宽度,高度,位深,颜色类型*/
channels = png_get_channels(png_ptr, info_ptr);
/*获取通道数*/
out->bit_depth = png_get_bit_depth(png_ptr, info_ptr);
/* 获取位深 */
color_type = png_get_color_type(png_ptr, info_ptr);
/*颜色类型*/
int i,j;
int size, pos = 0;
/* row_pointers里边就是rgba数据 */
png_bytep* row_pointers;row_pointers = png_get_rows(png_ptr, info_ptr);
out->width = png_get_image_width(png_ptr, info_ptr);
out->height = png_get_image_height(png_ptr, info_ptr);
size = out->width * out->height;
/* 计算图片的总像素点数量 */ 
if(channels == 4 || color_type == PNG_COLOR_TYPE_RGB_ALPHA){/*如果是RGB+alpha通道,或者RGB+其它字节*/ 
size *= (4*sizeof(unsigned char));
/* 每个像素点占4个字节内存 */
out->flag = HAVE_ALPHA;
/* 标记 */
out->rgba = (unsigned char**) malloc(size);
if(out->rgba == NULL){
/* 如果分配内存失败 */
fclose(pic_fp);
puts("错误(png):无法分配足够的内存供存储数据!");
return 1;
}
temp = (4 * out->width);
/* 每行有4 * out->width个字节 */
for(i = 0; i < out->height; i++){
for(j = 0; j < temp; j += 4){
/* 一个字节一个字节的赋值 */
out->rgba[0][pos] = row_pointers[i][j];
// redout->rgba[1][pos] = row_pointers[i][j+1];
// greenout->rgba[2][pos] = row_pointers[i][j+2];
// blueout->rgba[3][pos] = row_pointers[i][j+3];
// alpha++pos;
}
}
}else if(channels == 3 || color_type == PNG_COLOR_TYPE_RGB){
/* 如果是RGB通道 */
size *= (3*sizeof(unsigned char));
/* 每个像素点占3个字节内存 */
out->flag = NO_ALPHA;
/* 标记 */
out->rgba = (unsigned char**) malloc(size);
if(out->rgba == NULL){
/* 如果分配内存失败 */
fclose(pic_fp);
puts("错误(png):无法分配足够的内存供存储数据!");
return 1;
}
temp = (3 * out->width);
/* 每行有3 * out->width个字节 */
for(i = 0; i < out->height; i++){
for(j = 0; j < temp; j += 3){
/* 一个字节一个字节的赋值 */
out->rgba[0][pos] = row_pointers[i][j];
// redout->rgba[1][pos] = row_pointers[i][j+1];
// greenout->rgba[2][pos] = row_pointers[i][j+2];
// 
blue++pos;
}
}
}else{
return 1;
}

/* 撤销数据占用的内存 */
png_destroy_read_struct(&png_ptr, &info_ptr, 0); return 0;
}
以下是生成png图片文件的代码:
[cpp]  view plain copy
  1. int write_png_file(char *file_name , pic_data *graph)  
  2. /* 功能:将LCUI_Graph结构中的数据写入至png文件 */  
  3. {  
  4.     int j, i, temp, pos;  
  5.     png_byte color_type;   
  6.   
  7.     png_structp png_ptr;  
  8.     png_infop info_ptr;   
  9.     png_bytep * row_pointers;  
  10.     /* create file */  
  11.     FILE *fp = fopen(file_name, "wb");  
  12.     if (!fp)  
  13.     {  
  14.         printf("[write_png_file] File %s could not be opened for writing", file_name);  
  15.         return -1;  
  16.     }  
  17.   
  18.   
  19.     /* initialize stuff */  
  20.     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);  
  21.   
  22.     if (!png_ptr)  
  23.     {  
  24.         printf("[write_png_file] png_create_write_struct failed");  
  25.         return -1;  
  26.     }  
  27.     info_ptr = png_create_info_struct(png_ptr);  
  28.     if (!info_ptr)  
  29.     {  
  30.         printf("[write_png_file] png_create_info_struct failed");  
  31.         return -1;  
  32.     }  
  33.     if (setjmp(png_jmpbuf(png_ptr)))  
  34.     {  
  35.         printf("[write_png_file] Error during init_io");  
  36.         return -1;  
  37.     }  
  38.     png_init_io(png_ptr, fp);  
  39.   
  40.   
  41.     /* write header */  
  42.     if (setjmp(png_jmpbuf(png_ptr)))  
  43.     {  
  44.         printf("[write_png_file] Error during writing header");  
  45.         return -1;  
  46.     }  
  47.     /* 判断要写入至文件的图片数据是否有透明度,来选择色彩类型 */  
  48.     if(graph->flag == HAVE_ALPHA) color_type = PNG_COLOR_TYPE_RGB_ALPHA;  
  49.     else color_type = PNG_COLOR_TYPE_RGB;  
  50.       
  51.     png_set_IHDR(png_ptr, info_ptr, graph->width, graph->height,  
  52.         graph->bit_depth, color_type, PNG_INTERLACE_NONE,  
  53.         PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);  
  54.   
  55.     png_write_info(png_ptr, info_ptr);  
  56.   
  57.   
  58.     /* write bytes */  
  59.     if (setjmp(png_jmpbuf(png_ptr)))  
  60.     {  
  61.         printf("[write_png_file] Error during writing bytes");  
  62.         return -1;  
  63.     }  
  64.     if(graph->flag == HAVE_ALPHA) temp = (4 * graph->width);  
  65.     else temp = (3 * graph->width);  
  66.       
  67.     pos = 0;  
  68.     row_pointers = (png_bytep*)malloc(graph->height*sizeof(png_bytep));  
  69.     for(i = 0; i < graph->height; i++)  
  70.     {  
  71.         row_pointers[i] = (png_bytep)malloc(sizeof(unsigned char)*temp);  
  72.         for(j = 0; j < temp; j += 4)  
  73.         {  
  74.             row_pointers[i][j]   = graph->rgba[0][pos]; // red  
  75.             row_pointers[i][j+1] = graph->rgba[1][pos]; // green  
  76.             row_pointers[i][j+2] = graph->rgba[2][pos];   // blue  
  77.             if(graph->flag == HAVE_ALPHA)   
  78.                 row_pointers[i][j+3] = graph->rgba[3][pos]; // alpha  
  79.             ++pos;  
  80.         }  
  81.     }  
  82.     png_write_image(png_ptr, row_pointers);  
  83.   
  84.     /* end write */  
  85.     if (setjmp(png_jmpbuf(png_ptr)))  
  86.     {  
  87.         printf("[write_png_file] Error during end of write");  
  88.         return -1;  
  89.     }  
  90.     png_write_end(png_ptr, NULL);  
  91.   
  92.     /* cleanup heap allocation */  
  93.     for (j=0; j<graph->height; j++)  
  94.         free(row_pointers[j]);  
  95.     free(row_pointers);  
  96.   
  97.     fclose(fp);  
  98.     return 0;  
  99. }  
这个代码是从libpng给的示例代码中修改而来的,你可以参考一下。

相关文章:

图像解码之一——使用libjpeg解码jpeg图片

图像解码之二——使用libpng解码png图片

图像解码之三——giflib解码gif图片

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值