Server side image resizing

Nothxkbi

Banned
Joined
Mar 19, 2010
Messages
4,529
Reaction score
3
Location
Amanzimtoti - KZN
Well I've been painted into a corner with this latest project at work....working with images.

We've got a photo album on the intranet, the page is coded in asp.net. Fine.

But the images are way too large and are hitting our bandwidth everytime someone visits teh page.

So I've been asked to resize them server side before they're displayed client side. I'm stumped. Anybody got a piece of code that can do this? I've googled this **** for about 3 days now and I'm still stumped. Hulp! :(
 
Nevermind, I jumped the gun on this. Finally managed to get my code running. Stupid me, didn't import the libraries correctly! Anway this works perfectly.

Code:
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Drawing.Drawing2D" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.Drawing" %>

<script runat="server">

    Public Sub ResizeImage(ByVal ImagePath As String, Optional ByVal Quality As Integer = 100, Optional ByVal ContainerHeight As Integer = -1, Optional ByVal ContainerWidth As Integer = -1)

        Dim originalimg, thumb As System.Drawing.Image
        Try
            Dim Height As Integer
            Dim Width As Integer
            Dim client As New WebClient
            Dim objStream As System.IO.Stream
            objStream = client.OpenRead(ImagePath)
            ' Get the image stream
            originalimg = System.Drawing.Image.FromStream(objStream)

            If originalimg.Height <= ContainerHeight And originalimg.Width <= ContainerWidth Then
                ' image fits within container, use full image size
                Height = ContainerHeight
                Width = ContainerWidth
            ElseIf originalimg.Height > ContainerHeight And originalimg.Width > ContainerWidth Then
                ' image height and width are both greater than container
                If (originalimg.Height / ContainerHeight) > (originalimg.Width / ContainerWidth) Then
                    Height = ContainerHeight
                    Width = (ContainerHeight / originalimg.Height) * originalimg.Width
                Else
                    Width = ContainerWidth
                    Height = (ContainerWidth / originalimg.Width) * originalimg.Height
                End If
            ElseIf originalimg.Width > ContainerWidth Then
                ' image height > container height
                Width = ContainerWidth
                Height = (ContainerWidth / originalimg.Width) * ContainerHeight
            Else
                ' image width > container width
                Height = ContainerHeight
                Width = (ContainerHeight / originalimg.Height) * ContainerWidth
            End If


            thumb = MakeThumbnail(originalimg, Height, Width)

            Dim codecEncoder As ImageCodecInfo = GetEncoder("image/jpeg")
            Dim encodeParams As New EncoderParameters(1)
            Dim qualityParam As New EncoderParameter(Imaging.Encoder.Quality, Quality)
            encodeParams.Param(0) = qualityParam
            thumb.Save(Response.OutputStream, codecEncoder, encodeParams)

            originalimg.Dispose()
            thumb.Dispose()
        Catch ex As Exception
            Throw New Exception("Error processing JPEG", ex)
        End Try
    End Sub
    
    Function MakeThumbnail(ByVal Source_Img As System.Drawing.Image, ByVal height As Integer, ByVal width As Integer) As System.Drawing.Image
        Try
            Dim intOrginalWidth As Integer
            Dim intOrginalHeight As Integer
            Dim sngAspectRatio As Single

            intOrginalWidth = Source_Img.Width
            intOrginalHeight = Source_Img.Height
            sngAspectRatio = intOrginalHeight / height
            width = intOrginalWidth / sngAspectRatio

            Dim thumb As System.Drawing.Image = New Bitmap(width, height)
            Dim objGraphics As System.Drawing.Graphics
            objGraphics = System.Drawing.Graphics.FromImage(thumb)
            objGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic
            objGraphics.SmoothingMode = SmoothingMode.HighQuality
            objGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality
            objGraphics.CompositingQuality = CompositingQuality.HighQuality

            objGraphics.DrawImage(Source_Img, 0, 0, width, height)
            Return thumb
        Catch ex As Exception
            Throw (New Exception("Error in MakeThumbnail", ex))
        End Try

    End Function
    Function GetEncoder(ByVal mimeType As String) As ImageCodecInfo
        Dim codecs() As ImageCodecInfo = ImageCodecInfo.GetImageEncoders()
        For Each codec As ImageCodecInfo In codecs
            If codec.MimeType = mimeType Then
                Return codec
            End If
        Next
    End Function

    Sub Page_Load(ByVal Src As Object, ByVal E As EventArgs)
        Call ResizeImage("\\intranet_svr\Images\PhotoGallery\00001357.jpg", 100, 100, 100)
    End Sub
</script>
 
Why don't you just call a resized version of the image, fed through the response stream, to the client? That way you still have the original (big) image available on the server if you need it...
 
Jip. Create one or more thumbnails, depending on how you use the images (sidebar images might be smaller than those used in articles).
Less CPU overhead, just more storage.
 
Lulz I have absolutely no idea what you guys have just said.

Ok, put it this way:

