1

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

它出现在 Windows 10 更新构建 1709 之后。经过一些系统运行时间 - 几个小时 - 位图加载,图像列表项添加变得非常缓慢。一个 256x256 的 BMP 加载时间超过 10 秒……在执行此操作时,它会 100% 占用一个 CPU 内核。因此,可以在几秒钟内正常启动的已编译应用程序现在可以在几分钟内启动!

我经常使用休眠/恢复。显示驱动程序已有一年多的历史,因此这不是问题。

对此有何评论?

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

更新 2:替换为 Scanline 操作加快了速度。最近的 Windows 补丁一定让 Canvas.Pixels 在大量使用时变得非常缓慢。

4

1 回答 1

4
  1. GDI 画布Pixels[x][y]很慢。

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

  2. VCL/GDI 位图ScanLine[y]

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

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

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

    // 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在不再需要时(或在新分配之前)释放数组

于 2018-02-21T08:42:12.927 回答