Silverlight 4 Beta ile WebCam desteği ve fotoğraf çekimi!

0 dakikada yazıldı

7167 defa okundu

Düzenle

Silverlight 2 sonrasında CLR'a geçiş ve 3 ile gelen yeni özellikler
çerçevesinde en sık aldığım sorulardan biri Mikrofon ve Ses kartı
erişiminin olup olmadığıydı. Silverlight 4 ile beraber her iki donanıma
da doğrudan erişim geliyor. Bu erişim ile çok farklı uygulamalar
geliştirmek mümkün, ister görüntülü chat sistemleri, ister Silverlight
içerisinde doğrudan harici bir görüntü kaynağından gelen görüntüyü
proses eden barkod okuma uygulamaları olsun çok ilginç çözümler
geliştirilebilir. Biz bu yazımızda Silverlight 4 Beta içerisinden kamera
erişimine göz atacağız ve kamera görüntüsünden de bir kare almaya
çalışacağız. Aldığınız fotoğrafı sonrasında ister sunucuya gönderebilir
ister doğrudan kullanıcıya verebilirsiniz.

Kamera'ya nasıl ulaşırız?

Silverlight içerisinden sistemde bulunan tüm kameraların bir listesini
alabilir ve özelliklerine göre kamera seçebilirsiniz. Hatta söz konusu
kameraların tek tek hangi çözünürlüklerde ve kalitede kayıt
sağlayabileceğini de bulabilirsiniz.

[VB]

