自定义数字图象处理基类

原创 2013年12月02日 17:27:21

      在数字图象处理相关工程中,我们经常设计各种方法处理图像,比如变换,锐化,分割等等,从面向对象的角度出发,设计一个合适的图像处理基类,从基类继承拓展便于维护和设计,下面的图像处理类类名为ImageDib,以BMP文件为基础,实现了图像的信息存储以及显示基本操作。

头文件:

// ImageDib.h: interface for the ImageDib class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_IMAGEDIB_H__4FC00616_753D_4313_8CAE_4B5E8ED02544__INCLUDED_)
#define AFX_IMAGEDIB_H__4FC00616_753D_4313_8CAE_4B5E8ED02544__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


class ImageDib  
{
	//成员变量
	public:	
		unsigned char * m_pImgData; 				//图像数据指针
		LPRGBQUAD m_lpColorTable; 				//图像颜色表指针
		int m_nBitCount;						//每像素占的位数
	private:
		LPBYTE m_lpDib;						//指向DIB的指针
		HPALETTE m_hPalette;					//逻辑调色板句柄
		int m_nColorTableLength; 					//颜色表长度(多少个表项)
	public:
		int m_imgWidth;							//图像的宽,像素为单位
		int m_imgHeight; 						//图像的高,像素为单位
		LPBITMAPINFOHEADER m_lpBmpInfoHead; 	//图像信息头指针
	//成员函数
	public:
		ImageDib();							//构造函数
		ImageDib(CSize size, int nBitCount, LPRGBQUAD lpColorTable, 
		unsigned char *pImgData);           //带参数的构造函数
		~ImageDib();						//析构函数
		BOOL Read(LPCTSTR lpszPathName); 		//DIB读函数
		BOOL Write(LPCTSTR lpszPathName);       //DIB写函数
		int ComputeColorTabalLength(int nBitCount);	//计算颜色表的长度
		BOOL Draw(CDC* pDC, CPoint origin, CSize size); //图像绘制
		CSize GetDimensions();					//读取图像维数
		void ReplaceDib(CSize size, int nBitCount, LPRGBQUAD lpColorTable,
		unsigned char *pImgData);              	//用新的数据替换DIB
	private:
		void MakePalette();						//创建逻辑调色板
		void Empty();                         	//清理空间

};

#endif // !defined(AFX_IMAGEDIB_H__4FC00616_753D_4313_8CAE_4B5E8ED02544__INCLUDED_)


源文件:

// ImageDib.cpp: implementation of the ImageDib class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ImageDib.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

ImageDib::ImageDib()
{
	m_lpDib=NULL;//初始化m_lpDib为空。
	m_lpColorTable=NULL;				//颜色表指针为空
	m_pImgData=NULL;  				//图像数据指针为空
	m_lpBmpInfoHead=NULL;				//图像信息头指针为空
	m_hPalette = NULL;					//调色板为空
}

ImageDib::~ImageDib()
{
	//释放m_lpDib所指向的内存缓冲区
	if(m_lpDib != NULL) 
		delete [] m_lpDib; 
	
	//如果有调色板,释放调色板缓冲区
	if(m_hPalette != NULL)
		::DeleteObject(m_hPalette);
}

