暑假的时候做车用到SD卡保存摄像头OV7620的数据,采用SPI,图片大小是155*60,刚开始学这个没加什么东西,直接就把数据往SD里面塞,初始化创建了一个data1.txt的文件
rc =f_open(&testdata,"0:/data1.txt",FA_CREATE_ALWAYS|FA_WRITE);
if(FR_OK == rc)OLED_P6x8Str(0,4,"f_open is ok");
接下来就直接保存图像数据
for(i = 0;i < 60;i++)
{
for(j = 0;j < 156;j++)
{
if(j == 155)
filebuff[j] = 0;
else
filebuff[j]=ImageData[i][j];
}
f_write(&testdata,filebuff,156,&bw);
}
保存完了数据直接打开不了,后来整了一天怎么把这些数据合成bmp位图,下面是在vc++6.0用c语言写的
/**
文件名:createbmp.c
日期:2016.8.17
版本:2.0
作者:逆风
功能:实现将SD卡中保存的摄像头数据合成8位灰度图像(*.bmp),方便在小豹上位机上分析图像
使用方法:将SD卡中保存数据的txt文件放至指定路径(本程序是:G:\\101.txt)
运行createbmp.exe,如果没有出现错误则将在G盘根目录生成bmp位图(*.bmp)(从0.bmp,1.bmp...n.bmp)
*/
#include <STDIO.H>
#include <STRING.H>
#include <STDLIB.H>
//摄像头采集图像的大小要对应这里bmp位图的大小
#define WIDTH 155 //合成的bmp位图的宽,即摄像头采集的列数
#define HEIGHT 60 //合成的bmp位图的高,即摄像头采集的行数
#define WIDTHbyte 156//这里设置的156是因为必须为4的整数倍,即采集的155列向上补齐为156
#pragma pack(push, 1)
typedef unsigned char U8;
typedef unsigned short U16;
typedef unsigned int U32;
//文件信息头,占14个字节
typedef struct tagBITMAPFILEHEADER
{
U16 bfType; //说明文件的类型,该值必需是0x4D42,也就是字符'BM'
U32 bfSize; //说明文件的大小,以字节为单位
U16 bfReserved1; //保留,设置为0
U16 bfReserved2; //保留,设置为0
U32 bfOffBits; // 说明从BITMAPFILEHEADER结构开始到实际图像数据阵列字节间的字节偏移量
//这个参数是非常有用的,因为位图信息头和调色板的长度会根据不同情况而变化,
//所以你可以用这个偏移值迅速的从文件中读取到位数据
} BITMAPFILEHEADER;
//位图信息头,占40个字节
typedef struct tagBITMAPINFOHEADER
{
U32 biSize; //表示BITMAPINFOHEADER结构所需要的字节数
U32 biWidth; //表示图像的宽度,以像素为单位
U32 biHeight;
/*表示图像的高度,以像素为单位。
注:这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位图,
还是正向的位图。如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。
大多数的BMP文件都是倒向的位图,也就是时,高度值是一个正数。
*/
U16 biPlanes; //为目标设备说明位面数,其值将总是被设为1
U16 biBitCount; //表示比特数/像素,其值为1、4、8、16、24、或32
U32 biCompression; //表示图像数据压缩的类型,没有压缩的类型:BI_RGB(即为0)
U32 biSizeImage; //表示图像的大小,以字节为单位。当用BI_RGB格式时,可设置为0
U32 biXPelsPerMeter; //表示水平分辨率,用像素/米表示
U32 biYPelsPerMeter; //表示垂直分辨率,用像素/米表示
U32 biClrUsed; //表示位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)
U32 biClrImportant; //表示对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要
} BITMAPINFOHEADER;
//颜色表(调色板)(为可选项)
typedef struct tagRGBQUAD
{
U8 rgbBlue; // 蓝色的亮度(值范围为0-255)
U8 rgbGreen; // 绿色的亮度(值范围为0-255)
U8 rgbRed; // 红色的亮度(值范围为0-255)
U8 rgbReserved; // 保留,必须为0
} RGBQUAD;
//位图信息头和颜色表组成位图信息
typedef struct tagBITMAPINFO
{
BITMAPINFOHEADER bmiHeader; // 位图信息头
RGBQUAD bmiColors[1]; // 颜色表
} BITMAPINFO;
//文件信息头和位图信息组成位图文件
typedef struct tagBITMAP
{
BITMAPFILEHEADER bfHeader;
BITMAPINFO biInfo;
}BITMAPFILE;
#pragma pack(pop)
/*
#pragma pack(push, 1)
...
#pragma pack(pop)
这两句在VC编译时必须加上
如果不加上,由于编译器的问题,这里用BYTE声明,但因为编译器喜欢内存对齐,
实际占了还是4字节,改变一下成1字节对齐声明就可以了
*/
/*
注意:
Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充。
例如:一张24位10*10的图片,一行图像10个像素,共30字节,
由于Windows规定一个扫描行所占的字节数必须是4的倍数,而不足的以0填充,
所以一行图像在文件中实际存储了32个字节(补了2字节的0);而图片总的大小就不是54+30*10=354字节,
而是54+32*10=374字节
所以:
1. 在生成BMP文件时,如果一行图像的字节数不是4的倍数,则补0,而补后一行图像数据的大小的计算公式为:
bmppitch = ((biWidth * bitCountPerPix + 31) >> 5) << 2;
其中,biWidth--图片的宽度,bitCountPerPix--图片的位数。
2. 在读取BMP文件数据时也要注意这点。
*/
//生成BMP图片 在摄像头传回来数据的基础上加上文件信息头和位图信息头
int GenBmpFile(U8 (*pData)[WIDTH], U32 width, U32 height, const char *filename)
{
FILE *fp = fopen(filename, "wb");
if(!fp)
{
printf("fopen failed : %s, %d/n", __FILE__, __LINE__);
return 0;
}
U32 filesize = WIDTHbyte*height;
BITMAPFILE bmpfile;
bmpfile.bfHeader.bfType = 0x4D42;
bmpfile.bfHeader.bfSize = filesize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256;
bmpfile.bfHeader.bfReserved1 = 0;
bmpfile.bfHeader.bfReserved2 = 0;
bmpfile.bfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256;
bmpfile.biInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpfile.biInfo.bmiHeader.biWidth = width;
bmpfile.biInfo.bmiHeader.biHeight = height;
bmpfile.biInfo.bmiHeader.biPlanes = 1;
bmpfile.biInfo.bmiHeader.biBitCount = 8; //8位bmp图
bmpfile.biInfo.bmiHeader.biCompression = 0;
bmpfile.biInfo.bmiHeader.biSizeImage = 0;
bmpfile.biInfo.bmiHeader.biXPelsPerMeter = 0;
bmpfile.biInfo.bmiHeader.biYPelsPerMeter = 0;
bmpfile.biInfo.bmiHeader.biClrUsed = 0;
bmpfile.biInfo.bmiHeader.biClrImportant = 0;
//构造灰度图的调色版
RGBQUAD rgbquad[256];
int i;
for(i=0;i<256;i++)
{
rgbquad[i].rgbBlue=i;
rgbquad[i].rgbGreen=i;
rgbquad[i].rgbRed=i;
rgbquad[i].rgbReserved=0;
}
fwrite(&(bmpfile.bfHeader), sizeof(BITMAPFILEHEADER), 1, fp); //将文件信息头写进文件
fwrite(&(bmpfile.biInfo.bmiHeader), sizeof(BITMAPINFOHEADER), 1, fp); //将位图信息头写进文件
fwrite(&rgbquad,sizeof(RGBQUAD)*256,1, fp); //将调色板写进文件
//将图像数据写进文件
U8 *pEachLinBuf = (U8*)malloc(WIDTHbyte); //在内存中开辟空间
memset(pEachLinBuf, 0, WIDTHbyte); //将pEachLinBuf中所有数据设置为0
if(pEachLinBuf)
{
int h,w;
for(h = height-1; h >= 0; h--)
{
for(w = 0; w < width; w++)
{
//copy by a pixel
pEachLinBuf[w] = *(*(pData+h)+w);
}
fwrite(pEachLinBuf, WIDTHbyte, 1, fp);
}
free(pEachLinBuf);
}
fclose(fp);
return 1;
}
int main(char argc, char *argv[])
{
U8 pRGB[HEIGHT][WIDTH]; // 定义位图数据
memset(pRGB,0,sizeof(pRGB));//将所有数据都设置为0
long myfilesize = 0;
FILE *fpread = fopen("F:\\data1.txt", "rb");//打开摄像头保存数据的文件
if(!fpread)
{
printf("fopen failed : %s, %d/n", __FILE__, __LINE__);
return 0;
}
else
{
fseek(fpread,0,SEEK_END);//将文件指针移动文件结尾
myfilesize = ftell (fpread); ///求出当前文件指针距离文件开始的字节数
fseek(fpread,0,SEEK_SET);//将文件指针移动文件开头
}
char FilePath[1000] = {0};
int number = 0;
for(number = 0;number < myfilesize/(HEIGHT*WIDTHbyte);number++)
{
sprintf(FilePath, "F:\\图像%4d.bmp", number);
int h = 0;
for(h = 0; h < HEIGHT;h++)
{
fread(pRGB[h],WIDTHbyte,1,fpread);//读取每一行的数据。这里设置的156是因为必须为4的整数倍,即采集的155列向上补齐为156
// printf("%d\n",fread(pRGB[HEIGHT-1-h],WIDTHbyte,1,fpread));
if ( ferror ( fpread ) ){//如果读取错误
printf("File read error.");
}
}
GenBmpFile(&pRGB[0], WIDTH, HEIGHT, FilePath);//生成BMP文件
}
fclose(fpread);
return 0;
}
合成的图片:
然后就可以用上位机分析图片了
暂时还没发现什么大问题,之后有空再优化一下,接下来要是能做出个上位机来直接合成分析就好了