这段时间接到了一个新活,是关于图像处理的一个探地摄像头的项目。所以也差不多是时候开始学习一下数字图像处理的知识了。本来我们的方案是直接移植opencv,编译一下以后其他就基本啥都不用管了,非常方便。但是最后还是决定不适用这个方案。
opencv的平台依赖性太强,只能运行于X86电脑和嵌入式LINUX平台,这意味这一些底层永远都无法接触到。而且程序不可能跑在裸机平台上了。如果硬要一直到逻辑平台上的话代价比自己写一个程序要大。
前段时间自己一直在看关于opencv的书,就看那些乱七八糟一堆一堆的函数,感觉啥都没有学到。
前段时间看到这样一句话,我们需要警惕开源软件。没错他们是很香,但是他们会让你失去自己的独立性,真正的程序员最好应该是不给自己任何可以依赖的东西的。
所以我决定除了C库什么都不依赖,所有底层全部自己敲一遍,同时尽可能为以后扩展跨平台的特性提供接口。
写代码写到了今天,不可能在向之前一样闭着眼睛就开始写代码。写代码之前理清思路可以给自己省去许多麻烦。
现在再来回顾一下项目需求。
1.只用C库实现。
2.为今后的跨平台特性提供接口
3.函数高内聚低耦合,具有较强的可移植性
下面是系统框图
实现这个最大的问题在于C语言并不支持类的使用,在重载,继承等特性上也没有,想要实现这种面对对象的程序设计我们得要另外再想方法。
在实现上面其实主要就是图片的读取,保存,加载,显示,拷贝,析构等功能。现在基本已经实现。
BMP图片是windows操作系统中的标准图像文件格式,可以分为两类:设备相关位图(DDB)和设备无关位图(DIB),使用广泛。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。BMP文件的图像深度可选lbit、4bit、8bit及24bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。
1:位图头文件数据结构,它包含BMP图像文件的类型、显示内容等信息;
2:位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;
3:调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板;
4:位图数据,这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。
C 语言程序设计思路:
typedef struct tagBITMAPFILEHEADER
{
unsigned short bfType; //保存图片类型。 'BM'
unsigned long bfSize; //位图文件的大小,以字节为单位(3-6字节,低位在前)
unsigned short bfReserved1;//位图文件保留字,必须为0(7-8字节)
unsigned short bfReserved2;//位图文件保留字,必须为0(9-10字节)
unsigned long bfOffBits; //RGB数据偏移地址,位图数据的起始位置,以相对于位图(11-14字节,低位在前)
}BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER
{
unsigned long biSize; //本结构所占用字节数(15-18字节)
unsigned long biWidth; //位图的宽度,以像素为单位(19-22字节)
unsigned long biHeight; //位图的高度,以像素为单位(23-26字节)
unsigned short biPlanes; //目标设备的级别,必须为1(27-28字节)
unsigned short biBitCount; //每个像素所需的位数,必须是1(双色)(29-30字节),4(16色),8(256色)16(高彩色)或24(真彩色)之一
unsigned long biCompression;//位图压缩类型,必须是0(不压缩),(31-34字节)
//1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
unsigned long biSizeImage; //位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节)
unsigned long biXPelsPerMeter;//位图水平分辨率,每米像素数(39-42字节)
unsigned long biYPelsPerMeter;//位图垂直分辨率,每米像素数(43-46字节)
unsigned long biClrUsed; //位图实际使用的颜色表中的颜色数(47-50字节)
unsigned long biClrImportant; //位图显示过程中重要的颜色数(51-54字节)
}BITMAPINFOHEADER;
然后就是对于文件的一些读取写入的事情
在写程序是特别注意要将BMP的部分和图片有关处理的部分进行解耦。方便日后扩展其他的图片格式。
核心的文件主要有两个:bmp.c Mat.c
cv.h C图像类顶层头文件
/*************************************************
Copyright © Yueyang Co. Ltd. 2019-2029. All rights reserved.
File name: cv.h
Author: Yueyang
Version: V1.0
Description: LiteCV顶层头文件,提供基础数据类型
Others:
Log: 11.3 Yueyang
*************************************************/
#ifndef _CV_H
#define _CV_H
#define bool u8
#define false 0
#define true 1
#define PI 3.1415926
#define ARM_LINUX
//在不同的平台上一些数据的字长不一样
#ifdef WINDOWS
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;
typedef unsigned char BYTE;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
#endif
#ifdef X86_LINUX
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
typedef unsigned short WORD;
typedef u32 DWORD;
typedef u32 LONG;
typedef unsigned char BYTE;
#endif
#ifdef ARM_LINUX
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;
typedef unsigned char BYTE;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
#endif
#ifdef ARM_NONE
#endif
#endif // !CV_H
Mat.h 图像矩阵函数实现
/*************************************************
Copyright © Yueyang Co. Ltd. 2019-2029. All rights reserved.
File name: Mat.h
Author: Yueyang
Version: V1.0
Description: 提供Mat结构体
Others:
Log: 11.3 Yueyang
*************************************************/
#ifndef Mat_H
#define MAT_H
#include "cv.h"
#define BMP_8 0X01
#define BMP_565 0x02
#define BMP_888 0x03
#define BMP_32 0x04
#define JPEG 0X05
#define RGB(r,g,b) ((u32)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
typedef struct
{ // bmfh
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
}BITMAPFILEHEADER;
typedef struct
{ // bmih
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
}BITMAPINFOHEADER;
typedef struct tagRGBQUAD
{ // rgbq
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
}RGBQUAD;
typedef struct tagBITMAPINFO
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
}BITMAPINFO;
typedef struct
{
//! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
BITMAPFILEHEADER bmf;
BITMAPINFOHEADER bmi;
LONG highth, width;
u8 pictype;
char* PATH;
BYTE *imgData;
}Mat;
void Mat_INIT();
Mat MatCreate(u8* filepath,u16 width,u16 height,u8 type);
#endif // !Mat_H
bmp.h bmp位图处理函数接口
/*************************************************
Copyright © Yueyang Co. Ltd. 2019-2029. All rights reserved.
File name: bmp.h
Author: Yueyang
Version: V1.0
Description: 提供对于bmp文件的操作函数
Others:
Log: 11.3 Yueyang
*************************************************/
#ifndef BMP_H_INCLUDED
#define BMP_H_INCLUDED
#include "stdio.h"
#include "Mat.h"
//通配指针提供,跨平台主要的实现方式
void (*Li_free) (void *_Memory);
void * (*Li_malloc) (size_t _Size);
void * (*Li_memcpy) (void * _Dst,const void * _Src,size_t _Size);
void (*show) (Mat* mat);
u8* (*at) (Mat* mat,int width,int highth);
int (*process) (Mat* mat,int x,int y,u32 color);
Mat (*load) (char *filepath);
int (*save) (char *filepath,Mat* mat);
Mat (*copy) (Mat mat);
void (*destory) (Mat* mat);
Mat (*create) (u8* filepath,u16 width,u16 height,u8 type);
//检查路径是否合法
int CheckbmpFilePath(char *filepath);
//读BMP文件头
int ReadbmpFileHeader(char *filepath,BITMAPFILEHEADER *bmfh);
//打印BMP文件头
void PrintbmpFileHeader(BITMAPFILEHEADER *bmfh);
//读BMP信息头
int ReadbmpInfoHeader(char *filepath,BITMAPINFOHEADER *bmih);
//打印BMP信息头
void PrintbmpInfoHeader(BITMAPINFOHEADER *bmih);
//读取BMP的图像数据
int ReadbmpPixelData(char *filepath,BYTE *imgData);
//获取图像每一行所占用的字节数
LONG GetLineBytes(int imgWidth,int bitCount);
//打印位图数据信息
void PrintbmpPixelData(BYTE *imgData,int width,int height,int bitCount);
//提供一个MAT的结构体将其存储为BMP文件
int SaveAsbmpImage(char *filepath,Mat* mat);
//图片显示 注意在不同的硬件平台上需要重写这个函数
//加载BMP图片,并返回一个MAT结构体
Mat bmpload(char *filepath);
//对于图片的每一个像素分别操作
int bmpprocess(Mat* mat,int width,int highth,u32 color);
//获取BMP某个像素所在的地址
u8* bmpat(Mat* mat,int width,int highth);
//BMP拷贝函数
Mat bmpcopy(Mat mat);
//析构函数
void bmpdestory(Mat* mat);
void ARM_ShowbmpImage(Mat* mat,struct fb_var_screeninfo vinfo,struct fb_fix_screeninfo finfo,char *fbp);
#endif
bmp.c
/*************************************************
Copyright © Yueyang Co. Ltd. 2019-2029. All rights reserved.
File name: bmp.c
Author: Yueyang
Version: V1.0
Description: 提供对于bmp文件的操作函数
Others:
Log: 11.3 Yueyang
*************************************************/
#include
#include
#include
#include
#include "string.h"
#include "bmp.h"
int ReadbmpFileHeader(char *filepath,BITMAPFILEHEADER *bmfh)
{
FILE *fp;
fp=fopen(filepath,"rb");
if(!fp)
{
printf("Can not open the file:%s\n",filepath);
return -1;
}
if(fread(&bmfh->bfType,sizeof(WORD),1,fp)!=1)
{
printf("Can not read bfType in the file header.\n");
fclose(fp);
return -1;
}
if(fread(&bmfh->bfSize,sizeof(DWORD),1,fp)!=1)
{
printf("Can not read bfSize in the file header.\n");
fclose(fp);
return -1;
}
if(fread(&bmfh->bfReserved1,sizeof(WORD),1,fp)!=1)
{
printf("Can not read bfReserved1 in the file header.\n");
fclose(fp);
return -1;
}
if(fread(&bmfh->bfReserved2,sizeof(WORD),1,fp)!=1)
{
printf("Can not read bfReserved2 in the file header.\n");
fclose(fp);
return -1;
}
if(fread(&bmfh->bfOffBits,sizeof(DWORD),1,fp)!=1)
{
printf("Can not read bfOffBits in the file header.\n");
fclose(fp);
return -1;
}
fclose(fp);
return 0;
}
int ReadbmpInfoHeader(char *filepath,BITMAPINFOHEADER *bmih)
{
FILE *fp;
fp=fopen(filepath,"rb");
if(!fp)
{
printf("Can not open the file:%s\n",filepath);
return -1;
}
fseek(fp,14,SEEK_SET);
if(fread(&bmih->biSize,sizeof(DWORD),1,fp)!=1)
{
printf("Can not read biSize in the info header.\n");
fclose(fp);
return -1;
}
if(fread(&bmih->biWidth,sizeof(LONG),1,fp)!=1)
{
printf("Can not read biWidth in the info header.\n");
fclose(fp);
return -1;
}
if(fread(&bmih->biHeight,sizeof(LONG),1,fp)!=1)
{
printf("Can not read biHeight in the info header.\n");
fclose(fp);
return -1;
}
if(fread(&bmih->biPlanes,sizeof(WORD),1,fp)!=1)
{
printf("Can not read biPlanes in the info header.\n");
fclose(fp);
return -1;
}
if(fread(&bmih->biBitCount,sizeof(WORD),1,fp)!=1)
{
printf("Can not read biBitCount in the info header.\n");
fclose(fp);
return -1;
}
if(fread(&bmih->biCompression,sizeof(DWORD),1,fp)!=1)
{
printf("Can not read biCompression in the info header.\n");
fclose(fp);
return -1;
}
if(fread(&bmih->biSizeImage,sizeof(DWORD),1,fp)!=1)
{
printf("Can not read biSizeImage in the info header.\n");
fclose(fp);
return -1;
}
if(fread(&bmih->biXPelsPerMeter,sizeof(LONG),1,fp)!=1)
{
printf("Can not read biXPelsPerMeter in the info header.\n");
fclose(fp);
return -1;
}
if(fread(&bmih->biYPelsPerMeter,sizeof(LONG),1,fp)!=1)
{
printf("Can not read biYPelsPerMeter in the info header.\n");
fclose(fp);
return -1;
}
if(fread(&bmih->biClrUsed,sizeof(DWORD),1,fp)!=1)
{
printf("Can not read biClrUsed in the info header.\n");
fclose(fp);
return -1;
}
if(fread(&bmih->biClrImportant,sizeof(DWORD),1,fp)!=1)
{
printf("Can not read biClrImportant in the info header.\n");
fclose(fp);
return -1;
}
fclose(fp);
return 0;
}
int ReadbmpPixelData(char *filepath,BYTE *imgData)
{
BITMAPINFOHEADER bmih;
BITMAPFILEHEADER bmfh;
BYTE *data;
FILE *fp;
int n;
int width;
int height;
int bitCount;
DWORD dwLineBytes;
n=ReadbmpFileHeader(filepath,&bmfh);
if(n==-1)
{
printf("Can not read the file header of the BMP file.\n");
return -1;
}
n=ReadbmpInfoHeader(filepath,&bmih);
if(n==-1)
{
printf("Can not read the info header of the BMP file.\n");
return -1;
}
width=bmih.biWidth;
height=bmih.biHeight;
bitCount=bmih.biBitCount;
dwLineBytes=GetLineBytes(width,bitCount);
data=(BYTE*)Li_malloc(dwLineBytes*height*sizeof(BYTE));
if(!data)
{
printf("Can not allocate memory for the pixel data.\n");
return -1;
}
fp=fopen(filepath,"rb");
if(!fp)
{
printf("Can not open the file: %s\n",filepath);
Li_free(data);
return -1;
}
if(bitCount==8)
{
fseek(fp,bmfh.bfOffBits,SEEK_SET);
}
else if(bitCount==24)
{
fseek(fp,bmfh.bfOffBits,SEEK_SET);
}
else if(bitCount==16)
{
fseek(fp,bmfh.bfOffBits,SEEK_SET);
}
else
{
printf("DO NOT SUPPORT THIS KIND OF FILE\n");
return -1;
}
if(fread(data,dwLineBytes*height*sizeof(BYTE),1,fp)!=1)
{
printf("Can not read the pixel data.\n");
Li_free(data);
fclose(fp);
return -1;
}
Li_memcpy(imgData,data,dwLineBytes*height*sizeof(BYTE));
Li_free(data);
fclose(fp);
return 0;
}
void PrintbmpFileHeader(BITMAPFILEHEADER *bmfh)
{
printf("The contents in the file header of the BMP file:\n");
printf("bfOffBits: %ld\n",bmfh->bfOffBits);
printf("bfReserved1: %ld\n",bmfh->bfReserved1);
printf("bfReserved2: %ld\n",bmfh->bfReserved2);
printf("bfSize: %ld\n",bmfh->bfSize);
printf("bfType: %ld\n",bmfh->bfType);
}
void PrintbmpInfoHeader(BITMAPINFOHEADER *bmih)
{
printf("The content in the info header of the BMP file:\n");
printf("biBitCount: %ld\n",bmih->biBitCount);
printf("biClrImportant: %ld\n",bmih->biClrImportant);
printf("biClrUsed: %ld\n",bmih->biClrUsed);
printf("biCompression: %ld\n",bmih->biCompression);
printf("biHeight: %ld\n",bmih->biHeight);
printf("biPlanes: %ld\n",bmih->biPlanes);
printf("biSize: %ld\n",bmih->biSize);
printf("biSizeImage: %ld\n",bmih->biSizeImage);
printf("biWidth: %ld\n",bmih->biWidth);
printf("biXPelsPerMeter: %ld\n",bmih->biXPelsPerMeter);
printf("biYPelsPerMeter: %ld\n",bmih->biYPelsPerMeter);
}
LONG GetLineBytes(int imgWidth,int bitCount)
{
return (imgWidth*bitCount+31)/32*4;
}
void PrintbmpPixelData(BYTE *imgData,int width,int height,int bitCount)
{
int i;
int j;
int p;
DWORD dwLineBytes=GetLineBytes(width,bitCount);
if(bitCount==8)
{
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
p=*(imgData+dwLineBytes*(height-1-i)+j);
printf("%d,",p);
}
printf("\n");
}
}
else if(bitCount==24)
{
for(i=0;i<height;i++)
{
for(j=0;j<width*3;j++)
{
printf("(");
p=*(imgData+dwLineBytes*(height-1-i)+j);
printf("%d,",p);
j++;
p=*(imgData+dwLineBytes*(height-1-i)+j);
printf("%d,",p);
j++;
p=*(imgData+dwLineBytes*(height-1-i)+j);
printf("%d) ",p);
}
printf("\n");
}
}
else
{
printf("Only supported: 8 or 24 bits.\n");
}
}
int CheckbmpFilePath(char *filepath)
{
FILE *fp;
int len=strlen(filepath)/sizeof(char);
char ext[3];
if(filepath[0]!='\"')
{
strncpy(ext,&filepath[len-3],3);
if(!(ext[0]=='b' && ext[1]=='m' && ext[2]=='p'))
{
printf("Error: The file is not a BMP file.\n");
printf("Error: The extention of the filename must be 'bmp',not 'BMP'\n");
return -1;
}
fp=fopen(filepath,"r");
if(!fp)
{
printf("Error: The path is not correct.\n");
return -1;
}
fclose(fp);
}
else
{
printf("Error: The path must not include blank space.\n");
return -1;
}
return 0;
}
Mat bmpload(char *filepath)
{
int i,q;
int bitCount;
DWORD dwLineBytes;
Mat mat;
i=CheckbmpFilePath(filepath);
i=0;
mat.PATH=Li_malloc(100);
strcpy(mat.PATH,filepath);
i=ReadbmpFileHeader(filepath,&mat.bmf);
if(i!=-1)
{
printf("Read the file header successfully.\n");
}
else
{
printf("Read the file header failed.\n");
q=1;
}
i=ReadbmpInfoHeader(filepath,&mat.bmi);
if(i!=-1)
{
printf("Read the info header successfully.\n");
}
else
{
printf("Read the info header failed.\n");
q=1;
}
PrintbmpFileHeader(&mat.bmf);
PrintbmpInfoHeader(&mat.bmi);
mat.highth=mat.bmi.biHeight;
mat.width=mat.bmi.biWidth;
bitCount=mat.bmi.biBitCount;
mat.pictype=mat.bmi.biBitCount/8;
dwLineBytes=GetLineBytes(mat.width,bitCount);
mat.imgData=(BYTE*)Li_malloc(dwLineBytes*(mat.highth)*sizeof(BYTE));
if(!mat.imgData)
{
printf("Can not allocate memory for the image.\n");
q=1;
}
i=ReadbmpPixelData(filepath,mat.imgData);
if(i==-1)
{
printf("Read the pixel data failed.\n");
q=1;
}
else
{
printf("Read the pixel data successfully.\n");
}
return mat;
}
int bmpprocess(Mat* mat,int width,int highth,u32 color)
{
u32 offset;
u8 R=(u8)(color);
u8 G=(u8)(((WORD)(color)) >> 8);
u8 B=(u8)((color)>>16);
DWORD dwLineBytes=GetLineBytes(mat->width,24);
offset=dwLineBytes*(mat->highth-1-highth)+width*3;
*(mat->imgData+offset)=R;
*(mat->imgData+offset+1)=G;
*(mat->imgData+offset+2)=B;
return 0;
}
u8* bmpat(Mat* mat,int width,int highth)
{
u32 offset;
DWORD dwLineBytes=GetLineBytes(mat->width,24);
offset=dwLineBytes*(mat->highth-1-highth)+width*3;
return mat->imgData+offset;
}
int SaveAsbmpImage(char *filepath,Mat* mat)
{
FILE *fp;
RGBQUAD pal[256];
int i;
int height;
DWORD dwLineBytes;
Mat* dst;
height=mat->bmi.biHeight;
dwLineBytes=GetLineBytes(mat->bmi.biWidth,mat->bmi.biBitCount);
strcpy(mat->PATH,filepath);
fp=fopen(filepath,"wb");
if(!fp)
{
printf("Error: Can not open the file:%s\n",filepath);
}
for(i=0;i<256;i++)
{
pal[i].rgbReserved=0;
pal[i].rgbBlue=i;
pal[i].rgbGreen=i;
pal[i].rgbRed=i;
}
if(fwrite(&mat->bmf.bfType,sizeof(WORD),1,fp)!=1)
{
printf("Can not write bfType in the file header.\n");
fclose(fp);
}
if(fwrite(&mat->bmf.bfSize,sizeof(DWORD),1,fp)!=1)
{
printf("Can not write bfSize in the file header.\n");
fclose(fp);
}
if(fwrite(&mat->bmf.bfReserved1,sizeof(WORD),1,fp)!=1)
{
printf("Can not write bfReserved1 in the file header.\n");
fclose(fp);
}
if(fwrite(&mat->bmf.bfReserved2,sizeof(WORD),1,fp)!=1)
{
printf("Can not write bfReserved2 in the file header.\n");
fclose(fp);
}
if(fwrite(&mat->bmf.bfOffBits,sizeof(DWORD),1,fp)!=1)
{
printf("Can not write bfOffBits in the file header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biSize,sizeof(DWORD),1,fp)!=1)
{
printf("Can not write biSize in the info header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biWidth,sizeof(LONG),1,fp)!=1)
{
printf("Can not write biWidth in the info header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biHeight,sizeof(LONG),1,fp)!=1)
{
printf("Can not write biHeight in the info header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biPlanes,sizeof(WORD),1,fp)!=1)
{
printf("Can not write biPlanes in the info header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biBitCount,sizeof(WORD),1,fp)!=1)
{
printf("Can not write biBitCount in the info header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biCompression,sizeof(DWORD),1,fp)!=1)
{
printf("Can not write biCompression in the info header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biSizeImage,sizeof(DWORD),1,fp)!=1)
{
printf("Can not write biSizeImage in the info header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biXPelsPerMeter,sizeof(LONG),1,fp)!=1)
{
printf("Can not write biXPelsPerMeter in the info header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biYPelsPerMeter,sizeof(LONG),1,fp)!=1)
{
printf("Can not write biYPelsPerMeter in the info header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biClrUsed,sizeof(DWORD),1,fp)!=1)
{
printf("Can not write biClrUsed in the info header.\n");
fclose(fp);
}
if(fwrite(&mat->bmi.biClrImportant,sizeof(DWORD),1,fp)!=1)
{
printf("Can not write biClrImportant in the info header.\n");
fclose(fp);
}
if(mat->bmi.biBitCount==8)
{
if(fwrite(pal,sizeof(RGBQUAD),256,fp)!=256)
{
printf("Error: can not write the color palette.\n");
fclose(fp);
}
}
if(fwrite(mat->imgData,height*dwLineBytes,1,fp)!=1)
{
printf("Error: can not write the pixel data.\n");
fclose(fp);
}
fclose(fp);
printf("Save As the image successfully.\n");
return 0;
}
Mat bmpcopy(Mat mat)
{
Mat out;
out.bmf=mat.bmf;
out.bmi=mat.bmi;
out.highth=mat.highth;
out.width=mat.width;
out.pictype=mat.pictype;
out.PATH=Li_malloc(100);
strcpy(out.PATH,mat.PATH);
out.imgData=(BYTE*)Li_malloc(mat.highth*mat.width*3);
Li_memcpy(out.imgData,mat.imgData,mat.highth*mat.width*3);
return out;
}
void bmpdestory(Mat* mat)
{
free(mat->PATH);
free(mat->imgData);
}
#ifdef WINDOWS
void ShowbmpImage(Mat* mat)
{
char cmd[266];
strcpy(cmd,"start ");
strcat(cmd,mat->PATH);
printf("%s\n",cmd);
system(cmd);
}
#endif
#ifdef X86_LINUX
void ShowbmpImage(Mat* mat)
{
char cmd[266];
strcpy(cmd,"display ");
strcat(cmd,mat->PATH);
printf("%s\n",cmd);
system(cmd);
}
#endif
#ifdef ARM_LINUX
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void ARM_ShowbmpImage(Mat* mat,struct fb_var_screeninfo vinfo,struct fb_fix_screeninfo finfo,char *fbp)
{
int x,y;
u8* addr;
long int location = 0;
for(x=0;x<=mat->width;x++)
for(y=0;y<=mat->highth;y++)
{
addr=at(mat,x,y);
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
(y+vinfo.yoffset) * finfo.line_length;
*(fbp + location) = *(addr); /* blue */
*(fbp + location + 1) =*(addr+1);
*(fbp + location + 2) =*(addr+2); /* red */
*(fbp + location + 3) = 0x00;
}
}
#endif
Mat.c
/*************************************************
Copyright © Yueyang Co. Ltd. 2019-2029. All rights reserved.
File name: Mat.c
Author: Yueyang
Version: V1.0
Description: 提供Mat结构体
Others:
Log: 11.3 Yueyang
*************************************************/
#include "bmp.h"
#include "cv.h"
#include
#include
//创建一个空白的图片类
Mat MatCreate(u8* filepath,u16 width,u16 height,u8 type)
{
Mat mat;
mat.bmi.biBitCount=type*8;
mat.bmi.biSize=sizeof(BITMAPINFOHEADER);
mat.width=width;
mat.bmi.biWidth=width;
mat.highth=height;
mat.bmi.biHeight=height;
mat.bmi.biPlanes=1;
mat.bmi.biCompression=0;
mat.bmi.biSizeImage=height*width*type;
mat.bmi.biClrUsed=0;
mat.bmi.biClrImportant=0;
mat.bmi.biXPelsPerMeter=2874;
mat.bmi.biYPelsPerMeter=2874;
mat.bmf.bfType=((u16)'M'<<8)+'B';
mat.bmf.bfSize=786486;
mat.bmf.bfOffBits=54;
mat.imgData=Li_malloc(height*width*type);
mat.PATH=Li_malloc(100);
strcpy(mat.PATH,filepath);
return mat;
}
#ifdef WINDOWS
void Mat_Init()
{
show=ShowbmpImage;
at=bmpat;
process=bmpprocess;
load=bmpload;
save=SaveAsbmpImage;
destory=bmpdestory;
copy=bmpcopy;
create=MatCreate;
filewrite=fwrite;
fileread=fread;
fileopen=fopen;
fileseek=fseek;
fileclose=fclose;
Li_malloc=malloc;
Li_memcpy=memcpy;
Li_free=free;
}
#endif
#ifdef X86_LINUX
void Mat_Init()
{
show=ShowbmpImage;
at=bmpat;
process=bmpprocess;
load=bmpload;
save=SaveAsbmpImage;
copy=bmpcopy;
fileread=fread;
fileopen=fopen;
fileseek=fseek;
fileclose=fclose;
Li_malloc=malloc;
Li_memcpy=memcpy;
Li_free=free;
}
#endif
#ifdef ARM_LINUX
void Mat_Init()
{
show=ShowbmpImage;
at=bmpat;
process=bmpprocess;
load=bmpload;
save=SaveAsbmpImage;
copy=bmpcopy;
Li_malloc=malloc;
Li_memcpy=memcpy;
Li_free=free;
}
#endif
#ifdef ARM_NONE
#endif
其实重新造轮子这种事情看似没有意义,可是在这个过程中所能学到的东西绝不是会用opencv的几个函数所能相比的。
到目前为止笔者已经分别在WINDOWS,X86_LINUX,ARM_LINUX这三个平台上适配了这个图形系统。我会持续的在github中完善这个系统。
github地址:
LITECV github源码地址