Makale Özeti

Bu makalemle sizlerle birlikte hepmizin gün içinde kullanmış olduğu birkaç resim işleme tekniklerinin C# kodu ile programatik bir şekilde yapabileceğimizi inceleyeceğiz. Bu işlemleri yapmakla yükümlü bir class oluşturduktan sonra bu class dosyasını örnekli bir şekilde kullanarak işlemleri gerçekleştireceğiz.

Makale

         Merhabalar,

         Bu makalemle sizlerle birlikte hepmizin gün içinde kullanmış olduğu birkaç resim işleme tekniklerinin C# kodu ile programatik bir şekilde yapabileceğimizi inceleyeceğiz. Bu işlemleri yapmakla yükümlü bir class oluşturduktan sonra bu class dosyasını örnekli bir şekilde kullanarak işlemleri gerçekleştireceğiz. Bu işlemlerin daha iyi anlaşılabilmesi için ilk önce temel kavramlar üzerinde durmanın faydalı olacağını düşünmekteyim. Bundan dolayı bu makalede kullanacağımız temel kavramları inceleyecek olursak;

         Resim dediğimiz yapılar bilgisayar tarafından görüntülenirken veya işlenirken pixel bazında işlem yapılır. Pixel çok basit bir anlamda resmi oluşturan küçük noktacıklara denir. Bir resmin çözünürlüğü içerdiği pixel sayısı ile orantılıdır. Monitör çözünürlüğüne kullandığımız 1024x768 pixel ekranımızda oluşacak görüntünün soldan sağa doğru 1024 yukarıdan aşağı doğru ise 768 noktacıktan oluşacağı anlamına gelmektedir. Dolayısıyla gördüğümüz görüntünün içinde 1024x768 = 786.432 nokta vardır. aynı zamanda 3MegaPixel lik bir fotoğraf makinasının çekeceği resim 3.000.000 pixel den oluşacaktır. Resimlerdeki renkler biraz önce bahsettiğimiz her pixelin farklı bir renge sahip olması ile sağlanır. Dolayısıyla bir resimde ne kaadr çok pixel varsa resim renk geçişlerinde o kadar başarılı ve nettir. Bundan dolayı yüksek çözünürlüklü fotoğraf makinalarının çektiği resimler daha net olmaktadır.

         Bir pixelde sadece bir renk taşınabilmektedir. Bu pixelde bulunan renk ise üç farklı rengin bileşimi olarak karşımıza çıkabilir. Bu renkler Kırmızı,Yeşil ve Mavi'dir. Bu renklerden herbiri 0 ile 255 arasında bir değere sahip olarak birleştirklerinde görüntüleyebileceğimiz renkleri meydana getirirler. Kombinasyon hesabı yaparsak bu üç rengi belirttiğimiz aralıkta değerlerle kullanırsak elimizde 16.777.216 farklı renkten oluşan bir palet var demektir. Web tasarımı yapan arkadaşların #ffffff diye bahsettikleri renk kodu hexadecimal düzendedir ve Kırmızı,Yeşil,Mavi değerlerinin tamamı 255 değerindedir. Buda bu renklerin herbirinin bilgisayar tarafında bir byte'lık bir alan tutacağı anlamına gelmektedir. Hexadecimal bir kodda ilk iki karakter kırmızı, sonraki iki karakter yeşil ve son iki karakter mavi rengin değerini belirlemektedir. Bir rengi oluşturan bir bileşenin değerinin bir fazla veya bir az olması insan gözü tarafından tespit edilemediğinden bu mantık üzerine geliştirilmiş şifreleme yöntemleri mevcuttur.

         Şimdi isterseniz bu pixel lere .Net ile gelen classları kullarak nasıl erişebileceğimiz ve üzerlerinde değişiklikleri nasıl yapabileceğimiz konusunu inceleyelim. .Net ile bu işlemleri yapmamız için Bitmap nesnesinin metodlarını kullanacağiz. Bitmap nesnesi resmimizi temsil eden bir nesnedir. Resmizi Bitmap nesnesi olarak yükledikten sonra bu nesne üzerinde pixel basında işlem yapmamız gerekmektedir. Bunun için Bitmap nesnesinin GetPixel ve SetPixel metodlarını ağırlıklı olarak kullanacağız. Bu metodlardan GetPixel bizden ulaşmak istediğimiz pixelin resim üzerinde sağdan ve yukarıdan kaçıncı pixel olduğunu belirtmemizi isteyecek ve sonucunda bu pixelin sahip olduğu rengi bize döndürecektir. Diğer metod olan SetPixel ise aynı şekilde belirttiğimiz bir pixele renk atamamızı sağlayacaktır. Bunun yanı sıra elimizde olan Kırmızı,Yeşil ve Mavi renk değerlerinden bir renk oluşturmak için Color sınıfının FromArgb statik metoduna bu değerleri vererek istediğimiz rengi elde edebiliriz.

         Şimdi kullanacağımız metodlar ile ilgili ufak örnekler yaptıktan sonra resim işlemesinde kullanacağımız class'ımızı yazmaya başlayabiliriz.

         Bir resmin sağdan x. ve yukarıdan y. pixelinin rengini almak için kullanacağımız metod GetPixel idi. bmp nin Bitmap nesnesinin bir instance'i olduğunu düşünelim. o zaman bu metodun çalışma şekli ise : bmp.GetPixel(x,y) şeklindedir.

         Bir resmin sağdan x. ve yukarıdan y. pixelinin rengine değer atamak için kullanacağımız metod SetPixel idi. bmp nin Bitmap nesnesinin bir instance'i olduğunu düşünelim. o zaman bu metodun çalışma şekli ise : bmp.SetPixel(x,y,Color.Red) şeklindedir.

         Bir yukarıdaki uygulamada rengi bilinen bir renkden seçerek değilde r,g,b değerlerinden oluşturmak istersek kullanmamız gerek kod şu şekilde olacaktır : bmp.SetPixel(x,y,Color.FromArgb(123,12,178)) şeklinde olabilir.

         Bir resimde bulunan tüm pixelleri dolaşmak için resimin genişlik ve yükseklik değerleri içinde iç içe iki döngü ile dönemk gerekmektedir. Bunun örnek kodunu ise aşağıda bulabilirsiniz.

