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其它具体函数的算法和源代码。