用ASP.NET在網頁上顯示縮圖

來源:互聯網
上載者:User
asp.net|縮圖|網頁|顯示

網站上可能會有很多圖片,比如產品圖片等,而且他們可能大小不一,寬度和高度也不一定一樣,有的很大有的很小。如果放在一張網頁上,可能會破壞版面,但是如果強制讓他們按照指定的寬度和高度顯示,因為比例不同還會出現變形,顯示效果很糟糕,還有最大的缺點是,檔案尺寸絲毫沒有變化,當圖片很大的時候,使用者想要看到圖片,必須經過漫長等待下載圖片,怎麼辦呢?

好,這裡設計到了縮圖,就像Windows中的縮圖查看一樣,你所看到的是從原圖按照1:1比例縮小的圖片,而且滿足規定在指定寬度和高度的範圍內顯示(如果圖片填不滿,就用空白)。縮圖不是原圖,而是利用原圖即時按照指定大小產生的,他的好處就是你可以充分控制縮圖的品質,寬度高度,檔案大小也在合理的範圍內,省去漫長等待。

本文將討論如何產生縮圖,舉一反三,又可以派生許多用處,比如,自己寫一個驗證碼控制項等。

1、理解對圖片的請求和流
    一般來說,我們用http://xxx/a.aspx對a.aspx網頁請求。ASP.NET處理了網頁以後,就把該網頁的內容發送回瀏覽器。a.aspx的內容一般是含有超文本標記的文字檔流,這是誰都不會懷疑的。但是a.aspx不但能夠返回這種非常平常的網頁文本外,把它廣義開來,它其實可以放回任何類型的流資料。而,我們只需要對Response對象進行操作即可改變輸出資料流的內容。
    把影像檔看作是一個二進位流,我們試圖從一個影像檔建立了他的流對象,並且將流寫入到Response.OutputStream中,這樣影像檔就被發給了請求的瀏覽器。但是瀏覽器還必須要識別出這是一個影像檔,因此,在發送這個流之前,將Response.ContentType更改成這種影像檔的MIME類型。瀏覽器在收到這個流之後,調用相關的應用程式,映像就被顯示在了瀏覽器上。雖然實際地址還是aspx結尾。
    這樣我們就能很好理解怎麼去向使用者發送標記。例如,在一張普通的網頁中寫標記img標記,使他的src指向a.aspx。瀏覽器在得到這張網頁後,會處理img標記的內容,並向a.aspx發出請求,這是a.aspx作為映像流返回,瀏覽器就將圖片顯示出來。

2、產生縮圖
    有了上述技術基礎,我們可以建立這樣一個空的aspx網頁,他通過接受傳入的參數,產生縮圖的流,發送回瀏覽器。
    我們建立一個名叫GetThumbnail.aspx的檔案,內容如下:

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="GetThumbnail.aspx.vb" Inherits="_51use.GetThumbnail"%>

這一句Page指令僅僅是告訴伺服器,這個檔案的隱藏類是_51use.GetThumbnail,而如果我們都不作任何操作的話,這個檔案最終輸出時空的。
接下來看一下他的隱藏類是如何寫的,在這裡我們使用的是B語言:

程式碼:

Public Class GetThumbnail
    Inherits System.Web.UI.Page

#Region " Web Form設計器產生的程式碼 "

    '該調用是 Web Form設計器所必需的。
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

    End Sub

    '注意: 以下預留位置聲明是 Web Form設計器所必需的。
    '不要刪除或移動它。
    Private designerPlaceholderDeclaration As System.Object

    Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: 此方法調用是 Web Form設計器所必需的
        '不要使用代碼編輯器修改它。
        InitializeComponent()
    End Sub

#End Region

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        '在此處放置初始化頁的使用者代碼
        '擷取幾個參數,用以產生縮圖片
        '設定一個預設參數產生BitMap
        Response.Clear()
        Try
            Dim originalFileName As String = Server.MapPath(Request("fn"))
            Dim thumbnailWidth As Integer = Request("tw")
            Dim thumbnailHeight As Integer = Request("th")

            Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(originalFileName)
            Dim thisFormat As System.Drawing.Imaging.ImageFormat = img.RawFormat
            Dim newSize As System.Drawing.Size = Me.GetNewSize(thumbnailWidth, thumbnailHeight, img.Width, img.Height)
            Dim outBmp As New System.Drawing.Bitmap(thumbnailWidth, thumbnailHeight)
            Dim g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(outBmp)

            '設定畫布的描繪品質
            g.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
            g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
            g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
            g.Clear(System.Drawing.Color.FromArgb(255, 249, 255, 240))
            g.DrawImage(img, New Rectangle((thumbnailWidth - newSize.Width) / 2, (thumbnailHeight - newSize.Height) / 2, newSize.Width, newSize.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel)
            g.Dispose()

            If thisFormat.Equals(System.Drawing.Imaging.ImageFormat.Gif) Then
                Response.ContentType = "image/gif"
            Else
                Response.ContentType = "image/jpeg"
            End If

            '設定壓縮品質
            Dim encoderParams As New System.Drawing.Imaging.EncoderParameters
            Dim quality(0) As Long
            quality(0) = 100
            Dim encoderParam As New System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality)
            encoderParams.Param(0) = encoderParam

            '獲得包含有關內建映像編碼解碼器的資訊的ImageCodecInfo 對象。
            Dim arrayICI() As System.Drawing.Imaging.ImageCodecInfo = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()
            Dim jpegICI As System.Drawing.Imaging.ImageCodecInfo = Nothing
            For fwd As Integer = 0 To arrayICI.Length - 1
                If arrayICI(fwd).FormatDescription.Equals("JPEG") Then
                    jpegICI = arrayICI(fwd)
                    Exit For
                End If
            Next

            If Not jpegICI Is Nothing Then
                outBmp.Save(Response.OutputStream, jpegICI, encoderParams)
            Else
                outBmp.Save(Response.OutputStream, thisFormat)
            End If
        Catch ex As Exception

        End Try
    End Sub

    Function GetNewSize(ByVal maxWidth As Integer, ByVal maxHeight As Integer, ByVal width As Integer, ByVal height As Integer) As System.Drawing.Size
        Dim w As Double = 0.0
        Dim h As Double = 0.0
        Dim sw As Double = Convert.ToDouble(width)
        Dim sh As Double = Convert.ToDouble(height)
        Dim mw As Double = Convert.ToDouble(maxWidth)
        Dim mh As Double = Convert.ToDouble(maxHeight)

        If sw < mw And sh < mh Then
            w = sw
            h = sh
        ElseIf (sw / sh) > (mw / mh) Then
            w = maxWidth
            h = (w * sh) / sw
        Else
            h = maxHeight
            w = (h * sw) / sh
        End If
        Return New System.Drawing.Size(Convert.ToInt32(w), Convert.ToInt32(h))
    End Function
