GetBitmapBits函数功能:该函数将指定位图的位拷贝到缓冲区里。
函数原型:LONG GetBitmapBits(HBITMAP hbmp, LONG cbBuffer, LPVOID lpvBits);
参数:
hbmp:指向感兴趣的位图的句柄。
cbBuffer:指定要从位图拷贝到缓冲区的字节数。
lpvBits:指向接收位图位数据的缓冲区指针。这些位是按字节类型存储在数组中的。
返回值:如果该函数执行成功,那么返回值就是拷贝到缓冲区的字节数;如果该函数执行失败,那么返回值为0。
文件头,信息头和调色板的参考信息可以查看以下地址:
>
如果位图已经通过LoadBitmap加载到内存,则内存中的图像与显示设备紧密相关,比如原图是彩色,显示器是黑白色,通过bmpLoadBitmap(我的)后,内存中的图像数据是黑白色的数据,而且还与显示器位数有关。如果需要在原位图数据上进行图像处理,就不要bmpLoadBitmap来加载位图,而是打开文件获取位图数据。如果仅仅是在当前显示设备下进行效果处理,则可以使用bmpLoadBitmap加载位图,通过CBitmap的GetBitmapBit函数可以获取位图数据,如果是24位显示器,则每3个字节表示一个像素,其中第一个字节是B,第二个字节是G,第3个字节是R;如果是32位的显示器,每4个字节表示一个像素,一般前3个字节与24位显示器一样,第4个字节一般没有什么意义。
Microsoft Visual C++,(简称Visual C++、MSVC、VC++或VC)是Microsoft公司推出的开发Win32环境程序,面向对象的可视化集成编程系统。它不但具有程序框架自动生成、灵活方便的类管理、代码编写和界面设计集成交互 *** 作、可开发多种程序等优点,而且通过简单的设置就可使其生成的程序框架支持数据库接口、OLE2,WinSock网络、3D控制界面。
它以拥有“语法高亮”,IntelliSense(自动完成功能)以及高级除错功能而著称。比如,它允许用户进行远程调试,单步执行等。还有允许用户在调试期间重新编译被修改的代码,而不必重新启动正在调试的程序。其编译及建置系统以预编译头文件、最小重建功能及累加连结著称。这些特征明显缩短程式编辑、编译及连结花费的时间,在大型软件计划上尤其显著。
'使用DIB获取图象,根据他人代码修改,ImgData()中保存的是颜色
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Private Declare Function SetDIBits Lib "gdi32" (ByVal hdc As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Private Type BITMAPINFOHEADER '40 bytes
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Type RGBQUAD
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
rgbReserved As Byte
End Type
Private Type BITMAPINFO
bmiHeader As BITMAPINFOHEADER
bmiColors As RGBQUAD
End Type
Private Const DIB_RGB_COLORS = 0 ' color table in RGBs
Private Sub Command1_Click()
Picture1Line (0, 0)-(Picture1Width, Picture1Height), vbRed
Dim BITMAP As BITMAPINFO
Dim ImgData() As Byte'图象颜色
Dim lIndex As Long
Dim i As Long, j As Long, n As Long, t As Long, m
With BITMAP
bmiHeaderbiSize = 40 'BMP30版本
End With
If GetDIBits(Picture1hdc, Picture1PictureHandle, 0, 0, 0, BITMAP, DIB_RGB_COLORS) <> 0 Then '获取图像位图数据大小
ReDim ImgData(BITMAPbmiHeaderbiSizeImage - 1) '重定义数组准备接收位图数据
If GetDIBits(Picture1hdc, Picture1PictureHandle, 0, BITMAPbmiHeaderbiHeight, ImgData(0), BITMAP, DIB_RGB_COLORS) <> 0 Then '正式获取位图数据并将数据存入定义的数组中
'注意数组中颜色分量的存储顺序为:B、G、R(并不是R、G、B),如果你需要对图像进行处理只需改变数组中的数据即可完成
'我试验的位图62x62像素,24色图,3字节存储,每行188字节(一个扫描行的长度必须是4的倍数),这样扫描后共11656字节
' 下面这段程序是将图像亮度变暗(只作为演示,其它效果你可以自己动手做)
'注意:第一条扫描线的位置是从左下角开始
'BITMAPbmiHeaderbiHeight 位图的高度,单位是像素
'BITMAPbmiHeaderbiWidth 位图的宽度,单位是像素
'BITMAPbmiHeaderbiBitCount 图像的颜色位数
'每个像素点的颜色是:(从下往上)
t = ((BITMAPbmiHeaderbiWidth 3 + 3) \ 4) 4 '每行的字节数
For i = 1 To BITMAPbmiHeaderbiHeight
DoEvents
m = t (i - 1)
For j = 1 To BITMAPbmiHeaderbiWidth
n = m + (j - 1) 3
DebugPrint "(" & i & "," & j & ")" & n & ": R=" & ImgData(n) & " G=" & ImgData(n + 1) & " B=" & ImgData(n + 2)
Next
Next
For lIndex = 0 To BITMAPbmiHeaderbiSizeImage - 1
DoEvents
If ImgData(lIndex) - 100 < 0 Then
ImgData(lIndex) = 0
Else
ImgData(lIndex) = ImgData(lIndex) - 100
End If
Next
'
SetDIBits Picture2hdc, Picture2ImageHandle, 0, BITMAPbmiHeaderbiHeight - 1, ImgData(0), BITMAP, DIB_RGB_COLORS '将位图数据写入PICTURE2中
End If
End If
End Sub
int GetDIBits( HDC hdc, // handle to DC
HBITMAP hbmp, // handle to bitmap
UINT uStartScan, // first scan line to set
UINT cScanLines, // number of scan lines to copy
LPVOID lpvBits, // array for bitmap bits
LPBITMAPINFO lpbi, // bitmap data buffer
UINT uUsage // RGB or palette index);
}
lpvBits 就是二进制图像。。
两处可能性:
1、没有将bitmapdata设置成透明的。
2、bitmapbitmapDatagetPixel32(int(i(bitmapwidth/200)),int(j(bitmapheight/bitmaph)))计算错误。可能已超出原的范围,所以获取到的值是0,即是黑色。
建议检测方法:
1、确认bitmapdata已设置成透明,new BitmapData(width,height,true,0);//后面两个参数,true,0是设置透明的。
2、setPixel时,先将原的像素全部放到另一个BitmapData中,即相当于复制一次,查看保存是否带有黑色。此时,可以将添加到舞台中查看一下,确保未保存时,是正常的。如果检测正常,那么就可以肯定错误是第二个可能性导致的,此时,检测算法。
否则,就是保存的代码导致问题,故需要检测保存代码。
由于算法比较复杂,且没有具体例子,故无法协助检测。
用point 方法太慢了,还是用api的getDIBits和setDIBits吧,彩图转灰度图的代码如下:
Private Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Private Declare Function SetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BitMapInfo, ByVal wUsage As Long) As Long
Private Declare Function SetDIBits Lib "gdi32" (ByVal hdc As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BitMapInfo, ByVal wUsage As Long) As Long
Private Type BitMapInfoHeader ''文件信息头——BITMAPINFOHEADER
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Private Type RGBQuad
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
''rgbReserved As Byte
End Type
Private Type BitMapInfo
bmiHeader As BitMapInfoHeader
bmiColors As RGBQuad
End Type
Private Sub Command1_Click()
Dim ix As Integer
Dim iy As Integer
Dim iWidth As Integer '以像素为单位的图形宽度
Dim iHeight As Integer '以像素为单位的图形高度
Dim bytGray As Byte
Dim bytThreshold As Byte
Dim bits() As Byte '三维数组,用于获取原彩色图像中各像素的RGB数值以及存放转化后的灰度值
Dim bitsBW() As Byte '三维数组,用于存放转化为黑白图后各像素的值
'获取图形的宽度和高度
iWidth = Picture1ScaleWidth / ScreenTwipsPerPixelX
iHeight = Picture1ScaleHeight / ScreenTwipsPerPixelY
Picture1Picture = Picture1Image
'创建并初始化一个bitMapInfo自定义类型
Dim bi24BitInfo As BitMapInfo
With bi24BitInfobmiHeader
biBitCount = 32
biCompression = 0&
biPlanes = 1
biSize = Len(bi24BitInfobmiHeader)
biWidth = iWidth
biHeight = Picture1ScaleHeight / ScreenTwipsPerPixelY
End With
'重新定义数组大小
ReDim bits(3, 0 To iWidth, 0 To iHeight) As Byte
ReDim bitsBW(3, 0 To iWidth, 0 To iHeight) As Byte
'使用GetDIBits方法一次性获取picture1中各点的rgb值,比point方法或getPixel函数逐像素获取像素rgb要快出一个数量级
lrtn = GetDIBits(Picture1hdc, Picture1PictureHandle, 0&, iHeight, bits(0, 0, 0), bi24BitInfo, 0&)
'数组的三个维度分别代表像素的RGB分量、以图形左下角为原点的X和Y坐标。
'具体说来,这时bits(0,2,3)代表从图形左下角数起横向第2个纵向第3个像素的Blue值,而bits(1,2,3)和bits(2,2,3)分别的Green值和Red值
bytThreshold = 128 '这里定义转换为黑白图像时的阈值为128,即灰色亮度大于128的像素转为白色,小于128的像素转为黑的,此值可根据需要修改为0-255之前任意数值
For ix = 0 To iWidth
For iy = 0 To iHeight
'RGB转为灰度的算法有多种,这里给出常见的两种
'bytGray = bits(0, ix, iy) 011 + bits(1, ix, iy) 059 + bits(2, ix, iy) 03 '这是传统的根据三原色亮度加权得到灰阶的算法
bytGray = (bits(0, ix, iy) ^ 22 00722 + bits(1, ix, iy) ^ 22 07152 + bits(2, ix, iy) ^ 22 02126) ^ (1 / 22) '这是简化 sRGB IEC61966-21 [gamma=220],有点类似于photoshop中所用的算法
bits(0, ix, iy) = bytGray
bits(1, ix, iy) = bytGray
bits(2, ix, iy) = bytGray
'转为黑白图像
If bits(0, ix, iy) < bytThreshold Then
bitsBW(0, ix, iy) = 0
bitsBW(1, ix, iy) = 0
bitsBW(2, ix, iy) = 0
Else
bitsBW(0, ix, iy) = 255
bitsBW(1, ix, iy) = 255
bitsBW(2, ix, iy) = 255
End If
Next
Next
'将灰度图显示到picture2中
Picture2Picture = Picture2Image '如果picture2的picture属性为空,需要在setDIBits之前将其picture属性设置一下,否则无法显示出图形
SetDIBits Picture2hdc, Picture2PictureHandle, 0&, iHeight, bits(0, 0, 0), bi24BitInfo, 0&
Picture2Picture = Picture2Image
'将黑白图显示到picture3中
Picture3Picture = Picture3Image
SetDIBits Picture3hdc, Picture3PictureHandle, 0&, iHeight, bitsBW(0, 0, 0), bi24BitInfo, 0&
Picture3Picture = Picture3Image
End Sub
代码运行很快,如图所示基本可瞬间完成
(一)功能
实现了一个定时截取当前屏幕图像的小程序。
(二)准备工作
1)建立VC CONSOLE APPLICATION,选择MFC SUPPORT
2)在STDAFXH文件中加入头文件:conioh
(三)主程序
主程序代码如下:
char Filename[100];
int count = 0;
while(!_kbhit())//用户按键则退出
{
Sleep(5000);//挂起5秒
count ++;
sprintf(Filename, "%dbmp", count);
Screen(Filename);//调用Screen函数
}
以上代码每隔5秒钟调用一次函数Screen,将当前屏幕保存到文件中。
(四)工作函数Screen
Screen实现了当前屏幕内容到bmp文件的拷贝。
源代码如下:
void Screen(char filename[])
{
CDC pDC;//屏幕DC
pDC = CDC::FromHandle(GetDC(NULL));//获取当前整个屏幕DC
int BitPerPixel = pDC->GetDeviceCaps(BITSPIXEL);//获得颜色模式
int Width = pDC->GetDeviceCaps(HORZRES);
int Height = pDC->GetDeviceCaps(VERTRES);
cout << "当前屏幕色彩模式为" << BitPerPixel << "位色彩" << endl
<< "屏幕宽度:" << Width << endl
<< "屏幕高度:" << Height << endl << endl;
CDC memDC;//内存DC
memDCCreateCompatibleDC(pDC);
CBitmap memBitmap, oldmemBitmap;//建立和屏幕兼容的bitmap
memBitmapCreateCompatibleBitmap(pDC, Width, Height);
oldmemBitmap = memDCSelectObject(&memBitmap);//将memBitmap选入内存DC
memDCBitBlt(0, 0, Width, Height, pDC, 0, 0, SRCCOPY);//复制屏幕图像到内存DC
//以下代码保存memDC中的位图到文件
BITMAP bmp;
memBitmapGetBitmap(&bmp);//获得位图信息
FILE fp = fopen(filename, "w+b");
BITMAPINFOHEADER bih = {0};//位图信息头
bihbiBitCount = bmpbmBitsPixel;//每个像素字节大小
bihbiCompression = BI_RGB;
bihbiHeight = bmpbmHeight;//高度
bihbiPlanes = 1;
bihbiSize = sizeof(BITMAPINFOHEADER);
bihbiSizeImage = bmpbmWidthBytes bmpbmHeight;//图像数据大小
bihbiWidth = bmpbmWidth;//宽度
BITMAPFILEHEADER bfh = {0};//位图文件头
bfhbfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//到位图数据的偏移量
bfhbfSize = bfhbfOffBits + bmpbmWidthBytes bmpbmHeight;//文件总的大小
bfhbfType = (WORD)0x4d42;
fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);//写入位图文件头
fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);//写入位图信息头
byte p = new byte[bmpbmWidthBytes bmpbmHeight];//申请内存保存位图数据
GetDIBits(memDCm_hDC, (HBITMAP) memBitmapm_hObject, 0, Height, p,
(LPBITMAPINFO) &bih, DIB_RGB_COLORS);//获取位图数据
fwrite(p, 1, bmpbmWidthBytes bmpbmHeight, fp);//写入位图数据
delete [] p;
fclose(fp);
memDCSelectObject(oldmemBitmap);
}
(五)改进
可以在系统热键中加入自定义热键,进行动态的(按用户需要的)截屏 *** 作。
以上就是关于c++中GetBitmapBits(hbmp,382822,outBuffer)全部的内容,包括:c++中GetBitmapBits(hbmp,382822,outBuffer)、C++读取BMP图像、VC++图像处理中对BItmap文件结构的读取等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)