Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
300 views
in Technique[技术] by (71.8m points)

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

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
  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)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...