【问题标题】:Fast way of swapping Red/Blue bytes using ScanLine使用 ScanLine 交换红/蓝字节的快速方法
【发布时间】:2012-01-19 19:06:26
【问题描述】:

目前,我循环 Canvas.Pixels[] 属性并读取画布上的每个像素以交换红色/蓝色字节(出于特定原因)。但是,每张图片平均需要 2 秒,而且我需要转换 8,000 多张图片(一夜之间)。我知道我可以使用ScanLine 的方法更快地完成这项工作,但我对ScanLine 一无所知 - 它的编码水平比我熟悉的要低得多。最快的方法是什么?我愿意等待一段时间来完成,但如果我能把这段时间切成两半或更多,那还是很好的。

现在,这是我使用的程序:

procedure SwapBytes(var Bmp: TBitmap);
var
  X, Y: Integer;
  R, G, B: Byte;
  C: TColor;
begin
  for Y := 0 to Bmp.Height - 1 do begin
    for X := 0 to Bmp.Width - 1 do begin
      C:= Bmp.Canvas.Pixels[X,Y];
      R:= GetRValue(C);
      G:= GetGValue(C);
      B:= GetBValue(C);
      Bmp.Canvas.Pixels[X,Y]:= RGB(B, G, R)
    end;
  end;
end;

补充说明:最初转换超过 8,000 张图像是我需要它的第一步。但是,我也将在我们的软件中使用相同的东西来根据需要在现场自动转换任何图像。所以第三方转换器无法工作,因为我无法将其分发给我们的客户。

【问题讨论】:

  • docwiki 中有一个示例显示使用 ScanLine 和访问 RGB 三元组。
  • 哦,您发现您正在编写一个实用程序来转换您的图像。 “我有超过 8,000 张图片需要转换(一夜之间)”。没关系。
  • @KenWhite 谢谢,正在调查...
  • Here 也是关于扫描线的好读物。
  • @Jerry Dodge,如果你破解了jpeg.pas 源,你甚至可能不需要这个......(请参阅你的其他问题)

标签: delphi colors pixel scanline


【解决方案1】:

我会尝试以下方法。此版本仅适用于 24 位位图:

procedure SwapRedBluePixels(ABitmap: TBitmap);
var
  X: Integer;
  Y: Integer;
  Red: Byte;
  Pixel: PRGBTriple;
begin
  // check for the bit depth, it must be 24-bit if you use PRGBTriple pointer
  // for line scan; if it wouldn't the iterated line pointers would point to 
  // another place in the memory
  if ABitmap.PixelFormat <> pf24bit then
  begin
    ShowMessage('Your bitmap has color depth different from 24-bit');
    Exit;
  end;
  // iterate through the image vertically
  for Y := 0 to (ABitmap.Height - 1) do
  begin
    // access the line of pixels and get the pointer to the first pixel of 
    // that line
    Pixel := ABitmap.ScanLine[Y];
    // iterate through the scanned line pixels horizontally
    for X := 0 to (ABitmap.Width - 1) do
    begin
      // store the pixel's red channel value
      Red := Pixel.rgbtRed;
      // modify the pixel's red channel value
      Pixel.rgbtRed := Pixel.rgbtBlue;
      // modify the pixel's blue channel value
      Pixel.rgbtBlue := Red;
      // increment to get the next pixel pointer of the scanned line
      Inc(Pixel);
    end;
  end;
end;

更新 2:

此版本适用于 24 位和 32 位位图:

procedure SwapRedBluePixels(ABitmap: TBitmap);
var
  X: Integer;
  Y: Integer;
  Red: Byte;
  Size: Integer;
  Pixels: PByteArray;
begin
  // check the color depth and set the size of the pixel arrangement
  case ABitmap.PixelFormat of
    pf24bit: Size := SizeOf(TRGBTriple);
    pf32bit: Size := SizeOf(TRGBQuad);
  else
    // if the image is not 24-bit or 32-bit go away
    begin
      ShowMessage('Your bitmap has unsupported color depth!');
      Exit;
    end;
  end;

  // iterate through the image vertically
  for Y := 0 to (ABitmap.Height - 1) do
  begin
    // access the line of pixels and get the pointer to the first pixel of
    // that line
    Pixels := ABitmap.ScanLine[Y];
    // iterate through the scanned line pixels horizontally
    // for 24-bit images the pixels are stored like
    // B -> G -> R -> B -> G -> R etc.
    // for 32-bit images the pixels are stored like
    // B -> G -> R -> A -> B -> G -> R -> A etc.
    // so we can simply use e.g. byte array and iterate through
    // it, if we have 24-bit image, we have to read each element,
    // if 32-bit we have to skip the alpha (reserved) channel
    for X := 0 to (ABitmap.Width - 1) do
    begin
      // store the pixel's red channel value
      Red := Pixels^[(X * Size) + 2];
      // modify the pixel's red channel value
      Pixels^[(X * Size) + 2] := Pixels^[(X * Size)];
      // modify the pixel's blue channel value
      Pixels^[(X * Size)] := Red;
    end;
  end;
end;

【讨论】:

  • 看起来不错,谢谢。但我只是想到了一些事情 - 有没有一种方法可以让 ScanLine 只读取一个通道(1 个红色通道和 1 个蓝色通道)然后交换这些行?
  • @Jerry 红色和蓝色没有单独的行。这是一行像素。位图就是这样。
  • @AndriyM 实际上不,这就是ScanLine 的美妙之处,它可以直接与它来自的图像一起工作。
  • @AndriyM,它们从未被取出。 :) ScanLine 是指向一行像素的实际位图内存的指针。
  • @François,非常好,谢谢。包含 alpha 的位图不太常见。最常见的是 24 位。我会稍微修改一下我的答案(我只是从我的旧帖子中复制的)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 1970-01-01
  • 1970-01-01
  • 2014-07-20
  • 2016-06-05
  • 2015-03-03
  • 1970-01-01
相关资源
最近更新 更多