Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

[GDI] Полупрозрачная надпись


Страницы:   1 2

Kerk ©   (2005-10-11 19:59:00) 

сабж. как сделать?


Fenik   (2005-10-30 10:55:00) [1]

> Antonn ©  (30.10.05 06:05) [30]
> одно но, моя процедурка не подгоняет битмап вывода под свой размер, битмап вращается не только относительно центра, и накладывает с "прозрачным цветом".


Это да. У меня была несколько иная задача.


Antonn   (2005-10-30 06:05:00) [2]

Fenik ©   (30.10.05 0:33) [29]
Быстрее твоего  на 30-40%.

и даже больше, по крайней мере на 999 копированиях битмапов 256х256:)
одно но, моя процедурка не подгоняет битмап вывода под свой размер, битмап вращается не только относительно центра, и накладывает с "прозрачным цветом".


Fenik   (2005-10-30 00:33:00) [3]

> Antonn ©
> Я вот чем сильно интерсуюсь - быстрый поворот изображения, быстрее чем у меня. Может позаменять функции на ассемблер? Жаль только, я его не знаю:(


Воть:

procedureRotateOptimized(Src, Dest: TBitmap; Angle: Double; BackColor: TColor);
{
Angle - угол поворота, в градусах.
Для каждой точки результирующего растра (Dest) находится
соответствующая точка исходного (Src) по формуле:
XOld = XCenter + (XNew - XCenter)*Cos(A) - (YNew - YCenter)*Sin(A)
YOld = YCenter + (XNew - XCenter)*Sin(A) + (YNew - YCenter)*Cos(A)
Если найденая точка (XOld, YOld) не принадлежит исходному растру, то
точка (XNew, YNew) на результирующем растре закрашивается цветом BackColor.
-------
В данной процедуре XCenter и YCenter заданы по умолчанию как
середины ширины и высоты нового изображения соответственно.
-------
Для случаев 90, 180, 270 градусов лучше написать отдельные процедуры.
}
constDegToRad = Pi / 180;
type TRGBTripleArray = array[0..32768] ofTRGBTriple;
     PRGBTripleArray = ^TRGBTripleArray;
varDestRow: PRGBTriple;
   SrcRow:  PRGBTripleArray;
   BackRGB: TRGBTriple;
   X, Y, xOld, yOld, xNew, yNew: Integer;
   W, H, ICos, ISin: Integer;
   DCos, DSin, Left, Top: Extended;
begin
 W := Src.Width;
 H := Src.Height;
 BackRGB.rgbtRed   := Lo(BackColor);
 BackRGB.rgbtGreen := Lo(BackColor shr8);
 BackRGB.rgbtBlue  := Lo((BackColor shr8) shr8);
{ Определяем размеры результирующего растра }
 SinCos(Abs(Angle) * DegToRad, DSin, DCos);
 Dest.Width  := Round(Abs(W * DCos) + Abs(H * DSin));
 Dest.Height := Round(Abs(W * DSin) + Abs(H * DCos));
 Src.PixelFormat  := pf24Bit;
 Dest.PixelFormat := pf24Bit;

 SinCos(-Angle * DegToRad, DSin, DCos);
 ISin := Round(DSin * 65536);
 ICos := Round(DCos * 65536);
{ Выносим из цикла то, что можно вынести }
 Left := (W - Dest.Width * DCos + Dest.Height * DSin) / 2;
 Top  := (H - Dest.Width * DSin - Dest.Height * DCos) / 2;

  forY := 0 toDest.Height - 1 do begin
   DestRow := Dest.ScanLine[Y];
   xNew := Round((Left - (Y * DSin)) * 65536);
   yNew := Round((Top  + (Y * DCos)) * 65536);
    forX := 0 toDest.Width - 1 do begin
     xOld := xNew shr16; { N shr16  =  N div65536 }
     yOld := yNew shr16;
      if(xOld >= 0) and(xOld < W) and(yOld >= 0) and(yOld < H) then
      begin
       SrcRow   := Src.ScanLine[yOld];
       DestRow^ := SrcRow[xOld];
      end
      else
       DestRow^ := BackRGB;
     Inc(DestRow);
     Inc(xNew, ICos);
     Inc(yNew, ISin);
    end;
  end;
end;


Быстрее твоего  на 30-40%.
А если использовать TQuickPixels из статьи MBo, то даже моя функция работает в 2-4 раза быстрее, чем есть сейчас со ScanLine. Если же ещё сделать оптимизацию методов SetPixels24 и GetPixels24, то вообще космическая скорость будет :))


Fenik   (2005-10-25 22:51:00) [4]

> Antonn ©  (24.10.05 12:52) [25]
> как я понял, отличие от scanline лишь в универсальности.


А сравнить по скорости религия не позволяет?

> WondeRu ©  (25.10.05 12:02) [26]
> разумные доводы есть???


GDI+ вирусы в картинках запускает! :о))


Kerk   (2005-10-25 19:15:00) [5]

