2018-01-31 21:19:55 bjbz_cxy 阅读数 381
  • 6.小项目.图片解码播放器

    本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。

    7525 人正在学习 去看看 朱有鹏

这一系列的文章都将以BMP格式图像为主做处理,主要是为了让大家能对图像处理有一个良好的认知,后面会教大家写一个能支持BMP,JPG,JPEG,PNG等格式的图像处理库。

首先你要对图像处理以及图像理论有一个基本的认识,如果没有任何基本的图像知识的话我建议先看一下博主的这篇文章:Opencv学习笔记_计算机视觉是什么?Opencv的起源 虽然说这篇文章是介绍计算机视觉和opencv的但是其中包含了很多图像理论知识。

首先第一步要对BMP图像文件格式要有一个基本的认识:

BMP图像格式详解

一.简介
BMP(Bitmap-File)图形文件是Windows采用的图形文件格式,在Windows环境下运行的所有图象处理软件都支持BMP图象文件格式。Windows系统内部各图像绘制操作都是以BMP为基础的。Windows 3.0以前的BMP图文件格式与显示设备有关,因此把这种BMP图象文件格式称为设备相关位图DDB(device-dependent bitmap)文件格式。Windows 3.0以后的BMP图象文件与显示设备无关,因此把这种BMP图象文件格式称为设备无关位图DIB(device-independent bitmap)格式(注:Windows 3.0以后,在系统中仍然存在DDB位图,象BitBlt()这种函数就是基于DDB位图的,只不过如果你想将图像以BMP格式保存到磁盘文件中时,微软极力推荐你以DIB格式保存),目的是为了让Windows能够在任何类型的显示设备上显示所存储的图象。BMP位图文件默认的文件扩展名是BMP或者bmp(有时它也会以.DIB或.RLE作扩展名)。
 
二.BMP格式结构
BMP文件的数据按照从文件头开始的先后顺序分为四个部分:
◆ 位图文件头(bmp file header):  提供文件的格式、大小等信息
◆ 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
◆ 调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表
◆ 位图数据(bitmap data):图像数据区
 
BMP图片文件数据表如下:

 

数据段名称大小(byte)开始地址结束地址
位图文件头(bitmap-file header)
140000h000Dh
位图信息头(bitmap-information header)
40000Eh0035h
调色板(color table)
由biBitCount决定0036h未知
图片点阵数据(bitmap data)
由图片大小和颜色定未知未知

 

 
 
 
三.BMP文件头
BMP文件头结构体定义如下:
typedef struct tagBITMAPFILEHEADER
UINT16 bfType;        //2Bytes,必须为"BM",即0x424D 才是Windows位图文件
DWORD bfSize;         //4Bytes,整个BMP文件的大小
UINT16 bfReserved1;  //2Bytes,保留,为0
UINT16 bfReserved2;  //2Bytes,保留,为0
DWORD bfOffBits;     //4Bytes,文件起始位置到图像像素数据的字节偏移量
BITMAPFILEHEADER;
 
BMP文件头数据表如下:

 

变量名地址偏移大小作用说明
bfType0000h2Bytes
文件标识符,必须为"BM",即0x424D 才是Windows位图文件
‘BM’:Windows 3.1x, 95, NT,…  ‘BA’:OS/2 Bitmap Array  ‘CI’:OS/2 Color Icon   
‘CP’:OS/2 Color Pointer   ‘IC’:OS/2 Icon   
‘PT’:OS/2 Pointer
因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识“BM”就行
bfSize0002h4Bytes整个BMP文件的大小(以位B为单位)
bfReserved10006h2Bytes保留,必须设置为0
bfReserved20008h2Bytes保留,必须设置为0
bfOffBits000Ah4Bytes说明从文件头0000h开始到图像像素数据的字节偏移量(以字节Bytes为单位),以为位图的调色板长度根据位图格式不同而变化,可以用这个偏移量快速从文件中读取图像数据

 

 
 
四.BMP信息头
BMP信息头结构体定义如下:
typedef struct _tagBMP_INFOHEADER
{
DWORD  biSize;    //4Bytes,INFOHEADER结构体大小,存在其他版本I NFOHEADER,用作区分
LONG   biWidth;    //4Bytes,图像宽度(以像素为单位)
LONG   biHeight;    //4Bytes,图像高度,+:图像存储顺序为Bottom2Top,-:Top2Bottom
WORD   biPlanes;    //2Bytes,图像数据平面,BMP存储RGB数据,因此总为1
WORD   biBitCount;         //2Bytes,图像像素位数
DWORD  biCompression;     //4Bytes,0:不压缩,1:RLE8,2:RLE4
DWORD  biSizeImage;       //4Bytes,4字节对齐的图像数据大小
LONG   biXPelsPerMeter;   //4 Bytes,用象素/米表示的水平分辨率
LONG   biYPelsPerMeter;   //4 Bytes,用象素/米表示的垂直分辨率
DWORD  biClrUsed;          //4 Bytes,实际使用的调色板索引数,0:使用所有的调色板索引
DWORD biClrImportant;     //4 Bytes,重要的调色板索引数,0:所有的调色板索引都重要
}BMP_INFOHEADER;
 
BMP信息头数据表如下:

 

