asp.net ajax image zoom implementation part 2

Share on Facebook

A while ago, I wrote a blog post on how to implement an asp.net ajax zooming system. If you haven't read that post as yet, you may read it here. The approach was at the time very promising with the release of asp.net AJAX, but at this point in time, there are far more superior technologies such as silverlight and WPF for achieving rich content in the browser and also powerful javascript libraries such as jQuery,MooTools and scriptaculous. However, I did promise in that article to post actual implementation code once I got to a point in the project which was a basic implementation of the concepts. I have been busy for a long time and hardly found time to finish this up. There have been quite a few people reading the post and expressing disappointment at the end due to the absence of a code sample, so in keeping with the promise, I have whipped up some code to demonstrate the concepts enumerated in that post.

The fig below shows the demo in action:

You may preview and engage a live demo from here.

The resizing of the image on the fly is accomplished through the ImageResize class. The main method of the ImageResize class which does the heavy lifting is GetThumbNail and is listed below:

Public Overridable Overloads Function GetThumbnail() As System.Drawing.Image
            ' check  whether a new image is required
            Dim recalc As Boolean = False
            Dim new_width As Double = Width
            Dim new_height As Double = Height

            ' Check if there is a cached source image available.
            ' check if imagepath was defined if not use the image in the Image member
            If Not CheckIsSameSourceImage(_cachedImage) Then
                If _imagePath.Length > 0 Then
                    ' Load via stream rather than Image.FromFile to release the file
                    If Not IsNothing(_sourceImage) Then
                        _sourceImage.Dispose()
                    End If
                    ' To ensure the handle gets closed when the object goes out of scope
                    ' wrap the filestream in a "using" directive
                    Using _stream As Stream = New FileStream(_imagePath, FileMode.Open, FileAccess.Read)
                        _sourceImage = System.Drawing.Image.FromStream(_stream)
                    End Using
                    recalc = True
                End If
            End If

            'Check whether the required destination image properties have changed
            If Not CheckIsSameDestinationImage(_cachedImage) Then
                ' Yes, so we need to recalculate.
                ' If you opted to specify width and height as percentages of the original
                ' image's width and height, compute these now
                If (UsePercentages) Then
                    If (Width <> 0) Then
                        new_width = Double.Parse(_sourceImage.Width) * Width / 100
                        If (PreserveAspectRatio) Then
                            new_height = new_width * _sourceImage.Height / Double.Parse(_sourceImage.Width)
                        End If
                    End If

                    If (Height <> 0) Then
                        new_height = Double.Parse(_sourceImage.Height) * Height / 100
                        If (PreserveAspectRatio) Then
                            new_width = new_height * _sourceImage.Width / Double.Parse(_sourceImage.Height)
                        End If
                    End If
                Else
                    ' If you specified an aspect ratio and absolute width or height, then calculate this 
                    ' now; if you accidentally specified both a width and height, ignore the 
                    ' PreserveAspectRatio flag
                    If (PreserveAspectRatio) Then
                        If (Width <> 0 And Height = 0) Then
                            new_height = (Width / Double.Parse(_sourceImage.Width)) * _sourceImage.Height
                        ElseIf (Height <> 0 And Width = 0) Then
                            new_width = (Height / (Double.Parse(_sourceImage.Height)) * _sourceImage.Width)
                        End If
                    End If
                End If
                recalc = True
            End If

            If (recalc) Then
                ' Calculate the new image
                If Not IsNothing(_destinationImage) Then
                    _destinationImage.Dispose()
                    _graphics.Dispose()
                End If

                'Create a square bitmap as canvas
                Dim _bitmap As System.Drawing.Bitmap
                If new_width > new_height Then
                    _bitmap = New Bitmap(Double.Parse(new_width), Double.Parse(new_width), PixelFormatType)
                Else : _bitmap = New Bitmap(Double.Parse(new_height), Double.Parse(new_height), PixelFormatType)
                End If

                'Initialise graphics with In-Memory bitmap
                _graphics = Graphics.FromImage(_bitmap)

                'If there is a background Image setting, use it for the background
                If Not String.IsNullOrEmpty(_backgroundImageUrl) Then
                    Dim backgroundimage As System.Drawing.Bitmap
                    Using _stream As Stream = New FileStream(HttpContext.Current.Server.MapPath(_backgroundImageUrl), FileMode.Open, FileAccess.Read)
                        backgroundimage = System.Drawing.Bitmap.FromStream(_stream)
                    End Using
                    If Not IsNothing(backgroundimage) Then
                        _graphics.DrawImage(backgroundimage, 0, 0, _bitmap.Width, _bitmap.Height)
                    End If
                Else
                    'Else Set graphics canvas color to the set CanvasColor
                    _graphics.FillRectangle(_canvasColor, 0, 0, _bitmap.Width, _bitmap.Height)
                End If

                'Set various properties for Resizing
                _graphics.InterpolationMode = InterpolationType
                _graphics.SmoothingMode = SmoothingType
                _graphics.CompositingMode = CompositingModeType
                _graphics.CompositingQuality = CompositingQualityType
                Dim NewHeight As Integer = CType(new_height, Integer)
                Dim NewWidth As Integer = CType(new_width, Integer)

                'If AutoPositioning then center image vertically or 
                'horizontally depending on which dimension is larger
                'Resize proportionately
                If AutoPositioning Then
                    If new_width > new_height Then
                        _graphics.DrawImage(_sourceImage, PositionX, CType((NewWidth - NewHeight) / 2, Integer), NewWidth, NewHeight)
                    Else : _graphics.DrawImage(_sourceImage, CType((NewHeight - NewWidth) / 2, Integer), PositionY, NewWidth, NewHeight)
                    End If
                Else ' Not AutoPositioning
                    'Dim srcRect As New Rectangle(PositionX, PositionY, NewWidth, NewHeight)
                    'Dim destRect As New Rectangle(PositionX, PositionY, 300, 300)
                    '_graphics.DrawImage(_sourceImage, destRect, srcRect, GraphicsUnit.Pixel)
                    _graphics.RenderingOrigin() = New Point(NewWidth / 2, NewHeight / 2)
                    _graphics.DrawImage(_sourceImage, PositionX, PositionY, NewWidth, NewHeight)
                End If

                'Apply watermarks
                If Not String.IsNullOrEmpty(_watermarkImageUrl) Then
                    Dim watermarkimage As Bitmap
                    Using _stream As Stream = New FileStream(HttpContext.Current.Server.MapPath(_watermarkImageUrl), FileMode.Open, FileAccess.Read)
                        watermarkimage = System.Drawing.Image.FromStream(_stream)
                    End Using
                    'Draw at the top left corner
                    If NewWidth > NewHeight Then
                        _graphics.DrawImage(watermarkimage, 0, 0) 'NewWidth - 15)
                    Else : _graphics.DrawImage(watermarkimage, 0, 0) 'NewHeight - 15)
                    End If
                End If


                If Not String.IsNullOrEmpty(_watermarkText) Then
                    'Draw at the top left corner
                    If NewWidth > NewHeight Then
                        _graphics.DrawString(_watermarkText, _watermarkFont, _watermarkBrush, 0, 0) 'NewWidth - 15)
                    Else : _graphics.DrawString(_watermarkText, _watermarkFont, _watermarkBrush, 0, 0) 'NewHeight - 15)
                    End If
                End If

                _destinationImage = _bitmap
                ' Put the image in the Cache
                '_cachedImage = CType(Me.MemberwiseClone(), ImageResize)
            End If
            Return _destinationImage
        End Function

 

