C#调用动态链接库(libpng.dll)将bmp格式图片转换为png格式

C#调用动态链接库(libpng.dll)将bmp格式图片转换为png格式

链接库下载编译

  • libpng下载地址,我下载的是lpng1637.zip;
  • zlib,我下载在是zlib1211.zip;
  • 事实证明我只用到了libpng库,zlib没有用到,所以不用下载编译;
  • 解压进入lpng1637\projects\vstudio文件夹下,打开vstudio.sln,下面有七个子工程,如下图所示,只需要将libpng设为启动项目进行编译;
  • 注意你的解决方案配置是64位还是32位,取决于你你调用dll的工程是32位还是64位,我的是64位工程,所以采用64位编译环境。
  • 编译后会生成如下文件,将libpng16.dll拷到你需要的地方即可。

bmp图像转换为png函数实现

  • 直接在linpng工程下pngwrite.c中实现转换函数,以便后面好调用函数方便。
//这个PNGPI的头要添加上,编译生成在dll中才可以找到这个函数,否则没有这个函数
//int为你的函数返回类型
int PNGAPI
//传入参数png_file_name为png文件名,pixels为像素原始数据,width宽度,height高度,bit_depth位深
writePng(unsigned char* png_file_name, unsigned char*  pixels, int width, int height, int bit_depth)
{
	//当你需要读一个PNG文件或者写一个PNG文件的时候,你需要先定义两个结构体指针:
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	//创建png文件
	FILE *png_file = fopen(png_file_name, "wb");
	if (!png_file)
	{
		return -1;
	}
	//初始化两个结构体指针
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL)
	{
		printf("ERROR:png_create_write_struct/n");
		fclose(png_file);
		return 0;
	}
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		printf("ERROR:png_create_info_struct/n");
		png_destroy_write_struct(&png_ptr, NULL);
		return 0;
	}
	//将结构指针与文件流绑定
	png_init_io(png_ptr, png_file);
	//设置PNG文件的属性、写入PNG文件头、写入PNG文件
	png_set_IHDR(png_ptr, info_ptr,width,height,bit_depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	png_colorp palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof(png_color));
	if (!palette)
	{
		fclose(png_file);
		png_destroy_write_struct(&png_ptr, &info_ptr);
		return -1;
	}
	png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
	png_set_packing(png_ptr);
	png_write_info(png_ptr, info_ptr);//写入文件头
	//按行写入像素
	png_bytepp rows = (png_bytepp)png_malloc(png_ptr, height * sizeof(png_bytep));
	for (int i = height - 1; i >= 0; i--)
	{
		rows[height - 1 - i] = (png_bytep)(pixels + (i)* width * 3);
	}
	//写入png
	png_write_image(png_ptr, rows);
	png_write_end(png_ptr, info_ptr);
	free(rows);
	png_free(png_ptr, palette);
	palette = NULL;
	png_destroy_write_struct(&png_ptr, &info_ptr);
	fclose(png_file);
	return 0;
}

unity下C#调用动态链接库

[DllImport("libpng16")]
public static extern int writePng(string file_name,byte[] pixels,int width,int height,int bit_depth);

测试效果

  • 测试结果,将一张bmp转为png压缩保存时间间隔在1.3~1.5秒之间,效率较低
  • 可以参考LG模拟器中png保存方法,会不会快很多。
    在这里插入图片描述
基于libpng库将PNG图片数据转换为RGB数据的过程涉及到几个主要步骤。libpng是一个用于读取和写入PNG(便携式网络图形)格式图片的库。以下是使用libpng库将PNG图片转换为RGB数据的大致步骤: 1. 初始化libpng库,设置必要的函数指针。 2. 打开PNG图片文件,并创建一个png_structp结构体用于存储库的读取状态。 3. 创建一个png_infop结构体用于存储读取PNG图片时的信息。 4. 使用libpng的读取函数加载PNG图片,并对PNG文件头信息进行处理。 5. 读取PNG图片的像素数据。PNG图片可能包含多种类型的像素格式,比如索引彩色、灰度、RGB等。确保解码为RGB格式。 6. 将PNG图片像素数据转换为RGB格式,通常每像素3个字节,分别代表红色、绿色和蓝色通道。 7. 清理libpng使用过的资源,关闭PNG文件,并释放相关结构体。 下面是一个简化的代码示例,展示了如何使用libpng库读取PNG文件并提取RGB数据: ```c #include <png.h> #include <stdio.h> int main(int argc, char *argv[]) { FILE *fp = fopen("example.png", "rb"); png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep row = NULL; int width, height; // 初始化libpng结构体 if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) return -1; if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) { png_destroy_read_struct(&png_ptr, NULL, NULL); return -1; } // 设置错误处理函数 if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (row) free(row); fclose(fp); return -1; } // 设置libpng输入流 png_init_io(png_ptr, fp); // 读取PNG文件头信息 png_read_info(png_ptr, info_ptr); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); // 分配内存来存储每一行数据 row = (png_bytep) malloc(3 * width * sizeof(png_byte)); // 读取每一行数据 for (int y = 0; y < height; y++) { png_read_row(png_ptr, row, NULL); // 此处处理row中的数据,将其转换为RGB数据 } // 清理工作 if (row) free(row); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return 0; } ``` 请注意,这只是一个非常基础的示例。在实际的应用中,你可能需要处理各种PNG图片的不同特性,比如透明度(alpha通道)、调色板(palette-based images)和不同的像素深度。同时,错误处理和资源管理需要更加严谨。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智能驾驶小管家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值