这是关于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;
输出位图在传递给此过程时可能不为空,但可能包含任何格式的任何内容。它将在过程中被完全覆盖。
我想知道简单地更改其像素格式是否会产生一些开销(例如将旧内容转换为新像素格式(,那么我是否应该先以某种方式清除它,例如通过调用 _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 对比 0.322
除非我犯了实现错误,否则这非常重要。诚然,这是一个相当大的位图,但即使有 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;
时间与 类似。设置大小(0, 0(。
我不知道答案,但测试是有缺陷的。第一组以 pf8 位正确大小的位图结束,第二组以 pf8 位0x0结束。这是不一样的。不知何故,您不会在那里分配 10 倍 16*1024 x 8 *1024 = 128MB 位图。
最简单的选择当然是永远不要更改现有位图上的位度,而只需创建一个新位图。对于如此大的位图,如果您关心性能,则应不惜一切代价避免调整大小和更改像素类型。