Reputation: 7341
Some while ago I was trying to create an image uploading facility for the back-end of my website. I managed to achieve this, but I have still got poor image quality on the smaller images.
I need to create 4 images:
I generally manually resize and image to 1800 x 1800 with Photoshop or something before uploading it, then upload and resize using the code below (images are all jpgs)
Variables are:
resolution = the quality jpg resolution 0-100, I'm using 80 for these examples
Public Shared Sub ResizeImages(FileName, NewFileName, maxWidth, maxHeight, uploadDir, resolution)
Try
Dim originalImg As System.Drawing.Image = System.Drawing.Image.FromFile(uploadDir & FileName)
Dim aspectRatio As Double
Dim newHeight As Integer
Dim newWidth As Integer
' Calculate Size '
If originalImg.Width > maxWidth Or originalImg.Height > maxHeight Then
If originalImg.Width >= originalImg.Height Then ' image is wider than tall
newWidth = maxWidth
aspectRatio = originalImg.Width / maxWidth
newHeight = originalImg.Height / aspectRatio
Else ' image is taller than wide
newHeight = maxHeight
aspectRatio = originalImg.Height / maxHeight
newWidth = originalImg.Width / aspectRatio
End If
Else ' if image is not larger than max then keep original size
newWidth = originalImg.Width
newHeight = originalImg.Height
End If
Dim newImg As New Bitmap(originalImg, CInt(newWidth), CInt(newHeight)) '' blank canvas
Dim canvas As Graphics = Graphics.FromImage(newImg) 'graphics element
'*** compress ***'
Dim myEncoderParameters As EncoderParameters
myEncoderParameters = New EncoderParameters(1)
' set quality level based on "resolution" variable
Dim myEncoderParameter = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, CType(resolution, Int32))
myEncoderParameters.Param(0) = myEncoderParameter
canvas.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality
canvas.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
canvas.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality
canvas.DrawImage(newImg, New Rectangle(0, 0, newWidth, newHeight))
newImg.Save(uploadDir & (NewFileName), getCodec("image/jpeg"), myEncoderParameters)
'*** Close ***'
canvas.Dispose()
originalImg.Dispose()
newImg.Dispose()
'*** Nothing ***'
canvas = Nothing
newImg = Nothing
originalImg = Nothing
Catch ex As Exception
HttpContext.Current.Response.Write(ex.ToString & " " & uploadDir & " " & FileName & " _ " & NewFileName)
End Try
End Sub
To achieve all four images, I pass the sizes required as a list, and then loop that list, in descending order of intended file size, so, the largest one first, I then pass the most recently uploaded image into the function as the FileName
parameter so that each time, the function is receiving a smaller image, so not trying to resize a 2000x2000px image to 50x50px as I realise from reading various posts, that this much reduction will result in poor quality.
Having run the loops through in this method, my tiny thumbnails are quite good quality, but my middle images are still poor.
Here they are in descending size order:
http://www.hartnollguitars.co.uk/Products2/0/0/0/9/6/57/1347831580.jpg http://www.hartnollguitars.co.uk/Products2/0/0/0/9/6/57/1347831580-dis.jpg http://www.hartnollguitars.co.uk/Products2/0/0/0/9/6/57/1347831580-se.jpg http://www.hartnollguitars.co.uk/Products2/0/0/0/9/6/57/1347831580-tb.jpg
as you can see, both the "search" and "display" images are still blocky around the edge of the guitar.
What am I doing wrong?!
If my reduction is to much, how would I go about running an in-memory gradual reduction.
What I mean by this, is, it strikes me, that the function above is saving the file to disc each time, that must take up some time, so if I were to loop a reduction function, reducing the image in size, in small increments (say 10% at a time) in memory, and then save the final image to disc when the reduction reaches the correct size. I'm not sure how to do this though.
I'm using ASP.NET 2.0 and am relatively new to it, so I am not fully aware of all the methods available to me.
Any code examples would help greatly!
Thanks
Upvotes: 0
Views: 635
Reputation: 700302
What you are doing wrong is that you are creating a downsized image using the Bitmap
constructor, then you draw that image onto itself. The Bitmap
constructor can naturally not use the quality settings that you set in the Graphics
object later on to resize the image, so the quality will be poor.
Instead you should create a blank Bitmap
object with the constructor that takes only the size:
Dim newImg As New Bitmap(newWidth, newHeight)
Then you should draw the original image on the canvas:
canvas.DrawImage(originalImg, New Rectangle(0, 0, newWidth, newHeight))
Upvotes: 1