ImageDib::ImageDib(CSize size, int nBitCount, LPRGBQUAD lpColorTable,
			   unsigned char *pImgData)
{
	//如果没有位图数据传入,我们认为是空的DIB,此时不分配DIB内存
	if(pImgData==NULL){
		m_lpDib=NULL;
		m_lpColorTable=NULL;
		m_pImgData=NULL;  // 图像数据
		m_lpBmpInfoHead=NULL; //  图像信息头
		m_hPalette = NULL;
	}
	else{//如果有位图数据传入
		
		//图像的宽、高、每像素位数等成员变量赋值
		m_imgWidth=size.cx;
		m_imgHeight=size.cy;
		m_nBitCount=nBitCount;
		
		//根据每像素位数,计算颜色表长度
		m_nColorTableLength=ComputeColorTabalLength(nBitCount);
		
		//每行像素所占字节数,必须扩展成4的倍数
		int lineByte=(m_imgWidth*nBitCount/8+3)/4*4;
		
		//位图数据缓冲区的大小(图像大小)
		int imgBufSize=m_imgHeight*lineByte;
		
		//为m_lpDib一次性分配内存,生成DIB结构
		m_lpDib=new BYTE [sizeof(BITMAPINFOHEADER) + 
			sizeof(RGBQUAD) * m_nColorTableLength+imgBufSize];
		
		//填写BITMAPINFOHEADER结构
		m_lpBmpInfoHead = (LPBITMAPINFOHEADER) m_lpDib;
		m_lpBmpInfoHead->biSize = sizeof(BITMAPINFOHEADER);
		m_lpBmpInfoHead->biWidth = m_imgWidth;
		m_lpBmpInfoHead->biHeight = m_imgHeight;
		m_lpBmpInfoHead->biPlanes = 1;
		m_lpBmpInfoHead->biBitCount = m_nBitCount;
		m_lpBmpInfoHead->biCompression = BI_RGB;
		m_lpBmpInfoHead->biSizeImage = 0;
		m_lpBmpInfoHead->biXPelsPerMeter = 0;
		m_lpBmpInfoHead->biYPelsPerMeter = 0;
		m_lpBmpInfoHead->biClrUsed = m_nColorTableLength;
		m_lpBmpInfoHead->biClrImportant = m_nColorTableLength;
		
		//调色板句柄初始化为空,有颜色表时,MakePalette()函数要生成新的调色板
		m_hPalette = NULL;
		//如果有颜色表,则将颜色表拷贝进DIB的颜色表位置
		if(m_nColorTableLength!=0){
			
			//m_lpColorTable指向DIB颜色表的起始位置
			m_lpColorTable=(LPRGBQUAD)(m_lpDib+sizeof(BITMAPINFOHEADER));
			
			//颜色表拷贝
			memcpy(m_lpColorTable,lpColorTable,sizeof(RGBQUAD) * m_nColorTableLength);
			
			//创建逻辑调色板
			MakePalette();
		}
		
		//m_pImgData指向DIB位图数据起始位置
		m_pImgData = (LPBYTE)m_lpDib+sizeof(BITMAPINFOHEADER)+
			sizeof(RGBQUAD) * m_nColorTableLength;
		
		//拷贝图像数据进DIB位图数据区
		memcpy(m_pImgData,pImgData,imgBufSize);
	}
	
}


BOOL ImageDib::Read(LPCTSTR lpszPathName)
{
	//读模式打开图像文件
	CFile file;
	if (!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite))
		return FALSE;
	BITMAPFILEHEADER bmfh;
	//读取BITMAPFILEHEADER结构到变量bmfh中
	int nCount=file.Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
	//为m_lpDib分配空间,读取DIB进内存
	if(m_lpDib!=NULL)	delete []m_lpDib;
	m_lpDib=new BYTE[file.GetLength() -sizeof(BITMAPFILEHEADER)];
	file.Read(m_lpDib, file.GetLength() -sizeof(BITMAPFILEHEADER));
	//m_lpBmpInfoHead位置为m_lpDib起始位置
	m_lpBmpInfoHead = (LPBITMAPINFOHEADER)m_lpDib;
	//为成员变量赋值
	m_imgWidth=m_lpBmpInfoHead->biWidth;
	m_imgHeight=m_lpBmpInfoHead->biHeight;
	m_nBitCount=m_lpBmpInfoHead->biBitCount; 
	//计算颜色表长度
	m_nColorTableLength=	ComputeColorTabalLength(m_lpBmpInfoHead->biBitCount);
	//如果有颜色表,则创建逻辑调色板
	m_hPalette = NULL;
	if(m_nColorTableLength!=0){m_lpColorTable=
	(LPRGBQUAD)(m_lpDib+sizeof(BITMAPINFOHEADER));
	    MakePalette();
	}
	//m_pImgData指向DIB的位图数据起始位置
	m_pImgData = (LPBYTE)m_lpDib+sizeof(BITMAPINFOHEADER) +
		sizeof(RGBQUAD) * m_nColorTableLength;
	return TRUE;
}

