切换主题
C语言libpng库的使用
libpng
是一个用 C 语言编写的库,用于处理 PNG 格式的图片。它可以帮助你读写 PNG 文件、进行图片的压缩与解压缩操作,并处理图片的颜色、透明度等信息。
1. 安装 libpng
在 Linux 系统中,通常可以通过包管理器安装:
bash
sudo apt-get install libpng-dev
1
在 macOS 上,可以使用 Homebrew 安装:
bash
brew install libpng
1
Windows 系统可以从官方网站下载并进行安装,或使用包管理工具如 vcpkg
或 MSYS2
安装。
2. 包含头文件
在你的 C 语言程序中,使用 libpng 时需要包含 png.h
头文件:
c
#include <png.h>
1
3. 读取 PNG 文件
通过 libpng
读取 PNG 文件通常包括以下几个步骤:
- 打开 PNG 文件并初始化 libpng。
- 读取 PNG 图像数据。
- 处理图像数据。
- 关闭文件并清理资源。
下面是一个基本的读取 PNG 文件并获取其信息的示例:
c
#include <stdio.h>
#include <stdlib.h>
#include <png.h>
void read_png_file(char *filename) {
FILE *fp = fopen(filename, "rb");
if (!fp) abort();
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png) abort();
png_infop info = png_create_info_struct(png);
if (!info) abort();
if (setjmp(png_jmpbuf(png))) abort();
png_init_io(png, fp);
// 读取图像头信息
png_read_info(png, info);
// 获取图像信息
int width = png_get_image_width(png, info);
int height = png_get_image_height(png, info);
int bit_depth = png_get_bit_depth(png, info);
int color_type = png_get_color_type(png, info);
printf("Width: %d, Height: %d, Bit Depth: %d, Color Type: %d\n", width, height, bit_depth, color_type);
// 清理资源
png_destroy_read_struct(&png, &info, NULL);
fclose(fp);
}
int main() {
read_png_file("image.png");
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
在这个示例中:
png_create_read_struct()
初始化读取结构体。png_create_info_struct()
创建图像信息结构。png_init_io()
初始化文件读取。png_read_info()
读取图像头部信息。png_get_image_width()
、png_get_image_height()
等获取图像宽度、高度、颜色类型等信息。
4. 读取 PNG 图像数据
要读取图像的像素数据,我们需要逐行读取图像的像素。通常情况下,使用 png_read_rows()
逐行读取 PNG 文件数据。
c
#include <stdio.h>
#include <stdlib.h>
#include <png.h>
void read_png_file(char *filename) {
FILE *fp = fopen(filename, "rb");
if (!fp) abort();
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png) abort();
png_infop info = png_create_info_struct(png);
if (!info) abort();
if (setjmp(png_jmpbuf(png))) abort();
png_init_io(png, fp);
png_read_info(png, info);
int width = png_get_image_width(png, info);
int height = png_get_image_height(png, info);
int bit_depth = png_get_bit_depth(png, info);
int color_type = png_get_color_type(png, info);
printf("Width: %d, Height: %d, Bit Depth: %d, Color Type: %d\n", width, height, bit_depth, color_type);
// 分配内存来存储每行像素数据
png_bytep *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * height);
for (int i = 0; i < height; i++) {
row_pointers[i] = (png_byte *)malloc(png_get_rowbytes(png, info));
}
// 读取图像数据
png_read_image(png, row_pointers);
// 访问像素数据(例:打印首行数据)
for (int i = 0; i < width * 4; i++) { // 假设是 RGBA 图像
printf("%u ", row_pointers[0][i]);
}
// 清理资源
for (int i = 0; i < height; i++) {
free(row_pointers[i]);
}
free(row_pointers);
png_destroy_read_struct(&png, &info, NULL);
fclose(fp);
}
int main() {
read_png_file("image.png");
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
在这个例子中:
png_read_image()
读取图像数据并将每行像素存储在row_pointers
中。png_get_rowbytes()
获取每行的字节数。- 每个像素数据以 RGBA 或 RGB 的形式存储在
row_pointers
中,可以根据需要处理每个像素的值。
5. 保存 PNG 文件
保存 PNG 文件的过程与读取类似,关键步骤如下:
- 创建写入结构体。
- 设置文件输出。
- 写入图像数据。
以下是一个保存 PNG 文件的基本示例:
c
#include <stdio.h>
#include <stdlib.h>
#include <png.h>
void write_png_file(char *filename) {
int width = 256;
int height = 256;
int bit_depth = 8;
int color_type = PNG_COLOR_TYPE_RGBA;
// 创建一个文件输出流
FILE *fp = fopen(filename, "wb");
if (!fp) abort();
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png) abort();
png_infop info = png_create_info_struct(png);
if (!info) abort();
if (setjmp(png_jmpbuf(png))) abort();
png_init_io(png, fp);
// 设置图像信息
png_set_IHDR(
png, info, width, height,
bit_depth, color_type, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_DEFAULT
);
png_write_info(png, info);
// 创建并写入数据
png_bytep row = (png_bytep)malloc(4 * width);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
row[x*4] = x; // Red
row[x*4+1] = y; // Green
row[x*4+2] = 255; // Blue
row[x*4+3] = 255; // Alpha
}
png_write_row(png, row);
}
// 写入文件结束
png_write_end(png, NULL);
free(row);
png_destroy_write_struct(&png, &info);
fclose(fp);
}
int main() {
write_png_file("output.png");
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
在这个示例中:
png_create_write_struct()
初始化写入结构体。png_set_IHDR()
设置图像的头信息(宽度、高度、位深度、颜色类型等)。png_write_row()
将每行像素数据写入文件。png_write_end()
写入文件结束信息。
6. 错误处理
当 libpng 发生错误时,使用 png_jmpbuf()
进行跳转,以避免程序崩溃。例如:
c
if (setjmp(png_jmpbuf(png))) {
fprintf(stderr, "PNG 读取失败\n");
png_destroy_read_struct(&png, &info, NULL);
fclose(fp);
exit(1);
}
1
2
3
4
5
6
2
3
4
5
6
总结
- 读取 PNG 文件:使用
png_create_read_struct()
、png_create_info_struct()
和png_read_image()
等函数读取图像数据。 - 保存 PNG 文件:使用
png_create_write_struct()
、png_set_IHDR()
和png_write_row()
等函数保存图像。 - 处理图像数据:通过
png_bytep
类型的指针来访问图像的每个像素。 - 错误处理:使用
setjmp()
和longjmp()
来处理 libpng 可能出现的错误。
这些是 libpng 的基本用法,你可以根据需要处理图像的不同属性(例如调色板、灰度图像、透明度等)进行进一步的自定义操作。