Delphi / C++ builder Windows 10 1709 bitmap operations extremely slow

筅森魡賤 提交于 2019-12-01 11:04:23

问题


Anyone experienced this problem? :

It appeared after Windows 10 update to build 1709. After some system up time - a few hours -, bitmap loadings, imagelist item adding gets extremely slow. A 256x256 BMP loads in more than 10 seconds...while doing this, it occupies one CPU core 100%. So compiled applications that start up normally in seconds now start up in minutes!

I use hibernation/resume regularly. Display drivers are more than a year old, so that can't be the problem.

Any comment on this?

Update: I found that this happens with code that use Canvas.Pixels, so that can be changed, still it slowed down very much.

Update 2: Replacing with Scanline operations speeded up things. Recent Windows patch must have made Canvas.Pixels really slow on larger amount use.


回答1:


  1. GDI Canvas Pixels[x][y] is slow.

    It performs many checks and color conversions you have no idea (it is literally tens of subcalls if not hundreds). That is why it is so slow it is not matter of Win10. this behavior is there all the time from windows start at least to my knowledge it is matter of GDI not VCL (it has nothing to do with Borland/Embarcadero VCL). So do not use Pixels[x][y] heavily. Even clearing 1024x1024 image this way can be a matter of around second on some machines...

  2. VCL/GDI Bitmap ScanLine[y]

    This is Borland/Embarcadero specific (on pure GDI you need to use bits locking instead). Each bitmap has this property/function which return pointer to raw data of the bitmap for any y. It is as slow as Pixels[y][x] but if your bitmap does not change its pixel format nor it is resized then the pointer is still the same.

    This can be used for direct pixel access without any performance hits. You just remember all lines at each bitmap resize/reload into own array like. And afterwards use just that. That is usually up to ~10000x times faster then Pixels[x][y] if used properly.

    I usually copy ScanLine pointers to my own array in C++ like this:

    // 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];
    

    So port it to Delphi. Just beware that on some pixel formats the colors are RGB instead of BGR (or vice versa) so in some cases you need to reverse R,G,B order of colors (especially the predefined ones).

    As there are no checks so DO NOT ACCESS PIXELS OUTSIDE BITMAP it would most likely throw an access violation.

    And lastly do not forget to release the pyx array when not needed anymore (or before new allocation)



来源:https://stackoverflow.com/questions/48883674/delphi-c-builder-windows-10-1709-bitmap-operations-extremely-slow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!