4

我有一个用 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;
4

1 回答 1

1

那么,您究竟是如何将IMediaSample缓冲区数据复制到TBitmap和向后复制的呢?最有可能的事情,实际上比其他任何事情都更有可能,是您正在更改副本,并且永远不会将更改翻转回您向下游传递的缓冲区。另外在处理过程中遇到页面错误(例如在来回转换图像数据时内存分配过多)。

于 2012-01-06T18:42:11.390 回答