一、BMP编码简介

BMP(全称Bitmap)是Window操作系统中的标准图像文件格式,文件后缀名为“.bmp”,使用非常广。它采用位映射存储格式,除了图像深度可选以外,一般不采用其他任何压缩,因此,BMP文件所占用的空间很大,但是没有失真。BMP文件的图像深度可选1bit、4bit、8bit、16bit、24bit及32bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。
常见的BMP图像文件组成
1,位图头文件数据结构,它包含BMP图像文件的类型、显示内容等信息;
2,位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;
3,调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板;   
4,位图数据,这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值;

  • BMP文件头(14字节):BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。BMP文件头结构体定义如下:
//BMP文件头
typedef __packed struct
{u16  bfType ;      //文件标志.只对'BM',用来识别BMP位图类型u32  bfSize ;    //文件大小,占四个字节u16  bfReserved1 ;  //保留u16  bfReserved2 ;  //保留u32  bfOffBits ;    //从文件开始到位图数据(bitmap data)开始之间的偏移量
}BITMAPFILEHEADER ;
  • 位图信息头(40字节):BMP位图信息头数据用于说明位图的尺寸等信息。 BMP位图信息头结构体定义如下:
typedef __packed struct
{u32 biSize ;       //说明BITMAPINFOHEADER结构所需要的字数。long  biWidth ;        //说明图象的宽度,以象素为单位 long  biHeight ;        //说明图象的高度,以象素为单位 u16  biPlanes ;     //为目标设备说明位面数,其值将总是被设为1 u16  biBitCount ;     //说明比特数/象素,其值为1、4、8、16、24、或32u32 biCompression ;         //说明图象数据压缩的类型。其值可以是下述值之一://BI_RGB:没有压缩;//BI_RLE8:每个象素8比特的RLE压缩编码,压缩格式由2字节组成 //BI_RLE4:每个象素4比特的RLE压缩编码,压缩格式由2字节组成//BI_BITFIELDS:每个象素的比特由指定的掩码决定。u32 biSizeImage ;        //说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0  long  biXPelsPerMeter ;     //说明水平分辨率,用象素/米表示long  biYPelsPerMeter ;     //说明垂直分辨率,用象素/米表示u32 biClrUsed ;     //说明位图实际使用的彩色表中的颜色索引数u32 biClrImportant ;           //说明对图象显示有重要影响的颜色索引的数目,//如果是0,表示都重要。
}BITMAPINFOHEADER ;
  • 颜色表:颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色,如下所示:
typedef __packed struct
{u8 rgbBlue ;       //指定蓝色强度u8 rgbGreen ;   //指定绿色强度 u8 rgbRed ;    //指定红色强度 u8 rgbReserved ;   //保留,设置为0
}RGBQUAD ;
  • RGBQUAD结构数据的个数由biBitCount来确定:当biBitCount=1、4、8时,分别有2、16、256个表项;当biBitCount大于8时,没有颜色表项。BMP文件头、位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
typedef __packed struct
{ BITMAPFILEHEADER bmfHeader;BITMAPINFOHEADER bmiHeader;   RGBQUAD bmiColors[1];
}BITMAPINFO;
  • 位图数据:记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图一个像素值所占字节数:
    当biBitCount=1时,8个像素占1个字节;
    当biBitCount=4时,2个像素占1个字节;
    当biBitCount=8时,1个像素占1个字节;
    当biBitCount=16时,1个像素占2个字节;
    当biBitCount=24时,1个像素占3个字节;
    当biBitCount=32时,1个像素占4个字节; biBitCount=16,即高彩色(65K色)。当biCompression=BI_RGB(0),则采用RGB555格式,最高位恒为0;当biCompression=BI_BITFIELDS(3),则在原来调色板位置用3个DWORD类型的掩码替换,分别代表红、绿、蓝三色的掩码,一般是:
    0X7C00、0X03E0、0X001F。
    采用16位BMP编码(因为LCD就是16位色的,而且16位BMP编码比24位BMP编码更省空间),故需要设置biBitCount的值为16,这样得到新的位图信息(BITMAPINFO)结构体:
typedef __packed struct
{ BITMAPFILEHEADER bmfHeader;BITMAPINFOHEADER bmiHeader;   u32 RGB_MASK[3];     //调色板用于存放RGB掩码
}BITMAPINFO;

RGB_MASK[3],即颜色掩码,分别代表红、绿、蓝三色的掩码,分别是: 0X7C00、0X03E0、0X001F。

二、BMP编码流程

