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:
- Zoom image 1800 x 1800 px max
- Display image 180 x 275px max
- Search Image 120 x 100px max
- Tiny thumbnail 50 x 50px max
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:
- FileName = initially uploaded fine
- NewFileName = file name to save resized image as
- maxWidth / maxHeight – self explanatory
- uploadDir = the directory to save to
-
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
What you are doing wrong is that you are creating a downsized image using the
Bitmapconstructor, then you draw that image onto itself. TheBitmapconstructor can naturally not use the quality settings that you set in theGraphicsobject later on to resize the image, so the quality will be poor.Instead you should create a blank
Bitmapobject with the constructor that takes only the size:Then you should draw the original image on the canvas: