IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 4 - Vektorová grafika v C# .NET WPF - Úvod

V dnešní lekci si popíšeme co je to vektorová grafika a jak se liší oproti grafice rastrové. Dále si ukážeme, jak se k této problematice staví .NET framework a WPF. Poté si zkusíme přes XAML nakreslit pár jednoduchých objektů.

Vektorová vs. rastrová grafika

Velmi laicky můžeme říci, že vektorový obrázek si můžeme zvětšit jak chceme a nikdy se nám nerozmaže nebo nerozpixeluje. To je velmi lákavé, protože takový obrázek je plně responzivní a stále 100% ostrý, navíc zabírá velmi málo paměti a naše aplikace pak vypadá na všech zařízeních stejně hezky. Není divu, že např. SVG ikony jsou dnes na webu velmi populární. A i my budeme vektorové ikony ve svých WPF aplikacích preferovat.

Vektorový obrázek

Obrázek v sobě obsahuje matematický zápis souřadnic bodů (vrcholů) a jejich spojnic (hran), který vytváří požadovaný obrazec (např. trojúhelník, kruh, čtverec...). Kombinováním a prolínáním těchto obrazců se poté vytvářejí obrazce složitější. Dále se ve vektorových obrázcích specifikují informace jako tloušťka čáry, barva výplně atd. Z toho vyplývá, že s jakýmkoliv zvětšením či zmenšením obrazce se mění jen poměr vzdáleností mezi vrcholy.

Rasterizace

A jak se křivky vykreslí? To, co poté vidíme na obrazovce, se musí samozřejmě znovu "rasterizovat", neboli vykreslit na 2D ploše našeho monitoru:

mřížka znázorňuje zobrazitelné pixely, trojúhelník vektorovou grafiku, a zelená barva vykreslený trojúhelník - Grafika v C# .NET WPF

Jak sami vidíte, vykreslení vektorového obrázku na obrazovku vytváří při malém počtu pixelů "schody" neboli aliasing. WPF za nás však použije pokročilejší algoritmy, tzv. anti-aliasing, aby byly jednotlivé křivky obrázku vyhlazené.

Rastrový obrázek

Naopak rastrový obrázek, např ve formátu JPEG (když jej zjednodušíme a pomineme ztrátový algoritmus komprese), se skládá pouze z pixelů a jejich barvy. Pokud takový obrázek zvětšíme, základní algoritmus zdvojí počet pixelů, ale ty vycházejí pouze z původní informace, a tedy bude obraz ošklivě rozkostičkovaný a v lepším případě rozmazaný. O jelikož se hustota pixelů obrazovek stále zvyšuje, můžeme si být jistí, že uživatelé naši aplikaci zvětšovat budou.

Ukažme si, jak to vypadá, když se zvětší rastrový obrázek:

Ukázka zvětšení rastrového obrázku - Grafika v C# .NET WPF

A zde příklad zvětšení vektorového obrázku:

Ukázka zvětšení vektorového obrázku - Grafika v C# .NET WPF

Kdy použít vektorovou a kdy rastrovou grafiku?

Takže nyní máme představu, jaký je rozdíl mezi vektorovou a rastrovou grafikou. Nemůžeme říci, že jedna je lepší než druhá. Zjednodušeně můžeme říci, že na ikony bychom měli používat vektorové obrázky a na fotografie dostatečně kvalitní obrázky rastrové. Shrňme si nyní do pár bodů základní rozdíly:

Vektorová grafika

  • Jednodušší grafika jako ikony
  • Jakýkoliv grafický prvek, který se bude dynamicky zmenšovat či zvětšovat
  • Možnost i případné animace
  • Lze i dynamicky měnit barvu jednotlivých prvků v obrazci
  • Menší velikost souboru s obrázkem
  • Náročnější na výpočetní výkon

Rastrový obrázek

  • Tam, kde se jedná o reálnou fotografii, či složité obrazce
  • Tam, kde bude obraz vždy v nativním rozlišení, a nebude se s ním zoomovat
  • Kde je třeba detailního, fotorealistického obrázku se stíny a nasvícením, ale není výhodné zatěžovat GPU/CPU velmi složitou scénou
  • Vyšší nároky na velikost souboru
  • Výpočetní nenáročnost

Jak ve WPF pracovat s vektorovou grafikou

Jak možná již tušíte, standardně bez dalších rozšiřujících balíčků WPF ve Visual Studiu nepodporuje externí soubory vektorové grafiky. To jsou např.:

  • .svg - Scalable Vector Graphics
  • .eps, .ps - PostScript
  • .ai - Adobe Illustrator Artwork
  • .cdr - Corel Draw
  • .pdf - Portable Document Format

Zejména soubor SVG je v dnešní době etalon, který se uchytil ve webové grafice, a umí mimo jiné i animace. Bohužel je podporován až v novější verzi Creator's Update (tedy verze OS Windows 10 1709 z konce roku 2017) pod UWP (Universal Windows Platform), kde pro něj vznikla nová třída SvgImageSource.

Jak tedy na vektorovou grafiku ve WPF?

XAML

Řešením je XAML, který v základu využívá nástroje na kreslení jako <Rectangle>, <Line>, <Ellipse> a další, které se vykreslují jako vektorové objekty. S kreslením tvarů jsme se v našem kurzu již setkali. Nyní si ukážeme i další tvary a jak do XAML zkonvertovat SVG soubory.

