Delphi/C++ builder Windows 10 1709 位图操作极慢

标签 delphi c++builder tbitmap timagelist

有人遇到过这个问题吗? :

它是在 Windows 10 更新到 build 1709 后出现的。 经过一些系统运行时间(几个小时)后,位图加载、图像列表项添加变得非常慢。一张 256x256 BMP 的加载时间超过 10 秒……在这样做的同时,它占用了一个 CPU 核心 100%。 因此,原本在几秒钟内正常启动的已编译应用程序现在只需几分钟即可启动!

我经常使用休眠/恢复。 显示驱动程序已经使用一年多了,所以这不是问题。

对此有何评论?

更新: 我发现使用 Canvas.Pixels 的代码会发生这种情况,因此可以更改它,但速度仍然很慢。

更新2: 用扫描线操作代替可以加快速度。最近的 Windows 补丁一定会使 Canvas.Pixels 在大量使用时变得非常慢。

最佳答案

  1. GDI Canvas Pixels[x][y] 速度很慢。

    它执行许多您不知道的检查和颜色转换(实际上是数十个子调用,如果不是数百个)。这就是为什么它这么慢,这与Win10无关。这种行为从 Windows 启动起就一直存在,至少据我所知,这是 GDI 的问题,而不是 VCL 的问题(它与 Borland/Embarcadero VCL 无关) )。因此,请勿大量使用 Pixels[x][y]。在某些机器上,甚至以这种方式清除 1024x1024 图像也可能只需几秒的时间...

  2. VCL/GDI Bitmap ScanLine[y]

    这是 Borland/Embarcadero 特定的(在纯 GDI 上,您需要使用位锁定)。每个位图都有这个属性/函数,它返回指向任何y位图原始数据的指针。它与 Pixels[y][x] 一样慢,但如果您的位图没有更改其像素格式也没有调整大小,则指针仍然相同。

    这可用于直接像素访问,而不会影响性能。您只需记住每个位图调整大小/重新加载到自己的数组中的所有行即可。然后就使用它。如果使用得当,通常比 Pixels[x][y]~10000x 倍。

    我通常将 ScanLine 指针复制到 C++ 中我自己的数组,如下所示:

    // ok lests have some bitmap
    Graphics::TBitmap *bmp=new Graphics::TBitmap;
    bmp->Width=100;
    bmp->Height=100;
    // this is needed for direct pixel access after any LoadFromFile, Assign or resize 
    bmp->HandleType=bmDIB;    // allows use of ScanLine
    bmp->PixelFormat=pf32bit; // 32bit the same as int so we can use int* for pixels pointer
    
    DWORD **pyx=new DWORD*[bmp->Height];
    for (int y=0;y<bmp->Height;y++) pyx[y]=(DWORD*)bmp->ScanLine[y];
    
    // now we can render pixels fast like this:
    pyx[10][20]=0x0000FF00; // green dot at x=20, y=10
    // and also read it back fast:
    DWORD col=pyx[10][20];
    

    所以将其移植到Delphi。请注意,在某些像素格式上,颜色是 RGB 而不是 BGR(反之亦然),因此在某些情况下您需要反转 R,G,B 颜色顺序(尤其是预定义的颜色顺序)。

    由于没有检查,因此不要访问位图之外的像素,它很可能会引发访问冲突。

    最后,不要忘记在不再需要时(或在新分配之前)释放 pyx 数组

关于Delphi/C++ builder Windows 10 1709 位图操作极慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48883674/

相关文章:

delphi - Firemonkey组件中旋转时如何避免重复图像?

delphi - 为什么 Delphi 中的嵌套子例程会产生性能损失?

C++ 生成器或 Visual Studio

delphi - 是否可以在 Delphi 中平滑缩放的 TBitmap?

android - Delphi XE5 android 应用程序 keydown 和 keyup 事件

c - 如何将这个C函数指针转换为delphi函数

delphi - 释放 TBitmap 变量时出现访问冲突——释放后位图变量是否仍被分配?

c++ - 锁定后我应该解锁 TBitmap Canvas 吗?

c++ - 修复一些在 C++ 程序中扭曲字体的机器上的大系统字体?

具有 Fluent 界面的 C++ Builder 模式