ASP.NET ile Web Sitelerinin Ekran Görüntüsünü Almak

0 dakikada yazıldı

7885 defa okundu

Düzenle

Web sitelerinin ekran görüntülerini (screenshot) alarak kullanıma sunan
hizmetler internet üzerinde mevcut. Bu makalemizde ASP.NET tarafında
nasıl başka bir sitenin ekran görüntüsü resim olarak alabileceğimizi
inceleyeceğiz. İlk olarak ufak bir noktaya değinmekte fayda var;
bahsedeceğimiz teknik bazı özel koşullarda (hedef web sitesinin görsel
öğeleri JavaScript ile düzenlemesi) başarılı sonuç vermeyebiliyor. O
nedenle eğer yüzde yüzlük bir başarı istiyorsanız ihtiyacınız olan hedef
web sitesinin ekran görüntüsü otomatik olarak alan bir windows
uygulaması ile web siteniz arasında entegrasyon sağlamak. Peki o zaman
neden bu işi web ortamında yapıyoruz? Maalesef normal barındırma
(hosting) hizmetlerinde sunucu tarafına kendi uygulamalarınızı
yüklemenize izin verilemez. Makalemizde izlediğimiz teknikler ile
herhangi bir barındırma alanında bu tarz bir uygulama yapabilirsiniz.

İlk olarak gelin ufak bir demo ile aslında ne yapacağımızı görelim.
Aşağıdaki adreste bu makaledeki kodun kullanıldığı bir uygulama var.
Uygulama John K. tarafından makalemizdeki kodun üzerine renk palet
analizi de eklenerek düzenlendi. Sistem, girilen adresin ekran
görüntüsünü aldıktan sonra görüntü içerisinde kullanılan ana renkleri
buluyor. Siz de makalemizdeki yöntemi kullanarak eminim ki çok daha
farklı uygulamalar yapabilirsiniz. Eğer beni uygulamalarınızla ilgili
haberdar edebilirseniz ayrıca sevinirim.

http://www.todotoh.com/rgb/rgbanalysis.aspx

İş Başına

Peki bu işi nasıl yapacağız? İlk olarak .NET Framework'un en önemli
konseptini hatırlatmakta fayda var. Web ile windows uygulamalarında
aslında biz aynı Framework'ü kullanıyoruz. Yani eğer istersek windows
forms uygulamalarında kullandığımız tüm kütüphaneleri ve objeleri web
forms uygulamalarımızda da kullanabiliriz. Bir web sitesinin ekran
görüntüsü almak için WinForms'da kullanabileceğimiz WebBrowser
adında bir objemiz var.

Dim MyBrowser As New
WebBrowser

MyBrowser.ScrollBarsEnabled = False
MyBrowser.Size = New Size(1027,
768)

MyBrowser.Navigate("http://daron.yondem.com")
Dim myBitmap As New
Bitmap(1024, 768)

Dim DrawRect As New
Rectangle(0, 0, 1024, 768)

MyBrowser.DrawToBitmap(myBitmap, DrawRect)

Yukarıdaki kodumuz içerisinde yeni bir WebBrowser objesi yarattıktan
sonra ekranın kenarlarında kaydırma çubuklarının gözükmemesi için
ScrollBarsEnabled özelliğini False olarak düzenliyoruz. Bir
sonraki adımda Browser (Tarayıcı) objemizin boyutunu 1024*768
yaparak sanki web sitesi o çözünürlükte bir ekranda açılmışmış gibi bir
ortam yaratıyoruz. WebBrowser objesine ait .Navigate metoduna
verdiğimiz parametre ile sitemizin yüklenmesini sağlıyoruz. Uygun resim
ve çizim alanı değişkenlerimizi de tanımladıktan sonra yine
WebBrowser objesine ait .DrawToBitmap metodunu kullanarak
görüntüyü değişkenimize alıyoruz.

Tabi olay bu kadar kolay değil. Elimizdeki ilk sorun web sitesinin
yüklenmesini beklemek zorunda olmamız. Bunun için kör bir döngü
kullanacağız.

MyBrowser.Navigate(Me.URL)
While MyBrowser.ReadyState
<> WebBrowserReadyState.Complete

   Application.DoEvents()
End While

Kodumuzda WebBrowser objesinin ReadyState özelliğini kontrol
ederek Complete olana kadar kısır bir döngüye sokuyoruz. Döngü
içerisinde kullandığımız Application.DoEvents() kodu döngü süresince
WebBrowser'daki yüklemenin kilitlenmemesini ve devam etmesini
sağlayacak. Bir sonraki sorunumuz aslında çok daha kritik.
WebBrowser objesi özünde bir COM objesi olduğu için Single
Threaded
bir Thread içerisinde çalıştırılması gerekiyor. Bu aslında
biraz da işimize yarar, böylece tüm bu yükleme kodlarını başka bir
Thread içerisine almış oluruz.


