Kendi İnstagram Filtremizi Kodlayalım

0

Bugün Instagramda kullanılan resim filtrelerine benzer 2 tane filtreyi kendimiz kodyalarak yazacağız. Başlamadan önce  okumadıysanız Bitmap sınıfı,RGB ve DPI kavramı ile ilgili yazıyı okumanızı tavsiye ederim.

Ekran tasarımımız aşağıdaki gibi olacak.

instagram filtresi

Ekran açılmadan önce ComboBox’ı dolduruyorum. Ve Grayscale filtresinin seçili olarak gelmesini sağlıyorum

private void Form1_Load(object sender, EventArgs e)
{
            cbFiltre.Items.Add("Grayscale");
            cbFiltre.Items.Add("Sepia");
            cbFiltre.SelectedIndex = 0;
}

Sonraki adımda ise kullanıcının bir resim seçmesini sağlamak için Browse butonunu kullanıyoruz.Bunun için bir  OpenFileDialog nesnesi yaratıyorum.

Bu nesnenin filter özelliğine kullanıcının seçebileceği dosya uzantılarını koyuyoruz. Bu sayede belirtiğimiz uzantılar dışında dosya seçimi yapılamıyor. Tittle özelliğine ise açılan pencerenin başlığını verebiliriz.

dosyayolu.ShowDialog();

Yukarıda method ise Browse penceresinin belirttiğimiz filtreler çerçevesinde açılmasını sağlıyor. Daha sonra seçilen dosyanın yolunu TextBox’a atıyoruz ve bir Bitmap nesnesi yaratıyoruz.

 private void btnBrowse_Click(object sender, EventArgs e)
{
            OpenFileDialog dosyayolu = new OpenFileDialog();
            dosyayolu.Filter = "Resim Dosyası |*.jpg;*.nef;*.png ";
            dosyayolu.Title = "Resim Seç";
            dosyayolu.ShowDialog();
            txtLocation.Text= dosyayolu.FileName;
            pictureBefore.ImageLocation =txtLocation.Text;
            bmpBefore = new Bitmap(txtLocation.Text);
}

Kodun biraz daha okunur olması için enum tanımladım. Enumdaki değerleri Combobox’daki elemanların indeksine göre verdim.

enum Filtreler
{
   Grayscale=0,
   Sepia=1
}

Apply butonuna basıldığında ise ,kullanıcının seçtiği filtreye göre filtreyi uygulacak fonksiyonu çağırıyorum ve fonksiyona bitmap nesnesini gönderiyorum. Dönen bitmap nesnesini ise ekranın sağında bulunan pictureBoxAfter’a atıyorum.

private void bntApply_Click(object sender, EventArgs e)
{
            if (cbFiltre.SelectedIndex == (int)Filtreler.Grayscale)
            {
              bmpAfter= ApplyGrayscale(bmpBefore);
                pictureBoxAfter.Image = bmpAfter;
            }
            else if (cbFiltre.SelectedIndex == (int)Filtreler.Sepia)
            {
                bmpAfter = ApplySepia(bmpBefore);
                pictureBoxAfter.Image = bmpAfter;
            }
}

ApplyGrayscale’a gönderilen bitmap’ın bir kopyasını oluşturarak bmpFilter nesnesini yaratıyorum. Daha sonra resimde bulunan her pixeli işlemem gerektiğinden bunun için bir for yazıyorum.

GetPixel methodu ile  i ve j’ ye göre resmin o noktasında bulunan pixeli Color nesnesine atıyorum.Grayscale filtresinin formülüne göre  pixeldeki red,green ve blue değerlerinin ortalamasını buluyorum. Daha sonra red,green ve blue değeri, bulduğum ortalama değer olacak şekilde yeni bir renk yaratıyorum.

SetPixel  methodu ile de pixelin rengini değiştiryorum.

Örneğin Red=100, Green=120, Blue=170 olan bir pixelin yeni değerini bulmak için RGB değerlerinin ortalamasını alıyorum. (100+120+170)/3=130 yapıyor.  Daha sonra Red=130 Green=130 ve Blue=130 değerleri ile yeni bir renk oluşturarak pixelin rengini değiştiriyorum.

public Bitmap ApplyGrayscale (Bitmap bmp)
{          
            Rectangle rc = new Rectangle(0, 0, bmp.Width, bmp.Height);
            Bitmap bmpFilter = bmp.Clone(rc,bmp.PixelFormat);
            for (int i = 0; i < bmpFilter.Width; i++)
            {
                for (int j = 0; j < bmpFilter.Height; j++)
                {
                    Color c = bmpFilter.GetPixel(i, j);
                    int total = c.R + c.G + c.B;
                    int average = total / 3;
                    Color NewColor = Color.FromArgb(average, average, average);
                    bmpFilter.SetPixel(i, j, NewColor);
                }
            }
            return bmpFilter;
}

ApplySepia fonksiyonu ise benzer şekilde ilerliyor. Sadece filtrenin formülü farklı.Onuda buradan buldum. RGB değerleri 255’den büyük olamayacağı için önlem olarak formülün değeri 255 den büyükse 255 değerini ataması için Math.Min fonksiyonunu kullanıyorum.

 public Bitmap ApplySepia(Bitmap bmp)
{
    Rectangle rc = new Rectangle(0, 0, bmp.Width, bmp.Height);
    Bitmap bmpFilter = bmp.Clone(rc, bmp.PixelFormat);
    for (int i = 0; i < bmpFilter.Width; i++)
    {
          for (int j = 0; j < bmpFilter.Height; j++)
          {
            Color c = bmpFilter.GetPixel(i, j);
            int Red = Math.Min((int)((.393 * c.R) + (.769 * c.G) + (.189 * c.G)), 255);
            int Green = Math.Min((int)((.349 * c.R) + (.686 * c.G) + (.168 * c.G)), 255);
            int Blue = Math.Min((int)((.272 * c.R) + (.534 * c.G) + (.131 * c.G)), 255);
            Color NewColor = Color.FromArgb(Red, Green, Blue);
            bmpFilter.SetPixel(i, j, NewColor);
           }
     }
            return bmpFilter;        
}

Resim çıktıları:

Orjinal Resim
Orjinal Resim
Sepia
Sepia
grayscale
Grayscale

Sizde yukarıdaki kodlara benzer şekilde formülünü bildiğiniz bir filtreyi oluşturabilirsiniz. Ya da yeni formüller de yaratabilirsiniz.

Yukarıdaki programda filtreleri uygulama süresi 2,5 saniye gibi bir süre. Bu süre uzun bir süre. İlerleyen yazılarda görüntü işlemenin performansını nasıl arttıracağmızdan bahsedeceğim.

Kafa karıştırmaması açısında şimdilik performans konusuna girmedim. Yine ilerleyen yazılarda bu uygulamanın mobil versiyonunu da yazmayı düşünüyorum. Sonraki yazılarda görüşmek üzere.

CEVAP VER

Lütfen yorum giriniz!
Lütfen isminizi giriniz