BOOL ImageDib::Write(LPCTSTR lpszPathName)
{
	//写模式打开文件
	CFile file;
	if (!file.Open(lpszPathName, CFile::modeCreate | CFile::modeReadWrite 
		| CFile::shareExclusive))
		return FALSE;
	
	//填写文件头结构
	BITMAPFILEHEADER bmfh;
	bmfh.bfType = 0x4d42;  // 'BM'
	bmfh.bfSize = 0;
	bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
	bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
		sizeof(RGBQUAD) * m_nColorTableLength;	
	try {
		//文件头结构写进文件
		file.Write((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
		
		//文件信息头结构写进文件
		file.Write(m_lpBmpInfoHead,  sizeof(BITMAPINFOHEADER));
		
		//如果有颜色表的话,颜色表写进文件
		if(m_nColorTableLength!=0)
			file.Write(m_lpColorTable, sizeof(RGBQUAD) * m_nColorTableLength);
		
		//位图数据写进文件
		int imgBufSize=(m_imgWidth*m_nBitCount/8+3)/4*4*m_imgHeight;
		file.Write(m_pImgData, imgBufSize);
	}
	catch(CException* pe) {
		pe->Delete();
		AfxMessageBox(_T("write error"),MB_OK);
		return FALSE;
	}
	
	//函数返回
	return TRUE;
}


void ImageDib::MakePalette()
{
	//如果颜色表长度为0,则不创建逻辑调色板
	if(m_nColorTableLength == 0) 
		return;
	//删除旧的逻辑调色板句柄
	if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
	//申请空间,根据颜色表生成LOGPALETTE结构
	LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) +
		m_nColorTableLength * sizeof(PALETTEENTRY)];
	pLogPal->palVersion = 0x300;
	pLogPal->palNumEntries = m_nColorTableLength;
	LPRGBQUAD m_lpDibQuad = (LPRGBQUAD) m_lpColorTable;
	for(int i = 0; i < m_nColorTableLength; i++) {
		pLogPal->palPalEntry[i].peRed = m_lpDibQuad->rgbRed;
		pLogPal->palPalEntry[i].peGreen = m_lpDibQuad->rgbGreen;
		pLogPal->palPalEntry[i].peBlue = m_lpDibQuad->rgbBlue;
		pLogPal->palPalEntry[i].peFlags = 0;
		m_lpDibQuad++;
	}	
	//创建逻辑调色板
	m_hPalette = ::CreatePalette(pLogPal);
	//释放空间
	delete pLogPal;
}

int ImageDib::ComputeColorTabalLength(int nBitCount)
{
	int colorTableLength;
	switch(nBitCount) {
	case 1:
		colorTableLength = 2;
		break;
	case 4:
		colorTableLength = 16;
		break;
	case 8:
		colorTableLength = 256;
		break;
	case 16:
	case 24:
	case 32:
		colorTableLength = 0;
		break;
	default:
		ASSERT(FALSE);
	}
	ASSERT((colorTableLength >= 0) && (colorTableLength <= 256)); 
	return colorTableLength;
}

BOOL ImageDib::Draw(CDC* pDC, CPoint origin, CSize size)
{
	HPALETTE hOldPal=NULL;				//旧的调色板句柄
	if(m_lpDib == NULL) return FALSE;			//如果DIB为空,则返回0
	if(m_hPalette != NULL) {					//如果DIB有调色板
										//将调色板选进设备环境中
		hOldPal=::SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE);
		pDC->RealizePalette();			
	}
	pDC->SetStretchBltMode(COLORONCOLOR);  //设置位图伸缩模式
	//将DIB在pDC所指向的设备上进行显示
	::StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy,
		0, 0, m_lpBmpInfoHead->biWidth, m_lpBmpInfoHead->biHeight,m_pImgData,
		 (LPBITMAPINFO) m_lpBmpInfoHead, DIB_RGB_COLORS, SRCCOPY);
	if(hOldPal!=NULL)						//恢复旧的调色板
		::SelectPalette(pDC->GetSafeHdc(), hOldPal, TRUE);
	return TRUE;
}

CSize ImageDib::GetDimensions()
{	
	if(m_lpDib == NULL) return CSize(0, 0);
	return CSize(m_imgWidth, m_imgHeight);
}

void ImageDib::Empty()
{
	//释放DIB内存缓冲区
	if(m_lpDib != NULL) {
		delete [] m_lpDib;
		m_lpDib=NULL;
		m_lpColorTable=NULL;
		m_pImgData=NULL;  
		m_lpBmpInfoHead=NULL;
	}
	//释放逻辑调色板缓冲区
	if(m_hPalette != NULL){
		::DeleteObject(m_hPalette);
		m_hPalette = NULL;
	}
}