变量名
地址偏移
大小
作用说明
biSize
000Eh
4Bytes
BNP信息头即BMP_INFOHEADER结构体所需要的字节数(以字节为单位)
biWidth
0012h
4Bytes
说明图像的宽度(以像素为单位)
biHeight
0016h
4Bytes
说明图像的高度(以像素为单位)。这个值还有一个用处,指明图像是正向的位图还是倒向的位图,该值是正数说明图像是倒向的即图像存储是由下到上;该值是负数说明图像是倒向的即图像存储是由上到下。大多数BMP位图是倒向的位图,所以此值是正值。
biPlanes
001Ah
2Bytes
为目标设备说明位面数,其值总设置为1
biBitCount
001Ch
2Bytes
说明一个像素点占几位(以比特位/像素位单位),其值可为1,4,8,16,24或32
biCompression
001Eh
4Bytes
说明图像数据的压缩类型,取值范围为:
0         BI_RGB 不压缩(最常用)
1         BI_RLE8 8比特游程编码(BLE),只用于8位位图
2         BI_RLE4 4比特游程编码(BLE),只用于4位位图
3         BI_BITFIELDS比特域(BLE),只用于16/32位位图
4          
biSizeImage
0022h
4Bytes
说明图像的大小,以字节为单位。当用BI_RGB格式时,总设置为0
biXPelsPerMeter
0026h
4Bytes
说明水平分辨率,用像素/米表示,有符号整数
biYPelsPerMeter
002Ah
4Bytes
说明垂直分辨率,用像素/米表示,有符号整数
biClrUsed002Eh4Bytes说明位图实际使用的调色板索引数,0:使用所有的调色板索引
biClrImportant0032h4Bytes说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要。

 

 
五.BMP调色板
BMP调色板结构体定义如下:
typedef struct _tagRGBQUAD
{
BYTE  rgbBlue;       //指定蓝色强度
BYTE  rgbGreen;      //指定绿色强度
BYTE  rgbRed;        //指定红色强度
 BYTE  rgbReserved;  //保留,设置为0
RGBQUAD;
 
1,4,8位图像才会使用调色板数据,16,24,32位图像不需要调色板数据,即调色板最多只需要256项(索引0 - 255)。
颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。即首先4字节表示颜色号1的颜色,接下来表示颜色号2的颜色,依此类推。
颜色表中RGBQUAD结构数据的个数有biBitCount来确定,当biBitCount=1,4,8时,分别有2,16,256个表项。
当biBitCount=1时,为2色图像,BMP位图中有2个数据结构RGBQUAD,一个调色板占用4字节数据,所以2色图像的调色板长度为2*4为8字节。
当biBitCount=4时,为16色图像,BMP位图中有16个数据结构RGBQUAD,一个调色板占用4字节数据,所以16像的调色板长度为16*4为64字节。
当biBitCount=8时,为256色图像,BMP位图中有256个数据结构RGBQUAD,一个调色板占用4字节数据,所以256色图像的调色板长度为256*4为1024字节。
当biBitCount=16,24或32时,没有颜色表。
 
五.BMP图像数据区
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:
当biBitCount=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=24时,1个像素占3个字节;
Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充,
一个扫描行所占的字节数计算方法:
DataSizePerLine= (biWidth* biBitCount+31)/8;
// 一个扫描行所占的字节数
DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数
位图数据的大小(不压缩情况下):
DataSize= DataSizePerLine* biHeight;
 
颜色表接下来位为位图文件的图像数据区,在此部分记录着每点像素对应的颜色号,其记录方式也随颜色模式而定,既2色图像每点占1位(8位为1字节);16色图像每点占4位(半字节);256色图像每点占8位(1字节);真彩色图像每点占24位(3字节)。所以,整个数据区的大小也会随之变化。究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。

通过上面的描述,我们基本上对BMP图像文件格式有一个基本的认识了,那么我们可以通过c语言的结构体的内存对齐机制来依次读取这些头文件信息,并转化成可识别的十进制信息!

首先第一步,对c语言的基本类型定义别名,方便维护。

//8bit
typedef char UINT_8;
//16bit
typedef char UINT_16[2];
//22bit
typedef char UINT_22[3];
//256bit
typedef char UINT_256[256];
//32bit
typedef int  UINT_32;
//data
typedef char* DATA;
//64 fbit
typedef double FUINT_64;
//16bit int
typedef short SUINT_16;

然后根据头信息在文件中的字节偏移地址来定义结构体:

变量名地址偏移大小作用说明
bfType0000h2Bytes
文件标识符,必须为"BM",即0x424D 才是Windows位图文件
‘BM’:Windows 3.1x, 95, NT,…  ‘BA’:OS/2 Bitmap Array  ‘CI’:OS/2 Color Icon   
‘CP’:OS/2 Color Pointer   ‘IC’:OS/2 Icon   
‘PT’:OS/2 Pointer
因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识“BM”就行
bfSize0002h4Bytes整个BMP文件的大小(以位B为单位)
bfReserved10006h2Bytes保留,必须设置为0
bfReserved20008h2Bytes保留,必须设置为0
bfOffBits000Ah4Bytes说明从文件头0000h开始到图像像素数据的字节偏移量(以字节Bytes为单位),以为位图的调色板长度根据位图格式不同而变化,可以用这个偏移量快速从文件中读取图像数据



变量名
地址偏移
大小
作用说明
biSize
000Eh
4Bytes
BNP信息头即BMP_INFOHEADER结构体所需要的字节数(以字节为单位)
biWidth
0012h
4Bytes
说明图像的宽度(以像素为单位)
biHeight
0016h
4Bytes
说明图像的高度(以像素为单位)。这个值还有一个用处,指明图像是正向的位图还是倒向的位图,该值是正数说明图像是倒向的即图像存储是由下到上;该值是负数说明图像是倒向的即图像存储是由上到下。大多数BMP位图是倒向的位图,所以此值是正值。
biPlanes
001Ah
2Bytes
为目标设备说明位面数,其值总设置为1
biBitCount
001Ch
2Bytes
说明一个像素点占几位(以比特位/像素位单位),其值可为1,4,8,16,24或32
biCompression
001Eh
4Bytes
说明图像数据的压缩类型,取值范围为:
0         BI_RGB 不压缩(最常用)
1         BI_RLE8 8比特游程编码(BLE),只用于8位位图
2         BI_RLE4 4比特游程编码(BLE),只用于4位位图
3         BI_BITFIELDS比特域(BLE),只用于16/32位位图
4          
biSizeImage
0022h
4Bytes
说明图像的大小,以字节为单位。当用BI_RGB格式时,总设置为0
biXPelsPerMeter
0026h
4Bytes
说明水平分辨率,用像素/米表示,有符号整数
biYPelsPerMeter
002Ah
4Bytes
说明垂直分辨率,用像素/米表示,有符号整数
biClrUsed002Eh4Bytes说明位图实际使用的调色板索引数,0:使用所有的调色板索引
biClrImportant0032h4Bytes说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要。

注意这里一定要使用#pragma pack(1)告诉编译器结构体按1字节对齐(详细:详解C语言内存对齐)否则在读入文件流数据时会出现数据混淆的原因
//结构体
//图像结构体,防止结构体对齐否则读取文件流时出错,所以用pragma命令强制对齐
#pragma pack(1)  
typedef struct image_struct{
	UINT_16   image_pil;                //文件标识符  
	UINT_32   image_Size;               //文件大小  
	UINT_16   image_Reserved1;          //无需过问  
	UINT_16   image_Reserved2;          //无需过问  
	UINT_32   image_Offbits;            //头文件到图像数据偏移量  
	UINT_32   image_Stsize;             //结构体所需大小  
	UINT_32   image_Width;              //图像宽度  
	UINT_32   image_Height;             //图像高度  
	UINT_16   image_Planes;             //目标设备位面数  
	SUINT_16  image_Bitcount;           //像素点占用多少bit位  
	UINT_32   image_Compression;        //图像压缩类型  
	UINT_32   image_Sizeimage;          //图像的大小  
	UINT_32   image_Xpelspermeter;      //水平分辨率  
	UINT_32   image_Ypelspermeter;      //垂直分辨率  
	UINT_32   image_ClrUsed;            //调色板索引数  
	UINT_32   image_Clrlmportant;       //图像显示重要颜色索引数目  
	DATA      image_Data;               //图像数据 
	UINT_32   image_Data_Size;			//图像数据大小
}image; 
#pragma pack()  
下面开始写我们的第一个函数:image_load,加载图像文件
注意如果不使用c语言的内存对齐方式读取数据的话需要考虑大小端的问题,我们直接使用结构体来读取这样就不用考虑大小端的问题了,因为内存中的存储大小端与文件中是对应的!我们只需要直接读取到内存当中就行了!
//函数
//加载图像 
int image_load(struct image_struct** im, char *path){
	FILE *image_path_fp;
	image_path_fp = fopen(path, "rb");
	if (image_path_fp == NULL){
		return -1;
	}
	//取文件大小
	fseek(image_path_fp, 0, SEEK_END); //定位到文件末 
	int nFileLen = ftell(image_path_fp); //文件长度
	fseek(image_path_fp, 0, SEEK_SET);	//恢复到文件头,防止从文件尾读取数据
	//读取头信息
	if (fread((*im), (sizeof(struct image_struct) - ((sizeof(DATA/*image_Data*/)+(sizeof(UINT_32)/*image_Data_Size*/)))/*暂不读取数据,无法从头文件中获取数据偏移量,防止数据混乱*/), 1, image_path_fp) == 0){
		return -2;
	}
	//给data变量分配内存
	(*im)->image_Data = (DATA)malloc(nFileLen-(*im)->image_Offbits/*完整的数据大小*/);
	//判断是否分配成功
	if ((*im)->image_Data == NULL){	//如果没有可用堆内存则malloc返回NULL
		return -3;
	}
	//读取数据
	//读取前将文件指针挪移到文件头信息后,找到正确的数据存储区
	fseek(image_path_fp, 0, SEEK_SET);	//恢复到文件头,因为已经fread一次了,所以数据文件指针发生变更
	fseek(image_path_fp, (*im)->image_Offbits, SEEK_CUR);	//忽略头数据
	if (fread((*im)->image_Data, (nFileLen - (*im)->image_Offbits/*file - off = 实际大小*/), 1, image_path_fp) == 0){
		return -4;
	}
	//保存文件大小,方便读写操作
	(*im)->image_Data_Size = (nFileLen - (*im)->image_Offbits/*file - off = 实际大小*/);
	//文件指针释放,防止占用文件内核的临界资源
	fclose(image_path_fp);
	image_path_fp == NULL;
	return 0;
}
图像加载函数写完了,我们可能在使用结构体时会定义指针,所以为了方便我们在写一个用于分配内存的函数
//给图像数据分配内存
int image_malloc(struct image_struct** im){
	*im = (struct image_struct*)malloc(sizeof(struct image_struct));
	if (*im == NULL){
		return -1;
	}
	return 0;
}
还需要一个图像保存函数:
//保存图像数据到文件
int image_save_file(struct image_struct** im, char *path){
	FILE* file_fp = fopen(path, "wb+");	//以二进制可读写方式打开
	if (file_fp == NULL){	//判断文件指针是否为空
		return -1;
	}
	//写入头信息
	fwrite((*im), (*im)->image_Offbits/*直接写入头文件到数据的偏移量大小即可*/, 1, file_fp);
	//写入文件数据
	fwrite((*im)->image_Data, (*im)->image_Data_Size, 1, file_fp);
	return 0;

}
基本函数编写完成了,那么来做一个测试吧:
int main(){
	image *imga;
	image_malloc(&imga);
	image_load(&imga, "test.bmp");
	printf("图像宽度:%d\n", imga->image_Width); 
	printf("图像高度:%d\n", imga->image_Height);
	printf("图像文件占用字节:%d\n", imga->image_Size);
	printf("图像每个像素占用bit位:%d\n", imga->image_Bitcount);
	getchar();
}
完整代码:
/*Robust图像处理库
*版本:v1.0
*作者:周志豪
*4.17 19:09
*/
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
//类型定义
//8bit  
typedef char UINT_8;
//16bit  
typedef char UINT_16[2];
//22bit  
typedef char UINT_22[3];
//256bit  
typedef char UINT_256[256];
//32bit  
typedef int  UINT_32;
//data  
typedef char* DATA;
//64 fbit  
typedef double FUINT_64;
//16bit int  
typedef short SUINT_16;
//结构体
//图像结构体,防止结构体对齐否则读取文件流时出错,所以用pragma命令强制对齐
#pragma pack(1)  
typedef struct image_struct{
	UINT_16   image_pil;                //文件标识符  
	UINT_32   image_Size;               //文件大小  
	UINT_16   image_Reserved1;          //无需过问  
	UINT_16   image_Reserved2;          //无需过问  
	UINT_32   image_Offbits;            //头文件到图像数据偏移量  
	UINT_32   image_Stsize;             //结构体所需大小  
	UINT_32   image_Width;              //图像宽度  
	UINT_32   image_Height;             //图像高度  
	UINT_16   image_Planes;             //目标设备位面数  
	SUINT_16  image_Bitcount;           //像素点占用多少bit位  
	UINT_32   image_Compression;        //图像压缩类型  
	UINT_32   image_Sizeimage;          //图像的大小  
	UINT_32   image_Xpelspermeter;      //水平分辨率  
	UINT_32   image_Ypelspermeter;      //垂直分辨率  
	UINT_32   image_ClrUsed;            //调色板索引数  
	UINT_32   image_Clrlmportant;       //图像显示重要颜色索引数目  
	DATA      image_Data;               //图像数据 
	UINT_32   image_Data_Size;			//图像数据大小
}image; 
#pragma pack()  
//函数
//加载图像 
int image_load(struct image_struct** im, char *path){
	FILE *image_path_fp;
	image_path_fp = fopen(path, "rb");
	if (image_path_fp == NULL){
		return -1;
	}
	//取文件大小
	fseek(image_path_fp, 0, SEEK_END); //定位到文件末 
	int nFileLen = ftell(image_path_fp); //文件长度
	fseek(image_path_fp, 0, SEEK_SET);	//恢复到文件头,防止从文件尾读取数据
	//读取头信息
	if (fread((*im), (sizeof(struct image_struct) - ((sizeof(DATA/*image_Data*/)+(sizeof(UINT_32)/*image_Data_Size*/)))/*暂不读取数据,无法从头文件中获取数据偏移量,防止数据混乱*/), 1, image_path_fp) == 0){
		return -2;
	}
	//给data变量分配内存
	(*im)->image_Data = (DATA)malloc(nFileLen-(*im)->image_Offbits/*完整的数据大小*/);
	//判断是否分配成功
	if ((*im)->image_Data == NULL){	//如果没有可用堆内存则malloc返回NULL
		return -3;
	}
	//读取数据
	//读取前将文件指针挪移到文件头信息后,找到正确的数据存储区
	fseek(image_path_fp, 0, SEEK_SET);	//恢复到文件头,因为已经fread一次了,所以数据文件指针发生变更
	fseek(image_path_fp, (*im)->image_Offbits, SEEK_CUR);	//忽略头数据
	if (fread((*im)->image_Data, (nFileLen - (*im)->image_Offbits/*file - off = 实际大小*/), 1, image_path_fp) == 0){
		return -4;
	}
	//保存文件大小,方便读写操作
	(*im)->image_Data_Size = (nFileLen - (*im)->image_Offbits/*file - off = 实际大小*/);
	//文件指针释放,防止占用文件内核的临界资源
	fclose(image_path_fp);
	image_path_fp == NULL;
	return 0;
}
//给图像数据分配内存
int image_malloc(struct image_struct** im){
	*im = (struct image_struct*)malloc(sizeof(struct image_struct));
	if (*im == NULL){
		return -1;
	}
	return 0;
}
//将图像转换成反向图_该方法只能用于真彩图
int image_reverse_rgb(struct image_struct** im){
	if ((*im) == NULL){	//判断传递进来的图像指针是否为空
		return -1;
	}
	//转换成反向图很简单只需要将每个图像里的像素点转换成负的就可以了,注意在一个24位的图像文件中一个字节对应一个颜色值三个字节则为一个完整的像素点,所以我们一个一个像素点的转换就可以了
	//算法公式为:S=-R-G-B
	for (int i = 0; i < (*im)->image_Data_Size; ++i){
			if ((*im)->image_Data[i] == (int)0){	//如果等于0则不处理
				continue;	//开始下一次循环
			}//i*(*im)->image_Width + j
			(*im)->image_Data[i] = -(*im)->image_Data[i];	//调用宏函数转换
	}
	return 0;
}
//保存图像数据到文件
int image_save_file(struct image_struct** im, char *path){
	FILE* file_fp = fopen(path, "wb+");	//以二进制可读写方式打开
	if (file_fp == NULL){	//判断文件指针是否为空
		return -1;
	}
	//写入头信息
	fwrite((*im), (*im)->image_Offbits/*直接写入头文件到数据的偏移量大小即可*/, 1, file_fp);
	//写入文件数据
	fwrite((*im)->image_Data, (*im)->image_Data_Size, 1, file_fp);
	return 0;

}
int main(){
	image *imga;
	image_malloc(&imga);
	image_load(&imga, "test.bmp");
	printf("图像宽度:%d\n", imga->image_Width); 
	printf("图像高度:%d\n", imga->image_Height);
	printf("图像文件占用字节:%d\n", imga->image_Size);
	printf("图像每个像素占用bit位:%d\n", imga->image_Bitcount);
	getchar();
}

运行结果:

本篇先让大家对BMP格式有一个基本的认知,和读取图像头信息中较为重要的信息
2015-04-18 09:33:32 lihaoweicsdn 阅读数 1446
  • 6.小项目.图片解码播放器

    本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。

    7525 人正在学习 去看看 朱有鹏

最近写了个bmp图像读取,将图片转化为单一颜色的小程序,直接上代码,仅供参考。
1.先上测试函数(基本一看就知道流程)

/**********************************************************************************************
Author: Lihaowei
Date: 2015-04-2
version:0.0
Discriptions:
        1.This file is used to test "bitMapfunction.c"  (load a bitmap,convert bitmap to single-color
          image (R||G||B),and write a new bitmap).

************************************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "../include/bitMap.h"


void main()
{

    char filename_in[20] = "input.bmp";
    char filename_out1[20] = "output_r.bmp";
    char filename_out2[20] = "output_g.bmp";
    char filename_out3[20] = "output_b.bmp";

    BITMAPFILE* bitmap1,*bitmap2,*bitmap3;
    bitmap1 = loadBitmap(filename_in);
    bitmap2 = loadBitmap(filename_in);
    bitmap3 = loadBitmap(filename_in);

    toSingleColor(bitmap1,'R');
    toSingleColor(bitmap2,'G');
    toSingleColor(bitmap3,'B');
    writeBmp(filename_out1,bitmap1);
    writeBmp(filename_out2,bitmap2);
    writeBmp(filename_out3,bitmap3);
    free(bitmap1);
    free(bitmap2);
    free(bitmap3);
}


2.头文件

/***********************************bitMap.h***********************************************************
Author: Lihaowei
Date: 2015-04-2
version:0.0
Discriptions:

************************************************************************************************/
typedef unsigned char  u8;
typedef unsigned short u16;
typedef unsigned int   u32;
#pragma pack(1)
/*bitmap file header,size:14 bytes*/
typedef struct tagBITMAPFILEHEADER
{   
    u16 bfType; 
    u32 bfSize;
    u16 bfReserved1;
    u16 bfReserved2;
    u32 bfOffBits;
}BITMAPFILEHEADER;
/*bitmap information header,size:40 bytes*/
typedef struct tagBITMAPINFOHEADER
{
    u32 biSize;
    u32 biWidth;
    u32 biHeight;
    u16 biPlanes;
    u16 biBitCount;
    u32 biCompression;
    u32 biSizeImage;
    u32 biXPelsPerMeter;
    u32 biYPelsPerMeter;
    u32 biClrUsed;
    u32 biClrImportant;
}BITMAPINFOHEADER;
/*color palette,size:4 bytes*/
typedef struct tagRGBQUAD
{
    u8 rgbBlue;
    u8 rgbGreen;
    u8 rgbRed;
    u8 rgbReserved;
}RGBQUAD;

typedef struct tagBITMAP
{
    BITMAPFILEHEADER bfHeader;
    BITMAPINFOHEADER biHeader;
    RGBQUAD bmpColors[1];
    u8* imageData;
    u8* dataR;
    u8* dataG;
    u8* dataB;

}BITMAPFILE;

BITMAPFILE * loadBitmap(char *path);
void writeBmp(char *path ,BITMAPFILE *bitmap);
void toSingleColor(BITMAPFILE *bitmap,char color);//color='R'||'G'||'B'

2.功能源文件

/************************************bitMapfunction.c**********************************************************
Author: Lihaowei
Date: 2015-04-2
version:0.0
Discriptions:
        1.This file offer some functions to load a bitmap,convert bitmap to single-color
          image (R||G||B),and to write a new bitmap.
        2.To use these function , please include "bitMap.h" in your program 
************************************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include "../include/bitMap.h"



/*fuction:void toSingleColor(BITMAPFILE *bitmap,char color); */
/*convert to single-color image*/

/***********************************************************************************************/
void toSingleColor(BITMAPFILE *bitmap,char color)
{
    int i,j;
    int colorid=0;
    switch(color)
    {
        case 'R':   colorid = 0;
                break;
        case 'G':   colorid = 2;
                break;
        case 'B':   colorid = 1;
                break;
        default:    colorid = 1;
    }

    for(i =0; i < bitmap->biHeader.biHeight; i++)
    {

        for(j = 0; j < bitmap->biHeader.biWidth; j++)
        {

                *(bitmap->imageData+3*((bitmap->biHeader.biWidth)*i+j)+colorid) = 0;
                *(bitmap->imageData+3*((bitmap->biHeader.biWidth)*i+j)+(colorid+1)%3) = 0;
                /*if(*(bitmap->imageData+3*((bitmap->biHeader.biWidth)*i+j)+(colorid+2)%3) > 50)
                    (bitmap->imageData+3*((bitmap->biHeader.biWidth)*i+j)+(colorid+2)%3) = 255;
                  else
                    (bitmap->imageData+3*((bitmap->biHeader.biWidth)*i+j)+(colorid+2)%3) = 0;   */

        }
    }
}


/***********************************************************************************************/


/*fuction:BITMAPFILE * loadBitmap(char *path); */
/*load a bitmap*/
/***********************************************************************************************/
BITMAPFILE * loadBitmap(char *path)
{
    int i,j;
    BITMAPFILE * bitmap={0};
    FILE *bmfp=fopen(path,"r+");
    if( !bmfp )
    {
        printf("open %s error!\n",path);
        exit(0);
    }
    bitmap = (BITMAPFILE*)malloc(sizeof(BITMAPFILE));


    /********************************test the file to judge whether it is a bitmap**************************/
    unsigned short bfType = 0;

    fseek(bmfp, 0L, SEEK_SET);
    fread(&bfType, sizeof(char), 2, bmfp);
    if (0x4D42!= bfType)
    {
            printf("This is not a bmp file!!!\n");
            exit(1);
    }
    /*******************************************************************************************************/


    /*********************************read the Header of the bitmap*****************************************/
    /*read file information header*/

    fseek(bmfp, 0L, SEEK_SET);
    fread(&(bitmap->bfHeader), sizeof(unsigned char), sizeof(BITMAPFILEHEADER), bmfp);


    /*read bmp information header*/
    fread(&(bitmap->biHeader), 1 ,sizeof(BITMAPINFOHEADER), bmfp);


    /*read RGBQUAD information*/

    /******************************************************************************************************/

    /********************************read image data*******************************************************/
    /*read image data*/

    if(bitmap->biHeader.biBitCount == 24)
    {

        unsigned int width = bitmap->biHeader.biWidth;
        unsigned int height = bitmap->biHeader.biHeight;

        bitmap->imageData = (unsigned char*)malloc(sizeof(unsigned char)*width*3*height);
        bitmap->dataR     = (unsigned char*)malloc(sizeof(unsigned char)*width * height);
        bitmap->dataG     = (unsigned char*)malloc(sizeof(unsigned char)*width * height);
        bitmap->dataB     = (unsigned char*)malloc(sizeof(unsigned char)*width * height);
        fseek(bmfp,bitmap->bfHeader.bfOffBits,SEEK_SET);
        /*read imageData */
        fread(bitmap->imageData, sizeof(unsigned char), width*3*height, bmfp);
        for(i =0; i < bitmap->biHeader.biHeight; i++)
        {

            for(j = 0; j <bitmap->biHeader.biWidth; j++)
            {

                /*seperate R G B data from imageData */
                *(bitmap->dataB+(bitmap->biHeader.biHeight-i-1)*(bitmap->biHeader.biWidth)+j) =
                         *(bitmap->imageData+3*((bitmap->biHeader.biWidth)*i+j));

                *(bitmap->dataG+(bitmap->biHeader.biHeight-i-1)*(bitmap->biHeader.biWidth)+j) =
                         *(bitmap->imageData+3*((bitmap->biHeader.biWidth)*i+j)+1);

                *(bitmap->dataR+(bitmap->biHeader.biHeight-i-1)*(bitmap->biHeader.biWidth)+j) =
                         *(bitmap->imageData+3*((bitmap->biHeader.biWidth)*i+j)+2);


            }
        }
    }
    else
    {
        printf("Only handle 24bit per pixel bitMap\n");
        exit(0);
    }

    /******************************************************************************************************/

    /****************************write to dat file*********************************************************/
    /*write to dat file*/

    FILE* fpDataBmp1,*fpDataBmp2,*fpDataBmp3;
    /* New a file to save the data matrix */
    if((fpDataBmp1 = fopen("data_R.dat","w+")) == NULL)
    {
            printf("Failed to construct file bmpData_R.dat!");
            exit(1);
    }
    if((fpDataBmp2 = fopen("data_G.dat","w+")) == NULL)
    {
            printf("Failed to construct file bmpData_R.dat!");
            exit(1);
    }
    if((fpDataBmp3 = fopen("data_B.dat","w+")) == NULL)
    {
            printf("Failed to construct file bmpData_R.dat!");
            exit(1);
    }

    for(i =0; i < bitmap->biHeader.biHeight; i++)
    {
        fprintf(fpDataBmp1,"line %d :\n",i);
        fprintf(fpDataBmp2,"line %d :\n",i);
        fprintf(fpDataBmp3,"line %d :\n",i);
        for(j = 0; j < bitmap->biHeader.biWidth; j++)
        {

            fprintf(fpDataBmp1, "%-3d ", *(bitmap->dataR+(bitmap->biHeader.biHeight-i-1)*(bitmap->biHeader.biWidth)+j));
            fprintf(fpDataBmp2, "%-3d ", *(bitmap->dataG+(bitmap->biHeader.biHeight-i-1)*(bitmap->biHeader.biWidth)+j));
            fprintf(fpDataBmp3, "%-3d ", *(bitmap->dataB+(bitmap->biHeader.biHeight-i-1)*(bitmap->biHeader.biWidth)+j));

            if ((j+1)%32 == 0)
            {
                fprintf(fpDataBmp1, "\n");
                fprintf(fpDataBmp2, "\n");
                fprintf(fpDataBmp3, "\n");
            }
        }
    }
    fclose(fpDataBmp1);
    fclose(fpDataBmp2);
    fclose(fpDataBmp3);

    fclose(bmfp);
    return bitmap;
}
/***********************************************************************************************/



/*fuction:void writeBmp(char *path ,BITMAPFILE *bitmap); */


/*write a new bitmap*/
/***********************************************************************************************/
void writeBmp(char *path ,BITMAPFILE *bitmap)
{
    unsigned int width = bitmap->biHeader.biWidth;
    unsigned int height = bitmap->biHeader.biHeight;
    FILE *bmfp=fopen(path,"w+");
    if(bmfp == NULL)  
        {  
            printf("fopen %s failed !\n",path);  
            exit(1);  
        }  
    /***************************write image header****************************************/
    /*write file information header*/
    fseek(bmfp, 0L, SEEK_SET);
    fwrite(&(bitmap->bfHeader),sizeof(unsigned char), sizeof(BITMAPFILEHEADER), bmfp);


    /*write bmp information header*/
    fwrite(&(bitmap->biHeader), 1 ,sizeof(BITMAPINFOHEADER), bmfp);

    /*write RGBQUAD information*/
    /**************************************************************************************/

    /*write data*/
    fseek(bmfp, bitmap->bfHeader.bfOffBits, SEEK_SET);
    fwrite(bitmap->imageData,sizeof(unsigned char),width*3*height,bmfp);

}
/***********************************************************************************************/

一些原理性的细节之后再写博客补充吧。而且这个程序在数据对齐方面没注意,只支持24位真彩色图的处理。

2018-08-28 08:33:54 Eastmount 阅读数 9047
  • 6.小项目.图片解码播放器

    本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。

    7525 人正在学习 去看看 朱有鹏

该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子、图像增强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。希望文章对您有所帮助,如果有不足之处,还请海涵~

该系列在github所有源代码:https://github.com/eastmountyxz/ImageProcessing-Python
PS:请求帮忙点个Star,哈哈,第一次使用Github,以后会分享更多代码,一起加油。

同时推荐作者的C++图像系列知识:
[数字图像处理] 一.MFC详解显示BMP格式图片
[数字图像处理] 二.MFC单文档分割窗口显示图片
[数字图像处理] 三.MFC实现图像灰度、采样和量化功能详解
[数字图像处理] 四.MFC对话框绘制灰度直方图
[数字图像处理] 五.MFC图像点运算之灰度线性变化、灰度非线性变化、阈值化和均衡化处理详解
[数字图像处理] 六.MFC空间几何变换之图像平移、镜像、旋转、缩放详解
[数字图像处理] 七.MFC图像增强之图像普通平滑、高斯平滑、Laplacian、Sobel、Prewitt锐化详解

前文参考:
[Python图像处理] 一.图像处理基础知识及OpenCV入门函数

本篇文章主要讲解 OpenCV+Numpy 图像处理基础知识,包括读取像素和修改像素。知识点如下:
1.传统读取像素方法
2.传统修改像素方法
3.Numpy读取像素方法
4.Numpy修改像素方法

PS: 文章也学习了网易云高登教育的知识,推荐大家学习。

PSS:2019年1~2月作者参加了CSDN2018年博客评选,希望您能投出宝贵的一票。我是59号,Eastmount,杨秀璋。投票地址:https://bss.csdn.net/m/topic/blog_star2018/index

五年来写了314篇博客,12个专栏,是真的热爱分享,热爱CSDN这个平台,也想帮助更多的人,专栏包括Python、数据挖掘、网络爬虫、图像处理、C#、Android等。现在也当了两年老师,更是觉得有义务教好每一个学生,让贵州学子好好写点代码,学点技术,"师者,传到授业解惑也",提前祝大家新年快乐。2019我们携手共进,为爱而生。

一.传统读取像素方法

1.灰度图像,返回灰度值。
返回值=图像(位置参数),例:p = img[88,142] print§

# -*- coding:utf-8 -*-
import cv2

#读取图片
img = cv2.imread("picture.bmp", cv2.IMREAD_UNCHANGED)

#灰度图像
p = img[88, 142]
print(p)

#显示图像
cv2.imshow("Demo", img)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

#写入图像
cv2.imwrite("testyxz.jpg", img)

输出结果如下图所示:[131 131 131],由于该图是24位BMP,B=G=R输出三个相同的结果,有的图像仅有一个像素点则输出一个值。

2.BGR图像,返回值为B、G、R的值。
例:
b = img[78, 125, 0] print(b)
g = img[78, 125, 1] print(g)
r = img[78,125, 2] print®

# -*- coding:utf-8 -*-
import cv2

#读取图片
img = cv2.imread("test.jpg", cv2.IMREAD_UNCHANGED)

#BGR图像
b = img[78, 125, 0]
print(b)
g = img[78, 125, 1]
print(g)
r = img[78, 125, 2]
print(r)

#方法二
bgr = img[78, 125]
print(bgr)

#显示图像
cv2.imshow("Demo", img)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

#写入图像
cv2.imwrite("testyxz.jpg", img)

输出像素和图像如下所示:
155
104
61
[155 104 61]



二.传统修改像素方法

1.修改单个像素值
BGR图像可以通过位置参数直接访问像素值并进行修改,输出结果如下所示:

# -*- coding:utf-8 -*-
import cv2

#读取图片
img = cv2.imread("test.jpg", cv2.IMREAD_UNCHANGED)

#BGR图像
print(img[78, 125, 0])
print(img[78, 125, 1])
print(img[78, 125, 2])

#修改像素
img[78, 125, 0] = 255
img[78, 125, 1] = 255
img[78, 125, 2] =255

print(img[78, 125])
img[78, 125] = [10, 10, 10]
print(img[78, 125, 0])
print(img[78, 125, 1])
print(img[78, 125, 2])


#方法二
print(img[78, 125])
img[78, 125] = [10, 10, 10]
print(img[78, 125])

输出结果如下所示,通过两种方法分别将B、G、R像素值修改为255和0。
155
104
61
255
255
255
[255 255 255]
[10 10 10]


2.修改区域像素
通过访问图像数组的位置区域实现区域像素修改,比如 [100:150,400:500] 是访问第100到150行,400到500列的区域,再对该区域像素进行修改。代码如下所示:

# -*- coding:utf-8 -*-
import cv2

#读取图片
img = cv2.imread("test.jpg", cv2.IMREAD_UNCHANGED)

#BGR图像
img[100:150, 400:500] = [255, 255, 0]

#显示图像
cv2.imshow("Demo", img)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

#写入图像
cv2.imwrite("testyxz.jpg", img)

输出结果如下图所示,[255, 255, 0]是浅蓝色。



三.Numpy读取像素方法

使用Numpy进行像素读取,调用方式如下:
返回值 = 图像.item(位置参数)

# -*- coding:utf-8 -*-
import cv2
import numpy

#读取图片
img = cv2.imread("test.jpg", cv2.IMREAD_UNCHANGED)

#Numpy读取像素
blue = img.item(78, 100, 0)
green = img.item(78, 100, 1)
red = img.item(78, 100, 2)
print(blue)
print(green)
print(red)

#显示图像
cv2.imshow("Demo", img)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果如下,注意OpenCV读取图像通道是BGR,也可以转换成RGB在进行处理。
155
104
61



四.Numpy修改像素方法

使用Numpy的itemset函数修改像素,调用方式如下:
图像.itemset(位置, 新值)
例如:img.itemset((88,99), 255)

# -*- coding:utf-8 -*-
import cv2
import numpy

#读取图片
img = cv2.imread("test.jpg", cv2.IMREAD_UNCHANGED)

#Numpy读取像素
print(img.item(78, 100, 0))
print(img.item(78, 100, 1))
print(img.item(78, 100, 2))
img.itemset((78, 100, 0), 100)
img.itemset((78, 100, 1), 100)
img.itemset((78, 100, 2), 100)
print(img.item(78, 100, 0))
print(img.item(78, 100, 1))
print(img.item(78, 100, 2))

输出结果如下:
155
104
61
100
100
100

也可以同时输出B、G、R三个值,核心代码如下:

print(img[78, 78])
img.itemset((78, 78, 0), 0)
img.itemset((78, 78, 1), 0)
img.itemset((78, 78, 2), 0)
print(img[78, 78])
#[155 104  61]
#[0 0 0]


希望文章对大家有所帮助,如果有错误或不足之处,还请海涵。
(By:Eastmount 2018-08-28 早8点 https://blog.csdn.net/Eastmount/)

2014-03-19 16:22:35 u013809705 阅读数 899
  • 6.小项目.图片解码播放器

    本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。

    7525 人正在学习 去看看 朱有鹏

       为了比较windows下图像处理保存的bmp图片有效数据和其他平台处理出来的raw数据的差异,借此机会,解析学习下BMP文件格式。

首先QQ截取一张8乘8的纯蓝色(截取过程显示蓝色值170,经过winhex发现大片的AA,00,00)由此知道qq截图的存储是交错存储,不过是不是RGB顺利还有待考证(因为之前不同平台下存储RGB甚至RGBA的顺利不一定,另外图像处理库的读写也支持多种读写顺序),题外话了。

        在编译器工具链或者Windows系统头文件里很容易找到wingdi.h,里面定义了解析BMP文件数据的相关结构。

        在解析接下来的bmp文件是需要注意,x86下是小端存储,因此用winhex分析时候需要格外注意(这也就大概造成原本RGB通道变成BGR通道的原因——小端存储)。

        在注释部分以地址:数据十六进制:数据十进制的格式分析关键部分含义,参照winhex的截图。 

        一、BMP文件头

typedef struct tagBITMAPFILEHEADER {
	WORD	bfType;//[0x00-0x01]:4D42:略//位图类型,ASCII码显示Windows下是"BM"
	DWORD	bfSize;//[0x02-0x05]:000000F6:246//位图文件大小,246字节
	WORD	bfReserved1;
	WORD	bfReserved2;
	DWORD	bfOffBits;//[0x0A-0x0D]:00000036:54//位图数据文件相对文件头的偏移字节
} BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;
        二、BMP描述信息头

typedef struct tagBITMAPINFOHEADER{
	DWORD	biSize;//[0x0E-0x11]:00000028:40//描述信息头占用字节,加上文件头的14字节一共就是54字节
	LONG	biWidth;//[0x12-0x15]:00000008:8//图像宽度
	LONG	biHeight;//[0x16-0x19]:00000008:8//图像高度
	WORD	biPlanes;//[0x1A-0x1B]:0001:1//目标平面数,约定为1
	WORD	biBitCount;//[0x1C-0x1D]:0018:24//每个像素的比特宽度,24真彩色
	DWORD	biCompression;//[0x1E-0x21]:00000000:0//不压缩
	DWORD	biSizeImage;//[0x22-0x25]:000000C0:192//192=64*3,64个像素,每个像素3个通道
	LONG	biXPelsPerMeter;
	LONG	biYPelsPerMeter;
	DWORD	biClrUsed;//[0x2E-0x31]:00000000:0//使用所有调色板值
	DWORD	biClrImportant;//[0x32-0x35]:00000000:0//所有颜色索引均重要
} BITMAPINFOHEADER,*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;

               三、文件截图


2019-03-10 16:47:06 Aoman_Hao 阅读数 873
  • 6.小项目.图片解码播放器

    本课程是《朱有鹏老师嵌入式linux核心课程》第6部分,是一个课程后的小项目。用开发板本身自带的硬件完成一个基于linux API开发的图片解码播放器,实现了对BMP、JPG、PNG等格式图片进行解码播放的功能。

    7525 人正在学习 去看看 朱有鹏

C++开源项目:

Boost.GIL:通用图像库
CImg :用于图像处理的小型开源C++工具包
CxImage :用于加载,保存,显示和转换的图像处理和转换库,可以处理的图片格式包括 BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K。
FreeImage :开源库,支持现在多媒体应用所需的通用图片格式和其他格式。
GDCM:Grassroots DICOM 库
ITK:跨平台的开源图像分析系统
Magick++:ImageMagick程序的C++接口
MagickWnd:ImageMagick程序的C++接口
OpenCV : 开源计算机视觉类库
tesseract-ocr:OCR引擎
VIGRA :用于图像分析通用C++计算机视觉库
VTK :用于3D计算机图形学,图像处理和可视化的开源免费软件系统。

MakegGray 彩色转灰度

函数名称:MakegGray()
函数类型:void
功能:真彩色转化成256色灰度图像。

void MakeColorDib::MakegGray()    //灰度变化
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();   //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 for(int j=0;j<height;j++) // 每行
  for(int i=0;i<DibWidth;i+=3) // 每列
  {
   BYTE* pbyBlue = p_data++;   //得到蓝色值
   BYTE* pbyGreen = p_data++;  //得到绿色值
   BYTE* pbyRed = p_data++;    //得到红色值
   BYTE r = *pbyRed;
   BYTE g = *pbyGreen;
   BYTE b = *pbyBlue;
   //取到原r,g,b中的最大值作为像素三分量值的新值
   int gray=0;
   if(r>g)
    gray=r;
   else 
    gray=g;
   if(gray<b)
    gray=b;   
         *pbyBlue = gray;     //将取到的最大值赋给像素的蓝分量
   *pbyGreen = gray;    //将取到的最大值赋给像素的绿分量
   *pbyRed = gray;      //将取到的最大值赋给像素的红分量
  }
}

LightAlter 亮度调整

函数名称:LightAlter(int m_Light)
函数类型:void
参数:int m_Light,用户给定的阈值
功能:对图像使用阈值法进行亮度调整

void MakeColorDib::LightAlter(int m_Light)    //亮度调整
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();    //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 for(int j=0;j<height;j++) // 每行
 for(int i=0;i<DibWidth;i++) // 每列
 {   
  int a=0;
  a=int(*p_data*m_Light/100);   //调整当前点的亮度
  *p_data=a;
  //判断范围,取得合理的值
  if(a<0) 
   *p_data=0;  
     if(a>255)
   *p_data=255;
        p_data++;   //指向下一指针
 }
}