Partial Public Class MainPage

    Inherits UserControl

 

    Public Sub New()

        InitializeComponent()

    End Sub

 

    Private Sub MainPage_Loaded(ByVal sender As Object,
ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Dim Kameralar =
CaptureDeviceConfiguration
.GetAvailableVideoCaptureDevices

        Dim Liste = From inc In Kameralar

                    From formats In inc.SupportedFormats

                    Select New Kamera With {.Adi = inc.FriendlyName,

                                             .Format =
formats.FramesPerSecond & "fps," &

                                                formats.Width &
"x" & formats.Height,

                                             .Varsayilan =
inc.IsDefaultDevice}

 

        myGrid.ItemsSource = Liste

    End Sub

 

    Public Class Kamera

        Property Adi As String

        Property Format As String

        Property Varsayilan As Boolean

    End Class

End Class

Yukarıdaki örnek uygulamada ekran bir DataGrid bulunuyor. Bu gride
CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices ile
aldığımız tüm kameraları SupportedFormats dizilerindeki sağladıkları
çözünürlüklerle beraber joinleyerek aktarıyoruz. Benim test makinemde
tek kamera olduğu için aşağıdaki ekran görüntüsü ile karşılaştım.

Webcam'in desteklediğini ayarlar.
Webcam'in desteklediğini ayarlar.

Peki istediğimiz webcamden görüntüyü alıp nasıl gösterebiliriz?

İlk olarak kullanıcıdan izin almamız gerek. Eğer kullanıcı webcam
erişimine izin vermez ise hiçbirşey yapamayız. Session bazında saklanan
bu izni kullanıcıdan istemek için kullanacağımız metodun adı
RequestDeviceAccess şeklinde.

[VB]

        Dim IzinVarMi = CaptureDeviceConfiguration.AllowedDeviceAccess

        If Not IzinVarMi Then IzinVarMi = CaptureDeviceConfiguration.RequestDeviceAccess

Yukarıdaki ilk satırda AllowedDeviceAccess ile ilk olarak o anda
iznimiz var mı yoksa yok mu konusunu kontrol ediyoruz. Eğer iznimiz
varsa tekrar kullanıcıdan izin istemek saçma olur. Eğer yoksa hemen bir
alt satırda RequestDeviceAccess ile iznimizi istiyoruz.

Kullanıcıdan kameraya bağlanma izni istiyoruz.
Kullanıcıdan kameraya bağlanma izni istiyoruz.

İznimizi aldıktan sonra rahatlık istediğimiz bir Device'ı seçerek
cihazdan veri kaynağını alabiliriz. Sistemde farklı mikrofon ve
kameralar olabileceği için bunların kompinasyonundan bir
CaptureSource yaratabiliyorsunuz. Bizim örneğimizde sadece kameraya
ulaşacağımız için yaratacağımız CaptureSource'un sadece
VideoCaptureDevice özelliğini set edeceğiz.

[VB]

            Dim Cihaz = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice

            Dim Kaynak As New
CaptureSource

            Kaynak.VideoCaptureDevice = Cihaz

Tüm bu ayarları yaptıktan sonra sıra geliyor görüntü alma işlemini
başlatmaya ve alacağımız görüntüyü de bir yerlerde göstermeye. Bunun
için herhangi bir kontrolü kullanabilirsiniz çünkü görüntüyü bir
VideoBrush aracılığı ile alacağız ve bildiğiniz üzere
VideoBrush'ları da istediğimiz herhangi bir SL kontrolünde normal renk
fırçaları gibi kullanabiliyoruz.

[VB]

            Dim Firca As New
VideoBrush

            Firca.SetSource(Kaynak)

 

            Kaynak.Start()

            Dikdortgen.Fill = Firca

Yukarıdaki kodumuzda VideoBrush'ımızı yaratarak Source olarak eldeki
CaptureSource'u veriyoruz. Sonrasında CaptureSource üzerinden
görüntü veya ses yakalama işlemini başlatmak için Start metodunu
çağırmayı unutmamak gerek. En son olarak da eldeki VideoBrush'a adı
Dikdortgen olarak bir Rectangle'a basit bir şekilde aktarabiliriz.

Kamera görüntüsü karşınızda.
Kamera görüntüsü karşınızda.

Yukarıda gördüğünüz üzere kamera görüntüsünü almakla kalmayıp
Silverlight'taki Transformasyon ve PixelShader özelliklerini de
rahatlıkla bu görüntüler üzerine uygulayabiliyoruz. Uygulamanın tam
kodlarını aşağıda bulabilirsiniz.

[VB]

    Private Sub btnTikla_Click(ByVal sender As Object,
ByVal e As System.Windows.RoutedEventArgs) Handles btnTikla.Click

        Dim IzinVarMi = CaptureDeviceConfiguration.AllowedDeviceAccess

        If Not IzinVarMi Then IzinVarMi = CaptureDeviceConfiguration.RequestDeviceAccess

 

        If IzinVarMi Then

            Dim Cihaz = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice

            Dim Kaynak As New
CaptureSource

            Kaynak.VideoCaptureDevice = Cihaz

 

            Dim Firca As New
VideoBrush

            Firca.SetSource(Kaynak)

 

            Kaynak.Start()

            Dikdortgen.Fill = Firca

            Golge.Fill = Firca

        End If

    End Sub

[XAML]

<UserControl
xmlns:my="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"


x:Class="SilverlightApplication25.MainPage"

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

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

  
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

  
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

  
mc:Ignorable="d"

  
d:DesignHeight="300" d:DesignWidth="400">

 

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

        <Rectangle
x
:Name="Dikdortgen"
Height
="168" Width="249"
Canvas.Left
="20" Canvas.Top="19">

            <Rectangle.Effect>

                <BlurEffect
Radius
="15"/>

            </Rectangle.Effect>

        </Rectangle>

        <Button
x
:Name="btnTikla"
Content
="BAŞLAT" Height="25"
Width
="100" Canvas.Left="300"
Canvas.Top
="275" />

        <Rectangle x:Name="Golge"
Height="67" Canvas.Left="27.207" Canvas.Top="191" Width="249"
RenderTransformOrigin="0.5,0.5" UseLayoutRounding="False"
d:LayoutRounding="Auto">

           
<Rectangle.OpacityMask>

                <LinearGradientBrush
EndPoint="0.5,1" StartPoint="0.5,0">

                    <GradientStop
Color="Transparent" Offset="0"/>

                    <GradientStop
Color="White" Offset="1"/>

               
</LinearGradientBrush>

           
</Rectangle.OpacityMask>

           
<Rectangle.RenderTransform>

                <TransformGroup>

                    <ScaleTransform
ScaleY="-1" ScaleX="1"/>

                    <SkewTransform
AngleY="0" AngleX="52.651"/>

                    <RotateTransform
Angle="0"/>

                    <TranslateTransform
X="36.69"/>

                </TransformGroup>

           
</Rectangle.RenderTransform>

        </Rectangle>

    </Canvas>

</UserControl>

Kameradan fotoğrafı nasıl yakalarız?

Kameranın görüntüsünden fotoğraf yakalayabilmeniz için hazır bir API
doğrudan CaptureSource nesnesi üzerinden sunuluyor. Ama sunulan
API'ın birkaç ufak sorunu var. Birincisi eğer yukarıdaki gibi görüntüye
bir PixelShader eklediyseniz veya üzerine birşeyler bindirdiyseniz
maalesef bunların hiçbiri aldığınız fotoğrafta yer almayacaktır.
İkincisi ile eğer CaptureSource durdurulmuş ise son gelen kareyi alma
şansınız olmuyor. Gelin yine de ilk önce bu API'ye bir göz atalım sonra
da istersek daha farklı bir yöntem olarak ne uygulayabiliriz ona
bakarız.

[VB]

    Private Sub btnTikla2_Click(ByVal sender As Object,
ByVal e As System.Windows.RoutedEventArgs) Handles btnTikla2.Click

        If Kaynak IsNot Nothing Then

            Kaynak.AsyncCaptureImage(Sub(Foto)

                                                              
Dispatcher.BeginInvoke(Sub()

                                                               
                                          imgFoto.Source = Foto

                                                       
                                             End Sub)

                                                         End Sub)

        End If

    End Sub

Yukarıdaki kod içerisinde Kaynak olarak geçen nesne bizim bir önceki
örneğimizde başlattığımız CaptureSource nesnesi. Bu nesneyi UserControl
içerisinde tanımlayarak farklı eventlarda kullanılabilir hale
getirdikten sonra fotoğraf çekme işlemini yapacak düğmede nesnenin
varlığını kontrol ederek işleme devam ediyoruz. CaptureSource üzerinden
AsyncCaptureImage metodunu çağırdığınızda fotoğraf alma işlemini
yaparak bir Callback'e düşüyor. Bu Callback'den geri veri
döndürebilmek ve sahneye yeni koyduğumuz imgFoto adındaki Image
nesnesine source aktarabilmek adına Dispatcher üzerinden UI Thread'e
ulaşıyoruz. Tüm bunları lamdalarla yapınca iş epey kolayca halloluyor.

Fotoğrafımızı yakalayap sağa koyduk.
Fotoğrafımızı yakalayap sağa koyduk.

Gördüğünüz gibi aldığımız görüntü ana kaynaktan olduğu için Blur efekti
vs uygulanmış değil. Oysa orta kısımda gördüğümüzün tam aynısını almak
isterdi gönül. İşte böyle bir durumda doğrudan Silverlight 3 ile gelen
WriteableBitmap sınıfını kullanabiliriz.

[VB]

    Private Sub btnTikla2_Click(ByVal sender As Object,
ByVal e As System.Windows.RoutedEventArgs) Handles btnTikla2.Click

        Dim Goruntu As New
Imaging.WriteableBitmap(Dikdortgen,
Nothing)

        imgFoto.Source = Goruntu

    End Sub

Kodumuzda WriteableBitmap yaratırken ekranda hedef nesne olarak da
Rectangle tipindeki Dikdortgen'imizi veriyoruz. Böylece Blur vs
efektleri uygulanmış hali ile görüntüyü alabiliyoruz.

PixelShader efekti ile görüntüyü aldık.
PixelShader efekti ile görüntüyü aldık.

Artık aldığınız bu fotoğrafları işlemek veya doğrudan sunucuya bir web
servisi aracılığı ile göndermek vs tamamen size kalmış. Hepinize kolay
gelsin.