【摘要】 接收bmp图片编程,完成bmp图片翻转、水印添加等知识点。
一、摄像头练习 1. 改进拍照程序,至少bmp图片数据要正常,还可以将.c文件分隔成3个.c文件。
24位的真彩色bmp图片的构造:分为3个部分。
(1) 存放bmp头数据—主要存放bmp属性,rgb数据偏移量
(2) 存放bmp信息数据—存放宽度、高度、颜色位数
(3) 存放bmp图片源数据—rgb888
注意:
(1) bmp图片一行(宽度)的数据必须是4的倍数。
(2) bmp图片的源数据是从下到上,从左到右
bmp、jpg、png、mp4、mp3
2. 课后扩展知识: 拍照图片上加水印。比如:时间水印、或者自己的名字
(1) 第一种图片水印: 图片重叠。
(2) 在控制台终端屏幕上使用*号打印自己名字。
要求:
(1) 添加文字水印和数字水印。比如: 添加自己的名字和日期
(2) 实现任意位置添加任意的水印。
(3) 实现缩放功能,将图片可以任意放大和缩小。
3. 精简远程摄像头监控的代码文件。
将网页监控相关的代码文件单独提取出来进行编译,实现远程监控的效果。
使用gcc单独编译实现。(uvc)
分析: 程序是依靠makefile文件已经编译。首先从makefile文件入手。
主要修改的文件:mjpg_streamer.c
1. 改进拍照程序,至少bmp图片数据要正常,还可以将.c文件分隔成3个.c文件。
24位的真彩色bmp图片的构造:分为3个部分。
(1) 存放bmp头数据—主要存放bmp属性,rgb数据偏移量
(2) 存放bmp信息数据—存放宽度、高度、颜色位数
(3) 存放bmp图片源数据—rgb888
注意:
(1) bmp图片一行(宽度)的数据必须是4的倍数。
(2) bmp图片的源数据是从下到上,从左到右
bmp、jpg、png、mp4、mp3
2. 课后扩展知识: 拍照图片上加水印。比如:时间水印、或者自己的名字
(1) 第一种图片水印: 图片重叠。
(2) 在控制台终端屏幕上使用*号打印自己名字。
要求:
(1) 添加文字水印和数字水印。比如: 添加自己的名字和日期
(2) 实现任意位置添加任意的水印。
(3) 实现缩放功能,将图片可以任意放大和缩小。
3. 精简远程摄像头监控的代码文件。
将网页监控相关的代码文件单独提取出来进行编译,实现远程监控的效果。
使用gcc单独编译实现。(uvc)
分析: 程序是依靠makefile文件已经编译。首先从makefile文件入手。
任务2:汉字库的制作与使用 需要解决的问题:
1. 如何从汉字库里提取自己想要的点阵数据 。比如: 万邦易嵌
汉字库编码还是gbk编码: 有特定的公式可以计算点阵码的位置。
2. 如何区分中文还有英文
数据大于0x80就是中文,其他就是英文数据。 变量必须是: 无符号类型
注意: 写代码需要在中文编码的情况下编写!
3. 英文数据该如何取模?
从空格开始到~号结束 ,连续95个数据。
2.1 bmp图片缩放#include #include int piczoom(unsigned char *s_buff,unsigned int s_width,unsigned int s_height,unsigned char *buff,unsigned int width,unsigned int height);void *my_memcpy(void *v_dst,const void *v_src,unsigned char c);#pragma pack(1) /* 必须在结构体定义之前使用,这是为了让结构体中各成员按1字节对齐 *//*需要文件信息头:14个字节 */struct bitmapfileheader{ unsigned short bftype; //保存图片类似。 'bm' unsigned long bfsize; //图片的大小 unsigned short bfreserved1; unsigned short bfreserved2; unsigned long bfoffbits; //rgb数据偏移地址};/* 位图信息头 */struct bitmapinfoheader { /* bmih */ unsigned long bisize; //结构体大小 unsigned long biwidth; //宽度 unsigned long biheight; //高度 unsigned short biplanes; unsigned short bibitcount; //颜色位数 unsigned long bicompression; unsigned long bisizeimage; unsigned long bixpelspermeter; unsigned long biypelspermeter; unsigned long biclrused; unsigned long biclrimportant;};#define new_file_name new.bmp //缩放后的新图片名称#define src_file_name src.bmp //源图片名称/*图片放大与缩小示例*/int main(){ struct bitmapfileheader src_head; //源文件头数据 struct bitmapinfoheader src_info; //源文件参数结构 struct bitmapfileheader new_head; //新文件头数据 struct bitmapinfoheader new_info; //新文件参数结构 unsigned int new_width; //缩放后的宽度 unsigned int new_height; //缩放后的高度 unsigned char *new_buff; //存放新图片的数据 unsigned char *src_buff; //存放源图片的数据 unsigned int cnt=0; /*1. 打开图片文件*/ file *src_file=fopen(src_file_name,rb); file *new_file=fopen(new_file_name,wb); if(src_file==null||new_file==null) { printf(%s 源文件打开失败!\r\n,src_file_name); return; } /*2. 读取源图片参数*/ fread(&src_head,sizeof(struct bitmapfileheader),1,src_file); fread(&src_info,sizeof(struct bitmapinfoheader),1,src_file); printf(源图片尺寸:w=%d h=%d\r\n,src_info.biwidth,src_info.biheight); /*3. 获取新图片的尺寸*/ printf(输入新图片的宽度: ); scanf(%d,&new_width); printf(输入新图片的高度: ); scanf(%d,&new_height); printf(新图片尺寸:w=%d h=%d\r\n,new_width,new_height); /*4. 申请存放图片数据的空间*/ src_buff=malloc(src_info.biwidth*src_info.biheight*3); new_buff=malloc(new_width*new_height*3); if(new_buff==null||src_buff==null) { printf(malloc申请空间失败!\r\n); return -1; } /*5. 读取源图片rgb数据*/ fseek(src_file,src_head.bfoffbits,seek_set); //移动文件指针到rgb数据位置 fread(src_buff,1,src_info.biwidth*src_info.biheight*3,src_file); //读取源数据 /*6. 缩放图片*/ if(piczoom(src_buff,src_info.biwidth,src_info.biheight,new_buff,new_width,new_height)) { printf(图片缩放处理失败!\r\n); return -1; } /*7. 写入新图片数据*/ //填充文件头 memset(&new_head,0,sizeof(struct bitmapfileheader)); new_head.bftype=0x4d42; new_head.bfsize=54+new_width*new_height*3; new_head.bfoffbits=54; //填充文件参数 memset(&new_info,0,sizeof(struct bitmapinfoheader)); new_info.bisize=sizeof(struct bitmapinfoheader); new_info.biwidth=new_width; new_info.biheight=new_height; new_info.biplanes=1; new_info.bibitcount=24; //写入文件数据 fwrite(&new_head,sizeof(struct bitmapfileheader),1,new_file); fwrite(&new_info,sizeof(struct bitmapinfoheader),1,new_file); fseek(new_file,new_head.bfoffbits,seek_set); //移动文件指针到rgb数据位置 cnt=fwrite(new_buff,1,new_info.biwidth*new_info.biheight*3,new_file); //写数据 /*8. 关闭图片文件*/ fclose(new_file); fclose(src_file); printf(%s 新图片创建成功! 路径:程序运行路径下\r\n,new_file_name); return 0;}/*********************************************************************** 函数名称: piczoom* 功能描述: 近邻取样插值方法缩放图片* 注意该函数会分配内存来存放缩放后的图片,用完后要用free函数释放掉* 近邻取样插值的原理请参考网友lantianyu520所著的图像缩放算法* 输入参数: ptoriginpic - 内含原始图片的象素数据* ptzoompic - 内含缩放后的图片的象素数据* 输出参数: 无* 返 回 值: 0 - 成功, 其他值 - 失败***********************************************************************/int piczoom(unsigned char *ptoriginpic_aucpixeldatas,unsigned int ptoriginpic_iwidth,unsigned int ptoriginpic_iheight,unsigned char *ptzoompic_aucpixeldatas,unsigned int ptzoompic_iwidth,unsigned int ptzoompic_iheight){ unsigned int ptoriginpic_ilinebytes=ptoriginpic_iwidth*3; //一行的字节数 unsigned int ptzoompic_ilinebytes=ptzoompic_iwidth*3; //一行的字节数 unsigned long dwdstwidth=ptzoompic_iwidth; unsigned long* pdwsrcxtable; unsigned long x; unsigned long y; unsigned long dwsrcy; unsigned char *pucdest; unsigned char *pucsrc; unsigned long dwpixelbytes=3; //像素字节 pdwsrcxtable=malloc(sizeof(unsigned long) * dwdstwidth); if(null==pdwsrcxtable) { return -1; } for(x=0; x < dwdstwidth; x++)//生成表 pdwsrcxtable { pdwsrcxtable[x]=(x*ptoriginpic_iwidth/ptzoompic_iwidth); } for(y=0; y 2.2 bmp图片添加水印#include savebmp.h#include yuvtorgb.h/* 图片的象素数据 */typedef struct pixeldatas { int iwidth; /* 宽度: 一行有多少个象素 */ int iheight; /* 高度: 一列有多少个象素 */ int ibpp; /* 一个象素用多少位来表示 */ int ilinebytes; /* 一行数据有多少字节 */ int itotalbytes; /* 所有字节数 */ unsigned char *videobuf; //存放一帧摄像头的数据 //指向了存放摄像头数据的空间地址}t_pixeldatas;t_pixeldatas pixedata; //存放实际的图像数据/* usb摄像头相关参数定义*/struct v4l2_buffer tv4l2buf;int ifd;int listnum;unsigned char* pucvidebuf[4]; // 视频buff空间地址void camera_pthread(void);int main(int argc ,char *argv[]){ if(argc!=2) { printf(./app /dev/videox\n); return -1; } camera_init(argv[1]); //摄像头设备初始化 //开始采集摄像头数据,并编码保存为bmp图片 camera_pthread(); return 0;}//摄像头设备的初始化int camera_init(char *video){ int i=0; int cnt=0; //定义摄像头驱动的buf的功能捕获视频 int itype = v4l2_buf_type_video_capture; /* 1、打开视频设备 */ ifd = open(video,o_rdwr); if(ifd < 0) { printf(摄像头设备打开失败!\n); return 0; } struct v4l2_format tv4l2fmt; /* 2、 vidioc_s_fmt 设置摄像头使用哪种格式 */ memset(&tv4l2fmt, 0, sizeof(struct v4l2_format)); tv4l2fmt.type = v4l2_buf_type_video_capture; //视频捕获 //设置摄像头输出的图像格式 tv4l2fmt.fmt.pix.pixelformat=v4l2_pix_fmt_yuyv; /*设置输出的尺寸*/ tv4l2fmt.fmt.pix.width = 640; tv4l2fmt.fmt.pix.height = 480; tv4l2fmt.fmt.pix.field = v4l2_field_any; //vidioc_s_fmt 设置摄像头的输出参数 ioctl(ifd, vidioc_s_fmt, &tv4l2fmt); //打印摄像头实际的输出参数 printf(support format:%d\n,tv4l2fmt.fmt.pix.pixelformat); printf(support width:%d\n,tv4l2fmt.fmt.pix.width); printf(support height:%d\n,tv4l2fmt.fmt.pix.height); /* 3、vidioc_reqbufs 申请buffer */ /* 初始化pixedata结构体,为转化做准备 */ pixedata.ibpp =24; //高度 和宽度的赋值 pixedata.iheight = tv4l2fmt.fmt.pix.height; pixedata.iwidth = tv4l2fmt.fmt.pix.width; //一行所需要的字节数 pixedata.ilinebytes = pixedata.iwidth*pixedata.ibpp/8; //一帧图像的字节数 pixedata.itotalbytes = pixedata.ilinebytes * pixedata.iheight; pixedata.videobuf=malloc(pixedata.itotalbytes); //申请存放图片数据空间 //v412请求命令 struct v4l2_requestbuffers tv4l2reqbuffs; memset(&tv4l2reqbuffs, 0, sizeof(struct v4l2_requestbuffers)); /* 分配4个buffer:实际上由vidioc_reqbufs获取到的信息来决定 */ tv4l2reqbuffs.count = 4; /*在内核空间里开辟4个空间*/ /*支持视频捕获功能*/ tv4l2reqbuffs.type = v4l2_buf_type_video_capture; /* 表示申请的缓冲是支持mmap(内存映射) */ tv4l2reqbuffs.memory = v4l2_memory_mmap; /* 为分配buffer做准备 */ ioctl(ifd, vidioc_reqbufs, &tv4l2reqbuffs); for (i = 0; i
彩晶第四季中尺寸面板出货比重或攀升到56%
ETC大力推广的背后是怎样的
晨日科技与TCL的合作迈出重要一步
MiniLED离大规模商用化仅剩一步之遥?
三运放架构对仪表放大器的制约
Linux开发_BMP图片编程(翻转、添加水印)
浅谈LED在汽车中的应用及其驱动电路的设计
单片机程序框架开发知识总结
中国科学家开发深度强化学习框架:有效率识别复杂网络
华为HMS服务或将在欧洲亮相;佳能推出首款固态化光源投影机;小米10快充带动GaN市场...
cd4093应用开关电路图大全(感应式控制开关电路/脉冲发生器/密码锁)
真正意义上的全面屏离我们不远了,甩掉刘海屏是迟早的事
【解决方案】北海银基国际滨海旅游度假中心项目水世界能源管理系统的设计与应用
触摸屏技术的应用前景展望
采用TLV5618和SPCE061A芯片实现轮椅自主避障系统的软硬件设计
麦克斯韦理论:赫兹的电磁波实验
数字示波器通道耦合与触发耦合的区别
基于Android的屏幕水雾手机游戏的设计方案
华为nova5z即将发布 将搭载麒麟810处理器
SMT贴片机三种贴装头应该如何进行选择呢?