LightReverse 亮度取反

函数名称:LightReverse()
函数类型:void
功能:图像的亮度取反。

void MakeColorDib::LightReverse()    //亮度取反
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 for(int j=0;j<height;j++) // 每行
  for(int i=0;i<DibWidth;i++) // 每列
  {
   int a=*p_data;   //取得当前点的值
   *p_data=255-a;    //取反
   p_data++;  //指向下一指针  
  }
}

ContrastAlter 调整对比度(阈值法)

函数名称:ContrastAlter(int m_Increment)
函数类型:void
参数:int m_Increment,用户给定的阈值
功能:对图像使用阈值法调整对比度处理。

void MakeColorDib::ContrastAlter(int m_Increment)   ///对比度处理
{
 int nHigh = 255 - m_Increment;
 //对于极端情况加以处理
 if(nHigh < m_Increment)
 {
  nHigh = 127;
  m_Increment = 120;
 }
 if(m_Increment < -127)
  m_Increment = -120;
 //扩展或压缩区间的长度
 int nStretch = 255;
 if(m_Increment >= 0)
  nStretch = 255 - 2 * m_Increment;
 else
  nStretch = 255 + 2 * m_Increment;
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 if(m_Increment >= 0)   // m_Increment>=0时
 {
  for(int j=0;j<height;j++) // 每行
   for(int i=0;i<DibWidth-3;i+=3) // 每列
   {   
    //取得当前点(蓝色)的值,调整
    BYTE* pbyBlue = p_data++;    
    if(*pbyBlue<=m_Increment)
     *pbyBlue=0;
    else if(*pbyBlue>nHigh)
     *pbyBlue=255;
    else
     *pbyBlue=(BYTE)((((int)*pbyBlue - m_Increment) * 255) / nStretch );
    //取得当前点(绿色)的值,调整
    BYTE* pbyGreen = p_data++;
    if(*pbyGreen<=m_Increment)
     *pbyGreen=0;
    else if(*pbyGreen>nHigh)
     *pbyGreen=255;
    else
     *pbyGreen=(BYTE)((((int)*pbyGreen - m_Increment) * 255) / nStretch );
    //取得当前点(红色)的值,调整
    BYTE* pbyRed = p_data++;
    if(*pbyRed<=m_Increment)
     *pbyRed=0;
    else if(*pbyRed>nHigh)
     *pbyRed=255;
    else
     *pbyRed=(BYTE)((((int)*pbyRed - m_Increment) * 255) / nStretch );
   }
   
 }
 else  // m_Increment < 0 时
 {
  for(int j=0;j<height;j++)
   for(int i=0;i<DibWidth-3;i+=3)
   { //取得当前点(蓝色)的值,调整
    BYTE* pbyBlue = p_data++;
    *pbyBlue = (BYTE)((((int)(*pbyBlue) * nStretch) / 255) - m_Increment);
    //取得当前点(红色)的值,调整
    BYTE* pbyGreen = p_data++;
    *pbyGreen = (BYTE)((((int)(*pbyGreen) * nStretch) / 255) - m_Increment);
    //取得当前点(红色)的值,调整
    BYTE* pbyRed = p_data++;
    *pbyRed = (BYTE)((((int)(*pbyRed) * nStretch) / 255) - m_Increment);    
   }
 }
}
 

