我有一个用 DSPACK 组件库编写的 Delphi6 DirectShow 过滤器(推送源视频过滤器)。在我的 FillBuffer() 调用中,在将修改后的位图输出到目标媒体样本之前,我在一些简单的代码中遇到了一个真正令人烦恼的问题。代码如下所示。
如您所见,这只是两个简单的循环,它们使用字节指针遍历 24 位位图中的 RGB 值。此代码在非 DirectShow 测试应用程序中运行良好。但是,在我的 DirectShow 过滤器中,无论使用什么值,我都看不到渲染位图中的任何变化。您甚至可以看到一条测试线,我只是将每个字节设置为 0。我仍然看到未修改的图像。为了确保我没有幻像或损坏的位图对象,我添加了一行以在位图上打印一个简单的句子。该句子确实显示在渲染的位图上。
更令人困惑的是,当此代码运行时,我每秒会收到数千个软页面错误,正如任务管理器所报告的那样。如果我禁用此代码,软页面错误就会消失。什么可能导致代码这样做?我跟踪了循环,确实看到每行之后字节值都发生了变化,但图像仍然不受影响。
最后,如果有人知道不使用 Scanline 进行像素访问的快速方法,我想知道。我通过 TBitmap.Scanline 进行了跟踪,它调用了 FreeImage。如果可以的话,我想尽量减少内存分配。我不能使用 GR32.TBitmap32,因为我使用的是 Synopse 的快速 jpeg 解码器,它不适用于 TBitmap32 对象。
更新:问题是我在访问 ScanLine 属性之前没有将位图的PixelFormat属性设置为 pf24Bit 。有关更多信息,请参阅此线程:像素修改代码在主应用程序中运行速度很快,在 Delphi 6 DirectShow 过滤器中运行速度非常慢,还有其他问题
procedure brightnessTurboBoost(var clip: TBitmap; rangeExpansionPowerOf2: integer; shiftValue: Byte);
var
p0: PByte;
x,y: Integer;
begin
if (rangeExpansionPowerOf2 = 0) and (shiftValue = 0) then
exit; // These parameter settings will not change the pixel values.
for y := 0 to clip.Height-1 do
begin
p0 := clip.scanline[y];
// Can't just do the whole buffer as a big block of bytes since the
// individual scan lines may be padded for CPU alignment.
for x := 0 to (clip.Width - 1) * 3 do
begin
if rangeExpansionPowerOf2 >= 1 then
p0^ := IntToByte((p0^ shl rangeExpansionPowerOf2) + shiftValue)
else
p0^ := IntToByte(p0^ + shiftValue);
// Test wiping the image (didn't work, still see image).
// p0^ := 0;
Inc(p0);
end;
end;
clip.Canvas.TextOut(10, 10, 'HELLO THERE IS THERE ANYONE THERE?');
end;