for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    b.GetPixel(i,j);
                }
            }

         Artık bu iş için özelleşmiş classımızı yazmaya başlayabiliriz.
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
 
namespace ImageProcessing
{
    public class ImageProcessor
    {
        public ImageProcessor()
        {
 
        }
        public ImageProcessor(Image parImage)
        {
            Img = parImage;
        }
 
        private Image _Img;
        private Bitmap bmp;
        public Image Img
        {
            get
            {
                return _Img;
            }
            set
            {
                _Img = value;
                bmp = new Bitmap(_Img);
            }
        }
 
          Yukarıda bulunan kodu inceleyecek olursak Class'ımızın bir parametresiz birde parametresiz olmak üzere iki adet constructor vardır. Bu constructorlardan parametreli olan Image nesnesini parametre olarak almaktadır ve bunu Img propertysine atamaktadır. Bu propertynin set metodunda ise property e atanan Image nesnesi _Img yerel değişkeninde tutulmakta ve bunun yanı sıra bu property e gelen Image nesnesinden bir Bitmap nesnesi oluşturulup bmp yerel değişkeninde saklanmaktadır.

         Şimdi bu classımızın iş yapabilecek metodlarını inceleyelim;

         I) SiyahBeyaz
         Bu metodumuz verilen resmi siyah beyaz resime çevirecektir.

