png文件头_图片格式知识PNG

如何理解PNG的格式和他们用的算法,和jpeg有什么区别呢?我们可以看看

PNG是便携式网络图形( Portable Network Graphics)的缩写,由于PNG带有透明通道,无损压缩,可提升设计元素的呈现效果,因此设计上对PNG情有独钟,广泛的运用在设计、游戏、网页、app开发里,实际使用上由于存在很多误区,导致被滥用,这里对之前学习png的心得做个整理。

首先,PNG和诞生跟GIF格式有较大关系,这中间有很多趣事,可自行查阅。PNG的压缩过程是完全无损的,压缩过的文件可以准确地还原出原图,可封装多种pixfmt格式的数据,并且是一种可扩展的封装格式,

PNG文件格式里面包含不同的区块(chunks),各个区块带有不同类型的数据。典型的PNG数据包括四部分,而在此基础上,增加acTL(动画控制块)、fcTL(帧控制块)、fdAT(帧数据块)即为APNG动图格式。

  • PNG Signature(PNG签名块,包含PNG类型的标识)
  • IHDR(图像头部块,包含图片的宽度、高度、位的深度和颜色类型)
  • IDAT(图像数据块,像素压缩后的数据)
  • IEND(图像结束块,PNG结束标识)

2.PNG文件解析

PNG图像格式文件由一个8字节的PNG文件署名(PNG signature:0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A)和按照特定结构组织的3个以上的数据(chunk)组成。PNG定义了两种类型的数据

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PNG图片转为rc文件数据的步骤如下: 1. 使用图像处理库(如libpng)读取PNG文件数据。 2. 将PNG文件数据转换为C++代码格式的数组。 3. 将数组写入rc文件中。 以下是一个示例代码,将PNG文件转换为rc文件数据: ```cpp #include <fstream> #include <iostream> #include <string> #include <vector> #include <png.h> // 将PNG文件转换为C++代码格式的数组 std::vector<unsigned char> convertToByteArray(const std::string& filename) { std::vector<unsigned char> result; // 打开PNG文件 FILE* fp = fopen(filename.c_str(), "rb"); if (!fp) { std::cerr << "Error: Failed to open file " << filename << std::endl; return result; } // 读取PNG文件 png_byte header[8]; fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { std::cerr << "Error: " << filename << " is not a valid PNG file" << std::endl; fclose(fp); return result; } // 创建PNG读取器 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { std::cerr << "Error: Failed to create PNG read struct" << std::endl; fclose(fp); return result; } // 创建PNG信息结构体 png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { std::cerr << "Error: Failed to create PNG info struct" << std::endl; png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(fp); return result; } // 设置PNG读取错误处理 if (setjmp(png_jmpbuf(png_ptr))) { std::cerr << "Error: Failed to read PNG file " << filename << std::endl; png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return result; } // 将PNG读取器绑定到文件png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); // 读取PNG文件信息 png_read_info(png_ptr, info_ptr); // 获取PNG图像属性 png_uint_32 width, height; int bit_depth, color_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); // 设置PNG图像转换参数 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 (bit_depth < 8) { png_set_packing(png_ptr); } if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } // 更新PNG信息 png_read_update_info(png_ptr, info_ptr); // 计算PNG每行字节数 int row_bytes = png_get_rowbytes(png_ptr, info_ptr); // 分配内存存储PNG图像数据 png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); png_bytep data = (png_bytep)malloc(row_bytes * height); for (png_uint_32 i = 0; i < height; i++) { row_pointers[i] = data + i * row_bytes; } // 读取PNG图像数据 png_read_image(png_ptr, row_pointers); // 将PNG图像数据转换为C++代码格式的数组 result.push_back(' '); result.push_back(' '); result.push_back('{'); result.push_back('\n'); for (png_uint_32 i = 0; i < height; i++) { result.push_back(' '); result.push_back(' '); result.push_back(' '); result.push_back('"'); for (int j = 0; j < row_bytes; j++) { result.push_back('\\'); result.push_back('x'); char hex[3]; snprintf(hex, sizeof(hex), "%02x", row_pointers[i][j]); result.push_back(hex[0]); result.push_back(hex[1]); } result.push_back('"'); if (i < height - 1) { result.push_back(','); } result.push_back('\n'); } result.push_back(' '); result.push_back('}'); result.push_back(';'); // 释放内存 free(row_pointers); free(data); // 销毁PNG读取器 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); // 关闭PNG文件 fclose(fp); return result; } int main() { // 将PNG文件转换为rc文件数据 std::vector<unsigned char> data = convertToByteArray("image.png"); // 将rc文件数据写入文件 std::ofstream outfile("image.rc"); outfile.write((char*)data.data(), data.size()); outfile.close(); return 0; } ``` 使用rc文件中的数据的步骤如下: 1. 在DLL工程中添加rc文件。 2. 在DLL工程的文件中声明资源ID。 3. 在DLL工程的源文件中使用资源ID加载PNG图像资源。 以下是一个示例代码,使用rc文件中的数据: ```cpp // 在文件中声明资源ID #define IDB_IMAGE 100 // 在源文件中使用资源ID加载PNG图像资源 HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(IDB_IMAGE), RT_RCDATA); if (hResource) { HGLOBAL hGlobal = LoadResource(hInstance, hResource); if (hGlobal) { const unsigned char* data = (const unsigned char*)LockResource(hGlobal); if (data) { // 解析PNG图像资源 // ... UnlockResource(hGlobal); } FreeResource(hGlobal); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值