Exposal 曝光处理

函数名称:Exposal()
函数类型:void
功能:图像曝光处理。

void MakeColorDib::Exposal() //曝光处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 for(int j=0;j<height;j++) // 每行
  for(int i=0;i<DibWidth;i++) // 每列
  {
   BYTE* pbydata = p_data++;  //取得当前点的值
   BYTE a=*pbydata;   //传给临时变量
   *pbydata=(a>128)?a:(255-a);   //调整
  }
  
}
 

PaintColor 着色处理(阈值法)

函数名称:PaintColor(int m_Red,int m_Green,int m_Blue)
函数类型:void
参数:int m_Red、m_Green、m_Blue,用户给定的红绿蓝值
功能:对图像使用阈值法进行着色处理。

void MakeColorDib::PaintColor(int m_Red,int m_Green,int m_Blue) //着色处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 for(int j=0;j<height;j++) // 每行
  for(int i=0;i<DibWidth;i+=3) // 每列
  {   
   BYTE* pbyBlue = p_data++; //取得当前点(蓝色)的值     
   BYTE* pbyGreen = p_data++;  //取得当前点(绿色)的值
   BYTE* pbyRed = p_data++;    //取得当前点(红色)的值
   BYTE r = *pbyRed;
   BYTE g = *pbyGreen;
   BYTE b = *pbyBlue;
      BYTE gray=(BYTE)(((WORD)r * 59 + (WORD)g * 30 + (WORD)b * 11) / 100);
   *pbyBlue = (BYTE)((m_Blue * gray) / 255);  
   *pbyGreen = (BYTE)((m_Green * gray) / 255);
   *pbyRed = (BYTE)((m_Red * gray) / 255);
  }
}
 

