Silverlight 3.0 Beta içerisinde WriteableBitmap kullanımı.

0 dakikada yazıldı

6066 defa okundu

Düzenle

Silverlight içerisinde tamamen kod ile çizim yapmanın ötesinde bazı
durumlarda sıfırdan bir Bitmap oluşturmak da isteyebilirsiniz. Bazı
durumlarda ise belki de elinizde var olan bir Bitmap nesnesini
değiştirmek isteyebilirsiniz. Bu gibi durumlarda Silverlight 2.0
içerisinde derdimize derman olabilecek hazır bir API gelmezken artık
Silverlight 3.0 içerisinde WriteableBitmap nesnesi bulunuyor.
WriteableBitmap ile beraber istediğimiz Bitmap'i sıfırdan kod ile
yaratabiliyoruz. Hatta bununla kalmayıp çok güzel şeyler de
yapılabiliyor ama tüm bu güzel şeyleri görebilmek için biraz daha
makeleyi okumaya devam etmeniz gerekecek :)

Hadi sıfırdan Bitmap yaratalım?

Sıfırdan bir Bitmap yaratmak demek aslında bir resim veya fotoğraf
yaratırken her bir pikselde yer alacak renge karar vermek demektir.
Bununla ilgili kullanabileceğiniz çok ilginç algoritmalar
oluşturabilirsiniz. (Mandelbrot :)) Örneğin Quake1 zamanında 3D bir oyun
olarak gözükse de özünde bu şekilde ekrana Bitmap'ler pompalayan bir
yapıdan farklı bir mimarisi yoktu. Neyse konumuza dönelim ve bakalım biz
kendi bitmapimizi nasıl yaratabileceğiz.

[XAML]

    <Grid
x
:Name="LayoutRoot"
Background
="White">

        <Image

           x:Name="imgFoto" />

    </Grid>

Yukarıdaki şekli ile basit bir Image nesnesini Silverlight uygulamamızın
sahnesine yerleştiriyoruz. Bundan sonraki kodlarımızda söz konusu
nesnenin içerisine farklı Bitmap'ler oluşturarak yerleştireceğiz.

[VB]

        Dim bitmap As New
Imaging.WriteableBitmap(100, 100, Media.PixelFormats.Bgr32)