1)创建BMP位图信息,并初始化各个相关信息
首先,我们要设置BMP图片的分辨率为LCD分辨率、BMP图片的大小(整个BMP文件大小)、BMP的像素位数(16位)和掩码等信息。
2)创建新BMP文件,写入BMP位图信息
我们要保存BMP,当然要存放在某个地方(文件),所以需要先创建文件,同时先保存BMP位图信息,之后才开始BMP数据的写入。
3)保存位图数据
这里就比较简单了,只需要从LCD的GRAM里面读取各点的颜色值,依次写入第二步创建的BMP文件即可。注意:保存顺序(即读GRAM顺序)是从左到右,从下到上。
4)关闭文件
使用FATFS,在文件创建之后,必须调用f_close,文件才会真正体现在文件系统里面,否则是不会写入的!这个要特别注意,写完之后,一定要调用f_close。

三、JPEG简介

JPEG(Joint Photographic Experts Group)是一个由ISO和IEC两个组织机构联合组成的一个专家组,负责制定静态的数字图像数据压缩编码标准,这个专家组开发的算法称为JPEG算法,并且成为国际上通用的标准,因此又称为JPEG标准。 JPEG是一个适用范围很广的静态图像数据压缩标准,既可用于灰度图像又可用于彩色图像。 JPEG专家组开发了两种基本的压缩算法,一种是采用以离散余弦变换(Discrete Cosine Transform,DCT)为基础的有损压缩算法另一种是采用以预测技术为基础的无损压缩算法。使用有损压缩算法时,在压缩比为25:1的情况下,压缩后还原得到的图像与原始图像相比较,非图像专家难于找出它们之间的区别,因此得到了广泛的应用。

JPEG压缩编码分为三个步骤:
1)使用正向离散余弦变换(Forward Discrete Cosine Transform,FDCT)把空间域表示的图变换成频率域表示的图。
2)使用加权函数对DCT系数进行量化,这个加权函数对于人的视觉系统是最佳的。
3)使用霍夫曼可变字长编码器对量化系数进行编码。

四、JPEG拍照流程

1)初始化STM32F4的DCMI接口和OV2640模块
首先,我们要初始化STM32的DCMI接口(包括开启DMA和相关中断)和相关IO,然后配置好OV2640输出JPEG数据流。
2)读取OV2640模块的数据
在DCMI接口的驱动下,有序读取OV2640输出的JPEG数据流,我们采用DMA双缓冲来接收JPEG数据流,并将这些数据及时搬运到外部SRAM(通过DMA的传输完成中断来处理)。
3)保存JPEG数据
在采集完一帧JPEG数据后,利用fatfs,创建一个.jpg文件,然后将存储在外部SRAM的数组(以0XFF,0XD8开头)存储在这个文件里面,最后调用f_close关闭文件,即可实现JPEG拍照保存。

在摄像头实验里面,定义了一个很大的数组jpeg_buf(124KB)来存储JPEG图像数据,不过,本例程要用到内存管理,其他地方也要用到一些数组,所以,肯定无法再定义这么大的数组了。并且这个数组不能使用外部SRAM(实测:DCMI接口使用DMA直接传输JPEG数据到外部SRAM会出现数据丢失,所以DMA接收JPEG数据只能用内部SRAM),所以,本例程使用DMA的双缓冲机制来读取,DMA双缓冲读取JPEG数据框图如下图:
1、DMA接收来自OV2640的JPEG数据流,首先使用M0AR(内存1)来存储,当M0AR满了以后,自动切换到M1AR(内存2),同时程序读取M0AR(内存1)的数据到外部SRAM;当M1AR满了以后,又切回M0AR,同时程序读取M1AR(内存2)的数据到外部SRAM;依次循环(此时的数据处理,是通过DMA传输完成中断实现的,在中断里面处理),直到帧中断,结束一帧数据的采集,读取剩余数据到外部SRAM,完成一次JPEG数据的采集。
2、M0AR,M1AR所指向的内存,必须是内部内存,不过由于采用了双缓冲机制,我们就不必定义一个很大的数组,一次性接收所有JPEG数据了,而是可以分批次接收,数组可以定义的比较小。
3、将存储在外部SRAM的jpeg数据,保存为.jpg/.jpeg存放在SD卡,就完成了一次JPEG拍照。