WondeRu ©   (25.10.05 12:02) [26]
разумные доводы есть???


Нефиг использовать малораспространенные технологии.


WondeRu   (2005-10-25 12:02:00) [6]

Kerk ©   (20.10.05 1:07) [10]
В топку.


разумные доводы есть???


Antonn   (2005-10-24 12:52:00) [7]

Fenik ©   (24.10.05 11:45) [24]
как я понял, отличие от scanline лишь в универсальности.


Fenik   (2005-10-24 11:45:00) [8]

http://www.delphimaster.ru/articles/pixels/index.html


Antonn   (2005-10-24 06:29:00) [9]

Fenik ©   (23.10.05 22:10) [20]
Видел статью MBo на этом сайте?

нет, не видел. а какая?


Kerk   (2005-10-24 01:56:00) [10]

Ну почему бы все это не обсудить в комментариях к исходнику в Кладовке? Они ж для того и нужны? :)

Комментируют что-то мало :(


Fenik   (2005-10-23 22:16:00) [11]

> Antonn ©  (23.10.05 20:09) [19]
> конечно нужно пересмотреть весь код, а то каждому пользователю необходимо копировать 400 раз картинку 800*600 :)


Не нужно 400 раз копировать, достаточно одного %-)

Out: 748 x 503
In:  640 x 480
Число итераций - 1

Fenik - 190,09 ms
Fenik - 150,46 ms
Fenik - 146,45 ms
----------
Среднее Fenik - 162,34 ms

Antonn - 200,27 ms
Antonn - 204,24 ms
Antonn - 200,64 ms
----------
Среднее Antonn - 201,72 ms

Fenik быстрее Anton на 19,52 %


Fenik   (2005-10-23 22:10:00) [12]

Я тоже потестировал :)
Celeron 600

Out: 1024 x 768
In:  545 x 385
Число итераций - 35

Fenik - 3275,88 ms
Fenik - 3220,36 ms
Fenik - 3215,20 ms
----------
Среднее Fenik - 3237,15 ms

Antonn - 4766,58 ms
Antonn - 4764,01 ms
Antonn - 4745,72 ms
----------
Среднее Antonn - 4758,77 ms

Fenik быстрее Anton на 31,98 %


Могу код теста привести.
Так что, думаю с ассемблером заморачиваться не стоит, а вот над элементарной оптимизацией подумать.

> Antonn ©  (23.10.05 20:09) [19]
> Я вот чем сильно интерсуюсь - быстрый поворот изображения, быстрее чем у меня. Может позаменять функции на ассемблер? Жаль только, я его не знаю:(


Видел статью MBo на этом сайте?


Antonn   (2005-10-23 20:09:00) [13]

Ан нет, провел тест еще раз, при довольно больших изображениях (800*600) и 400 копированиях. Появилось отличие в производительности на ~11%, конечно нужно пересмотреть весь код, а то каждому пользователю необходимо копировать 400 раз картинку 800*600 :)

Я вот чем сильно интерсуюсь - быстрый поворот изображения, быстрее чем у меня. Может позаменять функции на ассемблер? Жаль только, я его не знаю:(


Fenik   (2005-10-23 20:07:00) [14]

> Antonn ©  (23.10.05 19:53) [17]
> визуально - чувствую, программно - не-а:)


Надо изображения побольше брать, а компутер послабее.

Кстати, ещё можно избавиться от нескольких лишних присваиваний. Будет вот так:

x2 := x_corS + _x; // Избавление ещё от лишних сложений типа x + _x
 for x := x_corS to _B_in.Width - 1 - x_cor do begin
   with RowIn[x] do begin
     InBlue  := rgbtBlue;
     InGreen := rgbtGreen;
     InRed  := rgbtRed;
   end;
   if not ((InRed = rc1) and (InGreen = gc1) and (InBlue = bc1)) then
   with RowOut[x2] do begin
     _r := rgbtRed + Trunc((InRed - rgbtRed) * D);
     if _r > 255 then rgbtRed := 255
       else if _r < 0 then rgbtRed := 0
       else rgbtRed := _r;

     _g := rgbtGreen + Trunc((InGreen - rgbtGreen) * D);
     if _g > 255 then rgbtGreen := 255
       else if _g < 0 then rgbtGreen := 0
       else rgbtGreen := _g;

     _b := rgbtBlue + Trunc((InBlue - rgbtBlue) * D);
     if _b > 255 then rgbtBlue := 255
       else if _b < 0 then rgbtBlue := 0
       else rgbtBlue := _b;
   end;
   Inc(x2);
 end;


Antonn   (2005-10-23 19:53:00) [15]

Fenik ©   (23.10.05 19:35) [16]
Если _r > 255, то проверка на < 0 зачем-то тоже производится. Нафига?

ага, тут я точно пролетел:)

> Чувствуешь разницу? :)