void ImageDib::ReplaceDib(CSize size, int nBitCount,  
						LPRGBQUAD lpColorTable,unsigned char *pImgData)
{ 
	//释放原DIB所占空间
	Empty();
	
	//成员变量赋值
	m_imgWidth=size.cx;
	m_imgHeight=size.cy;
	m_nBitCount=nBitCount;
	
	//计算颜色表的长度
	m_nColorTableLength=ComputeColorTabalLength(nBitCount);
	
	//每行像素所占字节数,扩展成4的倍数
	int lineByte=(m_imgWidth*nBitCount/8+3)/4*4;
	
	//位图数据的大小
	int imgBufSize=m_imgHeight*lineByte;
	
	//为m_lpDib重新分配空间,以存放新的DIB
	m_lpDib=new BYTE [sizeof(BITMAPINFOHEADER) + 
		sizeof(RGBQUAD) * m_nColorTableLength+imgBufSize];
	
	//填写位图信息头BITMAPINFOHEADER结构
	m_lpBmpInfoHead = (LPBITMAPINFOHEADER) m_lpDib;
	m_lpBmpInfoHead->biSize = sizeof(BITMAPINFOHEADER);
	m_lpBmpInfoHead->biWidth = m_imgWidth;
	m_lpBmpInfoHead->biHeight = m_imgHeight;
	m_lpBmpInfoHead->biPlanes = 1;
	m_lpBmpInfoHead->biBitCount = m_nBitCount;
	m_lpBmpInfoHead->biCompression = BI_RGB;
	m_lpBmpInfoHead->biSizeImage = 0;
	m_lpBmpInfoHead->biXPelsPerMeter = 0;
	m_lpBmpInfoHead->biYPelsPerMeter = 0;
	m_lpBmpInfoHead->biClrUsed = m_nColorTableLength;
	m_lpBmpInfoHead->biClrImportant = m_nColorTableLength;
	
	//调色板置空
	m_hPalette = NULL;
	
	//如果有颜色表,则将颜色表拷贝至新生成的DIB,并创建逻辑调色板
	if(m_nColorTableLength!=0){
		m_lpColorTable=(LPRGBQUAD)(m_lpDib+sizeof(BITMAPINFOHEADER));
		memcpy(m_lpColorTable,lpColorTable,sizeof(RGBQUAD) * m_nColorTableLength);
		MakePalette();
	}
	
	//m_pImgData指向DIB的位图数据起始位置
	m_pImgData = (LPBYTE)m_lpDib+sizeof(BITMAPINFOHEADER)+
		sizeof(RGBQUAD) * m_nColorTableLength;
	
	//将新位图数据拷贝至新的DIB中
	memcpy(m_pImgData,pImgData,imgBufSize);
}


 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

数字图象处理系列问题研究(matlab实现)

一、实验目的: 掌握基本的图象增强和变换方法,观察图象增强的效果,加深对图像增强和一些基本变换的理解。熟悉如何用matlab实验平台对图像进行增强和变换处理。 二、实验内容: 1.编程实现打开一...

matlab数字图象处理函数总结

Matlab数字数字图像处理函数汇总: 1、数字数字图像的变换 ① fft2:fft2函数用于数字数字图像的二维傅立叶变换,如:i=imread('104_8.tif'); j=fft2(i);...

数字图象处理MATLAB常用操作(转)

[plain] view plain copy   diagram = imread('C:\Users\Administrator\Desktop\Compressed\fiter\le...

opencv 数字图象处理 镜像变换 cvFlip()

图像镜像(Mirror)变换分为三种:一种是水平镜像;一种是垂直镜像;一种是对角镜像。图像的镜像变换不改变原图像的形状。 ##################################...

opencv 数字图象处理 图像平移变换

图像平移(Translation)变换是图像几何变换中最为简单的一种变换,是将一副图像中的所有像素都按照给定的偏移量在水平方向(沿x轴方向),或在垂直方向(沿y轴方向)移动。 void Tr...

数字图象处理之二维码图像提取算法(四)

拍摄印制在物品上的二维条码图像时, 除二维条码图案外,通常还会包含其他的背景信息,二维条码只占据整个图像的一部分。提出了一种条码的初步定位算法,能够迅速的定位二维条码的大致范围,并将其切割出来,去掉大...

数字图象处理之二维码图像提取算法(七)

二维条码图像提取主要是实现二维条码中码字的提取,包括图像预处理和码字提取两部分。具体的流程图如下所示:               整个图像提取流程大致分为 8 个步骤, 现按步...

《数字图象处理》——直方图均衡化

在直方图的基础上,也就出现了直方图的均衡化。     直方图均衡化的处理过程中就是在寻找一个变换函数(经常用累积分布函数(CDF)来当作变换函数),为什么呢?这在matlab冈萨雷斯书里面有...

数字图象处理之二维码图像提取算法(十二)

新年代码大放送: // test1.cpp : Defines the entry point for the console application. #include "stdafx.h" #...

数字图象处理之二维码图像提取算法(八)

PDF417 码几何失真的校正: (1)每个 PDF417 条码都包含一个起始符和终止符,且其模块比例是固定的。 利用这个特性,可以采取扫描条码左右边缘点,能后采用直线拟合方法来确定条码的...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)