Autor Téma: Jak vykreslit otočený PNG s průhledností  (Přečteno 401 krát)

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 765
  • Karma: 43
    • Verze Delphi: 10.3
Jak vykreslit otočený PNG s průhledností
« kdy: 16-12-2018, 20:10:40 »
Ahoj,

potřeboval bych načíst PNG soubor, který obsahuje průhlednost (alpha kanál), a ten pak vykreslit na tCanvas otočený. Při testování jsem zkoušel něco takového:

Kód: Delphi [Vybrat]
  1. ...
  2.     Obrazek:tPngImage;
  3. ...
  4.  
  5. procedure TMainForm.FormCreate(Sender: TObject);
  6.  begin
  7.  Obrazek:=TPngImage.Create;
  8.  Obrazek.LoadFromFile(ExtractFilePath(ParamStr(0))+'strom.png');
  9. end;
  10.  
  11. procedure TMainForm.PaintBox1Paint(Sender: TObject);
  12.  var Cil:tCanvas;
  13.      r:tRect;
  14.      a:integer;
  15.      xForm:TXForm;
  16.      Si,Co:double;
  17.      Uhel:double;
  18.  begin
  19.  Uhel:=DegToRad(5);
  20.  Cil:=PaintBox1.Canvas;
  21.  r:=PaintBox1.ClientRect;
  22.  
  23.  SinCos(Uhel, Si, Co);
  24.  xForm.eM11 := Co;
  25.  xForm.eM12 := Si;
  26.  xForm.eM21 := -Si;
  27.  xForm.eM22 := Co;
  28.  xForm.eDx  := 100;
  29.  xForm.eDy  := 70;
  30.  SetGraphicsMode(Cil.Handle, GM_ADVANCED);
  31.  SetMapMode(Cil.Handle, MM_TEXT);
  32.  SetWorldTransform(Cil.Handle, xForm);
  33.  
  34.  // cary
  35.  Cil.Pen.Color:=clBlue;
  36.  for a:=0 to r.Height div 8 do begin
  37.   Cil.MoveTo(0, a*8);
  38.   Cil.LineTo(r.Right, a*8);
  39.  end;
  40.  
  41.  // obrazek
  42.  r.Width:=r.Width div 2;
  43.  r.Height:=r.Height div 2;
  44.  Obrazek.Draw(Cil, r);
  45. end;

Obrázek se sice vykresli pootočený o těch 5 stupňů, ale nefunguje průhlednost. Když není použito otočení, průhlednost funguje správně. Nevíte prosím někdo, jak docílit průhledného obrázku i při otočení? Nouzová varianta by byla, držet si v paměti i bitmapu otočeného obrázku, ale rád bych se tomu vyhnul, protože jeden obrázek budu potřebovat zobrazit mnohokrát, přičemž úhel otočení bude různý.

Díky, K.

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 765
  • Karma: 43
    • Verze Delphi: 10.3
Re:Jak vykreslit otočený PNG s průhledností
« Odpověď #1 kdy: 16-12-2018, 20:47:08 »
Tak to není zrovna optimistická odpověď, ale alespoň mi ušetří hledání... Měl byste někdo radu, co použít místo toho? GDI Plus by to umělo? Budu pak potřebovat ty obrázky i posílat na tiskárnu, to bude asi další boj (seskládání do jedné obrovské bitmapy a její odeslání na tiskárnu bych se raději vyhnul, protože když to někdo zkusí poslat na plotr s velkým formátem papíru, nebude paměť stačit)... Do budoucna počítám s tím, že se vše předělá do OpenGL, ale to ještě chvíli potrvá, protože tam pro změnu nevím, jak inteligentně pracovat s fonty...

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 765
  • Karma: 43
    • Verze Delphi: 10.3
Re:Jak vykreslit otočený PNG s průhledností
« Odpověď #2 kdy: 16-12-2018, 23:12:24 »
Tak GDI+ to opravdu zvládne, akorát rychlost je tragická. Vykreslit obrázek 900x900 px na monitor v cílové velikosti 50x50 px trvá 32 ms, takže vykreslit 10x = 320 ms... Ještě se podívám na TDirect2DCanvas, tam by asi byl jen problém s těmi, co se ještě nevzdali Windows XP.

Offline vandrovnik

  • Guru
  • *****
  • Příspěvků: 765
  • Karma: 43
    • Verze Delphi: 10.3
Re:Jak vykreslit otočený PNG s průhledností
« Odpověď #3 kdy: 17-12-2018, 00:20:56 »
S TDirect2DCanvas to vypadá podstatně lépe - po trošce optimalizací jsem docílil toho, že vykreslit 10 000 obrázků trvá 22 ms :-)

Resp. s tím časem je to divné. tStopWatch naměří 22 ms, to samé naměřím sám pomocí QueryPerformanceCounter. Nicméně reálně to trvá déle. Když nechám vykreslit 100 000 větších obrázků, naměřím 187 ms, subjektivně to trvá lehce přes sekundu. Během toho vykreslování ve Správci úloh je CPU i GPU u té mé aplikace 0 %, ale přitom v celkovém vytížení GPU je vidět 100 %.