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的声明,读者从中可以了解该位图处理类的基本结构和将要实现的所有功能。
示例:
#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各个成员方法的定义以及算法原理。
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);
}
// 获取像素点颜色
// 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其它具体函数的算法和源代码。