利用libpng中的函数读写png文件

利用libpng中的函数读写png文件

分类: 图形处理 Linux C语言 3131人阅读 评论(10) 收藏 举报

以下是读取PNG图片的图像数据的代码,如果你要使用该代码,请补充剩余代码。

  1. #include <png.h>   
  2. #define PNG_BYTES_TO_CHECK 4   
  3.   
  4. int load_png_image( const char *filepath, /* 其它参数 */ )  
  5. {  
  6.         FILE *fp;  
  7.         png_structp png_ptr;  
  8.         png_infop info_ptr;  
  9.         png_bytep* row_pointers;  
  10.         char buf[PNG_BYTES_TO_CHECK];  
  11.         int w, h, x, y, temp, color_type;  
  12.   
  13.         fp = fopen( filepath, "rb" );  
  14.         if( fp == NULL ) {   
  15.                 return /* 你的返回值 */;  
  16.         }  
  17.           
  18.         png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );  
  19.         info_ptr = png_create_info_struct( png_ptr );  
  20.   
  21.         setjmp( png_jmpbuf(png_ptr) );   
  22.         /* 读取PNG_BYTES_TO_CHECK个字节的数据 */  
  23.         temp = fread( buf, 1, PNG_BYTES_TO_CHECK, fp );  
  24.         /* 若读到的数据并没有PNG_BYTES_TO_CHECK个字节 */  
  25.         if( temp < PNG_BYTES_TO_CHECK ) {  
  26.                 fclose(fp);  
  27.                 png_destroy_read_struct( &png_ptr, &info_ptr, 0);  
  28.                 return /* 你的返回值 */;  
  29.         }  
  30.         /* 检测数据是否为PNG的签名 */  
  31.         temp = png_sig_cmp( (png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK );  
  32.         /* 如果不是PNG的签名,则说明该文件不是PNG文件 */  
  33.         if( temp != 0 ) {  
  34.                 fclose(fp);  
  35.                 png_destroy_read_struct( &png_ptr, &info_ptr, 0);  
  36.                 return /* 你的返回值 */;  
  37.         }  
  38.           
  39.         /* 复位文件指针 */  
  40.         rewind( fp );  
  41.         /* 开始读文件 */  
  42.         png_init_io( png_ptr, fp );   
  43.         /* 读取PNG图片信息 */  
  44.         png_read_png( png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0 );  
  45.         /* 获取图像的色彩类型 */  
  46.         color_type = png_get_color_type( png_ptr, info_ptr );  
  47.         /* 获取图像的宽高 */  
  48.         w = png_get_image_width( png_ptr, info_ptr );  
  49.         h = png_get_image_height( png_ptr, info_ptr );  
  50.         /* 获取图像的所有行像素数据,row_pointers里边就是rgba数据 */  
  51.         row_pointers = png_get_rows( png_ptr, info_ptr );  
  52.         /* 根据不同的色彩类型进行相应处理 */  
  53.         switch( color_type ) {  
  54.         case PNG_COLOR_TYPE_RGB_ALPHA:  
  55.                 for( y=0; y<h; ++y ) {  
  56.                         for( x=0; x<w*4; ) {  
  57.                                 /* 以下是RGBA数据,需要你自己补充代码,保存RGBA数据 */  
  58.                                 /* 目标内存 */ = row_pointers[y][x++]; // red   
  59.                                 /* 目标内存 */ = row_pointers[y][x++]; // green   
  60.                                 /* 目标内存 */ = row_pointers[y][x++]; // blue   
  61.                                 /* 目标内存 */ = row_pointers[y][x++]; // alpha   
  62.                         }  
  63.                 }  
  64.                 break;  
  65.   
  66.         case PNG_COLOR_TYPE_RGB:  
  67.                 for( y=0; y<h; ++y ) {  
  68.                         for( x=0; x<w*3; ) {  
  69.                                 /* 目标内存 */ = row_pointers[y][x++]; // red   
  70.                                 /* 目标内存 */ = row_pointers[y][x++]; // green   
  71.                                 /* 目标内存 */ = row_pointers[y][x++]; // blue   
  72.                         }  
  73.                 }  
  74.                 break;  
  75.         /* 其它色彩类型的图像就读了 */  
  76.         default:  
  77.                 fclose(fp);  
  78.                 png_destroy_read_struct( &png_ptr, &info_ptr, 0);  
  79.                 return /* 你的返回值 */;  
  80.         }  
  81.         png_destroy_read_struct( &png_ptr, &info_ptr, 0);  
  82.         return 0;  
  83. }  
#include <png.h>
#define PNG_BYTES_TO_CHECK 4

