最近看到一片关于如何使用C语言读和写png图片格式
我要讲的三个大部分分别是:
1、libpng是什么,能做什么?
1
2
|
png_structp png_ptr=NULL;
//libpng的结构体
png_infop info_ptr=NULL;
//libpng的信息
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
int
iRetVal;
png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
if
(!png_ptr)
goto
错误处理;
info_ptr=png_create_info_struct(png_ptr);
if
(!info_ptr)
{
png_destroy_write_struct(&png_ptr,NULL);
goto
错误处理;
}
iRetVal=
setjmp
(png_jmpbuf(png_ptr));
//安装错误处理跳转点
//当libpng内部出现错误的时候,libpng会调用longjmp直接跳转到这里运行。
if
(iRetVal)
//setjmp的返回值就是libpng跳转后提供的错误代码(貌似总是1,但是还是请大家看libpng的官方文档)
{
fprintf
(stderr,
"错误码:%d\n"
,iRetVal);
goto
错误处理;
}
|
1
|
png_destroy_write_struct(&png_ptr,&info_ptr);
|
1
2
3
|
FILE
*fp=
fopen
(
"C:\\TEST.PNG"
,
"wb"
);
if
(!fp)
goto
错误处理;
|
1
|
png_init_io(png_ptr,fp);
|
01
02
03
04
05
06
07
08
09
10
|
//设置PNG文件头
png_set_IHDR(png_ptr,info_ptr,
图像宽度,图像高度,
//尺寸
8,
//颜色深度,也就是每个颜色成分占用位数(8表示8位红8位绿8位蓝,如果有透明通道则还会有8位不透明度)
PNG_COLOR_TYPE_RGB,
//颜色类型,PNG_COLOR_TYPE_RGB表示24位真彩深色,PNG_COLOR_TYPE_RGBA表示32位带透明通道真彩色
PNG_INTERLACE_NONE,
//不交错。PNG_INTERLACE_ADAM7表示这个PNG文件是交错格式。交错格式的PNG文件在网络传输的时候能以最快速度显示出图像的大致样子。
PNG_COMPRESSION_TYPE_BASE,
//压缩方式
PNG_FILTER_TYPE_BASE);
//这个不知道,总之填写PNG_FILTER_TYPE_BASE即可。
png_set_packing(png_ptr);
//设置打包信息
png_write_info(png_ptr,info_ptr);
//写入文件头
|
1
2
|
png_structp png_ptr=NULL;
//libpng的结构体
png_infop info_ptr=NULL;
//libpng的信息
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
int
iRetVal;
png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
if
(!png_ptr)
goto
错误处理;
info_ptr=png_create_info_struct(png_ptr);
if
(!info_ptr)
{
png_destroy_read_struct(&png_ptr,NULL,NULL);
goto
错误处理;
}
iRetVal=
setjmp
(png_jmpbuf(png_ptr));
//安装错误处理跳转点
//当libpng内部出现错误的时候,libpng会调用longjmp直接跳转到这里运行。
if
(iRetVal)
//setjmp的返回值就是libpng跳转后提供的错误代码(貌似总是1,但是还是请大家看libpng的官方文档)
{
fprintf
(stderr,
"错误码:%d\n"
,iRetVal);
goto
错误处理;
}
|
1
|
png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
|
1
2
3
|
FILE
*fp=
fopen
(
"C:\\TEST.PNG"
,
"rb"
);
if
(!fp)
goto
错误处理;
|
1
2
|
png_init_io(png_ptr,fp);
png_read_info(png_ptr, info_ptr);
|
1
|
png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,&color_type,NULL,NULL,NULL);
|
1
2
|
png_color_16p pBackground;
png_get_bKGD(png_ptr,info_ptr,&pBackground);
|
1
2
3
4
5
6
7
8
|
typedef
struct
png_color_16_struct
{
png_byte index;
png_uint_16 red;
png_uint_16 green;
png_uint_16 blue;
png_uint_16 gray;
} png_color_16;
|
01
02
03
04
05
06
07
08
09
10
|
if
(colortype==PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
//要求转换索引颜色到RGB
if
(colortype==PNG_COLOR_TYPE_GRAY && bit_depth<8)
png_set_expand_gray_1_2_4_to_8(png_ptr);
//要求位深度强制8bit
if
(bit_depth==16)
png_set_strip_16(png_ptr);
//要求位深度强制8bit
if
(png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png_ptr);
if
(colortype == PNG_COLOR_TYPE_GRAY || colortype == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
//灰度必须转换成RGB
|
1
2
3
4
5
6
7
|
ppLinePtrs=(
COLORREF
**)
malloc
(g_dwHeight*
sizeof
(
COLORREF
*));
//列指针
if
(!ppLinePtrs)
goto
Error;
i=g_dwHeight;
y=0;
while
(i--)
//逆行序读取,因为位图是底到上型
ppLinePtrs[y++]=(
COLORREF
*)&g_pBits[i*g_dwWidth];
|