Внезапно! "Патентованный" StretchBlt круто продул самоделке!

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Внезапно! "Патентованный" StretchBlt круто продул самоделке!

Сообщение Alex2013 » 17.02.2025 17:43:48

Честно говоря думал что будет наоборот...
Немного вдохновленный подсказками LLM и старым опытом работы с RawImage (через который идёт прямое обращение к данным картинки ) написал вот такой примитивный "уменьшитель"(почему "уменьшитель"? - Потому что чем меньше размер "исходящей" картинки тем быстрее эта крякозябра работает хотя написал я её с не целью добиться какого-то ускорения, а с надеждой уменьшить обращения к WinApi в многопоточном режиме)
Код: Выделить всё
Function ScaleNN(B:TBitmap;W,H:Integer):TBitmap;
    var
     SrcX,SrcY,x,y : Integer;
     C:Longint;
     bpp,bpl:integer;
     Rbpl:integer;
      PA:Pointer;
    begin

       Result := TBitmap.Create;
       Result.PixelFormat := b.PixelFormat;
       Result.SetSize(W, H);

   // Вставка для теста "StretchBlt"   
   //========================
   if  StdScaleMode then begin
       StretchBlt(Result.Canvas.Handle,0,0,Result.Width,Result.Height
             ,B.Canvas.Handle,0,0,b.Width,b.Height,  SRCCOPY  );
        exit;
       end ;
//-----------------
       BPP:= B.RawImage.Description.BitsPerPixel div 8;
       BPL:= B.RawImage.Description.BitsPerLine div 8;

       RBPL:= Result.RawImage.Description.BitsPerLine div 8;

       Result.BeginUpdate;

      for X := 0 to W - 1 do begin
      SrcX := trunc((X * B.Width )/ Result.Width);

      for Y := 0 to H - 1 do begin
       SrcY := trunc((Y * B.Height)/ Result.Height);

       PA:=Pointer(B.RawImage.Data)+(BPL*SrcY)+SrcX*BPP;
       move(PA^,C ,bpp);

      PA:=Pointer(Result.RawImage.Data)+(rBPL*Y)+(X*BPP);
      if Integer(Pa)-Integer(Result.RawImage.Data) < Result.RawImage.DataSize then
       begin
         move(C,PA^,bpp);
       end;

        end
      end;

      Result.EndUpdate;
    end;



Однако добившись более-мнение стабильной работы решил проверить стандартное масштабирование ( с мыслю "вдруг быстрее будет" )
Результат удивил!
Тест загрузки списка 2 StdScaleMode=true
Многопоточный
Время 7,85 c

Тест загрузки списка 2 StdScaleMode=false
Многопоточный
Время 4,43 c

Тест загрузки списка 2 StdScaleMode=true
Однопоточный
Время 23,18 c

Тест загрузки списка 2 StdScaleMode=false
Однопоточный
Время 12,38 c


Спрашивается что такое делает StretchBlt чтобы работать НАСТОЛЬКО (особенно если учесть, что там не только масштабирование крутится ) медленнее ? :roll:
( Всегда считал BitBilt/StretchBlt '"эталонном оптимизации" а тут такое ... ) :idea:
Зы
Хотя при работе в "сторону увеличения" ситуация может быть обратная но это вполне предсказуемо.
Alex2013
долгожитель
 
Сообщения: 3100
Зарегистрирован: 03.04.2013 11:59:44

Re: Внезапно! "Патентованный" StretchBlt круто продул самоде

Сообщение sts » 20.02.2025 09:40:14

А вы заметили что в нее передаются хендлы устройста HDC а не хендл битмапа HBITMAP? эти функции предназначены для работы с устройствами типа дисплей или принтер, битмапы есть двух видов DIB и DDB, может у вас они разные и тратится на перекодировку
sts
постоялец
 
Сообщения: 443
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Re: Внезапно! "Патентованный" StretchBlt круто продул самоде

Сообщение Alex2013 » 20.02.2025 21:35:20

sts писал(а):А вы заметили что в нее передаются хендлы устройста HDC а не хендл битмапа HBITMAP? эти функции предназначены для работы с устройствами типа дисплей или принтер, битмапы есть двух видов DIB и DDB, может у вас они разные и тратится на перекодировку

Это верная мысль но BitBilt/StretchBlt по идее используют аппаратное ускорение впрочем возможно никто особо не заморачивался оптимизации "уменьшения" ( Но кстати и мой код можно слегка оптимизировать , при уменьшении особо ничего не ускорить ( разве что вычисление адреса можно немного более оптимально переписать), а вот при увеличении можно заменить пиксели квадратиками правда не совсем ясно будет ли от этого выигрыш в скорости )

Зы
Кстати интересно как как не слишком тормозя улучшить качество ( особенно при уменьшении )?
Простейшая идея слегка сгладить картинку перед "окончательным масштабированием" (Стандартный "Гаусс" не подходит бо работает очень медленно но есть и SplitBlur который хоть и топорнее но точно быстрее еще есть AntiAlias но он довольно сомнителен )
Alex2013
долгожитель
 
Сообщения: 3100
Зарегистрирован: 03.04.2013 11:59:44

Re: Внезапно! "Патентованный" StretchBlt круто продул самоде

Сообщение sts » 21.02.2025 10:15:51

Alex2013 писал(а):Это верная мысль но BitBilt/StretchBlt по идее используют аппаратное ускорение впрочем возможно никто особо не заморачивался оптимизации "уменьшения"

не так, это означает например что к устройству одновременно могут быть обращения из разных потоков а значит есть оверхед с блокировкой, помнится я както наблюдал как две проги рисовали свои интерфейсы, сначала одна нарисует линию, потом другая и так по очереди, т.е. прежде чем вывести на устройство для каждой линии картинки идет захват мютекса, потом выводится линия картинки, потом освобождение мютекса и так для всех линий картинки.
в общем использование этих функций для генерации превьюшек, так сказать несколько оптимистично.
аппаратное ускорение используется если целевой HDC является железом с ускорителем

Добавлено спустя 3 часа 14 минут 57 секунд:
Re: Внезапно! "Патентованный" StretchBlt круто продул самоделке!
Alex2013 писал(а):Кстати интересно как как не слишком тормозя улучшить качество ( особенно при уменьшении )?

использовать GDIPlus он делает HDC с ускорением и для картинок в памяти
sts
постоялец
 
Сообщения: 443
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Снег Север и гости: 8

Рейтинг@Mail.ru