        public Image SiyahBeyaz()
        {
            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    int hede = (bmp.GetPixel(i, j).R + bmp.GetPixel(i, j).G + bmp.GetPixel(i, j).B) / 3;
 
                    bmp.SetPixel(i, j, Color.FromArgb(hede, hede, hede));
                }
            }
            return bmp;
        }
         Bir resmi Siyah-Beyaz yapmak için o resmin her pixelinin renk değirinin R,G,B değerlerinin ortalaması olacak  şekilde değiştirilmesi gerekmektedir. Yukarıda bulunan kod ise bu resmin her pixelinin renk değerini R,G,B değerlerinin ortalaması olacak şekilde yeniden set etmektedir.
         II) Negatif
         Bu metodumuz verilen resmi negatif haline çevirecektir.

        public Image Negatif()
        {
            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    bmp.SetPixel(i, j, Color.FromArgb(255 - bmp.GetPixel(i, j).R, 255 - bmp.GetPixel(i, j).G, 255 - bmp.GetPixel(i, j).B));
                }
            }
            return bmp;
        }
          Bir resmin negatifini almak için o resmin her pixelinin R,G,B değerlerinin terslerinden yeni bir renk oluşturup o pixele geri atamak gerekir. R,G,B değerlerinin terslerini almak için bu değerlerin 255 den olan farkını almak yeterli olacaktır.
         III)Red,IV)Green,V)Blue
        
Bu metod verilen resmin kırmızı,yeşil,mavi tonlarda oluşturulmasını sağlayacaktır.

        public Image Red()
        {
            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    bmp.SetPixel(i, j, Color.FromArgb(bmp.GetPixel(i, j).R, 0, 0));
                }
            }
            return bmp;
        }
         Bir resme kırmızı filtresini uygulamak için o resimde bulunan her pixelin sadece R değerinden oluşacak rengi taşıması sağlanmalıdır.,Aynı şekilde bir resme yeşil veya mavi filtreleri uygulamak içinde her pixelin sadece uygulanan filtre renk bileşeninden oluşması sağlanmalıdır.
         VI)Sepia
        
Bu metod verilen resmin nostaljik bir görüntüye bürünmesini sağlar birçok fotoğraf makinası direkt bu filtre ile resim çekilmesini desteklemektedir.

        public Image Sepia()
        {
            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    int Red = bmp.GetPixel(i, j).R * 393 / 1000 + bmp.GetPixel(i, j).G * 769 / 1000 + bmp.GetPixel(i, j).B * 189 / 1000;
                    int Green = bmp.GetPixel(i, j).R * 349 / 1000 + bmp.GetPixel(i, j).G * 686 / 1000 + bmp.GetPixel(i, j).B * 168 / 1000;
                    int Blue = bmp.GetPixel(i, j).R * 272 / 1000 + bmp.GetPixel(i, j).G * 534 / 1000 + bmp.GetPixel(i, j).B * 131 / 1000;
                    if (Red > 255) { Red = 255; }
                    if (Green > 255) { Green = 255; }
                    if (Blue > 255) { Blue = 255; }
                    bmp.SetPixel(i, j, Color.FromArgb(Red, Green, Blue));
                }
            }
            return bmp;
        }
          Bir resme sepia filtresi uygulamak için bir pixelin her renk bileşeni farklı katsayılar ile çarpılarak renk bileşenleri yeniden oluşturulur. Bu renk bileşenlerinden yeni bir renk oluşturulur ve ilgili pixel rengi olarak atanır.
         VII)Sola Döndür
         Bu metod verilen resmin sola 90 derece döndürülmesine yarar

        public Image SolaDondur()
        {
            Bitmap b = new Bitmap(bmp.Height, bmp.Width);
            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    b.SetPixel(j, b.Height - 1 - i, bmp.GetPixel(i, j));
                }
            }
            return b;
        }
         Bir resmi sola döndürmek için pixellerin renkleriyle değil yerleriyle oynamak gereklidir. Bunun için bir pixelin y koordinatını x koordinatına almak ve x koordinatını ters düz ederek y koordinatına almak gerekir.
         VIII)Sağa Döndür
        