End Class


我們在Page_Load事件處理函數中,先擷取要產生縮圖的原始檔案的路徑,和縮圖的寬度高度。
然後設定了一個子函數GetNewSize用以計算真正縮圖的大小(為什麼還要計算阿?因為縮圖的寬高比和原始圖片的寬高比不一樣,縮小的圖片要保證比例,按照比例縮小的原始圖片,是按照約束在指定縮圖寬高範圍內的原則,填充不滿的地方使用背景色填補空白。另外,原圖比縮圖小的話,我們就不做放大,而是按原圖輸出,所以計算是必須的)。

我們從原始映像建立了他的Image對象,並獲得它的格式等資訊,稍後用得到。

接下來建立一個BitMap對象,並由新的BitMap對象建立畫板。設定畫筆品質為高,交錯模式為高品質立方式,這些的目的是使用最好的品質描繪縮圖,否則圖片縮小後資訊丟失圖片失真就不好看了。接著,用指定的寬度和高度將原始映像的Image對象“畫”在新的畫板上。

修改Response.ContentType,這一步是告訴瀏覽器發送回的流的MIME類型,這個內容包含在HTTP Header中發送給瀏覽器。

映像畫好了,現在我們要將其壓縮一下,因為位元影像對象是很大的,不利於傳輸。因此下面的操作,我們設定一些高品質的壓縮參數,根據獲得的ICI(映像編碼解碼器資訊),使用BitMap的Save方法將圖片儲存在Response.OutputStream流中。

這樣在瀏覽器看來,對該網頁的請求,相當於對一個圖片檔案的請求,只不過圖片是即時產生的,只需傳遞參數合法有效,即可得到該圖片的縮圖。

3、使用縮圖
    使用縮圖就變得相對簡單了,只需要在URL後附上參數fn表示原始檔案的位置(相對於根目錄),tw縮圖寬度,th縮圖高度,下列簡單顯示了在Repeater中使用的情景:

<asp:Repeater id=repWareList runat="server" DataSource="<%# dsWareList %>">
  <ItemTemplate>
    <div class="ItemContainer">
      <p><img src='../lib/GetThumbnail.aspx?fn=<%# Server.UrlEncode(Configurationsettings.AppSettings("WareImgPath") & Container.DataItem("WareImgPath"))%>&tw=120&th=120' width="120" height="120" ></p>
    </div>
  </ItemTemplate>
</asp:Repeater>


代碼中藍色部分就是對該頁請求的URL,使用<%# Server.UrlEncode(Configurationsettings.AppSettings("WareImgPath") & Container.DataItem("WareImgPath"))%>語句從資料庫獲得路徑和檔案名稱適當構造成一個有效請求路徑。工作就算完成了。

下面就等著看看縮圖的效果:

後記
    本文中所述的縮圖產生法,使用的是流的概念,和檔案系統也不沾邊,因此這種方式可以跳過對檔案系統許可權檢查,百分之百正確運行。當然,也可以藉助檔案系統。另外,根據上面流輸出的概念,舉一反三,可以弄出很多用法,例如NeoDynamic的條碼控制項,你會發現條碼圖片的路徑居然就是本頁頁面,他巧妙地將對本頁的請求通過對幾個特徵參數的判定而轉向產生圖片流,從而達到了不添加任何頁面,不藉助檔案系統的“神奇效果”,只需要一個DLL即可使用。
    另外,很多人問產生驗證碼圖片,也可以使用這樣的思路,自己做一個這樣的控制項,或者網頁。如果能做自訂控制項更好。相信大家有這個能力。
    最後,還是提倡大家都去翻翻MSDN,有很大協助。安裝VS的時,7CD裝的版本其中三張是MSDN Library,包含了近乎所有你想要瞭解的東西。如果有時間,不妨多訪問一下MSDN中國,不定期會有一些優秀的文章在上面。



相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。