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

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

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

第一部分:准备工作

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

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//显示处理后的位图
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
         int minHeight=bm.bmHeight
         dc.StretchBlt(0 ,0 ,minWidth,minHeight,&dcMem,0 ,0,minWidth,minHeight,SRCCOPY);
     }
     dcMem.SelectObject(&pOldBitmap);    
}

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

第二部分:位图处理类CImageUtility

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

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#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 构造函数和析构函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 获取(设置)指定位置像素的颜色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 获取像素点颜色
// RGB 用户存储颜色返回值的数组引用
// rowIndex 行坐标,从0开始
// colIndex 列坐标,从1开始
bool CImageUtility::getPixelColor( int (&RGB)[3], long row, long col){
     if (!(row
         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其它具体函数的算法和源代码。


你可能感兴趣的:(VC/C/C++,图像处理与机器视觉)