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