визуально - чувствую, программно - не-а:)
замерял через QueryPerformanceCounter, среднее от 200 копирований изображений 128*128. Разницы практически нет(т.е. она есть, но "скачет" от одного варианта, к другому, от теста к тесту). Может если отключить оптимизацию, то разница и будет. Я потому и бросил оптимизировать да ассемблерными вставками заменять, что все одно. Да и не такие уж тормоза, чтобы придераться к скорости выполнения:)


> ЗЫ: Подчеркивания _перед _именами _перемнных читаются
> просто ужасно!

_ну _не _знаю, мне наоборот проще такие выявлять, я так выделяю наиболее важные, _привычка:)


Fenik   (2005-10-23 19:35:00) [16]

Смотрим первую процедуру CopyTransparentBitmap:

        _r:= trunc(RowOut[x+_x].rgbtRed+(((RowIn[x].rgbtRed-RowOut[x+_x].rgbtRed) /100)*_transparent));

Почему бы в начале не завести такую вот переменную

D: Double;
...
D := _transparent / 100;


которая избавила бы нас от трех лишних делений при каждой итерации:

        _r:= trunc(RowOut[x+_x].rgbtRed+(RowIn[x].rgbtRed-RowOut[x+_x].rgbtRed) * D);

Потом лишние обращения к памяти через указатели тоже нехорошо. Ещё сложение можно вынести за перделы Trunc, чтобы оно было целочисленным. Получаем:

  OutRed := RowOut[x + _x].rgbtRed;
  InRed := RowIn[x].rgbtRed;
  _r := OutRed + Trunc((InRed - OutRed) * D);


Смотрим дальше:

       if _r>255 then _r:=255; if _r<0 then _r:=0;

Если _r > 255, то проверка на < 0 зачем-то тоже производится. Нафига?
Надо так:


  if _r > 255 then _r := 255
    else if _r < 0 then _r := 0;


Подытожим:

  x2 := x_corS + _x; // Избавление ещё от 6-и лишних сложений типа x + _x
  for x := x_corS to _B_in.Width - 1 - x_cor do begin
    with RowIn[x] do begin
      InBlue  := rgbtBlue;
      InGreen := rgbtGreen;
      InRed   := rgbtRed;
    end;
    if not ((InRed = rc1) and (InGreen = gc1) and (InBlue = bc1)) then
    begin
      OutRed := RowOut[x2].rgbtRed;
      _r := OutRed + Trunc((InRed - OutRed) * D);
      if _r > 255 then _r := 255
        else if _r < 0 then _r:=0;

      OutGreen := RowOut[x2].Green;
      _g := OutGreen + Trunc((InGreen - OutGreen) * D);
      if _g > 255 then _g := 255
        else if _g < 0 then _g := 0;

      OutBlue := RowOut[x2].rgbtBlue;
      _r := OutBlue + Trunc((InBlue - OutBlue) * D);
      if _b > 255 then _b := 255
        else if _b < 0 then _b := 0;

      RowOut[x2].rgbtRed   := _r;
      RowOut[x2].rgbtGreen := _g;
      RowOut[x2].rgbtBlue  := _b;
    end;
    Inc(x2);
  end;


Чувствуешь разницу? :)

---------
Ещё к примеру PrepareBitmapBluuum:

  _r:=trunc(_r/sqr(_persent*2+1));
  _g:=trunc(_g/sqr(_persent*2+1));
  _b:=trunc(_b/sqr(_persent*2+1));


Здесь опять тоже самое. Главное правило оптимизации: выноси за пределы цикла всё, что можно вынести:

var D: Double;
begin
  D := 1/sqr(_persent*2+1);
  ...
  ...
  _r := Trunc(_r * D);
  _g := Trunc(_g * D);
  _b := Trunc(_b * D);


D := 1/sqr.. сделано для того, чтобы в цикле использовать умножение вместо деления, т.к. умножение быстрее.
И так далее и тому подобное...

----
ЗЫ: Подчеркивания _перед _именами _перемнных читаются просто ужасно!


Antonn   (2005-10-23 18:14:00) [17]

Fenik ©   (23.10.05 17:49) [14]
Хоть бы маленько оптимизировал..

хоть чего оптимизировать? :)
обращение к width,height не такие и ресурсоемкие. куча проверок - для "безопасности" выполнения, чтоб без всяких АВ (я на этом помешан:)).


> Про оформление кода ваще молчу :))

Нет там оформления:) Я то все там понимаю, никого не заставляю ворошить его.
Вот ниче больше не положу:)


Fenik   (2005-10-23 17:49:00) [18]

> http://kladovka.net.ru/index.cgi?pid=list&rid=252

Хоть бы маленько оптимизировал..
Про оформление кода ваще молчу :))


Kerk   (2005-10-22 11:13:00) [19]

Собственно, вот:
http://kladovka.net.ru/index.cgi?pid=list&rid=252
:)


Antonn   (2005-10-20 03:20:00) [20]

выложил, модератор проверяет:)

там, кстати, не только прозрачный текст, но и под углом. Да и другие функции есть.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо