Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
Delphi
FastAntialiasing
antialias
16. srpna 2002, 00.00 | Pokračování tématu práce s grafikou a speciálně antialiasingu. V dnešním díle se budeme zabývat kritickou otázkou celé problematiky, a tou je rychlost zpracování. Zrychlení si pak můžete otestovat i na přiložené ukázkové aplikaci.
Všichni z Vás co četli první část tohoto článku a to článek Aliasing a Antialiasing již určitě vědí, o co půjde v příštích pár odstavcích. Dokonce se mezi čtenáři našel člověk, který na velký nedostatek Antialiasingu presentovaném v minulém díle upozornil a také již naznačil možnost jeho řešení. Tímto zmiňovaným nedostatkem je samozřejmě rychlost. A protože je antialiasing velmi častá věc v počítačové grafice, tak není možné, abychom na jeho provedení čekali v případě mého PC (750MHz) 5-6s.Uvědomme si nejprve, čím je ono zpoždění způsobeno. Vždyť algoritmus jen přečte barvu a pak jednoduchou aritmetickou operací vypočítá barvu druhou,kterou zase zapíše. Právě zde je ale zakopán pes. Naši barvu totiž čteme a zapisujeme vlastností objektu TCanvas Pixels.
Tato vlastnost požívá pro čtení funkci GetPixel a pro zápis proceduru SetPixel definované:
|
Obě metody musejí spolupracovat s pamětí grafické karty (číst, zapisovat) a tato operace je obzvláště pomalá a během antialiasingu se provádí výška x šířka –krát. Můsíme tedy vymyslet způsob jak všechny nebo alespoň většinu údajů z grafické paměti přečíst (zapsat) najednou. K tomu nám pomůže vlastnost objektu TBitmap ScanLine.
Metoda Scan line je definovaná:
ScanLine[Row: Integer]: Pointer;
a bude zřejmě třeba použití této metody lehce objasnit. Vstup metody je snad jasný. Row nám označuje řádek bitmapy, který chceme číst (zapisovat). Zajímavější je výstup. Metoda vrací ukazatel na adresovaný řádek (Row), který je již ale uložen v operační paměti. Je dobré vědět, že řádek bitmapy uložený v grafické paměti není pouze pole barev. Grafická karta pracuje přímo se složkami RBG a proto má každý pixel uložený jako strukturu RGB typu TRGBTriple. Nyní již víme dost na to abychom mohli s metodou ScanLine pracovat. Pro usnadnění si zavedeme nový typ.
|
PRGBArray je ukazatel na řádek bitmapy, který nám vrátí metoda ScanLine. A high(smallint) nám vrátí maximální velikost typu smallint. Je to proto, že na starších počítačích a hlavně ve starších verzích Delphi je max. počet prvků pole omezen velikostí integru a ta je na 16.bit Delphi právě smallint. K samotnému algoritmu budeme potřebovat tyto proměnné: Row1, Row2, Row3, DestRow: pRGBArray; Row1-3 jsou řádky bitmapy která je kreslená v 3-násobném rozlišení a DesRow je potom výsledný řádek. Bude také nutné si vytvořit nové 2 bitmapy protože je nutné aby byly v 24-bit formátu, jinak metoda ScanLine nefunguje. Pokud by bitmapa měla nastavenou více jak 24-bit paletu, došlo by při zpracování k chybě. Já jsem nové bitmapy nazval big_bmp a out_bmp. Názvy jsou snad jasné. Důležité je jejich správné vytvoření a zinicializování.
|
Podobně vytvoříme i ostatní bitmapy. Metoda Draw nám kopíruje bitmapu z komponenty Image do pomocné proměnné. Teď jen pepíšeme náši proceduru antialias z předchozího článku, tak aby fungovala s metodou ScanLine. Je to v podstatě úplně to samé. Některé nejasnosti jsou popsány v komentáři.
|
Nakonec se nesmí zapomenout uvolnit pomocné proměnné. Výsledný obraz je naprosto totožný i při použití metody Pixels, ale výrazně se celý algoritmus urychlil a to u mě přibližně o 5-6 násobek předchozího času tzn asi na 0,8-1s. Pokud si někteří čtenáři pamatují, že v minulém článku šlo změnou konstanty z dosáhnout efektu Motion Blur, tak je musím upozornit, že v tomto případě je tato možnost možná až po malé úpravě.
Ukázka (190kb)Poslat článek
Nyní máte možnost poslat odkaz článku svým přátelům:
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007