StealthRT
StealthRT

Reputation: 10542

asp.net image aspect ratio help

Hey all, i am in need of some help with keeping an image aspect ratio in check. This is the aspx code that i have to resize and upload an image the user selects.

 <%@ Page Trace="False" Language="vb" aspcompat="false" debug="true" validateRequest="false"%> 
 <%@ Import Namespace=System.Drawing %>
 <%@ Import Namespace=System.Drawing.Imaging %>
 <%@ Import Namespace=System %>
 <%@ Import Namespace=System.Web %>
 <SCRIPT LANGUAGE="VBScript" runat="server">
 const Lx = 500 ' max width for thumbnails
 const Ly = 60  ' max height for thumbnails
 const upload_dir = "/uptest/"  ' directory to upload file
 const upload_original = "sample"   ' filename to save original as (suffix added by script)
 const upload_thumb = "thumb"   ' filename to save thumbnail as (suffix added by script)
 const upload_max_size = 512    ' max size of the upload (KB) note: this doesn't override any server upload limits
 dim fileExt    ' used to store the file extension (saves finding it mulitple times)
 dim newWidth, newHeight as integer ' new width/height for the thumbnail
 dim l2 ' temp variable used when calculating new size
 dim fileFld as HTTPPostedFile  ' used to grab the file upload from the form
 Dim originalimg As System.Drawing.Image    ' used to hold the original image
 dim msg    ' display results
 dim upload_ok as boolean   ' did the upload work ?
 </script>
 <%
 randomize() ' used to help the cache-busting on the preview images
 upload_ok = false

 if lcase(Request.ServerVariables("REQUEST_METHOD"))="post" then
fileFld = request.files(0)  ' get the first file uploaded from the form (note:- you can use this to itterate through more than one image)
if fileFld.ContentLength > upload_max_size * 1024 then
    msg = "Sorry, the image must be less than " & upload_max_size & "Kb"
else
    try
        originalImg = System.Drawing.Image.FromStream(fileFld.InputStream)
        ' work out the width/height for the thumbnail. Preserve aspect ratio and honour max width/height
        ' Note: if the original is smaller than the thumbnail size it will be scaled up
        if originalImg.Height > Ly then
            newWidth = Ly * (originalImg.Width / originalImg.Height)
            newHeight = Ly
        end if

        Dim thumb As New Bitmap(newWidth, newHeight)

        'Create a graphics object           
        Dim gr_dest As Graphics = Graphics.FromImage(thumb)

        ' just in case it's a transparent GIF force the bg to white 
        dim sb = new SolidBrush(System.Drawing.Color.White)
        gr_dest.FillRectangle(sb, 0, 0, thumb.Width, thumb.Height)

        'Re-draw the image to the specified height and width
        gr_dest.DrawImage(originalImg, 0, 0, thumb.Width, thumb.Height)

        try
            fileExt = System.IO.Path.GetExtension(fileFld.FileName).ToLower()
            originalImg.save(Server.MapPath(upload_dir & upload_original & fileExt), originalImg.rawformat)
            thumb.save(Server.MapPath(upload_dir & upload_thumb & fileExt), originalImg.rawformat)
            msg = "Uploaded " & fileFld.FileName & " to " & Server.MapPath(upload_dir & upload_original & fileExt)
            upload_ok = true
        catch
            msg = "Sorry, there was a problem saving the image."
        end try
        ' Housekeeping for the generated thumbnail
        if not thumb is nothing then
            thumb.Dispose()
            thumb = nothing
        end if
    catch
        msg = "Sorry, that was not an image we could process."
    end try
end if

' House Keeping !
if not originalImg is nothing then
    originalImg.Dispose()
    originalImg = nothing
end if

 end if
 %>

What i am looking for is a way to just have it go by the height of what i set it:

 const Ly = 60  ' max height for thumbnails

And have the code for the width just be whatever. So if i had an image... say 600 x 120 (w h) and i used photoshop to change just the height, it would keep it in ratio and have it 300 x 60 (w x h). Thats what i am looking to do with this code here. However, i can not think of a way to do this (or to just leave a wildcard for the width setting.

Any help would be great :o)

David

Upvotes: 0

Views: 2447

Answers (2)

Lilith River
Lilith River

Reputation: 16468

Actually, you need to compare the aspect ratios. Comparing height doesn't tell you which dimension is relatively the longest - sorry dingle_thunk.

if (Ly / Lx) > oldImage.Height / oldImage.Width then
   newWidth = Ly * (oldImage.Width / oldImage.Height)
   newHeight = Ly
else if
   newWidth = Lx
   newHeight = Lx * (oldImage.Height / oldImage.Width)
end if

Also, it's best to use a Using clause instead of calling .Dispose. Any number of exceptions out of your control can cause the code to stop executing, leaving the GDI handles and allocated memory undisposed.

.NET does not garbage collect them properly, which is why MS says System.Drawing is unsupported in ASP.NET.

Also, you should set the Interpolation mode on the graphics object to get the best quality:

graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode  = SmoothingMode.HighQuality;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;  

And last, bitmap.Save() does a terrible job of encoding images by default. It only works properly with 32-bit PNG images. You need to specify encoder parameters for Jpegs, and quantize the bitmap before saving it as a GIF image.

See 30 Image Resizing pitfalls for the full list...

Also, you may consider using a popular free library instead, if you'd like to support more image formats and reduce your code to a single line:

ImageBuilder.Current.Build(fileFld, Server.MapPath(upload_dir & upload_original & fileExt), new ResizeSettings("maxwidth=500&maxheight=50&bgcolor=white"));

Upvotes: 1

alirobe
alirobe

Reputation: 906

Couldn't you just replace that whole if/else/endif block with something along these lines?

if oldImage.Height > Ly then
    newWidth = Ly * (NewImage.Width / NewImage.Height)
    newHeight = Ly
end if

Upvotes: 1

Related Questions