Dim NewTh As New
Threading.Thread(AddressOf
DoIt)

NewTh.SetApartmentState(Threading.ApartmentState.STA)
NewTh.Start()

Yukarıda bir Thread tanımı yer alıyor. Bu tanım içerisinde en önemli
nokta ikinci satırdaki kod. Yarattığımız Thread için
SetApartmentState diyerek çalışma şeklini
SingleThreadedApartment haline çeviriyoruz. Tüm sorunları aştık,
geriye kaldı gelen ekran görüntüsünü uygun şekilde küçültme kodumuza. Bu
işlem için çok farklı teknikler kullanılabilir, ben aşağıda bu
tekniklerden birine ait kodu paylaşacağım. Makalemizin esas konusu bu
olmadığı için detaya girmeyeceğim.

Dim imgOutput As System.Drawing.Image = myBitmap
Dim oThumbNail As System.Drawing.Image = New Bitmap(twidth, theight, _
                imgOutput.PixelFormat)
Dim g As Graphics =
Graphics.FromImage(oThumbNail)

g.CompositingQuality =
Drawing2D.CompositingQuality.HighSpeed

g.SmoothingMode = Drawing2D.SmoothingMode.HighSpeed
g.InterpolationMode =
Drawing2D.InterpolationMode.HighQualityBilinear

Dim oRectangle As Rectangle = New Rectangle(0, 0, twidth, theight)
g.DrawImage(imgOutput, oRectangle)

Şimdi gelin tüm bu kodları birleştirerek bir Class yapısı içerisinde
projelerimizde kullanacağımız kodumuzu inceleyelim.

Imports System
Imports System.Drawing
Imports
System.Drawing.Imaging

Imports
System.Windows.Forms

Imports
System.Diagnostics

 
Namespace
GetSiteThumbnail

 
    Public Class GetImage
        Private S_Height As Integer
        Private S_Width As Integer
        Private F_Height As Integer
        Private F_Width As Integer
        Private MyURL As String
 
        Property ScreenHeight()
As Integer

            Get
                Return
S_Height

            End Get
            Set(ByVal value As Integer)
                S_Height = value
            End Set
        End Property
 
        Property ScreenWidth()
As Integer

            Get
                Return
S_Width

            End Get
            Set(ByVal value As Integer)
                S_Width = value
            End Set
        End Property
 
        Property ImageHeight()
As Integer

            Get
                Return
F_Height

            End Get
            Set(ByVal value As Integer)
                F_Height = value
            End Set
        End Property
 
        Property ImageWidth()
As Integer

            Get
                Return
F_Width

            End Get
            Set(ByVal value As Integer)
                F_Width = value
            End Set
        End Property
 
        Property WebSite() As String
            Get
                Return
MyURL

            End Get
            Set(ByVal value As String)
                MyURL = value
            End Set
        End Property
 
        Sub New(ByVal
WebSite As String, ByVal ScreenWidth As Integer, ByVal ScreenHeight As Integer, ByVal ImageWidth As Integer, ByVal ImageHeight As Integer)

            Me.WebSite =
WebSite

            Me.ScreenWidth =
ScreenWidth

            Me.ScreenHeight =
ScreenHeight

            Me.ImageHeight =
ImageHeight

            Me.ImageWidth =
ImageWidth

        End Sub
 
        Function GetBitmap()
As Bitmap

            Dim Shot As New
WebPageBitmap(Me.WebSite, Me.ScreenWidth, Me.ScreenHeight)

            Shot.GetIt()
            Dim Pic As Bitmap = Shot.DrawBitmap(Me.ImageHeight, Me.ImageWidth)
            Return Pic
        End Function
    End Class
 
    Class WebPageBitmap
        Dim MyBrowser As WebBrowser
        Dim URL As String
        Dim Height As Integer
        Dim Width As Integer
 
        Sub New(ByVal
url As String, ByVal width As Integer, ByVal height As Integer)

            Me.Height =
Height

            Me.Width =
width

            Me.URL = url
            MyBrowser = New
WebBrowser

            MyBrowser.ScrollBarsEnabled = False
            MyBrowser.Size = New
Size(Me.Width, Me.Height)

        End Sub
 
        Sub GetIt()
            MyBrowser.Navigate(Me.URL)
            While
MyBrowser.ReadyState <> WebBrowserReadyState.Complete

                Application.DoEvents()
            End While
        End Sub
 
        Function
DrawBitmap(ByVal theight As Integer, ByVal twidth As Integer) As Bitmap

            Dim myBitmap As New