NeonLight 霓虹处理

函数名称:NeonLight()
函数类型:void
功能:使图像产生霓虹处理效果。

void MakeColorDib::NeonLight()   //霓虹处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-4;j++) // 每行
 {
  for(int i=0;i<DibWidth-1;i++) // 每列
  {
    int pby_pt=0;
    //对像素执行算法
    pby_pt=(*(p_data+(height-j-1)*DibWidth+i)-*(p_data+(height-j-1)*DibWidth+i+3))
       *(*(p_data+(height-j-1)*DibWidth+i)-*(p_data+(height-j-1)*DibWidth+i+3))
       +(*(p_data+(height-j-1)*DibWidth+i)-*(p_data+(height-j-2)*DibWidth+i))
       *(*(p_data+(height-j-1)*DibWidth+i)-*(p_data+(height-j-2)*DibWidth+i));
   *(p_temp+(height-j-1)*DibWidth+i)=2*int(sqrt(pby_pt));
   //判断合法性
   if(*(p_temp+(height-j-1)*DibWidth+i)<0)
     *(p_temp+(height-j-1)*DibWidth+i)=0;
   if(*(p_temp+(height-j-1)*DibWidth+i)>255)
     *(p_temp+(height-j-1)*DibWidth+i)=255;
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;   //删除暂时分配内存
}
 

Smoothness 平滑处理

函数名称:Smoothness()
函数类型:void
功能:使图像平滑处理。

void MakeColorDib::Smoothness()   //平滑处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    int h[3][3];////定义(3x3)矩阵
 h[0][0] = 1;  h[0][1] = 1; h[0][2] = 1;
 h[1][0] = 1;  h[1][1] = 1; h[1][2] = 1;
 h[2][0] = 1;  h[2][1] = 1; h[2][2] = 1;
    BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-2;j++) // 每行
 {
  for(int i=0;i<DibWidth-8;i++) // 每列
  {
         double pby_pt=0;
                    //对应的第0行的值乘以矩阵对应值,再相加
       pby_pt= h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
        +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
        +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6))
                    //对应的第1行的值乘以矩阵对应值,再相加
        +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
        +h[1][1]*(*(p_data+(height-j-2)*DibWidth+i+3))
        +h[1][2]*(*(p_data+(height-j-2)*DibWidth+i+6))
                    //对应的第2行的值乘以矩阵对应值,再相加
              +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i))
     +h[2][1]*(*(p_data+(height-j-3)*DibWidth+i+3))
     +h[2][2]*(*(p_data+(height-j-3)*DibWidth+i+6));
   *(p_temp+(height-j-2)*DibWidth+i+3)=abs(int(pby_pt/9));//取总和的的平均值
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;//删除暂时分配内存
}
 

