问题
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:
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 clearing1024x1024
image this way can be a matter of around second on some machines...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 asPixels[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 thenPixels[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