Bitmap(Width, Height)

            Dim DrawRect As New
Rectangle(0, 0, Width, Height)

            MyBrowser.DrawToBitmap(myBitmap, DrawRect)
            Dim imgOutput As System.Drawing.Image = myBitmap
            Dim oThumbNail As System.Drawing.Image = New Bitmap(twidth, theight,
imgOutput.PixelFormat)

            Dim g As Graphics =
Graphics.FromImage(oThumbNail)

            g.CompositingQuality =
Drawing2D.CompositingQuality.HighSpeed

            g.SmoothingMode =
Drawing2D.SmoothingMode.HighSpeed

            g.InterpolationMode =
Drawing2D.InterpolationMode.HighQualityBilinear

            Dim oRectangle As Rectangle = New Rectangle(0, 0, twidth, theight)
            g.DrawImage(imgOutput, oRectangle)
            Try
                Return
oThumbNail

            Catch ex As Exception
            Finally
                imgOutput.Dispose()
                imgOutput = Nothing
                MyBrowser.Dispose()
                MyBrowser = Nothing
            End Try
        End Function
    End Class
 
End Namespace

Yarattığımız iki classtan biri olan GetImage programcıdan alacağı
ekran görüntüsüne ait çözünürlük bilgilerini ve geri döndüreceği resmin
boyut bilgilerini alıyor. Aldığı bilgiler çerçevesinde ekran
görüntüsünün alınması sonrasında da görüntünün istenen boyuta
küçültülmesini sağlayacak. WebPageBitmap class'ımız ise ekran
görüntüsünün alınmasından ve sonrasında da tekrar boyutlandırılmasında
sorumlu. Tabi tüm bu işlemleri ayrı bir Thread içerisinde yapmamız
gerektiğinden bahsetmiştik. Şimdi de gelin yukarıdaki Class'ımızı
sayfamızda nasıl kullanabileceğimize bakalım.

Partial Class _Default
    Inherits
System.Web.UI.Page

 
    Protected Sub Button1_Click(ByVal sender As Object,
ByVal e As System.EventArgs) Handles Button1.Click

        Dim NewTh As New
Threading.Thread(AddressOf
DoIT)

       
NewTh.SetApartmentState(Threading.ApartmentState.STA)

        NewTh.Start()
        While NewTh.ThreadState
= Threading.ThreadState.Running

        End While
        Image1.ImageUrl = TextBox1.Text.Replace(".", "_") & ".jpg"
    End Sub
 
    Sub DoIT()
        Try
            Dim thumb As New
GetSiteThumbnail.GetImage("http://" & TextBox1.Text, 1024, 768,
320, 240)

            Dim x As System.Drawing.Bitmap =
thumb.GetBitmap()

            x.Save(Server.MapPath(".") & "\" & TextBox1.Text.Replace(".", "_") & ".jpg")
        Catch ex As Exception
            Dim y As System.IO.StreamWriter =
System.IO.File.CreateText("C:\Inetpub\wwwroot\screeny\error.txt")

            y.WriteLine(ex.Message & vbCrLf & ex.Source)
            y.Flush()
            y.Close()
        Finally
        End Try
    End Sub
End Class 

Code-Behind dosyamızın kodunu yukarda inceleyebilirsiniz. Button1'e
tıklandığında uygun Thread'i yaratarak DoIT Sub'ını çalıştıracağı
şekilde hazırlıyoruz. Basit bir şekilde Thread'in bitmesini beklemek
için yine kısır bir döngü kullanarak ThreadState durumunu kontrol
ettik. Ekran görüntüsü alındığı gibi kullanıcıya göstermek için biraz
kullanıcıyı bekletmemiz gerekecek. Eğer siz bir AJAX web sitesi
hazırlıyorsanız ekran görüntüsünün alınmasını beklemektense bir AJAX
Timer ile durumu kontrol edip kullanıcıya bilgi verebilirsiniz.

DoIT Sub'ımız içerisine bakarsak aslında bir önceki Class
yapımızı kullandığımızı görüyoruz. Ben kodumda ekran görüntüsünü ve
oluşursa herhangi bir hatayı farklı yerlere kaydettim. Siz bu konumları
değiştirerek farklı yapılar kurabilirsiniz.

Tüm bu kodlara ek olarak daha yüksek performanslı bir sonuç için
kodunuzun daha önce alınmış ekran görüntülerini kontrol ederek eğer söz
konusu adrese ait ekran görüntüsü çok eski değilse yenisini almadan
kullanıcıya eskisi de göstermesini sağlayabilirsiniz.

Hepinize kolay gelsin.

Makale Kaynak Kodu - 03092007_1.zip (3,48
KB)