VC编程实现位图处理类(显示位图、加载位图、获取/设置像素点颜色)

2012-03-16 20:06:30|?次阅读|上传:wustguangh【已有?条评论】发表评论

关键词:C/C++, 图形/图像|来源:唯设编程网

前面的文章介绍了VC编程实现色彩空间之间相互转换的计算原理、公式和具体的VC实现代码,本文将以此为基础,介绍VC编程进行位图处理的基本知识,内容包括:在CStatic空间中缩放显示位图、加载HBITMAP位图到CBitmap对象并关联到LPBYTE类型的数组空间、获取(设置)指定左边点的颜色RGB值。

第一部分:准备工作

作为测试的先决条件,首先介绍将位图(CBitmap)缩放显示到CStatic控件中的方法,VC源代码如下:

示例:

//显示处理后的位图
void CTestApplicationDlg::ShowDesBmp(){    
    if(pImgUtility==NULL)
        return;
    //将pStatic指向要显示的地方
    CStatic *pStatic = NULL;
    //根据ID获取Static控件
    pStatic=(CStatic*)GetDlgItem(IDC_IMGNEW);
    ////////////////////////////////////////////////
    /**这一步相当重要,否则无法实现自绘*****/
    ////////////////////////////////////////////////
    pStatic->ModifyStyle(0,BS_OWNERDRAW);
    //创建DC
    CClientDC dc(pStatic);

    CBitmap* pDesBmp=pImgUtility->getCBitmap();
    //获取图片内容
    BITMAP bm;    
    pDesBmp->GetBitmap(&bm);
    CDC dcMem;

    //创建兼容DC
    dcMem.CreateCompatibleDC(GetDC());
    CBitmap *pOldBitmap=(CBitmap*)dcMem.SelectObject(pDesBmp);
    CRect lRect;

    //获取Static控件的大小范围
    pStatic->GetClientRect(&lRect);    
    //判断是否需要调整到适合画布
    if(((CButton*)GetDlgItem(IDC_CHECK4))->GetCheck())
        dc.StretchBlt(
            lRect.left ,lRect.top ,lRect.Width(),lRect.Height(),
            &dcMem,
            0 ,0,bm.bmWidth,bm.bmHeight,
            SRCCOPY
        );
    else{
        int minWidth=bm.bmWidth<lRect.Width()?bm.bmWidth:lRect.Width();
        int minHeight=bm.bmHeight<lRect.Height()?bm.bmHeight:lRect.Height();
        dc.StretchBlt(0 ,0 ,minWidth,minHeight,&dcMem,0 ,0,minWidth,minHeight,SRCCOPY);
    }
    dcMem.SelectObject(&pOldBitmap);    
}

其中,pImgUtility是一个CImageUtility指针类型的成员变量,CImageUtility是一个VC位图处理程序的类,在下面的内容中将详细介绍。

第二部分:位图处理类CImageUtility

首先介绍位图处理类CImageUtility的声明,读者从中可以了解该位图处理类的基本结构和将要实现的所有功能。

示例:

#pragma once
#include "..ColorUtilityColorUtility.h"
#pragma comment(lib,"..debugColorUtility.lib")

enum GrayType{
	AVERAGE,	//平均值
	MIDVALUE,	//中间值
	L_VALUE		//LAB中的L分量
};
enum AutoGradationType{
	g_L_VALUE,		//LAB中的L分量
	g_RGB			//RGB自动色阶
};
class AFX_EXT_CLASS CImageUtility
{
private:
	CBitmap *bmpSrc;
	BITMAP bmSrcInfo;
	DWORD dwBmByteSize;  
	//开辟内存空间
	LPBYTE pBmBits;
	int nPixBytes;
	//求每行剩余字节数 
	int nRemainLineBytes; 	
public:	
	CImageUtility(HBITMAP hBitmap);
	~CImageUtility(void);
	// 加载位图资源
	void loadHBitmap(HBITMAP hBitmap);
	// 返回位图
	CBitmap* getCBitmap();
	// 获取像素点颜色
	// RGB 用户存储颜色返回值的数组引用
	// rowIndex 行坐标,从0开始
	// colIndex 列坐标,从1开始
	bool getPixelColor(int (&RGB)[3],long row,long col);
	// 设置像素点颜色
	// RGB 用户存储颜色的数组引用
	// rowIndex 行坐标,从0开始
	// colIndex 列坐标,从1开始
	bool setPixelColor(const int (&RGB)[3],size_t row,size_t col);
	// 自动色阶
	// gType 自动色阶的算法
	// darkLimen 暗调阈值
	// brightLimen 高光阈值
	void ImageAutoGradationProcess(AutoGradationType gType=g_L_VALUE,
		double darkLimen=0.001,
		double brightLimen=0.001);
	// 图像灰度化处理
	// gType-灰度计算方式
	void ImageGrayProcess(GrayType bAvgType=L_VALUE);
	// 图像极值化(二值话)处理
	// limen-阈值
	void ImageExtreamProcess(double limen);
	//反相
	void ImageReverseProcess();
	//切除二值图的空白边
	void ImageCutBlankProcess();
	//位图拷贝的实现
	static HBITMAP CopyBitmap(HBITMAP hSourcehBitmap,RECT* pRect=NULL);		
};

