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

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

Вывод картинки с прозрачным цветом - сдела криво, как правильнее?


TheEd ©   (2012-09-19 12:03:00) 

Господа Мастера!
В двух словах есть компонент, в задачи которого входит вывести на свою канву сначала фоновый TImage, потом как бы поверх него (в реальности на ту же канву), некоторый TPicture так, чтобы определённый цвет не выводился (был бы прозрачным).
Помучившись и не найдя другого решения, я сделал так:
ввел два дополрительных TBitmap в которых храню маски для дальнейшего комбинирования OR'ом и AND'ом. Получилось вот что:

   FBackImage      : TImage; // фоновый пикчур
   FImageUp        : TPicture; // пикчур что выводится поверх
   FTransparentColorUp : TColor; // прозрачный цвет пикчура
   FBackImageMaskUpAND       : TBitmap; // маски
   FBackImageMaskUpOR        : TBitmap;  // маски
...
  // выводим фон
 CopyMode := cmSrcCopy;
 CopyRect(myRect, BackImage.Picture.Bitmap.Canvas, SomeRect);
  // вычисляем маски - это жесть :)
 if (FImageUp.Bitmap <> nil) and (not FImageUp.Bitmap.Empty) then
   with FImageUp.Bitmap do
   begin
     FBackImageMaskUpAND.Width := Width;
     FBackImageMaskUpAND.Height := Height;
     FBackImageMaskUpOR.Width := Width;
     FBackImageMaskUpOR.Height := Height;
     for i := 0 to Width - 1 do
       for j := 0 to Height - 1 do
         if  Canvas.Pixels[i, j] = FTransparentColorUp
           then begin
             FBackImageMaskUpOR.Canvas.Pixels[i,j] := $00000000;
             FBackImageMaskUpAND.Canvas.Pixels[i,j] := $00FFFFFF;
           end
           else begin
             FBackImageMaskUpOR.Canvas.Pixels[i,j] := $00FFFFFF;
             FBackImageMaskUpAND.Canvas.Pixels[i,j] := Canvas.Pixels[i, j];
           end;
   end;
  // выводим пикчур
 CopyMode := cmSrcPaint;
 CopyRect(SomeRect1, FBackImageMaskUpOR.Canvas, SomeRect2);
 CopyMode := cmSrcAnd;
 CopyRect(SomeRect1, FBackImageMaskUpAND.Canvas, SomeRect2);


Данный код тормозит при старте т.к. компонентов несколько десятков, и каждый вычисляет свои маски.
Совершенно очевидно что есть более "правильный способ". Помогите плиз!


TheEd   (2012-09-20 12:56:00) [1]


> Автоматическое масштабирование прозрачности — в любом случае
> тема больная...

да, согласен - огород я в своё время нагородил (см. пост 1) аж ужас. Но решение найдено (пост 9) теперь вроде гемор снят с повестки дня...
Всем поучавствовашим - большое спасибо!


брат Птибурдукова   (2012-09-19 20:50:00) [2]


> TheEd   (19.09.12 18:26) [7]
Автоматическое масштабирование прозрачности — в любом случае тема больная...


TheEd   (2012-09-19 19:16:00) [3]


> Более 9000 раз. Я гарантирую это.

спасибо, поэкспериментирую.

Кстати нашёл метод как обойти маштабирование с транспарентом: завожу второй битмап нужного размера, на него CopyRect'ом втискиваю пикчур, а потом его рисую Draw'ом на нужную канву. Примерно так:
procedure TForm1.Button6Click(Sender: TObject);
var
 b1, b2 : TBitMap;
begin
 b1 := TBitmap.Create;
 b2 := TBitmap.Create;
 try
   with b2 do
     LoadFromFile('C:\SomePicture.bmp');
   with b1 do
   begin
     PixelFormat := pf32bit;
     HandleType := bmDIB;
     Width := b2.Width * 2;
     Height := b2.Height div 2;
     Transparent := TRUE;
     TransparentColor := clWhite;
   end;
   with b1.Canvas do
     CopyRect(Rect(0,0,b1.Width,b1.Height), b2.Canvas, Rect(0,0,b2.Width,b2.Height));
   Canvas.Draw(50,50,b1);
 finally
   b1.Free;
   b2.Free;
 end;
end;


Dimka Maslov   (2012-09-19 18:53:00) [4]


> Насколько это будет быстрее чем доступ к пикселам канвы


Более 9000 раз. Я гарантирую это.

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


TheEd   (2012-09-19 18:26:00) [5]

Так, косячок - вспомнил наконец то в чём:
я использовал не Canvas.Draw, а Canvas.CopyRectдля того, чтобы мастшабировать пикчур при выводе! Draw работает без проблем, а вот CopyRect - льёт без учёта транспарента :(


TheEd   (2012-09-19 17:27:00) [6]


> Плохиш ©   (19.09.12 15:54) [5]
> первая же ссылка с примером, буквально, из 3х строк.

Спасибо, кажется то что надо, счас буду пробовать!


Плохиш   (2012-09-19 15:54:00) [7]

http://www.google.de/#hl=de&sclient=psy-ab&q=delphi%20draw%20bitmap%20transparent&oq=&gs_l=&pbx=1&bav=on.2,or.r_gc.r_pw.r_qf.&fp=8e4aa2aca92b6bd5&bi w=1034&bih=592&pf=p&pdl=300

первая же ссылка с примером, буквально, из 3х строк.


TheEd   (2012-09-19 15:41:00) [8]


> У TBitmap есть свойства TransparentMode и TransparentColor

да, но я как только его не пробовал прорисовывать, оно не работает в методе CopyRect... Если я не прав - ткните плиз носом.


TheEd   (2012-09-19 15:38:00) [9]


> Для битмапов - см в сторону ScanLine

Как я понял ScanLine вернёт указатель на область памяти которую всё же перебирать побайтно надо. Насколько это будет быстрее чем доступ к пикселам канвы?


Dimka Maslov   (2012-09-19 13:46:00) [10]

У TBitmap есть свойства TransparentMode и TransparentColor


icWasya   (2012-09-19 13:40:00) [11]

Для битмапов - см в сторону ScanLine


Наверх

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