reklama

Staňte se programátorem: Napište si malý Photoshop

Bitmapový editor Paint.NET je napsaný v jazyku C#. Dnes vám ukážeme, jak snadno lze v tomto jazyku napsat základní fotografické efekty. Napište si s námi takový malý Photoshop.

Jedním z nejznámějších desktopových programů napsaných pro Microsoft .NET Framework je bitmapový editor Paint.NET. Ačkoliv se zatím svými možnostmi a schopnostmi nemůže rovnat s vyspělými grafickými editory, je jednou z vlajkových lodí této platformy, většina .NET vývojářů se totiž soustředí především na webové aplikace, ASP.NET aj.

Bitmapový editor s fotografickými efekty I.

Bitmapový editor bez množství nejrůznějších fotografických a kreativních filtrů by v těžké konkurenci nemohl obstát. Dnes vám tedy ukážeme, jak si v jazyku C# napsat filtr, který původní obrázek převede do odstínu šedi, přidá mu historický nádech pomocí sépiového efektu a převede jej do negativu. Kód si pak budete moci vyzkoušet v jednoduchém editoru, který obrázek s efektem bude umět i uložit.

Klepněte pro větší obrázek  Klepněte pro větší obrázek
Náš jednoduchý editor s třemi bitmapovými efekty

V dnešním projektu se tedy dozvíte, jakým způsobem lze manipulovat s jednotlivými pixely obrázku, jejichž změnou budete moci na bitmapě vytvářet grafické efekty. Nejprve vám vysvětlíme teorii a ukážeme několik jednoduchých grafických efektů. Příští týden pak přijde řada i na složitější algoritmy.

Úprava pixelů bitmapy standartním způsobem

K pixelům bitmapy, která je realizována třídou System.Drawing.Bitmap, můžete přistupovat pomocí metody GetPixel a SetPixel. Metoda GetPixel vrací instanci struktury System.Drawing.Color představující barvu pixelu ležící na určitých souřadnicích X,Y v bitmapě. K nastavení pixelu na určitou souřadnici lze pak použít metodu SetPixel.

Následující metoda nastaví pouze červený filtr bitmapy:

void NastavCervenou(Bitmap b)
{
  for (int x = 0; x< b.Width; x++)
  {
    for (int y = 0; y<b.Height; y++)
    {
      Color vybBarva = b.GetPixel(x,y);
      b.SetPixel(x,y, Color.FromArgb(vybBarva.R,0,0));
    }
  }
}

Kód tedy vlastně u každého pixelu obrázku v barevném modelu RGB ponechá pouze červený kanál a zelený a modrý nastaví na nulu. Jednoduše řečeno, výsledek bude vypadat jako zobrazení pouze červeného kanálu v kdejakém bitmapovém editoru.

Rychlejší úprava pixelů bitmapy pomocí unsafe kódu

Nevýhodou tohoto postupu je jeho pomalý výkon – metody SetPixel a GetPixel jsou časově poměrně náročné. Pro zrychlení manipulace s pixely budete muset pracovat přímo s pamětí pomocí unsafe (nezabezpečeného) kódu.

Například takto by vypadala předchozí metoda NastavCervenou za použití efektivnějšího unsafe kódu:

using System.Drawing.Imaging;
using System.Drawing;

. . .

unsafe Bitmap NastavCervenou(Bitmap b)
{
 
// Uzamkne v paměti data bitmapy tak, aby s nimi bylo možno pracovat.
 
BitmapData bd = b.LockBits(new Rectangle(0,0,b.Width,b.Height),
                             ImageLockMode.ReadWrite,
                             PixelFormat.Format32bppArgb);

  for (int y = 0; y< b.Height; y++)
  {
    // Vytvoří ukazatel na začátek y-té řádky bitmapy
    int* ukzt = (int*)((int)bd.Scan0 + y * bd.Stride);
    for (int x = 0; x <b.Width; x++)
    {
      // Vybere barvu pixelu
      Color c = Color.FromArgb(*ukzt);
      Color cervenyOdstin = Color.FromArgb(c.R,0,0);
      // Nastaví barvu pixelu
      *ukzt = cervenyOdstin.ToArgb();
      // Posune ukazatel na x-tý pixel v dané řádce
      ukzt++;
   
}
  }
 
b.UnlockBits(bd);
  return b;
}