Embossment 浮雕处理

函数名称:Embossment()
函数类型:void
功能:产生图像浮雕处理效果。

void MakeColorDib::Embossment()   //浮雕处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height;j++) // 每行
 {
  for(int i=0;i<DibWidth-4;i++) // 每列
  {
    int pby_pt=0;
    //对像素得每个分量执行算法
    pby_pt=*(p_data+(height-j-1)*DibWidth+i)
       -*(p_data+(height-j-1)*DibWidth+i+3)+128;
    *(p_temp+(height-j-1)*DibWidth+i+3)=pby_pt;
   //检验合法性
   if(*(p_temp+(height-j-1)*DibWidth+i+3)<0)
    *(p_temp+(height-j-1)*DibWidth+i+3)=0;
   else if(*(p_temp+(height-j-1)*DibWidth+i+3)>255)
    *(p_temp+(height-j-1)*DibWidth+i+3)=255;
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;   //删除暂时分配内存
}

Spread 图像扩散

函数名称:Spread()
函数类型:void
功能:图像扩散处理。

void MakeColorDib::Spread()   //扩散处理
{ 
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-4;j++) // 每行
 {
  for(int i=0;i<DibWidth-14;i++) // 每列
  {
    int m=0,n=0;
    m=rand()%5; //取得行随机数
    n=rand()%5; //取得列随机数
    int pby_pt=0; 
    pby_pt=*(p_data+(height-j-1-m)*DibWidth+i+3*n);//得到对应随机像素值
    *(p_temp+(height-j-3)*DibWidth+i+6)=pby_pt;
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;   //删除暂时分配内存
}
 

Sharp 锐化

函数名称:Sharp()
函数类型:void
功能:图像锐化处理。

void MakeColorDib::Sharp()   //图像锐化
{
  BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    BYTE *p_temp=new BYTE[height*DibWidth];
 for(int j=0;j<height-1;j++) // 每行
 {
  for(int i=0;i<DibWidth-5;i++) // 每列
  {
         int pby_pt=0; 
   pby_pt= *(p_data+(height-j-2)*DibWidth+i+3)
          -*(p_data+(height-j-1)*DibWidth+i);
   *(p_temp+(height-j-2)*DibWidth+i+3)=*(p_data+(height-j-2)*DibWidth+i+3)
                                     +abs(int(pby_pt/4));
   if(*(p_temp+(height-j-2)*DibWidth+i+3)>255)
      *(p_temp+(height-j-2)*DibWidth+i+3)=255;
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;  //删除暂时分配内存
}

HighLVBO 阈值法进行高通滤波

函数名称:HighLVBO(int m_GaoTong)
函数类型:void
参数:int m_GaoTong,用户给定的阈值来选择矩阵
功能:对图像使用阈值法进行高通滤波。

void MakeColorDib::HighLVBO(int m_GaoTong)   //高通滤波
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 int h[3][3];  ////定义(3x3)矩阵
 if(m_GaoTong==1)
 {   //矩阵1(基本高通)
  h[0][0] =1;   h[0][1] =-2;  h[0][2] =1;
  h[1][0] =-2;  h[1][1] =5;   h[1][2] =-2;
  h[2][0] =1;   h[2][1] =-2;  h[2][2] =1;
 }
 else if(m_GaoTong==2)
 {   //矩阵2(中等高通)
  h[0][0] = 0;   h[0][1] = -1; h[0][2] = 0;
  h[1][0] = -1;  h[1][1] =  5; h[1][2] = -1;
  h[2][0] = 0;   h[2][1] = -1; h[2][2] = 0;
 }
 else
 {   //矩阵3(过量高通)
  h[0][0] = -1;  h[0][1] = -1; h[0][2] = -1;
  h[1][0] = -1;  h[1][1] =  9; h[1][2] = -1;
  h[2][0] = -1;  h[2][1] = -1; h[2][2] = -1;
 }
    BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-2;j++) // 每行
 {
  for(int i=0;i<DibWidth-8;i++) // 每列
  {
   int pby_pt=0;
   //对应的第0行的值乘以矩阵对应值,再相加
   pby_pt=  h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
    +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
    +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6))
    //对应的第1行的值乘以矩阵对应值,再相加
    +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
    +h[1][1]*(*(p_data+(height-j-2)*DibWidth+i+3))
    +h[1][2]*(*(p_data+(height-j-2)*DibWidth+i+6))
    //对应的第2行的值乘以矩阵对应值,再相加
    +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i))
    +h[2][1]*(*(p_data+(height-j-3)*DibWidth+i+3))
    +h[2][2]*(*(p_data+(height-j-3)*DibWidth+i+6));
   *(p_temp+(height-j-2)*DibWidth+i+3)=abs(pby_pt);
   if(pby_pt>255) //判断是否越界
    *(p_temp+(height-j-2)*DibWidth+i+3)=255;
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;  //删除暂时分配内存
}

