-
Есть стандартный код, где нужно пройти по всем пикселям изображения и сделать что-нибудь с ними. Как его ускорить, оптимизировать, развернуть циклы и т.д.? Если изображение 32-bpp?
procedure DummyFX(Bmp: TBitmap);
var
P : PRGBA; X, Y: LongInt;
begin
For Y:= 0 to Bmp.Height - 1 do
begin
P:= Bmp.Scanline[Y];
For X:= 0 to Bmp.Width - 1 do
begin
P.R:= 255; P.G:= 0;
P.B:= 30;
P.A:= 30;
Inc(P);
end;
end;
end;
-
* Как ускорить ход?
Как ускорить код обработки всех пикселей?
-
Например, использовать SSE/MMX + проверить, эффективно ли будет развернуть циклы
-
распараллелить на несколько потоков.
-
Ещё применение CUDA/ OpenCL можно рассмотреть
-
> MBo © (04.03.13 14:40) [2]
Может еще есть какие варианты?
-
Зависит от: // Что-то делаем.
-
> MBo © (05.03.13 05:36) [6] > Зависит от:
Т.е. сам перебор всех пикселей не оптимизировать? Может ещё тормозить TBitmap, знаю внутри он не оптимален.
-
>Может ещё тормозить TBitmap, знаю внутри он не оптимален. Небольшое время расходуется на получение ScanLine, но на фоне времени обработки самой строки им обычно можно пренебречь. Если очень хочется, то можно получить адрес первой строки и смещение строк (оно обычно отрицательное) и работать как с обычным куском памяти.
-
Bmp.Width - обращается к методу, что тормозит вложенный цикл. Заменяем на локальную переменную. P:= Bmp.Scanline[Y]; - хотя тоже тормозит, но вызывается в Bmp.Width раз меньше.
For заменяем на repeat until. Раскрутка цикла. Но обычно это всё копейки ,так как то что внутри занимает раз в 10-100 больше времени. Остаётся только распараллеливание задачи.
-
>Bmp.Width - обращается к методу, что тормозит вложенный цикл. Заменяем на локальную переменную.
Не нужно
-
GetScanline - неимоверно тяжелая функция!
DIBNeeded, где CopyBitmap. GDIFlush. Высчитывает BytesPerScanline, который можно рассчитать заранее.
Закоментил первые и ничего не вылетало и продолжает работать! Но как сделать без правки VCL? В потомке нельзя перекрыть метод GetScanline.
Как быть?
-
>GetScanline - неимоверно тяжелая функция! Она что, тратит время, сравнимое с обработкой строки? Вот библиотека попиксельного доступа: http://www.delphimaster.ru/articles/pixels/index.htmlОднако она на каждом шаге вычисляет адрес пикселов. При произвольных обращениях к разным местам картинки QPixels работает быстрее сканлайна. При последовательной обработке строк чуть быстрее сканлайн.
-
> Как быть?
не вызывать GetScanline, вычислять указатели самостоятельно.
-
Я использую такой вот код procedure Loop2D_3(var r:TBitMap; bm1,bm2:TBitMap; proc1:TProcLoop2d_1;proc2:TProcLoop2d_2); Overload;
var i,j,k,p:Integer;
LL,uf:Integer;
p1,p2,p3:PAByte;
begin
LL:=DWord(bm1.ScanLine[1])-DWord(bm1.ScanLine[0]);
LL:=LL-1;
p1:=r.ScanLine[0];
p2:=bm1.ScanLine[0];
p3:=bm2.ScanLine[0];
j:=bm1.Height;
repeat
Proc1(LL,p1,p2,p3);
Inc(PByte(p1),LL);
Inc(PByte(p2),LL);
Inc(PByte(p3),LL);
dec(j);
until j=0;
end; Накладные расходы этого кода составляют 1% точность измерения 0,001 или 0,1%.
-
> MBo © (12.03.13 08:19) [12] > > >GetScanline - неимоверно тяжелая функция! > Она что, тратит время, сравнимое с обработкой строки? > > Вот библиотека попиксельного доступа: > http://www.delphimaster.ru/articles/pixels/index.html > Однако она на каждом шаге вычисляет адрес пикселов. При > произвольных обращениях к разным местам картинки QPixels > работает быстрее сканлайна. При последовательной обработке > строк чуть быстрее сканлайн.
Попиксельно не надо. > RWolf © (12.03.13 09:33) [13] > > > > Как быть? > > не вызывать GetScanline, вычислять указатели самостоятельно. >
Да, думаю сделать методы Lock(), Unlock. Побыстрее будет.
> Павиа (12.03.13 13:41) [14] > > Я использую такой вот код
А что это такое, не понял. Что в цикле? Эффект?
-
-
Считай на ГПУ, скорость в разы увеличится.
-
Удалено модератором
-
вообще по сокращению кода может ни чего не сделать, а вот по скорости можно. Если сократить количество циклов повторяющихся, если известно что количество циклов положительно, то разложить в цикле на два, если делится на 4, то разложить на 4 и т. д.
-
Кто-то поднял древнюю тему, спам опять лезет? От себя по теме могу добавить следующее:
> Может ещё тормозить TBitmap, знаю внутри он не оптимален.
Враньё. Обычная API-обёртка над HDC/HBITMAP/DIB, да, совсем слегка кривоватая, но ни об "тормозить" или "не оптимален" речь не идёт.
> Bmp.Width - обращается к методу, что тормозит вложенный цикл.
Тоже, извините, враньё. Возможно так будет если использовать Делфи3 (и старее), или полностью принудительно отключить оптимизатор, не знаю... Но Делфи7 и Берлин такого не допускают, я смотрел асм-код.
И вообще обычно тормозят вовсе не циклы, а именно это "что-то делаем", сравните вот скорости ваших обработок и просто заливку одним цветом.
Кстати вычитал на одном другом форуме что вместо прыганий со Scanline можно просто работать через TPNGObject.Pixels[].
-
Удалено модератором
|