STM32照相机(OV2640)相关推荐

  1. 基于STM32、OV2640及ESP8266的无线图传

    一.简介: 本文利用STM32F407单片机.OV2640摄像机模块以及ESP8266 WIFI模块,并基于C#编写的TCP上位机服务,来实现图像的无线传输. 本文受启发于博客:ESP8266+STM ...

  2. 【STM32】OV2640摄像头学习笔记 转

    [STM32]OV2640摄像头学习笔记 2019年03月03日 13:01:35 淹死的大白鲨 阅读数 4736更多 分类专栏: [STM32] 版权声明:本文为博主原创文章,遵循 CC 4.0 B ...

  3. STM32照相机实验

    BMP编码简介: 典型的BMP图像文件由4部分组成: 1,位图头文件数据结构,它包含BMP图像文件的类型.显示内容等信息: 2,位图信息数据结构,它包含有BMP图像的宽.高.压缩方法,以及定义颜色等信 ...

  4. STM32 F4 OV2640摄像头学习笔记(一)

    //尝试写作,记录学习过程. 一.OV2640摄像头简介 本节将主要讲解OV2640摄像头基础部分和一些引脚配置. OV2640传感器简介 OV2640是Omni Vision公司生产的一颗1/4寸的 ...

  5. STM32 F4 OV2640摄像头学习笔记(三)

    四.DCMI(Digital camera interface)接口 功能描述 STM32F4 自带了一个数字摄像头(DCMI)接口,该接口是一个同步并行接口,能够接收外部8位.10位.12位或14位 ...

  6. STM32——照相机

    一.BMP编码简介 1.什么是BMP? BMP(全称Bitmap)是Windows操作系统中的标准图像文件格式,文件后缀名为".bmp".它采用位映射存储格式,除了图像深度可选外, ...

  7. 【STM32】OV2640摄像头学习笔记

    目录: 一.OV2640 Camera 二.读取OV2640模块图像数据过程: 三.DCMI(Digital camera interface)接口 四.SCCB协议 1.起始信号 2.停止信号 五. ...

  8. STM32 F4 OV2640摄像头学习笔记(二)

    二.OV2640数据读取过程 OV2640模块初始化 初始化IO口 上电并复位 读取传感器ID 执行初始化序列 完成初始化 2. OV2640数据读取 如图2.1 OV2640行输出时序图所示,OV2 ...

  9. STM32F407传输OV2640视频数据并在PC端显示

    一.整体架构 STM32使用DCMI驱动OV2640,DMA通道获取图像数据,然后通过以太网将数据发送至PC端,PC端通过socket接收数据,并用BufferedImage将其显示.(PC端使用的j ...

最新文章

  1. 如何使用Bootstrap4和ES6创建自定义确认框
  2. 2020人工神经网络第一次作业-参考答案第十部分
  3. 4.2.1 路由算法与路由协议概述(静态路由和动态路由---距离-向量路由算法---链路状态路由算法、层次路由)
  4. eeprom的wp 引脚_EEPROM
  5. Delphi中的进制转换
  6. UIView使用UIMotionEffect效果
  7. 手把手教你学Dapr - 5. 状态管理
  8. 修改数据表部分字段方法封装-及-动态生成对象并动态添加属性
  9. jlabel字怎么变化_怎样才能把字写好?详解最科学的练字方法及步骤
  10. 前端笔记-Vue中缺少router-view导致跳转失效
  11. 动手为王 | Oracle 数据库跨版本升级迁移实践
  12. tiktok+独立站怎么引流?
  13. spring底层原理
  14. java集合类程序代码_Java集合类源代码分析二:ArrayList(1)
  15. Git合并特定commits 到另一个分支
  16. POJ 3468 A Simple Problem with Integers(线段树区间更新)
  17. 总结htmlfile:未知的运行时错误
  18. C语言程序设计 授课日历 2010年春季
  19. mac使用fish的时候添加可执行文件路径
  20. 独立安装 lamp 兄弟连

热门文章

  1. 【花雕】全国青少年机器人技术一级考试备考实操搭建手册10
  2. 一次搞懂什么是IP 子网掩码 默认网关 DNS
  3. 备份工具xtrabackup
  4. 天玑1100相当于骁龙多少处理器
  5. linux 查看网卡是否万兆_linux/centos如何查看网卡是100M还是1000M?
  6. 数据治理:1.数据脱敏—6种数据脱敏方案
  7. 4G5G网络优化面试题
  8. java todataurl_利用canvas中toDataURL()将图片转为dataURL(base64)的方法详解
  9. 蓝牙耳机哪个品牌好用?2023口碑最好的蓝牙耳机推荐
  10. 元宇宙 | 数字平行宇宙