GetPixel太慢,有什么快的方法?

ckc 2010-07-20 10:46:32
HBITMAP hbmp,hbmp2;
HDC hdc,hmemdc;
char *data,*p;

hdc=CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);
hmemdc=CreateCompatibleDC(hdc);
hbmp=CreateCompatibleBitmap(hdc,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
hbmp2=SelectObject(hmemdc,hbmp);
BitBlt(hmemdc,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),hdc,0,0,SRCCOPY);
hbmp=SelectObject(hmemdc,hbmp2);
data=calloc(3,GetSystemMetrics(SM_CXSCREEN)*GetSystemMetrics(SM_CYSCREEN));
GetBitmapBits(hbmp,px*py*3,data);

找了好多资料,写了上面的代码,按道理说已经把数据取到了data中了,可是验证却发现好象不对头
想问下这个错在哪里?
或者有好心人把能用的代码发一个给我,网上找到的大多都不全。
...全文
1099 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
dzq138 2012-05-18
  • 打赏
  • 举报
回复
CreateDIBSection 可在得到内存.
我测试的,用读内存会比GetPixel快三百倍以上..

大意是这样的:
bool CDZQRippleWnd::GetDCBitmapByte(CDC *pDstDC,BYTE *Bitmap,int iWidth,int iHeight)
{
int nSavedDC = pDstDC->SaveDC(); //保存原始DC
//拷屏,新建一个DC来拷贝目标区域
CDC bmpDC;
bmpDC.CreateCompatibleDC(pDstDC);
CBitmap bmp ;
bmp.CreateCompatibleBitmap(pDstDC , iWidth , iHeight);
CBitmap* pOldBmp = (CBitmap*)bmpDC.SelectObject(&bmp);
bmpDC.BitBlt(0 , 0 , iWidth , iHeight , pDstDC , iWidth, iHeight , SRCCOPY);
//获取bmpDC中的图形数据到BYTE数组
HDC hDIBDC = CreateCompatibleDC(NULL);
BITMAPINFO hdr;
ZeroMemory(&hdr , sizeof(BITMAPINFO));

hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
hdr.bmiHeader.biWidth = iWidth;
hdr.bmiHeader.biHeight = iHeight;
hdr.bmiHeader.biPlanes = 1;
hdr.bmiHeader.biBitCount = 32; /* 这里统一用位图形,原因是位图形结构相对固定,每个像素用个字节表示。每行末尾不需要添加额外的字节。而位图形,每行末尾需要添加额外的字节,以保证每行的字节数是的整数倍 如果想缩减开销和字节数,可以采用位的图形,不过就会多出一些判断添加额外自己的代码。*/

HBITMAP hDIBitmap = CreateDIBSection(hDIBDC, (BITMAPINFO *)&hdr, DIB_RGB_COLORS,(void **)&Bitmap, NULL, 0);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hDIBDC, hDIBitmap);
BitBlt(hDIBDC,0,0,iWidth,iHeight,bmpDC,0,0,SRCCOPY);
SelectObject(hDIBDC, hOldBmp);
return true;
}
jojjay 2010-07-20
  • 打赏
  • 举报
回复
fread读进来自己做提取函数!
Happy0403 2010-07-20
  • 打赏
  • 举报
回复
用GetDIBits
wltg2001 2010-07-20
  • 打赏
  • 举报
回复
GetPixel确实慢,有个API:GetDIBits也可以获取位图的数据,你试试
hastings 2010-07-20
  • 打赏
  • 举报
回复
另外:hdc=CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL);不是用来拷屏的。
用2楼的方法
hastings 2010-07-20
  • 打赏
  • 举报
回复
Note This function is provided only for compatibility with 16-bit versions of Windows. Applications should use the GetDIBits function.
littleplane 2010-07-20
  • 打赏
  • 举报
回复
getpixel是很慢,可以先拷屏,这样屏幕数据都到内存中了,速度还是很快的。
ckc 2010-07-20
  • 打赏
  • 举报
回复
如果分数不够可以另外开贴加分,这个版我最大只能100分
ckc 2010-07-20
  • 打赏
  • 举报
回复
各位,说详细点好吗?网上片言只语的文章已经太多啦,
我的要求就是找个比getpixel速度快的方法
不要MFC,vc6下面可以用的简单的方法,越简单越好
m_tornado 2010-07-20
  • 打赏
  • 举报
回复
记得CDC还有个GetCurrentBitmap
fishion 2010-07-20
  • 打赏
  • 举报
回复
真的是拷屏?如果是直接用HWND hwnd = ::GetDesktopWindow(); HDC hDC = ::GetDC(hwnd);得到桌面DC就可以了
littleplane 2010-07-20
  • 打赏
  • 举报
回复
你是想拷屏吗?我有一个资源就是拷屏的,你可以看一下,最后数据都在一个位图类里面
iamshuke 2010-07-20
  • 打赏
  • 举报
回复
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
);

正好我这里有示例代码,以前在CSDN上回复写的。
不过有人已经给出方向了,google一下GetDIBits能找到不少能用的代码,例如这个:
http://topic.csdn.net/t/20050218/15/3790238.html
不能指望每次提的问题都让别人给出严丝合缝的代码, 别人指出了正确的方向,咱们程序员就应该有能力去实现。

