20200705@学习C语言第13天
严正声明,这篇文章属于汇编整理型,整理部分属于原创。参考自北京理工大学MOOC公开课,以及百科、博文等资料,已经在相应处附上链接。
图像处理实例
学习C语言最重要的就是要会应用到实践中去,图像处理就是一个非常典型的应用。在别人还在折腾ps蒙板时,你一秒不到就可以实现图片的合成,并且只要稍稍修改代码就可以实现更多样的处理。这到底是怎样做到的呢???来和初学第13天的小学渣一起看看吧。
我们要实现的目的是把这两张图片合成:
图1(图片来源于MOOC北京理工大学公开课)
图2(图片来源于MOOC北京理工大学公开课)
要做这件事情,我们首先了解一下图像文件的特点:
图像文件结构(File structure of images)一般的图像文件结构主要都包含有文件头、文件体和文件尾等三部分。
文件头的主要内容包括产生或编辑该图像文件的软件的信息以及图像本身的参数。这些参数必须完整地描述图像数据的所有特征,因此是图像文件中的关键数据。
文件体主要包括图像数据以及颜色变换查找表或调色板数据。这部分是文件的主体,对文件容量的大小起决定作用。如果是真彩色图像,则无颜色变换查找表或调色板数据,对于256色的调色板,每种颜色值用24 bit表示,则调色板的数据长度为256×3(Byte)。
文件尾可包含一些用户信息。文件尾是可选项,有的文件格式不包括这部分内容。
代码很长,不着急,我们逐条分析:
代码1
// forclass1.cpp : Defines the entry point for the console application.
//
#include "stdio.h"
#include "malloc.h"
#include "memory.h"
#include "math.h"
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef long LONG;
#pragma pack (2)
#define PAI 3.1415926
typedef struct tagBITMAPFILEHEADER {
// bmfh
WORD bfType; //TYPE == BM
DWORD bfSize; //文件大小
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits; //图像像素起始位置
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{
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 {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
struct BMPStruct
{
BITMAPFILEHEADER fileHeader; //文件头
BITMAPINFOHEADER bmphead; //图像头
int lineByte; //图像的实际宽度
RGBQUAD *pColorTable; //颜色表指针
unsigned char *pBmpBuf; //读入图像数据的指针
};
BMPStruct myBMP[3];
bool readBmp(char *bmpName, BMPStruct* curBMP)
{
FILE *fp=fopen(bmpName,"rb");//二进制读方式打开指定的图像文件
if(fp==0) return 0;
//跳过位图文件头结构BITMAPFILEHEADER
fread(&curBMP->fileHeader, sizeof(BITMAPFILEHEADER), 1,fp);
//定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
fread(&curBMP->bmphead, sizeof(BITMAPINFOHEADER), 1,fp); //获取图像宽、高、每像素所占位数等信息
curBMP->lineByte=(curBMP->bmphead.biWidth * curBMP->bmphead.biBitCount/8+3)/4*4;//灰度图像有颜色表,且颜色表表项为256
if(curBMP->bmphead.biBitCount == 8)
{
//申请颜色表所需要的空间,读颜色表进内存
curBMP->pColorTable=new RGBQUAD[256];
fread(curBMP->pColorTable,sizeof(RGBQUAD),256,fp);
}
//申请位图数据所需要的空间,读位图数据进内存
//curBMP->pBmpBuf=new unsigned char[curBMP->lineByte * curBMP->bmphead.biHeight];
curBMP->pBmpBuf = (unsigned char *)malloc(curBMP->lineByte * curBMP->bmphead.biHeight);
fread(curBMP->pBmpBuf,1,curBMP->lineByte * curBMP->bmphead.biHeight,fp);
fclose(fp);//关闭文件
return 1;//读取文件成功
}
bool saveBmp(char *bmpName, BMPStruct* curBMP)
{
FILE *fp=fopen(bmpName,"wb");//二进制写方式打开指定的图像文件
if(fp==0) return 0;
//跳过位图文件头结构BITMAPFILEHEADER
fwrite(&curBMP->fileHeader, sizeof(BITMAPFILEHEADER), 1,fp);
//定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
fwrite(&curBMP->bmphead, sizeof(BITMAPINFOHEADER), 1,fp); //获取图像宽、高、每像素所占位数等信息
if(curBMP->bmphead.biBitCount == 8)
{
//申请颜色表所需要的空间,读颜色表进内存
curBMP->pColorTable=new RGBQUAD[256];
fwrite(curBMP->pColorTable,sizeof(RGBQUAD),256,fp);
}
//申请位图数据所需要的空间,读位图数据进内存
fwrite(curBMP->pBmpBuf,1,curBMP->lineByte * curBMP->bmphead.biHeight,fp);
fclose(fp);//关闭文件
return 1;//读取文件成功
}
int compose(BMPStruct mybmp[3])
{
if (myBMP[0].bmphead.biHeight < myBMP[1].bmphead.biHeight || myBMP[0].bmphead.biWidth < myBMP[1