[C#]

            System.Windows.Media.Imaging.WriteableBitmap bitmap =

                new
System.Windows.Media.Imaging.WriteableBitmap(100, 100,

                    System.Windows.Media.PixelFormats.Bgr32);

WriteableBitmap nesnesini yaratırken oluşturacağımız Bitmap'in genişlik
ve yükseklik değerlerinin yanı sıra bir de Piksel formatını
tanımlıyoruz. Bu aşamada iki seçenek söz konusu. Eğer Bgr32
kullanırsanız resminizde R (Red), G (Green) ve B (Blue) kanalları yer
alacaktır. Eğer Pbgra32 kullanırsanız RGB'ye ek olarak bir de Alpha
(şeffaflık) kanalı kullanabilirsiniz. Yani özünde eğer oluşturacağınız
resmin şeffaflığı olacak ise Pbgra32, olmayacaksa Bgr32 kullanmanız
uygun olacaktır.

[VB]

        bitmap.Lock()

Lock ve Unlock metodlarını Bitmap yaratma işleminin başında ve
sonunda kullanacağız. Bu metodların amacı Bitmap yaratılırken veya
değiştirilirken söz konusu değişikliklerin görsel olarak ekrana
yansımasını engellemek. Lock işlemini de yaptığımıza göre artık yavaş
yavaş çizimimizi yapmaya başlayalım.

[VB]

        For y As Integer
= 0 To 99

            For x As Integer
= 0 To 99

                Dim renkler(3) As Byte

                renkler(0) = x 'B
(Mavi)

                renkler(1) = x 'G
(Yeşil)

                renkler(2) = y 'R
(Kırmızı)

                bitmap((x * 100) + y) = BitConverter.ToInt32(renkler,
0)

            Next

        Next

[C#]

            for (int y = 0; y <= 99; y++)

            {

                for (int x = 0; x <= 99; x++)

                {

                    byte[] renkler =
new byte[4];

                    renkler[0] = (byte)x; //B
(Mavi)

                    renkler[1] = (byte)x; //G
(Yeşil)

                    renkler[2] = (byte)y; //R
(Kırmızı)

                    bitmap[(x * 100) + y] = BitConverter.ToInt32(renkler, 0);

                }

            }

WriteableBitmap içerisinde herhangi bir piksele ulaşmak gerçekten çok
kolay. Ulaşmak istediğiniz bir pikselin indeks numarasını doğrudan
bitmap(0) şeklinde vererek söz konusu piksele ulaşabiliyorsunuz.
Indeks numarası sürekli soldan sağa giderek satır bittiğinde de bir alt
satıra geçerek devam ediyor. Böylece iç içe iki döngü kullanarak
rahatlıkla tüm pikselleri gezebiliyoruz. Piksellere renk atama işlemini
yaparken üçlü bir byte yaratıp 255 üzerinden RGB değerlerini
verip sonra da Byte'ımızı Int32'ye çevirip Bitmap'imize atıyoruz.
Şimdilik örneğimizde döngülerden değerler alıp kullandık ki her
seferinde biraz daha farklı bir renk yaratılsın.

[VB]

        bitmap.Invalidate()

        bitmap.Unlock()

        imgFoto.Source = bitmap

Son olarak Invalidate metodu ile verdiğimiz değerlerden Bitmap'in
çizilmesini ve Unlock ile de gösterilebilir olmasını sağladıktan
sonra XAML içerisinde tanımladığımız Image nesnesine kaynak olarak
atıyoruz.

Yarattığımız Bitmap karşımızda!
Yarattığımız Bitmap karşımızda!

Yukarıdaki görselde gördüğünüz Bitmap'i tamamen kendi kodumuz ile
yaratmış olduk. Bu şekilde Bitmap yaratma proseslerini Multithread
olarak çalıştırarak farklı animasyonlar yapmak da mümkün.

Başka başka?

WriteableBitmap'in bir diğer özelliği ise ekrandaki herhangi bir
Silverlight elementinin görselliğini alabiliyor olması. Böylece belki de
ekranda gösterdiğiniz bir Grid'in görselliğini resim olarak alabilir
veya belki de oynattığınız bir videonun o anki karesini
yakalayabilirsiniz. Tüm bunları WriteableBitmap ile yapmak gerçekten çok
kolay.

[XAML]

<UserControl

   x:Class="SilverlightApplication26.MainPage"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   Width="400"

   Height="300">

    <Grid

       x:Name="LayoutRoot"

       Background="White">

        <Image

           Height="100"

           HorizontalAlignment="Left"

           VerticalAlignment="Top"

           Source="Flower.jpg"

           Width="100"

           x:Name="imgFoto" />

        <Image

           Height="100"

           HorizontalAlignment="Right"

           VerticalAlignment="Top"

           Width="100"

           x:Name="imgFoto2" />

    </Grid>

</UserControl>

Yukarıdaki gibi iki adet Image kontrolümüzün olduğu bir uygulama
düşünelim. Image'lardan birinde Flower.jpg adındaki dosya gösterilirken
diğeri ise boş. Biz kodumuz ile bir Image kontrolündeki görselliği alıp
diğerine kaynak olarak vereceğiz.

[VB]

        Dim bitmap As New
Imaging.WriteableBitmap(100, 100, PixelFormats.Pbgra32)

        bitmap.Render(imgFoto, imgFoto.RenderTransform)

        imgFoto2.Source = bitmap

[C#]

               System.Windows.Media.Imaging.WriteableBitmap bitmap =

                   new
System.Windows.Media.Imaging.WriteableBitmap(100, 100, PixelFormats.Pbgra32);

                bitmap.Render(imgFoto, imgFoto.RenderTransform);

                imgFoto2.Source = bitmap;

Gördüğünüz gibi WriteableBitmap nesnemizi her zamanki gibi yarattıktan
sonra tek yaptığımız Render metodunu çağırmak. Render metodu ilk olarak
görselliği alacağı Silverlight elementinin adını istiyor. İkinci
parametre ise söz konusu kontrole uygulanmış olan RenderTransform
özellikleri. Böylece Render işlemi esnasında tam olarak doğru
koordinatlar yakalanabiliyor. Sonrasında elimizdeki bitmap'i başka bir
Image nesnesine kaynak olarak verebiliyoruz. Bu işlemi belirli aralıkla
yaparsanız kabaca WPF'teki VisualBrush efektini elde etmeniz de mümkün.

Hepinize kolay gelsin.