linux安装lib包_linux生成静态库

linux安装lib包_linux生成静态库前几天手里的智能锁项目,收到产品的建议(命令)说,就是人脸识别成功的时候,不要只显示摄像头捕捉到的图像,要弄个酷炫一点的背景,背景里图片中间有个圆圈,人脸就放到圆圈里也就是类似这样。。当然,这是我思考了好几个小时的结果,开始想不明白要怎么实现,其实想通了也很简单,三个步骤A把背景图像的RGB读出来out_bufB把摄像头采集到的图像读出来(分辨率和背…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

前几天手里的智能锁项目 , 收到产品的建议(命令)说 , 就是人脸识别成功的时候 , 不要只显示摄像头捕捉到的图像 , 要弄个酷炫一点的背景, 背景里图片中间有个圆圈, 人脸就放到圆圈里也就是类似这样。。

linux安装lib包_linux生成静态库

当然, 这是我思考了好几个小时的结果, 开始想不明白要怎么实现,其实想通了也很简单, 三个步骤

A 把背景图像的RGB读出来 out_buf

B 把摄像头采集到的图像读出来(分辨率和背景图像一样) , in_buf

C 如果out_buf当前像素点是黑色不变, 否则填充in_buf到out_buf

有了思路了 ,  就要付诸行动  , 花了好几个小时来了解了一下PNG图片的格式 , 又找到一个资料比较全的库 , 就各种找资料 , 把png的读写跑了一遍 ,  特意记录一下

关于PNG文件格式这里不讨论 , 有兴趣的朋友直接百度”PNG文件格式”会得到自己想要的答案


一: 安装PNG库文件

因为PNG文件需要用到zlib进行编解码,  所以用到libpng的同时也需要zlib加密解密

本文使用的是libpng版本和zlib版本如下:

linux安装lib包_linux生成静态库

下载地址:

https://sourceforge.net/projects/libpng/files/

下载完之后如下命令顺序执行:

libpng:
#解压
tar -xzvf libpng-1.6.26.tar.gz && cd libpng-1.6.26
#安装
./configure
make check
sudo make install
sudo ldconfig

zlib:
#解压:
tar -xf zlib-1.2.11.tar.xz && cd zlib-1.2.11
#安装
./configure 
sudo make install
sudo make

Jetbrains全家桶1年46,售后保障稳定

安装成功如下图 :

linux安装lib包_linux生成静态库

运行pkg-config libpng16 zlib –libs –cflags得到正确的头文件和链接库的位置

二 : 使用libpng

libpng有一套自己的流程如下:

1:初始化png_structp结构体 (用于和打开的文件指针绑定)

2:初始化png_infop结构体 (此结构体包含各种图片信息)

3:设置错误返回点 (如果是Libpng内部出现错误, 则会跳到你设置的错误返回点处执行)

4:绑定文件IO流到png_structp结构体 (打开的文件和png_structp结构体实例进行绑定)

5:写入需要生成PNG图像的信息, 信息内容包括尺寸, 位深度,颜色类型,是否交错, 换行等等,按照格式逐个填写就行了

6:写入实际的RGB数据到绑定好的png_structp结构体

7:写入文件尾部信息

8:清理工作 (释放申请的内存, 注销png_structp结构体)

代码如下 :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <png.h>


#define PNG_BYTES_TO_CHECK	8
#define HAVE_ALPHA			1
#define NOT_HAVE_ALPHA		0

typedef struct _pic_data pic_data;
struct _pic_data {
	int width, height; 	//长宽
	int bit_depth; 	   	//位深度
	int alpha_flag;		//是否有透明通道
	unsigned char *rgba;//实际rgb数据
};

int check_is_png(FILE **fp, const char *filename) //检查是否png文件
{
	char checkheader[PNG_BYTES_TO_CHECK]; //查询是否png头
	*fp = fopen(filename, "rb");
	if (*fp == NULL) {
		printf("open failed ...1\n");
		return 0;
	}
	if (fread(checkheader, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) //读取png文件长度错误直接退出
		return 0;
	return png_sig_cmp(checkheader, 0, PNG_BYTES_TO_CHECK); //0正确, 非0错误
}

int decode_png(const char *filename, pic_data *out) //取出png文件中的rgb数据
{
	png_structp png_ptr; //png文件句柄
	png_infop	info_ptr;//png图像信息句柄
	int ret;
	FILE *fp;
	if (check_is_png(&fp, filename) != 0) {
		printf("file is not png ...\n");
		return -1;
	}
	printf("launcher[%s] ...\n", PNG_LIBPNG_VER_STRING); //打印当前libpng版本号

	//1: 初始化libpng的数据结构 :png_ptr, info_ptr
	png_ptr  = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 
	info_ptr = png_create_info_struct(png_ptr);

	//2: 设置错误的返回点
	setjmp(png_jmpbuf(png_ptr));
	rewind(fp); //等价fseek(fp, 0, SEEK_SET);

	//3: 把png结构体和文件流io进行绑定 
	png_init_io(png_ptr, fp);
	//4:读取png文件信息以及强转转换成RGBA:8888数据格式
	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0); //读取文件信息
	int channels, color_type; 
	channels 	= png_get_channels(png_ptr, info_ptr); //通道数量
	color_type 	= png_get_color_type(png_ptr, info_ptr);//颜色类型
	out->bit_depth = png_get_bit_depth(png_ptr, info_ptr);//位深度	
	out->width 	 = png_get_image_width(png_ptr, info_ptr);//宽
	out->height  = png_get_image_height(png_ptr, info_ptr);//高
	
	//if(color_type == PNG_COLOR_TYPE_PALETTE)
	//	png_set_palette_to_rgb(png_ptr);//要求转换索引颜色到RGB
	//if(color_type == PNG_COLOR_TYPE_GRAY && out->bit_depth < 8)
	//	png_set_expand_gray_1_2_4_to_8(png_ptr);//要求位深度强制8bit
	//if(out->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(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
	//	png_set_gray_to_rgb(png_ptr);//灰度必须转换成RG
	printf("channels = %d color_type = %d bit_depth = %d width = %d height = %d ...\n",
			channels, color_type, out->bit_depth, out->width, out->height);

	int i, j, k;
	int size, pos = 0;
	int temp;
	
	//5: 读取实际的rgb数据
	png_bytepp row_pointers; //实际存储rgb数据的buf
	row_pointers = png_get_rows(png_ptr, info_ptr); //也可以分别每一行获取png_get_rowbytes();
	size = out->width * out->height; //申请内存先计算空间
	if (channels == 4 || color_type == PNG_COLOR_TYPE_RGB_ALPHA) { //判断是24位还是32位
		out->alpha_flag = HAVE_ALPHA; //记录是否有透明通道
		size *= (sizeof(unsigned char) * 4); //size = out->width * out->height * channel
		out->rgba = (png_bytep)malloc(size);
		if (NULL == out->rgba) {
			printf("malloc rgba faile ...\n");
			png_destroy_read_struct(&png_ptr, &info_ptr, 0);
			fclose(fp);
			return -1;
		}
		//从row_pointers里读出实际的rgb数据出来
		temp = channels - 1;
		for (i = 0; i < out->height; i++) 
			for (j = 0; j < out->width * 4; j += 4) 
				for (k = temp; k >= 0; k--)
					out->rgba[pos++] = row_pointers[i][j + k];
	} else if (channels == 3 || color_type == PNG_COLOR_TYPE_RGB) { //判断颜色深度是24位还是32位
		out->alpha_flag = NOT_HAVE_ALPHA;
		size *= (sizeof(unsigned char) * 3);
		out->rgba = (png_bytep)malloc(size);
		if (NULL == out->rgba) {
			printf("malloc rgba faile ...\n");
			png_destroy_read_struct(&png_ptr, &info_ptr, 0);
			fclose(fp);
			return -1;
		}
		//从row_pointers里读出实际的rgb数据
		temp = (3 * out->width);
		for (i = 0; i < out->height; i ++) {
			for (j = 0; j < temp; j += 3) {
				out->rgba[pos++] = row_pointers[i][j+2];
				out->rgba[pos++] = row_pointers[i][j+1];
				out->rgba[pos++] = row_pointers[i][j+0];
			}
		}
	} else return -1; 
	//6:销毁内存
	png_destroy_read_struct(&png_ptr, &info_ptr, 0);
	fclose(fp);
	//此时, 我们的out->rgba里面已经存储有实际的rgb数据了
	//处理完成以后free(out->rgba)
	return 0;
}

int RotationRight90(unsigned char * src, int srcW, int srcH, int channel) //顺时针旋转90度
{
	unsigned char * tempSrc = NULL; //临时的buf用来记录原始的图像(未旋转之前的图像)
	int mSize = srcW * srcH * sizeof(char) * channel;
	int i = 0;
	int j = 0;
	int k = 0;
	int l = 3;
	int desW = 0;
	int desH = 0;

	desW = srcH;
	desH = srcW;

	tempSrc = (unsigned char *)malloc(sizeof(char) * srcW * srcH * channel);
	memcpy(tempSrc, src, mSize); //拷贝原始图像至tempbuf
	for(i = 0; i < desH; i ++)
	{
		for(j = 0; j < desW; j ++)
		{
			for(k = 0; k < channel; k ++)
			{
				src[(i * desW + j) * channel + k] = tempSrc[((srcH - 1 - j) * srcW + i) * channel + k]; //替换像素
			}
		}
	}
	free(tempSrc);
	return 0;
}

int write_png_file(const char *filename , pic_data *out) //生成一个新的png图像
{
	png_structp png_ptr;
	png_infop 	info_ptr;
	png_byte color_type;
	png_bytep * row_pointers;
	FILE *fp = fopen(filename, "wb");
	if (NULL == fp) {
		printf("open failed ...2\n");
		return -1;
	}
	//1: 初始化libpng结构体  
	png_ptr	= png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (!png_ptr) {
		printf("png_create_write_struct failed ...\n");
		return -1;
	}
	//2: 初始化png_infop结构体 , 
	//此结构体包含了图像的各种信息如尺寸,像素位深, 颜色类型等等
	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		printf("png_create_info_struct failed ...\n");
		return -1;
	}
	//3: 设置错误返回点
	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("error during init_io ...\n");
		return -1;
	}
	//4:绑定文件IO到Png结构体
	png_init_io(png_ptr, fp);
	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("error during init_io ...\n");
		return -1;
	}
	if (out->alpha_flag == HAVE_ALPHA) color_type = PNG_COLOR_TYPE_RGB_ALPHA;
	else color_type = PNG_COLOR_TYPE_RGB;
	//5:设置以及写入头部信息到Png文件
	png_set_IHDR(png_ptr, info_ptr, out->width, out->height, out->bit_depth,
	color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	png_write_info(png_ptr, info_ptr);
	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("error during init_io ...\n");
		return -1;
	}
	int channels, temp;
	int i, j, pos = 0;
	if (out->alpha_flag == HAVE_ALPHA) {
		channels = 4;
		temp = (4 * out->width);
		printf("have alpha ...\n");
	} else {
		channels = 3;
		temp = (3 * out->width);
		printf("not have alpha ...\n");
	}
	// 顺时针旋转90度 , 旋转完了一定要把width 和height调换 不然得到的图像是花的  旋转三次就是逆时针旋转一次
	//RotationRight90(out->rgba, out->width, out->height, channels);
	//RotationRight90(out->rgba, out->height, out->width, channels);
	//RotationRight90(out->rgba, out->width, out->height, channels);
	row_pointers = (png_bytep*)malloc(out->height * sizeof(png_bytep));
	for (i = 0; i < out->height; i++) {
		row_pointers[i] = (png_bytep)malloc(temp* sizeof(unsigned char));
		for (j = 0; j < temp; j += channels) {
			if (channels == 4) {
				row_pointers[i][j+3] = out->rgba[pos++];
				row_pointers[i][j+2] = out->rgba[pos++];
				row_pointers[i][j+1] = out->rgba[pos++];
				row_pointers[i][j+0] = out->rgba[pos++];
			} else {
				row_pointers[i][j+2] = out->rgba[pos++];
				row_pointers[i][j+1] = out->rgba[pos++];
				row_pointers[i][j+0] = out->rgba[pos++];
			}
		}
	}
	//6: 写入rgb数据到Png文件
	png_write_image(png_ptr, (png_bytepp)row_pointers);
	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("error during init_io ...\n");
		return -1;
	}
	//7: 写入尾部信息
	png_write_end(png_ptr, NULL);
	//8:释放内存 ,销毁png结构体
	for (i = 0; i < out->height; i ++)
		free(row_pointers[i]);
	free(row_pointers);
	png_destroy_write_struct(&png_ptr, &info_ptr);
	fclose(fp);
	return 0;
}

