这是关于 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)。