int load_png_image( const char *filepath, /* 其它参数 */ )
{
        FILE *fp;
        png_structp png_ptr;
        png_infop info_ptr;
        png_bytep* row_pointers;
        char buf[PNG_BYTES_TO_CHECK];
        int w, h, x, y, temp, color_type;

        fp = fopen( filepath, "rb" );
        if( fp == NULL ) { 
                return /* 你的返回值 */;
        }
        
        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) ); 
        /* 读取PNG_BYTES_TO_CHECK个字节的数据 */
        temp = fread( buf, 1, PNG_BYTES_TO_CHECK, fp );
        /* 若读到的数据并没有PNG_BYTES_TO_CHECK个字节 */
        if( temp < PNG_BYTES_TO_CHECK ) {
                fclose(fp);
                png_destroy_read_struct( &png_ptr, &info_ptr, 0);
                return /* 你的返回值 */;
        }
        /* 检测数据是否为PNG的签名 */
        temp = png_sig_cmp( (png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK );
        /* 如果不是PNG的签名,则说明该文件不是PNG文件 */
        if( temp != 0 ) {
                fclose(fp);
                png_destroy_read_struct( &png_ptr, &info_ptr, 0);
                return /* 你的返回值 */;
        }
        
        /* 复位文件指针 */
        rewind( fp );
        /* 开始读文件 */
        png_init_io( png_ptr, fp ); 
        /* 读取PNG图片信息 */
        png_read_png( png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0 );
        /* 获取图像的色彩类型 */
        color_type = png_get_color_type( png_ptr, info_ptr );
        /* 获取图像的宽高 */
        w = png_get_image_width( png_ptr, info_ptr );
        h = png_get_image_height( png_ptr, info_ptr );
        /* 获取图像的所有行像素数据,row_pointers里边就是rgba数据 */
        row_pointers = png_get_rows( png_ptr, info_ptr );
        /* 根据不同的色彩类型进行相应处理 */
        switch( color_type ) {
        case PNG_COLOR_TYPE_RGB_ALPHA:
                for( y=0; y<h; ++y ) {
                        for( x=0; x<w*4; ) {
                                /* 以下是RGBA数据,需要你自己补充代码,保存RGBA数据 */
                                /* 目标内存 */ = row_pointers[y][x++]; // red
                                /* 目标内存 */ = row_pointers[y][x++]; // green
                                /* 目标内存 */ = row_pointers[y][x++]; // blue
                                /* 目标内存 */ = row_pointers[y][x++]; // alpha
                        }
                }
                break;

        case PNG_COLOR_TYPE_RGB:
                for( y=0; y<h; ++y ) {
                        for( x=0; x<w*3; ) {
                                /* 目标内存 */ = row_pointers[y][x++]; // red
                                /* 目标内存 */ = row_pointers[y][x++]; // green
                                /* 目标内存 */ = row_pointers[y][x++]; // blue
                        }
                }
                break;
        /* 其它色彩类型的图像就读了 */
        default:
                fclose(fp);
                png_destroy_read_struct( &png_ptr, &info_ptr, 0);
                return /* 你的返回值 */;
        }
        png_destroy_read_struct( &png_ptr, &info_ptr, 0);
        return 0;
}



以下是生成png图片文件的代码:

  1. int write_png_file(char *file_name , pic_data *graph)  
  2. /* 将puc_data结构中的数据写入至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. }  
int write_png_file(char *file_name , pic_data *graph)
/* 将puc_data结构中的数据写入至png文件 */
{
	int j, i, temp, pos;
	png_byte color_type; 

	png_structp png_ptr;
	png_infop info_ptr; 
	png_bytep * row_pointers;
	/* create file */
	FILE *fp = fopen(file_name, "wb");
	if (!fp)
	{
		printf("[write_png_file] File %s could not be opened for writing", file_name);
		return -1;
	}


	/* initialize stuff */
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

	if (!png_ptr)
	{
		printf("[write_png_file] png_create_write_struct failed");
		return -1;
	}
	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		printf("[write_png_file] png_create_info_struct failed");
		return -1;
	}
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		printf("[write_png_file] Error during init_io");
		return -1;
	}
	png_init_io(png_ptr, fp);


	/* write header */
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		printf("[write_png_file] Error during writing header");
		return -1;
	}
	/* 判断要写入至文件的图片数据是否有透明度,来选择色彩类型 */
	if(graph->flag == HAVE_ALPHA) color_type = PNG_COLOR_TYPE_RGB_ALPHA;
	else color_type = PNG_COLOR_TYPE_RGB;
	
	png_set_IHDR(png_ptr, info_ptr, graph->width, graph->height,
		graph->bit_depth, color_type, PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

	png_write_info(png_ptr, info_ptr);


	/* write bytes */
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		printf("[write_png_file] Error during writing bytes");
		return -1;
	}
	if(graph->flag == HAVE_ALPHA) temp = (4 * graph->width);
	else temp = (3 * graph->width);
	
	pos = 0;
	row_pointers = (png_bytep*)malloc(graph->height*sizeof(png_bytep));
	for(i = 0; i < graph->height; i++)
	{
		row_pointers[i] = (png_bytep)malloc(sizeof(unsigned char)*temp);
		for(j = 0; j < temp; j += 4)
		{
			row_pointers[i][j]   = graph->rgba[0][pos]; // red
			row_pointers[i][j+1] = graph->rgba[1][pos]; // green
			row_pointers[i][j+2] = graph->rgba[2][pos];   // blue
			if(graph->flag == HAVE_ALPHA) 
				row_pointers[i][j+3] = graph->rgba[3][pos]; // alpha
			++pos;
		}
	}
	png_write_image(png_ptr, row_pointers);

	/* end write */
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		printf("[write_png_file] Error during end of write");
		return -1;
	}
	png_write_end(png_ptr, NULL);

    /* cleanup heap allocation */
	for (j=0; j<graph->height; j++)
		free(row_pointers[j]);
	free(row_pointers);

    fclose(fp);
    return 0;
}


这个代码是从libpng给的示例代码中修改而来的,你可以参考一下。

代码没测试,如果有错误请自己修改,如有疑惑,请参考互联网上的其它相关文章,libpng源码包里也有示例程序可以参考。


相关文章:

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值