int main(int argc, char **argv)
{
	pic_data out;
	if (argc == 3) {
		decode_png(argv[1], &out);
		write_png_file(argv[2], &out);
		free(out.rgba);
	} else {
		puts("please input two file, \nargv[1]:source.png argv[2]:dest.png");	
	}
	return 0;
}

编译需要链接已经安装好的libpng 和 zlib库

gcc test.c `pkg-config libpng16 zlib –libs –cflags` 

功能就是简单得读取PNG格式图片, 再生成(写入)一个新的一模一样的图片 ,  代码中把图片旋转注释了 , 亲测也是可用的。

最后送上一张随便百度的PNG格式图片, 还有一张就是项目的图片(无视本人)

linux安装lib包_linux生成静态库

 linux安装lib包_linux生成静态库

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/230605.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 联想笔记本电脑键盘灯在哪里开_笔记本自带键盘没反应

    联想笔记本电脑键盘灯在哪里开_笔记本自带键盘没反应在联想系列笔记本电脑中,有一个键盘等功能,它们不仅可以看起来很酷,而且可以在光线相对较低时打开键盘灯,以便我们可以清楚地看到键盘上的按键,但是许多用户我不知道如何打开联想的键盘灯。实际上,有些快捷键可以快速打开。让我们与您分享在联想笔记本电脑键盘上按哪个键。具体步骤如下:1、某些Lenovo笔记本电脑型号具有键盘背光功能,可以通过“FN+Space”将其打开。对于支持此功能的Zhi型号,在d…

  • vue解决跨域的几种办法_前端跨域解决方案

    vue解决跨域的几种办法_前端跨域解决方案什么是跨域  跨域指浏览器不允许当前页面的所在的源去请求另一个源的数据。源指协议,端口,域名。只要这个3个中有一个不同就是跨域。这里列举一个经典的列子:#协议跨域http://a.baidu.com访问https://a.baidu.com;#端口跨域http://a.baidu.com:8080访问http://a.baidu.com:80;#域名跨域http://a.baidu.com访问http://b.baidu.com;  现在很多公司都是采用前后分离的方式开发。那么出

  • Shell脚本(三)重定向

    Shell脚本(三)重定向

  • 服务器四通道内存性能提升,四通道内存性能怎么样

    服务器四通道内存性能提升,四通道内存性能怎么样四通道的内存有提升,但是性价比不是很好,如果是发烧友那不需要考虑什么了,如果是实用主义者四通道带来的性能的提升可能不会在使用中有太多的明显的感受。组建四通道内存很简单,有足够的内存条卡槽,X79的芯片组,i7-3960K的处理器,Apacer宇瞻猎豹DDR3-16002GB*4或者海盗船DDR316002GB*4的内存条就可以了,当然其他品牌的内存条也可以,这里只是举例,四条一样…

  • MAC NavicatPremium15 永久激活码[免费获取]

    (MAC NavicatPremium15 永久激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html…

  • 2020,最新手机号码手机验证正则表达式,持续更新

    2020,最新手机号码手机验证正则表达式,持续更新最近在跟一个别人写好上线的项目,今天出了一个bug,部分正常的手机号验证格式不通,查看了代码发现正则表达式有较大的错误,如图:存在的问题:1.存在逗号2.不够全面,部分正常的手机号验证不通过所以决定自己写,百度一下手机号的格式,下面应该是比较全面,所以就自己根据下面的写验证的正则表达式,如有小伙伴发现下图仍有遗漏请在评论指出,我看到会马上更新最后写出来的正则表达式:Patternp=Pattern.compile(“^1(3([1-35-9]\\d|4[1-..

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号