LowLVBO 图像低通滤波

函数名称:LowLVBO()
函数类型:void
功能:实现图像低通滤波(3x3)。

void MakeColorDib::LowLVBO()   //低通滤波(3x3)
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    double h[3][3];////定义(3x3)矩阵
 h[0][0] = 0.1;  h[0][1] = 0.1; h[0][2] = 0.1;
 h[1][0] = 0.1;  h[1][1] = 0.2; h[1][2] = 0.1;
 h[2][0] = 0.1;  h[2][1] = 0.1; h[2][2] = 0.1;
 BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-2;j++) // 每行
 {
  for(int i=0;i<DibWidth-8;i++) // 每列
  {
   double pby_pt=0;
            //对应的第0行的值乘以矩阵对应值,再相加 
   pby_pt=  h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
    +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
    +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6))
    //对应的第0行的值乘以矩阵对应值,再相加
    +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
    +h[1][1]*(*(p_data+(height-j-2)*DibWidth+i+3))
    +h[1][2]*(*(p_data+(height-j-2)*DibWidth+i+6))
    //对应的第0行的值乘以矩阵对应值,再相加
    +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i))
    +h[2][1]*(*(p_data+(height-j-3)*DibWidth+i+3))
    +h[2][2]*(*(p_data+(height-j-3)*DibWidth+i+6));
   *(p_temp+(height-j-2)*DibWidth+i+3)=abs(int(pby_pt));
  }
 }
 memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
 delete []p_temp;  //删除暂时分配内存
}
 

LowVBObig 低通滤波

函数名称:LowVBObig()
函数类型:void
功能:实现函数低通滤波(5*5)