When you upload or save the specific image on the server, use that nice code of yours to save multiple versions of the same image, i.e. nice-photo.jpg, nice-photo-64x64.jpg and nice-photo-32x32jpg. That way, you have the original BIG photo that was uploaded (nice-photo.jpg), as well as 2 different sized thumbnail images of 32x32 and 64x64 pixels each. You'll end up saving the original image with n-amount of other images with specific sizes, for specific uses.
 
Ok, put it this way:

When you upload or save the specific image on the server, use that nice code of yours to save multiple versions of the same image, i.e. nice-photo.jpg, nice-photo-64x64.jpg and nice-photo-32x32jpg. That way, you have the original BIG photo that was uploaded (nice-photo.jpg), as well as 2 different sized thumbnail images of 32x32 and 64x64 pixels each. You'll end up saving the original image with n-amount of other images with specific sizes, for specific uses.

+1 Facebook does something similar, although I don't think they keep nice-photo.jpg
 
I suppose it's a question of scale, and YAGNI

Scale, yes, YAGNI, no. Keeping an original uploaded image has none of the disadvantages mentioned in the rationale. Keeping original images has come in handy with my projects when clients decide to change dimensions, etc. All I do then is to run a script that generates the new thumbnails from the originals instead of telling the client to re-upload all their images again.

As for that code: does it resize and stream the image to the browser each time? If so it's extremely inefficient. How are the images uploaded? If via a CMS of some sort simply create the relevant thumbnail on upload. You simply run a script to create these thumbnails from the existing images.
 
Well thanks for all the helpfull input guys. After scratching my head and fighting with this page for some time I managed to get it working much like Facebook and sets all your uploaded images the same size. The page itself is still rough and needs a lot of cleaning up but the code itself works great!

Code:
<%@ Page LANGUAGE="VB" Debug="true" EnableViewState="true"%>

<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Drawing" %>

<script runat="server">
    Sub image_upload_btn_Click(ByVal sender As Object, ByVal e As EventArgs) Handles image_upload_btn.ServerClick

        If (CheckFileType(image_name_hdn.PostedFile.FileName)) Then
            Dim FilePath As String = "~/images/" & image_name_hdn.FileName
            image_name_hdn.SaveAs(MapPath(FilePath))
            Dim NewSize As System.Drawing.Size = New System.Drawing.Size(385, 305)
            Dim originalBitmap As Bitmap = CType(System.Drawing.Image.FromStream(image_name_hdn.PostedFile.InputStream), Bitmap)
            ResizePicture(originalBitmap, FilePath, NewSize)
        Else
            errormessage_lbl.Text = "Only .jpg files are allowed!"
        End If
    End Sub

    Sub ResizePicture(ByRef ImgToResize As Bitmap, ByRef newpath As String, ByVal newsize As Size)
        Using newbmp As New Bitmap(newsize.Width, newsize.Height), oldbmp As Bitmap = ImgToResize

            Using newgraphics As Graphics = Graphics.FromImage(newbmp)
                newgraphics.Clear(Color.FromArgb(-1))
                If CSng(oldbmp.Width) / CSng(newsize.Width) = CSng(oldbmp.Height) / CSng(newsize.Height) Then
                    newgraphics.DrawImage(oldbmp, 0, 0, newsize.Width, newsize.Height)
                ElseIf CSng(oldbmp.Width) / CSng(newsize.Width) > CSng(oldbmp.Height) / CSng(newsize.Height) Then
                    newgraphics.DrawImage(oldbmp, 0.0F, CSng(newbmp.Height) / 2.0F - (oldbmp.Height * (CSng(newbmp.Width) / CSng(oldbmp.Width))) / 2.0F, CSng(newbmp.Width), oldbmp.Height * (CSng(newbmp.Width) / CSng(oldbmp.Width)))
                ElseIf CSng(oldbmp.Width) / CSng(newsize.Width) < CSng(oldbmp.Height) / CSng(newsize.Height) Then
                    newgraphics.DrawImage(oldbmp, CSng(newbmp.Width) / 2.0F - (oldbmp.Width * (CSng(newbmp.Height) / CSng(oldbmp.Height))) / 2.0F, 0.0F, oldbmp.Width * (CSng(newbmp.Height) / CSng(oldbmp.Height)), CSng(newbmp.Height))
                End If

                newgraphics.Save()
                newbmp.Save(MapPath(newpath), System.Drawing.Imaging.ImageFormat.Jpeg)
                newbmp.Dispose()
            End Using
        End Using
    End Sub
    
    Private Function CheckFileType(ByVal FileName As String) As Boolean

        Dim Ext As String = Path.GetExtension(FileName)

        Select Case (Ext.ToLower())

            Case (".jpg")

                Return (True)

            Case (".jpeg")

                Return (True)

            Case Else

                Return (False)

        End Select

    End Function

</script>
    
    
    
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Image_Upload</title>
</head>
<body>
    <form id="frm_Upload" runat="server">
    <div>
        <asp:FileUpload id="image_name_hdn" runat="server"></asp:FileUpload>
        &nbsp;&nbsp;
        <input id="image_upload_btn" type="button" value="Upload" runat="server"/><br />
        <br />
        <asp:Label ID="errormessage_lbl" runat="server"></asp:Label>
    </div>
    </form>
</body>
</html>
 
Top
Sign up to the MyBroadband newsletter
X