Bu metod verilen resmin sağa 90 derece döndürülmesine yarar.

        public Image SagaDondur()
        {
            Bitmap b = new Bitmap(bmp.Height, bmp.Width);
            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    b.SetPixel(b.Width - j - 1, i, bmp.GetPixel(i, j));
                }
            }
            return b;
        }
          Bir resmi sağa döndürmek için pixellerin renkleriyle değil yerleriyle oynamak gereklidir. Bunun için bir pixelin x koordinatını y koordinatına almak ve y koordinatını ters düz ederek x koordinatına almak gerekir.
         IX)Dikey Ayna
        
Bu metod verilen resmin dikey eksende bir ayna görüntüsüne maruz kalmasının sonucundaki görüntüyü elde etmemize yarar.

        public Image DikeyAyna()
        {
            Bitmap b = new Bitmap(bmp.Width, bmp.Height);
            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    b.SetPixel(i, b.Height - j - 1, bmp.GetPixel(i, j));
                }
            }
            return b;
        }
          Bir resme dikey ayna filtresi uygulamak için pixellerin x eksenindeki koordinatlarını sabit tutarken y eksenindeki koordinatlarını tersdüz etmek gerekmektedir.
         X)Yatay Ayna
        
Bu metod verilen resmin yatay eksende bir ayna görüntüsüne maruz kalmasının sonucundaki görüntüyü elde etmemize yarar.

        public Image YatayAyna()
        {
            Bitmap b = new Bitmap(bmp.Width, bmp.Height);
            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    b.SetPixel(b.Width - i - 1, j, bmp.GetPixel(i, j));
                }
            }
            return b;
        }
          Bir resme dikey ayna filtresi uygulamak için pixellerin y eksenindeki koordinatlarını sabit tutarken x eksenindeki koordinatlarını tersdüz etmek gerekmektedir.
         XI)Boyutlandır
        
Bu metod verilen resmin verilen boyuta küçültülmesine veya büyütülmesine yarar.
        public Image Boyutlandir(int width, int height)
        {
            return _Img.GetThumbnailImage(width, height, null, new IntPtr(10000000));
        }
          Bir resmin yeniden boyutlandırılması için Image nesnesinin GetThumbnailImage metodunun yeni genişlik ve yükseklik değerleri verilerek çalıştırılması ile sağlanabilir.
         XII)Kes
        
Bu metod verilen resimdeki iki koordinat arasında kalan alandan yeni bir resim oluşturulmasına yarar.

        public Image Kes(int top, int left, int bottom, int right)
        {
            Bitmap b = new Bitmap(right - left, bottom - top);
            for (int i = left; i < right; i++)
            {
                for (int j = top; j < bottom; j++)
                {
                    b.SetPixel(i - left, j - top, bmp.GetPixel(i, j));
                }
            }
            return b;
        }
          Bir resmin belirli koordinatlar arasında yer alan kısmında yer alan tüm pixellerin aynen yeni bir resme aktarılması sonucu belirtilen alandan yeni bir resim oluşturulmuş olur.
         XIII)Renk Değiştir
        
Bu metod resimde bulunan bir rengin başka bir renkle birebir değiştirilmesine yarar.

        public Image RenkDegistir(Color clr1, Color clr2)
        {
            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    if (bmp.GetPixel(i, j) == clr1)
                    {
                        bmp.SetPixel(i, j, clr2);
                    }
                }
            }
            return bmp;
        }
          Bir resimde bulunan tüm renklerin değiştirilebilmesi için bir renge uyan tüm pixellerin bulunması ve bunların yeni renk değeri ile değiştirilmesi yeterli olacaktır.
         Sizinde görmüş olduğunuz gibi resim işleme konusunda günlük hayatta bir çok kere kullandığımız işlemler .Net ile gelen classlar ve metodlar ile kolaylıkla yapılabilmektedir. Başka yaklaşımlar kullanarak resme uygulanabilecek teknikleri çoğaltmak mümkün olacaktır.

oztamer@hotmail.com
tamer.oz@yazgelistir.com
oztamer@hotmail.com
Ornek Kodlar