首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

GetPixel的速度太慢了,请教怎么用GetDIBits解决这个有关问题

2012-03-05 
GetPixel的速度太慢了,请问如何用GetDIBits解决这个问题?声明:不想用TBitmap,务必用GetDIBits解决,怎么搞?

GetPixel的速度太慢了,请问如何用GetDIBits解决这个问题?
声明:不想用TBitmap,务必用GetDIBits解决,怎么搞?(也就是说只想用API搞定)

一下这段代码是我自己写的,对屏幕的每个点进行扫描。速度非常慢!!
即使把ListBox1.items.add(inttostr(Pix));注释掉,也要1分半钟左右,才能扫描完。
本人机器酷睿双核,4G内存,配置算是很不错了,还这么慢,怎么办?
procedure TForm1.Button1Click(Sender: TObject);
var
  X, Y: integer;
  iX, iY: integer;
  pix: DWORD;
  DC: HDC;
begin
  DC := GetDC(0);
  X := GetSystemMetrics(SM_CXSCREEN); //得到屏幕的宽度
  Y := GetSystemMetrics(SM_CYSCREEN); //得到屏幕的高度
  for iY := 4 to Y do //高度
  for iX := 1 to X do //宽度
  begin
  Pix := Windows.GetPixel(DC, iX, iY); 
  ListBox1.items.add(inttostr(Pix)); //输入每个像素点的颜色值
  end;
  Windows.ReleaseDC(0, DC);
end;

///////////////////////// 这里是重点了 /////////////////////////
查了资料后,才知道可以用GetDIBits这个API,但是用起来好复杂,
找到了C代码后,将它翻译成了Delphi代码,却不知道怎么将lpBuf里面的每个像素点输出了。
研究了整整2天,能查到的资料也非常少,跪求高手解决,300相送。

procedure TForm1.Button6Click(Sender: TObject);
const
  HEAP_ZERO_MEMORY = $8;
var
  b: BITMAPINFO;
  bb: bitmap;
  lpBuf: array of byte;
  _hbitmap, hold: hbitmap;
  _hdc, _hcdc: hdc;
  hp: thandle;
  dwx, dwy: dword;
begin
  dwX := GetSystemMetrics(SM_CXSCREEN);
  dwY := GetSystemMetrics(SM_CYSCREEN);
  _hDC := GetDC(0);
  _hcDC := CreateCompatibleDC(_hDC);
  _hBitmap := CreateCompatibleBitmap(_hDC, dwX, dwY);
  hOld := SelectObject(_hcDC, _hBitmap);

  BitBlt(_hcDC, 0, 0, dwX, dwY, _hDC, 0, 0, SRCCOPY);

  bb.bmWidth := dwX;
  bb.bmHeight := dwY;
  bb.bmPlanes := 1;
  bb.bmWidthBytes := bb.bmWidth * 3;
  bb.bmBitsPixel := 3;
  bb.bmType := 0;

  b.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
  b.bmiHeader.biWidth := dwX;
  b.bmiHeader.biHeight := dwY;
  b.bmiHeader.biPlanes := 1;
  b.bmiHeader.biBitCount := 24;
  b.bmiHeader.biCompression := BI_RGB;
  b.bmiHeader.biSizeImage := 0;
  b.bmiHeader.biXPelsPerMeter := 0;
  b.bmiHeader.biYPelsPerMeter := 0;
  b.bmiHeader.biClrUsed := 0;
  b.bmiHeader.biClrImportant := 0;
  b.bmiColors[0].rgbBlue := 8;
  b.bmiColors[0].rgbGreen := 8;
  b.bmiColors[0].rgbRed := 8;
  b.bmiColors[0].rgbReserved := 0;
  hp := GetProcessHeap;

  lpBuf := HeapAlloc(hp, HEAP_ZERO_MEMORY, bb.bmHeight * bb.bmWidth * 4);
  GetDIBits(_hcDC, _hBitmap, 0, dwY, lpBuf, b, DIB_RGB_COLORS);

  for x := 1 to dwX do //////////// 这里到底应该怎么输入每个像素点的颜色值啊???
  for y := 1 to dwY do /// 难道是我的代码没翻译好?????????
  ListBox1.Items.Add(lpBuf[x, y]); //输入每个像素点的颜色


  ReleaseDC(0, _hDC);
  DeleteDC(_hcDC);
  DeleteObject(_hBitmap);
  DeleteObject(hOld);
  HeapFree(hp, 0, lpBuf);
end;

///////////////////////// 这里是重点了 /////////////////////////
查了资料后,才知道可以用GetDIBits这个API,但是用起来好复杂,
找到了C代码后,将它翻译成了Delphi代码,却不知道怎么将lpBuf里面的每个像素点输出了。
研究了整整2天,能查到的资料也非常少,跪求高手解决。
声明:不想用TBitmap,务必用GetDIBits解决,怎么搞?

[解决办法]

Delphi(Pascal) code
var  saveBitmap, Bitmap: HBITMAP;  memDC: HDC;  DC: HDC;  bmi: TBitmapInfo;  Buf: Pointer;  p: PRGBTriple;  Stride, Offset: Integer;  x, y: Integer;  w, h: Integer;begin  w := GetSystemMetrics(SM_CXSCREEN);   h := GetSystemMetrics(SM_CYSCREEN);  Stride := ((w * 24 + 31) and $ffffffe0) shr 3;  GetMem(Buf, h * Stride);  try    DC := GetDC(0);    Bitmap := CreateCompatibleBitmap(DC, w, h);    try      memDC := CreateCompatibleDC(DC);      saveBitmap := SelectObject(memDC, Bitmap);      try        BitBlt(memDC, 0, 0, w, h, DC, 0, 0, SRCCOPY);      finally        SelectObject(memDC, saveBitmap);        DeleteDC(memDC);      end;      bmi.bmiHeader.biSize := Sizeof(TBitmapInfoHeader);      bmi.bmiHeader.biWidth := w;      bmi.bmiHeader.biHeight := h;      bmi.bmiHeader.biPlanes := 1;      bmi.bmiHeader.biBitCount := 24;      bmi.bmiHeader.biCompression := BI_RGB;      GetDIBits(DC, Bitmap, 0, h, Buf, bmi, DIB_RGB_COLORS);    finally      DeleteObject(Bitmap);      ReleaseDC(0, DC);    end;  // 因为屏幕像素点数量在100万以上,下面这段代码可能造成程序没反应,如果要用这段代码测试一下,可把前面的w,h分别改为100{    Offset := Stride - bmi.bmiHeader.biWidth * 3;    p := Buf;    for y := 1 to h do    begin      for x := 1 to w do      begin         ListBox1.Items.Add(IntToStr(RGB(p^.rgbtRed, p^.rgbtGreen, p^.rgbtBlue)));         Inc(p);      end;      Inc(Integer(p), Offset);    end;}  finally    FreeMem(Buf);  end;end; 

热点排行