Schválně si všimněte klíčového slova unsafe v deklaraci metody, které říká, že kód v této metodě budou používány ukazatele. Více o ukazatelích se dozvíte třeba na tomto webu.

K tomu, aby bylo možné ve Visual Studiu zkompilovat program obsahující unsafe kód, je nutné tuto vlastnost povolit v menu Project -> Project Options -> Debug.

Pro přístup k pixelum bitmapy je musíte uzamknout v paměti pomocí metody LockBits, která jako argument očekává instanci třídy Rectangle představující část bitmapy, jejíž data mají být uzamknuta, druhým argumentem je položka výčtového typu System.Drawing.Imaging.ImageLockMode, která nám definuje způsob, kterým můžete přistupovat k pixelům bitmapy.

Posledním argumentem je položka výčtového typu System.Drawing.Imaging.PixelFormat určující barevnou hloubku bitmapy. Následně cyklem projdete jednotlivé řádky bitmapy. Pozici prvního pixelu v y-tém řádku v bitmapy vypočítáte za použití vlastnosti Scan0 a Stride třídy BitmapData. Vlastnost Scan0 představuje počáteční pixel bitmapy a vlastnost Stride délku jedné řádky. Pro přesun na další pozici v řádce je nutné zvýšit ukazatel o hodnotu 1. Po dokončení úprav bitmapy, lze její data z paměti uvolnit pomocí metody UnLockBits.

A teď už slíbené fotografické filtry

Převod barev do odstínů šedi

Klepněte pro větší obrázek Klepněte pro větší obrázek
Převod do odstínů šedi a výsledný obrázek

Algoritmus s unsafe kódem může v C# vypadat třeba takto:

unsafe Bitmap SedaSkala(Bitmap b)
{
  BitmapData bd = b.LockBits(new Rectangle(0,0,b.Width,b.Height),
                            
ImageLockMode.ReadWrite,
                             PixelFormat.Format32bppArgb);

  for (int y = 0; y< b.Height; y++)
  {
    int* ukzt = (int*)((int)bd.Scan0 + y * bd.Stride);
    for (int x = 0; x <b.Width; x++)
    {
      Color c = Color.FromArgb(*ukzt);
      int seda = (int)(0.299 * c.R + 0.587 * c.G + 0.114 * c.B);
      Color sedaBarva = Color.FromArgb(seda,seda,seda);
      *ukzt = sedaBarva.ToArgb();
      ukzt++;
    }
  }
  b.UnlockBits(bd);
  return b;
}

Invertování barev

Klepněte pro větší obrázek  Klepněte pro větší obrázek  Klepněte pro větší obrázek  Klepněte pro větší obrázek
Negativ v několika podobách, efekty totiž můžete kombinovat, a výsledný obrázek

Algoritmus s unsafe kódem může v C# vypadat třeba takto:

unsafe Bitmap Invert(Bitmap b)
{
  BitmapData bd = b.LockBits(new Rectangle(0,0,b.Width,b.Height),
                                           ImageLockMode.ReadWrite,
                                           PixelFormat.Format32bppArgb);

  for (int y = 0; y< b.Height; y++)
  {
    int* ukzt = (int*)((int)bd.Scan0 + y * bd.Stride);
    for (int x = 0; x <b.Width; x++)
    {
      Color vybrBarva = Color.FromArgb(*ukzt);
      Color invBarva = Color.FromArgb(255-vybrBarva.R,
                                      255-vybrBarva.G,
                                      
255-vybrBarva.B);

      *ukzt = invBarva.ToArgb();
      ukzt++;
    }
  }
  b.UnlockBits(bd);
  return b;
}

Vytvoření sépiového nádechu

Klepněte pro větší obrázek  Klepněte pro větší obrázek
Nakonec nesmí chybět ještě sépiový efekt

Algoritmus s unsafe kódem může v C# vypadat třeba takto:

