0

这是关于 Delphi、32 位和 Windows/VCL:

对于接受输入位图并使用给定格式(PixelFormat:pf8Bit 带有灰度调色板)写入输出位图的过程,我使用以下代码:

procedure ConvertBitmap(_inBmp: TBitmap; _outBmp: TBitmap);
begin
  _outBmp.PixelFormat := pf8Bit;
  _outBmp.Palette := MakeGrayPalette();
  _outBmp.SetSize(_inBmp.Width, _inBmp.Height);
  // code that works on ScanLines goes here
end;

输出位图在传递到此过程时可能不是空的,但可能包含任何格式的任何内容。它将在程序中被完全覆盖。

我想知道简单地更改它的 PixelFormat 是否会产生一些开销(例如将旧内容转换为新的像素格式),所以我应该先以某种方式清除它,例如通过调用 _outBmp.SetSize(0, 0) 或任何其他方式?如果是,最有效的方法是什么?

编辑:

我只是用这段代码做了一些计时:

procedure TimingTest;
var
  Stopwatch1: TStopwatch;
  Stopwatch2: TStopwatch;
  bmp: TBitmap;
  i: Integer;
begin
  bmp := TBitmap.Create;
  try
    Stopwatch1 := TStopwatch.Create;
    Stopwatch2 := TStopwatch.Create;
    for i := 0 to 10 - 1 do begin
      bmp.PixelFormat := pf24bit;
      bmp.SetSize(16 * 1024, 8 * 1024);
      Stopwatch1.Start;
      bmp.PixelFormat := pf8bit;
      bmp.Palette := MakeGrayPalette();
      Stopwatch1.Stop;
    end;
    for i := 0 to 10 - 1 do begin
      bmp.PixelFormat := pf24bit;
      bmp.SetSize(16 * 1024, 8 * 1024);
      Stopwatch2.Start;
      bmp.SetSize(0, 0);
      bmp.PixelFormat := pf8bit;
      bmp.Palette := MakeGrayPalette();
      Stopwatch2.Stop;
    end;
    l_Timing.Caption := Format('%.3f [s] vs %.3f [s]', [
    Stopwatch1.ElapsedMilliseconds / 1000, Stopwatch2.ElapsedMilliseconds / 1000]);
  finally
    FreeAndNil(bmp);
  end;
end;

我电脑上的结果(并不慢):5.331 [s] vs. 0.322 [s]

除非我犯了一个实现错误,否则这非常重要。诚然,这是一个相当大的位图,但即使使用更合理的 4096x4096 尺寸,我也会得到 0.693 与 0.040,如果多次执行此操作(实际上是几百万次),这仍然很重要。

这以明确的“是”回答了是否存在性能影响的问题。

剩下的问题是: SetSize(0,0) 是清除位图的最有效方法还是有更好的方法?

编辑2:

TBitmap.Assign(nil) 是另一种清除位图的方法:

    for i := 0 to 10 - 1 do begin
      bmp.PixelFormat := pf24bit;
      bmp.SetSize(16 * 1024, 8 * 1024);
      Stopwatch3.Start;
      bmp.Assign(nil);
      bmp.PixelFormat := pf8bit;
      bmp.Palette := MakeGrayPalette();
      Stopwatch3.Stop;
    end;

时序类似于 .SetSize(0, 0)。

4

1 回答 1

0

我不知道答案,但测试有缺陷。第一组以 pf8bit 大小正确的位图结束,第二组是 pf8bit 0x0。这不一样。不知何故,您不会在那里分配 10 次 16*1024 x 8 *1024 = 128MB 位图。

最简单的选择当然是永远不要更改现有位图上的位图,而只需创建一个新位图。对于如此大的位图,如果您关心性能,则应不惜一切代价避免调整大小和更改像素类型。

于 2020-01-02T17:53:34.683 回答