Delphi / C++ Builder Операции с растровыми изображениями Windows 10 1709 чрезвычайно медленные
Кто-нибудь испытывал эту проблему?:
Он появился после обновления Windows 10 до сборки 1709. После некоторого времени загрузки системы - нескольких часов - загрузки растровых изображений, добавление элементов списка изображений становится чрезвычайно медленным. BMP 256x256 загружается более чем за 10 секунд... при этом он занимает одно ядро процессора на 100%. Таким образом, скомпилированные приложения, которые обычно запускаются за считанные секунды, теперь запускаются за считанные минуты!
Я регулярно использую спящий режим / резюме. Драйверы дисплея старше года, так что это не может быть проблемой.
Любой комментарий по этому поводу?
Обновление: я обнаружил, что это происходит с кодом, который использует Canvas.Pixels, так что его можно изменить, но при этом он сильно замедлился.
Обновление 2: замена операций Scanline ускорила работу. Недавний патч Windows, должно быть, сделал Canvas.Pixels действительно медленным при большем использовании.
1 ответ
GDI Canvas
Pixels[x][y]
медленный.Он выполняет много проверок и преобразований цветов, о которых вы даже не подозреваете (это буквально десятки промежуточных вызовов, если не сотни). Вот почему это так медленно, это не имеет значения, Win10. Такое поведение существует все время с момента запуска Windows, по крайней мере, насколько мне известно, это вопрос GDI, а не VCL (это не имеет никакого отношения к Borland/Embarcadero VCL). Так что не используйте
Pixels[x][y]
сильно. Даже очистка1024x1024
На некоторых машинах этот способ может занять считанные секунды...VCL / GDI Bitmap
ScanLine[y]
Это специфично для Borland/Embarcadero (на чистом GDI вместо этого вам нужно использовать битовую блокировку). Каждое растровое изображение имеет это свойство / функцию, которые возвращают указатель на необработанные данные растрового изображения для любого
y
, Это так медленно, какPixels[y][x]
но если ваше растровое изображение не меняет свой пиксельный формат и размер не изменяется, указатель остается прежним.Это может быть использовано для прямого пиксельного доступа без каких-либо потерь производительности. Вы просто помните, все строки в каждом растровом изображении изменяют размер / перезагружают в собственный массив как. И потом используйте именно это. Это обычно до
~10000x
в разы быстрееPixels[x][y]
если используется правильно.Я обычно копирую
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 (особенно предопределенных).
Поскольку нет никаких проверок, поэтому НЕ ДОПУСКАЙТЕ ПИКСЕЛЕЙ ВНЕ BITMAP, это, скорее всего, вызовет нарушение прав доступа.
И, наконец, не забудьте выпустить
pyx
массив, когда он больше не нужен (или перед новым распределением)