unsafe Bitmap Sepia(Bitmap b)
{
  BitmapData bd = b.LockBits(new Rectangle(0,0,b.Width,b.Height),
                                           ImageLockMode.ReadWrite,
                                           PixelFormat.Format32bppArgb);

  for (int y = 0; y< b.Height; y++)
  {
    int* ukzt = (int*)((int)bd.Scan0 + y * bd.Stride);
    for (int x = 0; x <b.Width; x++)
    {
      Color c = Color.FromArgb(*ukzt);
      int sepia = (int)(0.299 * c.R + 0.587 * c.G + 0.114 * c.B);
      int r = (int)((sepia > 206) ? 255 : sepia + 49);
      int g = (int)((sepia< 14) ? 0 : sepia - 14);
      int bl = (int)((sepia < 56) ? 0 : sepia - 56);
      Color sepiaColor = Color.FromArgb(r,g,bl);
      *ukzt = sepiaColor.ToArgb();
      ukzt++;
    }
  }
  b.UnlockBits(bd);
  return b;
}

Jak na složitější efekty? Přečtěte si příští článek

V tomto článku jsme vám ukázali, jakým způsobem lze manipulovat s pixely bitmapy za použití unsafe kódu. Příště vás seznámíme s pokročilejšími grafickými efekty.

Nakonec nesmí chybět ani slíbený spustitelný program a projekt.  K prvnímu budete potřebovat nainstalovaný novější Microsoft .NET Framework, pakliže si budete chtít projekt upravit a sestavit, budete potřebovat bezplatné vývojové prostředí Microsoft Visual C# 2008 Express Edition.

Máte zajímavý tip na drobnou aplikaci, kterou byste zde chtěli vidět? Neváhejte a napište nám váš nápad do diskuze pod článkem. 

Témata článku: Programování, Adobe Photoshop, Family, Kody

25 komentářů

Nejnovější komentáře

  • kvok 20. 8. 2008 14:50:06
    "Máte zajímavý tip na drobnou aplikaci, kterou byste zde chtěli vidět?...
  • jehoVista 19. 8. 2008 23:11:18
    imagemagick
  • jehoVista 19. 8. 2008 23:10:27
    Dva radkove komentare na 150 radek kodu? Kdyz ma slouzit vyuce?
reklama
Určitě si přečtěte

Vybíráte herní periferii nebo hardware? Pak zapomeňte na nálepku Gaming

Vybíráte herní periferii nebo hardware? Pak zapomeňte na nálepku Gaming

** Herní hardware se od toho běžného často liší jen vzhledem ** Při výběru stále nezapomínejte na základní parametry ** Poradíme jak vybrat herní hardware i periferie

20.  2.  2017 | Stanislav Janů | 36

10 nejhorších produktů v historii Microsoftu

10 nejhorších produktů v historii Microsoftu

20.  2.  2017 | Karel Javůrek | 141

AMD oficiálně představilo procesory Ryzen. Známe i jejich české ceny

AMD oficiálně představilo procesory Ryzen. Známe i jejich české ceny

** AMD uvedlo první tři procesory Ryzen 7 ** Všechny budou pracovat s osmi jádry a šestnácti vlákny ** Na pulty obchodů se dostanou už za týden

22.  2.  2017 | Stanislav Janů | 132

Pojďme programovat elektroniku: Žádný bastlíř se neobejde bez armády švábů

Pojďme programovat elektroniku: Žádný bastlíř se neobejde bez armády švábů

** Každý bastlíř se po čase neobjede bez armády švábů ** Dnes si některé z nich vyzkoušíme ** Třeba zázračný posuvný registr

19.  2.  2017 | Jakub Čížek | 40

EU se děsí Windows 10. Prý o nás vědí až příliš. Microsoft chystá změny

EU se děsí Windows 10. Prý o nás vědí až příliš. Microsoft chystá změny

** Evropští úředníci chtějí, aby byly Desítky transparentnější ** Microsoft od jara skutečně chystá změny ** Ochráncům soukromí to ale nestačí

21.  2.  2017 | Jakub Čížek | 218

Remix Singularity: Microsoft si na tom vylámal zuby. Jak dopadne Android?

Remix Singularity: Microsoft si na tom vylámal zuby. Jak dopadne Android?

** Microsoft do svých telefonů integroval desktopové prostředí ** Moc to ale nevyšlo, chyběl pořádný výkon ** Teď to zkoušejí ex-googleři s Remix Singularity

23.  2.  2017 | Jakub Čížek | 74


Aktuální číslo časopisu Computer

Supertéma o počítačové bezpečnosti

AMD Ryzen přichází

Velké testy kinoprojektorů a levných špuntových sluchátek

Příslušenství do USB-C

reklama
reklama