void MakeColorDib::LowLVBObig()   //低通滤波(5x5)
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 int h[5][5];//定义(5x5)矩阵
 h[0][0] = 1;  h[0][1] = 1; h[0][2] = 1; h[0][3] = 1; h[0][4] = 1;
 h[1][0] = 1;  h[1][1] = 2; h[1][2] = 2; h[1][3] = 2; h[1][4] = 1;
 h[2][0] = 1;  h[2][1] = 2; h[2][2] = 3; h[2][3] = 2; h[2][4] = 1;
 h[3][0] = 1;  h[3][1] = 2; h[3][2] = 2; h[3][3] = 2; h[3][4] = 1;
 h[4][0] = 1;  h[4][1] = 1; h[4][2] = 1; h[4][3] = 1; h[4][4] = 1;
 BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-4;j++) // 每行
 {
  for(int i=0;i<DibWidth-14;i++) // 每列
  {
         int pby_pt=0;
         //对应的第0行的值乘以矩阵对应值,再相加
   pby_pt=h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
      +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
      +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6))
         +h[0][3]*(*(p_data+(height-j-1)*DibWidth+i+9))
      +h[0][4]*(*(p_data+(height-j-1)*DibWidth+i+12))
                  //对应的第1行的值乘以矩阵对应值,再相加
         +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
         +h[1][1]*(*(p_data+(height-j-2)*DibWidth+i+3))
      +h[1][2]*(*(p_data+(height-j-2)*DibWidth+i+6))
      +h[1][3]*(*(p_data+(height-j-2)*DibWidth+i+9))
      +h[1][4]*(*(p_data+(height-j-2)*DibWidth+i+12))
                  //对应的第2行的值乘以矩阵对应值,再相加
         +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i))
      +h[2][1]*(*(p_data+(height-j-3)*DibWidth+i+3))
      +h[2][2]*(*(p_data+(height-j-3)*DibWidth+i+6))
      +h[2][3]*(*(p_data+(height-j-3)*DibWidth+i+9))
      +h[2][4]*(*(p_data+(height-j-3)*DibWidth+i+12))
                  //对应的第3行的值乘以矩阵对应值,再相加
         +h[3][0]*(*(p_data+(height-j-4)*DibWidth+i))
         +h[3][1]*(*(p_data+(height-j-4)*DibWidth+i+3))
      +h[3][2]*(*(p_data+(height-j-4)*DibWidth+i+6))
      +h[3][3]*(*(p_data+(height-j-4)*DibWidth+i+9))
      +h[3][4]*(*(p_data+(height-j-4)*DibWidth+i+12))
                  //对应的第4行的值乘以矩阵对应值,再相加
         +h[4][0]*(*(p_data+(height-j-5)*DibWidth+i))
      +h[4][1]*(*(p_data+(height-j-5)*DibWidth+i+3))
      +h[4][2]*(*(p_data+(height-j-5)*DibWidth+i+6))
      +h[4][3]*(*(p_data+(height-j-5)*DibWidth+i+9))
      +h[4][4]*(*(p_data+(height-j-5)*DibWidth+i+12));
                  //为了计算方便我们把除以35(矩阵权和)放在求总和之后
   *(p_temp+(height-j-3)*DibWidth+i+6)=abs(int(pby_pt/35));
  }
 }
 memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
 delete []p_temp;  //删除暂时分配内存
}

ShuiPingGROW 水平增强

函数名称:ShuiPingGROW()
函数类型:void
功能:使图像水平增强。

void MakeColorDib::ShuiPingGROW()   //水平增强
{
BYTE *p_data;     //原图数据区指针
int wide,height,DibWidth;    //原图长、宽、字节宽
p_data=this->GetData ();   //取得原图的数据区指针
   wide=this->GetWidth ();  //取得原图的数据区宽度
   height=this->GetHeight ();   //取得原图的数据区高度
DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
int h[3][1];//定义(3x1)矩阵
h[0][0] = -1;  
h[1][0] = 2; 
h[2][0] = -1;
BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
for(int j=0;j<height-2;j++) // 每行
{
 for(int i=0;i<DibWidth-8;i++) // 每列
 {
  int pby_pt=0;
  //对应的3行的值乘分别以矩阵对应值,再相加
  pby_pt= h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
   +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
   +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i));
  if(pby_pt>20)
   *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt)+100;
  else
   *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt);
 }
}
memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
   delete []p_temp;  //删除暂时分配内存
}

ChuiZhiGROW 垂直增强

函数名称:ChuiZhiGROW()
函数类型:void
功能:使图像垂直增强。

void MakeColorDib::ChuiZhiGROW()   //垂直增强
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 int h[1][3];//定义(1x3)矩阵
 h[0][0] = -1; 
 h[0][1] = 2;
 h[0][2] = -1;
 BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-2;j++) // 每行
 {
  for(int i=0;i<DibWidth-8;i++) // 每列
  {
   int pby_pt=0;
   //对应的第0行的值乘以矩阵对应值,再相加
   pby_pt= h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
    +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
    +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6));
   if(pby_pt>20)
    *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt)+100;
   else
    *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt);
  }
 }
 memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
 delete []p_temp;  //删除暂时分配内存
}

ShuangXiangGROW 双向增强

函数名称:ShuangXiangGROW()
函数类型:void
功能:使图像双向增强。

void MakeColorDib::ShuangXiangGROW()    //双向增强
{
BYTE *p_data;     //原图数据区指针
int wide,height,DibWidth;    //原图长、宽、字节宽
p_data=this->GetData ();   //取得原图的数据区指针
  wide=this->GetWidth ();  //取得原图的数据区宽度
  height=this->GetHeight ();   //取得原图的数据区高度
DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
int h[3][3];//定义(3x3)矩阵
h[0][0] = -1;  h[0][1] = -1; h[0][2] = -1;
h[1][0] = -1;  h[1][1] =  8; h[1][2] = -1;
h[2][0] = -1;  h[2][1] = -1; h[2][2] = -1; 
BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
for(int j=0;j<height-2;j++) // 每行
{ 
for(int i=0;i<DibWidth-8;i++) // 每列
{
 int pby_pt=0;
 //对应的第0行的值乘以矩阵对应值,再相加
 pby_pt= h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
  +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
  +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6))
  //对应的第1行的值乘以矩阵对应值,再相加
  +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
  +h[1][1]*(*(p_data+(height-j-2)*DibWidth+i+3))
  +h[1][2]*(*(p_data+(height-j-2)*DibWidth+i+6))
  //对应的第2行的值乘以矩阵对应值,再相加
  +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i))
  +h[2][1]*(*(p_data+(height-j-3)*DibWidth+i+3))
  +h[2][2]*(*(p_data+(height-j-3)*DibWidth+i+6));
 if(pby_pt>20)
  *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt)+100;
 else
  *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt);
}
} 
memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
delete []p_temp;  //删除暂时分配内存
}

Mosaic 马塞克

函数名称:Mosaic()
函数类型:void
功能:使图像产生马赛克效果。

void MakeColorDib::Mosaic()    //马赛克
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-4;j+=5) // 每行
 { 
     for(int i=0;i<DibWidth-14;i+=15) // 每列
  {   //对应周围(5x5)矩阵蓝色值求和平均
   int pby_pt=0;
   for(int m=0;m<5;m++)
    for(int n=0;n<15;n+=3)
    {   
     pby_pt+=*(p_data+(height-j-1-m)*DibWidth+i+n);
    }
    
   for(m=0;m<5;m++)
    for(int n=0;n<14;n+=3)
    {
     *(p_temp+(height-j-1-m)*DibWidth+i+n)=int(pby_pt/25);
    } 
            //对应周围(5x5)矩阵绿色值求和平均
   pby_pt=0;
   for(m=0;m<5;m++)
    for(int n=0;n<15;n+=3)
    {
     pby_pt+=*(p_data+(height-j-1-m)*DibWidth+i+n+1);
    }
   for(m=0;m<5;m++)
    for(int n=0;n<14;n+=3)
    {
     *(p_temp+(height-j-1-m)*DibWidth+i+n+1)=int(pby_pt/25);
    }
            //对应周围(5x5)矩阵红色值求和平均
   pby_pt=0;
   for(m=0;m<5;m++)
    for(int n=0;n<15;n+=3)
    {
     pby_pt+=*(p_data+(height-j-1-m)*DibWidth+i+n+2);
    }
   for(m=0;m<5;m++)
    for(int n=0;n<14;n+=3)
    {
     *(p_temp+(height-j-1-m)*DibWidth+i+n+2)=int(pby_pt/25);
    }
  }   
 }
 memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
 delete []p_temp;  //删除暂时分配内存
}

我的个人博客文章地址,欢迎访问
我的CSDN文章地址,欢迎访问
我的简书文章地址,欢迎访问
我的GitHub主页,欢迎访问

图像处理matlab

阅读数 2543

没有更多推荐了,返回首页