下面开始介绍位图处理类CImageUtility各个成员方法的定义以及算法原理。

2.1 构造函数和析构函数
CImageUtility::CImageUtility(HBITMAP hBitmap)
	:bmpSrc(NULL),dwBmByteSize(0),nPixBytes(0),nRemainLineBytes(0)
{
	loadHBitmap(hBitmap);
}
// 加载位图资源
void CImageUtility::loadHBitmap(HBITMAP hBitmap){
	//释放内存空间
	GlobalFree(pBmBits);
	if(hBitmap==NULL)
		return;
	bmpSrc = CBitmap::FromHandle(hBitmap);  

	bmpSrc->GetBitmap( &bmSrcInfo );  

	dwBmByteSize = bmSrcInfo.bmWidthBytes * bmSrcInfo.bmHeight;  
	//开辟内存空间
	pBmBits = (LPBYTE) GlobalAlloc(GPTR, dwBmByteSize);  
	bmpSrc->GetBitmapBits(dwBmByteSize, pBmBits);  

	nPixBytes = bmSrcInfo.bmBitsPixel/8;
	//求每行多余的数据
	nRemainLineBytes = (bmSrcInfo.bmWidthBytes - bmSrcInfo.bmWidth * nPixBytes)%2; //每行剩余字节数 
}
// 返回位图
CBitmap* CImageUtility::getCBitmap(){
	return bmpSrc;
}
CImageUtility::~CImageUtility(void)
{
	//释放内存空间
	GlobalFree(pBmBits);
}
2.2 获取(设置)指定位置像素的颜色
// 获取像素点颜色
// RGB 用户存储颜色返回值的数组引用
// rowIndex 行坐标,从0开始
// colIndex 列坐标,从1开始
bool CImageUtility::getPixelColor(int (&RGB)[3],long row,long col){
	if(!(row<bmSrcInfo.bmHeight&&col<bmSrcInfo.bmWidth))
		throw runtime_error("错误:像素坐标越界!");
	if(nPixBytes>=3){
		RGB[0]=pBmBits[row*bmSrcInfo.bmWidthBytes+col*nPixBytes + 2];
		RGB[1]=pBmBits[row*bmSrcInfo.bmWidthBytes+col*nPixBytes + 1];
		RGB[2]=pBmBits[row*bmSrcInfo.bmWidthBytes+col*nPixBytes + 0];
		return true;
	}else{
		return false;
	}
}
// 设置像素点颜色
// RGB 用户存储颜色的数组引用
// rowIndex 行坐标,从0开始
// colIndex 列坐标,从1开始
bool CImageUtility::setPixelColor(const int (&RGB)[3],size_t row,size_t col){
	if(nPixBytes>=3){
		pBmBits[row*bmSrcInfo.bmWidthBytes+col*nPixBytes + 2]=RGB[0];
		pBmBits[row*bmSrcInfo.bmWidthBytes+col*nPixBytes + 1]=RGB[1];
		pBmBits[row*bmSrcInfo.bmWidthBytes+col*nPixBytes + 0]=RGB[2];
		return true;
	}else{
		return false;
	}
}

至此,我们便完成了位图处理类CImageUtility的初始化和准备工作,下文将详细介绍位图处理类CImageUtility其它具体函数的算法和源代码。

发表评论0条 】
网友评论(共?条评论)..
VC编程实现位图处理类(显示位图、加载位图、获取/设置像素点颜色)