Vytvoření aplikace

Začneme pracovat na aplikaci, která bude ve výsledku vypadat takto:

Grafika v C# .NET WPF

Vytvořte si nový projekt a přepněte se do XAML části:

Grafika v C# .NET WPF

Zde si vytvoříme <Grid>, a ten rozdělíme na 9 rovnoměrných "chlívečků" s těmito parametry:

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="1*"/>
    <ColumnDefinition Width="1*"/>
    <ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
    <RowDefinition Height="1*"/>
    <RowDefinition Height="1*"/>
    <RowDefinition Height="1*"/>
</Grid.RowDefinitions>

To nám rozdělí pracovní plochu na 3 * 3 chlívečky, které si budou díky parametru * udržovat poměr s velikostí okna. Okno by mělo vypadat v návrháři takto (objekty přidáme samozřejmě později):

Grafika v C# .NET WPF

Vložení jednotlivých prvků

Nyní si ukažme, jak vykreslíme základní tvary.

Rectangle

Jako první vložíme obdélník <Rectangle>, vyplněný zelenou barvou a se žlutým okrajem:

<Rectangle Stroke="Bisque" StrokeThickness= "5" Fill="Aquamarine" Margin="10" Grid.Row="0" Grid.Column="0" />

Výsledek:

Grafika v C# .NET WPF

Stroke je barva okraje, StrokeThickness je síla čáry okraje v pixelech. Fill je barva výplně, Margin je odskok od okrajů, Grid.Row a Grid.Column určuje, ve kterém z našich "chlívečků" bude obrazec umístěný.

Rectangle - Čtverec

Druhý obdélník je speciální v tom, že je to vlastně čtverec. Hlídá si zde svou aktuální šířku, a tu nastavuje i pro výšku. Toho dosáhneme přiřazením Binding:

<Rectangle StrokeThickness= "5" Margin="10" Grid.Row="1" Grid.Column="0" Width="{Binding ActualHeight, Mode=OneWay, RelativeSource={RelativeSource Mode=Self}}" Stroke="Black">

Výsledek:

Grafika v C# .NET WPF

Binding může nahrazovat konstantní hodnotu v kterémkoliv parametru proměnnou nebo referencí na jinou proměnou, v našem případě na aktuální výšku obdélníku: Width="{Binding ActualHeight, Mode=OneWay, RelativeSource={RelativeSource Mode=Self}}"

Ellipse

Poté tu máme <Ellipse>, kde je nastavení stejné jako v případě čtverce, ale okořenil jsem to efekty přechodů, jak pro výplň Fill, tak pro okraje Stroke:

<Ellipse StrokeThickness= "5" Margin="10" Grid.Row="0" Grid.Column="1">
    <Ellipse.Stroke>
        <LinearGradientBrush>
            <GradientStop Color="#FFFFFF03" Offset="0"/>
            <GradientStop Color="#FF000CFF" Offset="1"/>
        </LinearGradientBrush>
    </Ellipse.Stroke>
    <Ellipse.Fill>
        <RadialGradientBrush>
            <GradientStop Color="#FF0633FF" Offset="0"/>
            <GradientStop Color="Red" Offset="1"/>
            <GradientStop Color="#FFFFF500" Offset="0.7"/>
            <GradientStop Color="#FF3AFF00" Offset="0.403"/>
            <GradientStop Color="#FFFF16B5" Offset="0.837"/>
        </RadialGradientBrush>
    </Ellipse.Fill>
</Ellipse>

Výsledek:

Grafika v C# .NET WPF

Pro čáru Stroke využíváme lineární přechod, tedy postupný přechod, v tomto případě mezi dvěma barvami, od spodní modré, po horní žlutou. Color nastavuje logicky barvu, a Offset výchozí pozici na barevné škále – neboli jaké místo bude pro danou barvu vyhrazeno. Postupuje se po 0.1 krocích nebo jemnějších, maximální hodnota je 1. Výplň Fill jsme pro změnu nastavili na přechod několika barev, tentokráte na kruhový přechod.

Ellipse - Kruh

Nyní opět pomocí Bindingu nakreslíme místo elipsy kruh. Postup je totožný jako u našeho čtverce:

<Ellipse x:Name="ellipse" Stroke="Black" Fill="AliceBlue" Margin="10" Grid.Row="1" Grid.Column="1" Width="{Binding ActualHeight, Mode=OneWay, RelativeSource={RelativeSource Mode=Self}}"/>

Pokračovat budeme příště.


 

Předchozí článek
3D grafika v C# .NET WPF - Koule a hrany
Všechny články v sekci
Grafika v C# .NET WPF
Přeskočit článek
(nedoporučujeme)
Vektorová grafika v C# .NET WPF - Kreslení dalších tvarů
Článek pro vás napsal Michal Kotek
Avatar
Uživatelské hodnocení:
4 hlasů
Autor se věnuje programování již od útlých let, aktuálně se věnuje výrobě Webových stránek jako fullstack, využívám Nette framework. Mám znalosti jazyků JS, PHP, SASS C# .NET, C++ pro Arduino. Jo a strašně rád střílím ;)
Aktivity