如何获得TRGBTriple的画布?

时间:2014-08-02 19:05:42

标签: delphi canvas graphic

您好我使用此代码在画布上获取屏幕

procedure GetScreen(var vBitmap : TBitmap);
var vDC     : hdc;
    vCanvas : TCanvas;
begin
   vDC            := GetDC(0);
   vCanvas := TCanvas.Create;
   vCanvas.Handle := vDC;

   vBitmap.Canvas.CopyRect(Rect(0, 0, Screen.Width, Screen.Height),
                        vCanvas,
                        Rect(0, 0, Screen.Width, Screen.Height));

   vCanvas.Free;
   ReleaseDC(0, vDC);

end;
执行需要大约20 ms的

,让我在每个像素中运行并使用此函数与给定颜色进行比较

function CompareColor(Color1, Color2 : TRGBTriple): Double;
var vR, vG, vB : Byte;
begin
   vR := abs(Color1.rgbtRed - Color2.rgbtRed);
   vG := abs(Color1.rgbtGreen - Color2.rgbtGreen);
   vB := abs(Color1.rgbtBlue - Color2.rgbtBlue);

   Result := (((vR + vG + vB) / 3) / 255);
end;

但是因为我需要将每个TColor转换成TRGBTriple

vCorCmp.rgbtRed   := GetRValue(vBitmap.Canvas.Pixels[nX, nY]);
vCorCmp.rgbtGreen := GetGValue(vBitmap.Canvas.Pixels[nX, nY]);
vCorCmp.rgbtBlue  := GetBValue(vBitmap.Canvas.Pixels[nX, nY]);

我失去了超过一秒的时间来转换整个TCanvas,我的问题是,我怎样才能获得屏幕上的TRGBTriple数组而不是TColor数组呢?

2 个答案:

答案 0 :(得分:3)

TBitmap.Canvas.Pixels[]属性本质上很慢。要快速访问,您需要使用TBitmap.ScanLines属性:

type
  TRGBTripleArray = array[0..32767] of TRGBTriple;
  PRGBTripleArray = ^TRGBTripleArray;
var
  Pixels: PRGBTripleArray;
...
vBitmap.PixelFormat := pf24bit;
vBitmap.Canvas.CopyRect(Rect(0, 0, Screen.Width, Screen.Height),
                        vCanvas,
                        Rect(0, 0, Screen.Width, Screen.Height));
...
For nY := 0 to vBitmap.Height-1 do
begin
  pixels := PRGBTripleArray(vBitmap.Scanline[nY]);
  For nX := 0 to vBitmap.Width-1 do
  begin
    vCorCmp.rgbtRed   := pixels^[nX].rgbtRed;
    vCorCmp.rgbtGreen := pixels^[nX].rgbtGreen;
    vCorCmp.rgbtBlue  := pixels^[nX].rgbtBlue;
    ...
  end;
end;

或者,如果您使用的是Delphi 2009或更高版本:

{$POINTERMATH ON}

var
  Pixels: PRGBTriple;
...
vBitmap.PixelFormat := pf24bit;
vBitmap.Canvas.CopyRect(Rect(0, 0, Screen.Width, Screen.Height),
                        vCanvas,
                        Rect(0, 0, Screen.Width, Screen.Height));
...
For nY := 0 to vBitmap.Height-1 do
begin
  pixels := PRGBTriple(vBitmap.Scanline[nY]);
  For nX := 0 to vBitmap.Width-1 do
  begin
    vCorCmp.rgbtRed   := pixels[nX].rgbtRed;
    vCorCmp.rgbtGreen := pixels[nX].rgbtGreen;
    vCorCmp.rgbtBlue  := pixels[nX].rgbtBlue;
    ...
  end;
end;

有关详细信息,请参阅此处:

How to use ScanLine property for 24-bit bitmaps?

答案 1 :(得分:1)

而不是使用TBitmap使用Graphics32的TBitmap32(免费http://graphics32.org)。我已经在几个原型设计项目中使用它,并发现即使你使用.pixels作为简单代码,他的性能仍然比常规TBitmap快几倍。

TBitmap32.Canvas.pixels []会返回一个TColor32,您可以使用Color32ToRGB函数转换RGB组件或使用Color32ToRGBA转换RGB alpha。如果您不关心其他颜色组件,可以单独使用红色,绿色或蓝色。