The code for the generic handler class (ImageZoomHandler.ashx) which feeds the asp.net image control's ImageUrl property is listed below:

Imports System.IO
Imports System
Imports System.Web

Public Class ImageSizeHandler : Implements IHttpHandler
    
    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
        
        'Read in the image filename to create a thumbnail of
        Dim imageUrl As String = context.Request.QueryString("img")
        If imageUrl.StartsWith("../") Then
            imageUrl = imageUrl.Replace("../", "")
        End If
    
        'Read in the dimensions
        Dim width As Integer = context.Request.QueryString("w")
        Dim height As Integer = context.Request.QueryString("h")
        Dim xPos As Integer = 0
        Dim yPos As Integer = 0
        If Not String.IsNullOrEmpty(context.Request.QueryString("x")) Then
            xPos = Integer.Parse(context.Request.QueryString("x"))
        End If
        If Not String.IsNullOrEmpty(context.Request.QueryString("y")) Then
            yPos = Integer.Parse(context.Request.QueryString("y"))
        End If                
              
        'create a new instance of the resizer class and set necessary properties
        Dim imgResizer As Commerce.Common.ImageResize = New Commerce.Common.ImageResize
        imgResizer.ImagePath = context.Server.MapPath("~/" + imageUrl)
        
        If width < 400 And height < 400 Then
            imgResizer.Width = width
            imgResizer.Height = height
            imgResizer.PositionX = xPos
            imgResizer.PositionY = yPos
        ElseIf width >= 400 Or height >= 400 Then
            Dim OriginX As Integer = 0
            Dim OriginY As Integer = 0
            If width >= 400 Then
                OriginX = (400 - width) / 2
                OriginY = (400 - height) / 2
            Else
                OriginX = (400 - height) / 2
                OriginY = (400 - height) / 2
            End If
            imgResizer.Width = width
            imgResizer.Height = height
            imgResizer.PositionX = OriginX + xPos
            imgResizer.PositionY = OriginY + yPos
        End If
        
        imgResizer.PreserveAspectRatio = True
        imgResizer.AutoPositioning = False
        imgResizer.UsePercentages = False
        
        'Initialise response stream
        context.Response.Clear()
        context.Response.BufferOutput = True
        context.Response.ContentType = "image/jpeg"
        context.Response.AppendHeader("content-disposition", "filename=ProductImage.jpg")
        
        'create new image and render to Output Stream of Response.
        imgResizer.GetThumbnail().Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
        context.Response.End()        
    End Sub
 
    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property

End Class

As you may have realised from the downloaded project, the system is no where near perfect. My objective for posting it here is for someone to pick it up, fine tune it and add some icing on it, so we can all use it sometime in the future.
Please post any comments below.
Cheers!

You may download the visual studio project for the demo as a zip archive by clicking the link below:

ImageZoom.zip (321.98 kb)

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkListkick it on DotNetKicks.comTwitThis

Comments are closed

About Me

When not scratching my head for solutions to software challenges, I spend my time playing with my little boy - Michael Jnr.

Quotations

"Success is the ability to go from one failure to another with no loss of enthusiasm."
Sir Winston Churchill

Donate with PayPal - it

Calendar

<<  July 2010  >>
MoTuWeThFrSaSu
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2005 - 2010

Search