#include <math.h>
void CDibtestDlg::OnOK()
{
// TODO: Add extra validation here
HDC hDesktopDC = ::GetDC(NULL);
HDC hTmpDC = CreateCompatibleDC(hDesktopDC);
HBITMAP hBmp = CreateCompatibleBitmap(hDesktopDC, 500, 500); //500x500, 示例数据
SelectObject(hTmpDC, hBmp);
BitBlt(hTmpDC, 0, 0, 500, 500, hDesktopDC, 0, 0, SRCCOPY);
DeleteObject(hTmpDC);

BITMAP bm;
PBITMAPINFO bmpInf;
if(GetObject(hBmp,sizeof(bm),&bm)==0)
{
::ReleaseDC(NULL,hDesktopDC);
return ;
}

int nPaletteSize=0;
if(bm.bmBitsPixel<16)
nPaletteSize=(int)pow(2,bm.bmBitsPixel);

bmpInf=(PBITMAPINFO)LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER)+
sizeof(RGBQUAD)*nPaletteSize+(bm.bmWidth+7)/8*bm.bmHeight*bm.bmBitsPixel);

BYTE* buf=((BYTE*)bmpInf) +
sizeof(BITMAPINFOHEADER)+
sizeof(RGBQUAD)*nPaletteSize;

//-----------------------------------------------
bmpInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInf->bmiHeader.biWidth = bm.bmWidth;
bmpInf->bmiHeader.biHeight = bm.bmHeight;
bmpInf->bmiHeader.biPlanes = bm.bmPlanes;
bmpInf->bmiHeader.biBitCount = bm.bmBitsPixel;
bmpInf->bmiHeader.biCompression = BI_RGB;
bmpInf->bmiHeader.biSizeImage = (bm.bmWidth+7)/8*bm.bmHeight*bm.bmBitsPixel;
//-----------------------------------------------

if(!::GetDIBits(hDesktopDC,hBmp,0,(UINT)bm.bmHeight,buf,bmpInf,DIB_RGB_COLORS))
{
::ReleaseDC(NULL,hDesktopDC);
LocalFree(bmpInf);
return ;
}

::ReleaseDC(NULL,hDesktopDC);

CString sMsg;
sMsg.Format("BitsPixel:%d,width:%d,height:%d",
bm.bmBitsPixel,bm.bmWidth,bm.bmHeight);
AfxMessageBox(sMsg);

CClientDC dc(this);

int nOffset;
BYTE r,g,b;
int nWidth = bm.bmWidth*bm.bmBitsPixel/8;
nWidth = ((nWidth+3)/4)*4; //4字节对齐

if(bmpInf->bmiHeader.biBitCount == 8)
{
for(int i=0; i<bm.bmHeight; i++)
{
for(int j=0; j<bm.bmWidth; j++)
{
RGBQUAD rgbQ;
rgbQ = bmpInf->bmiColors[buf[i*nWidth+j]];
dc.SetPixel(j,bm.bmHeight-i,RGB(rgbQ.rgbRed,rgbQ.rgbGreen,rgbQ.rgbBlue)); //测试显示
}
}
}
else if(bmpInf->bmiHeader.biBitCount == 16)
{
for(int i=0; i<bm.bmHeight; i++)
{
nOffset = i*nWidth;
for(int j=0; j<bm.bmWidth; j++)
{
b = buf[nOffset+j*2]&0x1F;
g = buf[nOffset+j*2]>>5;
g |= (buf[nOffset+j*2+1]&0x03)<<3;
r = (buf[nOffset+j*2+1]>>2)&0x1F;

r *= 8;
b *= 8;
g *= 8;

dc.SetPixel(j, bm.bmHeight-i, RGB(r,g,b)); //测试显示
}
}
}
else if(bmpInf->bmiHeader.biBitCount == 24)
{
for(int i=0; i<bm.bmHeight; i++)
{
nOffset = i*nWidth;
for(int j=0; j<bm.bmWidth; j++)
{
b = buf[nOffset+j*3];
g = buf[nOffset+j*3+1];
r = buf[nOffset+j*3+2];

dc.SetPixel(j, bm.bmHeight-i, RGB(r,g,b)); //测试显示
}
}
}
else if(bmpInf->bmiHeader.biBitCount == 32)
{
for(int i=0; i<bm.bmHeight; i++)
{
nOffset = i*nWidth;
for(int j=0; j<bm.bmWidth; j++)
{
b = buf[nOffset+j*4];
g = buf[nOffset+j*4+1];
r = buf[nOffset+j*4+2];

dc.SetPixel(j, bm.bmHeight-i, RGB(r,g,b)); //测试显示
}
}
}

DeleteObject(hBmp);
LocalFree(bmpInf);

//CDialog::OnOK();
}
ckc 2010-07-20
  • 打赏
  • 举报
回复
我只需要读,不需要修改。
如果可以,给出能用的代码,只给出方向的就不麻烦啦
jameshooo 2010-07-20
  • 打赏
  • 举报
回复
1.GetDIBits把位图数据复制到内存缓冲
2.任意修改缓冲数据
3.SetDIBits把缓冲复制回DC

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