Delphi图像处理中ScanLine的使用

发布时间 2023-11-14 22:07:17作者: 熊大熊二

一般我们在Delphi中进行图像处理时采用Pixels像素点赋值的方法,Delphi代码如下:

var
x,y:Integer;
cColor:TColor;
begin
  for y:=0 to Image1.Height-1 do
    for x:=0 to Image1.Width-1 do
      cColor:=Image1.Canvas.Pixels[i,j];
end;


但是这种方法有个缺点,处理速度很慢,小图像还可以,对于大点的图像来说就太慢了。
Delphi提供了一种扫描线ScanLine方法是对图像的一行进行扫描,获取本行中各像素的内存地址。众所周知,内存操作肯定会比常规的像素点赋值速度快很多,所以将大大提高图像的处理速度。

Delphi代码如下:

var
P:array[0..100] of PByteArray;//像素数组       
y:Integer;
begin
  for y:=0 to Bmp.Height-1 do
  begin
    P[y]:=Bmp.ScanLine[y];//将图片所有像素值存入P
  end;
end;


这样就将一个图像的所有像素都存入了P这个数组
在SysUtils单元中可以看出PByteArray实际上是一个Byte类型的数组
所以我们声明的P:array[0..100] of PByteArray;实际上可以看成是一个二维数组
P数组就是一个图像像素的缓冲区,它的一维是图像Y坐标,二维是图像的X坐标。
这样,如果我们要对图像的某个像素赋值,例如将第一行、第二列的像素赋值为白色,可用下面的Delphi代码

var
P:array[0..100] of PByteArray;//像素数组
x,y:Integer;
begin
  for y:=0 to Bmp.Height-1 do
  begin
    P[y]:=Bmp.ScanLine[y];//将图片所有像素值存入P
  end;
  y:=0;//第一行
  x:=1;//第二列
  P[y][x*3]:=255;//像素的第一字节
  P[y][x*3+1]:=255;//像素的第二字节
  P[y][x*3+2]:=255;//像素的第三字节
end;


上面的代码中,我们使用的图像是24位色的(TPixelFormat:=pf24bit),也就是一张真彩色的图片,pf24bit的图像中,每个像素在内存中占用三个字节,分别表示RGB值的分量,所以我们可以对三个字节直接赋值

在其它类型的图像中就不一定能这样赋值了

TPixelFormat:=pf1bit的图像(单色图)中每像素用1位来表示,所以要使用位操作来给像素赋值

TPixelFormat:=pf4bit的图像中每像素用4位来表示,也要使用位操作来给像素赋值

TPixelFormat:=pf8bit的图像中每像素用8位来表示,可以使用Byte类型的值给像素赋值,不过这类图像比较特殊,它的像素值并不是真正的颜色值,而只是调色板上颜色的索引值,这点要注意

TPixelFormat:=pf15bit的图像也是一种比较特殊的图像,它每像素用16位来表示,第1位为0,后15位每5位分别表示RGB值,所以也要使用位操作来给像素赋值

TPixelFormat:=pf16bit的图像中每像素用16位来表示,绿色占6位,其它红、蓝两种颜色占5位(为什么要这样?我也不知道,要问制定Bitmap格式的人了,据说是因为人眼对绿色比较敏感)

TPixelFormat:=pf24bit的图像每个像素用3个字节表示,这就不说了,参看上面的代码

TPixelFormat:=pf32bit的图像每个像素用4个字节表示,前面3个字节分别表示RGB值的分量,最后一个字节表示Alpha值