Take the following two images:
Dev Version - IIS7 Windows 7 Pro 64bit Machine
Live Version - IIS7 Windows Server 2008 64bit Machine
Note how the Live Version is "pixelly" & looks low quality, the Dev Version however is smooth, anti-aliased & looks fine. These are both generated by identical code:
' Settings
Dim MaxHeight As Integer = 140
Dim MaxWidth As Integer = 140
Dim WorkingFolderPath As String = "\\server\share\bla\"
Dim AllowedFileExtensions As New ArrayList
AllowedFileExtensions.Add(".jpg")
AllowedFileExtensions.Add(".jpeg")
' Select an image to use from the WorkingFolder
Dim ImageFileName As String = ""
Dim WorkingFolder As New IO.DirectoryInfo(WorkingFolderPath)
Dim SourceImages As IO.FileInfo() = WorkingFolder.GetFiles()
For Each SourceImage As IO.FileInfo In SourceImages
If AllowedFileExtensions.Contains(SourceImage.Extension.ToLower) = True Then
ImageFileName = SourceImage.Name
End If
Next
' Determine path to selected image (if no image was found use a placeholder)
Dim PhysicalPath As String = ""
If ImageFileName = "" Then
' No Image was found, use the filler image
PhysicalPath = Server.MapPath("ProductOfTheMonthMissing.jpg")
Else
' An Image was found, Redirect to it / build path for Thumnailing
If Request.QueryString("FullSize") = "true" Then
Response.Redirect("../share/bla/" & ImageFileName)
Else
PhysicalPath = WorkingFolderPath & ImageFileName
End If
End If
' Load image and output in binary (resizing if necessary)
Using ProductImage As System.Drawing.Image = System.Drawing.Image.FromFile(PhysicalPath)
Dim newWidth As Integer = ProductImage.Width
Dim newHeight As Integer = ProductImage.Height
' Check if selected size is too big, if so, determine new size
If ProductImage.Width > MaxWidth Or ProductImage.Height > MaxHeight Then
Dim ratioX As Double = CDbl(MaxWidth) / ProductImage.Width
Dim ratioY As Double = CDbl(MaxHeight) / ProductImage.Height
Dim ratio As Double = Math.Min(ratioX, ratioY)
newWidth = CInt(ProductImage.Width * ratio)
newHeight = CInt(ProductImage.Height * ratio)
End If
' Create a new bitmap from the image with new size
Dim Codecs As ImageCodecInfo() = ImageCodecInfo.GetImageEncoders()
Dim CodecInfo As ImageCodecInfo = Nothing
Dim ProductOfTheMonth As New Bitmap(ProductImage, newWidth, newHeight)
Dim ReSizer As Graphics = Graphics.FromImage(ProductOfTheMonth)
ReSizer.InterpolationMode = InterpolationMode.HighQualityBicubic
ReSizer.SmoothingMode = SmoothingMode.HighQuality
ReSizer.PixelOffsetMode = PixelOffsetMode.HighQuality
ReSizer.CompositingQuality = CompositingQuality.HighQuality
' Ensure the encoder uses the best quality settings
Dim EncoderParams As New EncoderParameters(3)
EncoderParams.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L)
EncoderParams.Param(1) = New EncoderParameter(System.Drawing.Imaging.Encoder.ScanMethod, CInt(EncoderValue.ScanMethodInterlaced))
EncoderParams.Param(2) = New EncoderParameter(System.Drawing.Imaging.Encoder.RenderMethod, CInt(EncoderValue.RenderProgressive))
' Set jpeg as the output codec
For Each Codec As ImageCodecInfo In Codecs
If Codec.MimeType = "image/jpeg" Then
CodecInfo = Codec
End If
Next
' Ready a memory stream and byte array
Dim MemStream As New MemoryStream()
Dim bmpBytes As Byte()
' Save the image the the memory stream & prep ContentType for HTTP reasponse
Response.ContentType = "image/jpeg"
ProductOfTheMonth.Save(MemStream, CodecInfo, EncoderParams)
' Flush memory stream into byte array & flush to browser
bmpBytes = MemStream.GetBuffer()
Response.BinaryWrite(bmpBytes)
' Cleanup
ProductOfTheMonth.Dispose()
MemStream.Close()
ProductImage.Dispose()
End Using
What is the reason behind this & how do I address the issue? Presumably its a GD issue on the live web server - but I have no idea what - I tried to be as thorough as possible in setting graphic and codec settings but its still different?
Edit: Source Image is identical in both examples too (Located on a central unc share) - copy of source image here
Re-saving an already compressed image leads to the so-called “photocopier effect” meaning that an image loses its quality due to being resaved many times in a row, which is also called generation loss.
Acquisition geometry-Image acquisition geometric factors affecting image quality include a source to image receptor distance, orientation, the amount of magnification, and size of the focal spot.
I've had and, answered a similar question here: Graphics wrong image interpolation in .Net, but in short it seems like different platforms use different internal algorithms (or perhaps it's an internal rounding problem in GDI).
Anyway, the problem is in the settings. So try the following:
Using s As Bitmap = DirectCast(Bitmap.FromFile(PhysicalPath), Bitmap)
Dim scale As Double = Math.Min(140.0 / s.Width, 140.0 / s.Height)
Using d As New Bitmap(CInt(Math.Floor(scale * s.Width)), CInt(Math.Floor(scale * s.Height)), System.Drawing.Imaging.PixelFormat.Format24bppRgb)
Using dg As Graphics = Graphics.FromImage(d)
dg.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
dg.SmoothingMode = SmoothingMode.HighQuality
dg.PixelOffsetMode = PixelOffsetMode.HighQuality
dg.CompositingQuality = CompositingQuality.HighQuality
dg.Clear(Color.White)
dg.DrawImage(s, New Rectangle(0, 0, d.Width, d.Height), New Rectangle(0, 0, s.Width, s.Height), GraphicsUnit.Pixel)
End Using
Dim jpegArgs As New EncoderParameters(3)
jpegArgs.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L)
jpegArgs.Param(1) = New EncoderParameter(System.Drawing.Imaging.Encoder.ScanMethod, CInt(EncoderValue.ScanMethodInterlaced))
jpegArgs.Param(2) = New EncoderParameter(System.Drawing.Imaging.Encoder.RenderMethod, CInt(EncoderValue.RenderProgressive))
Dim Codecs As ImageCodecInfo() = ImageCodecInfo.GetImageEncoders()
Dim jpegParams As ImageCodecInfo = Nothing
'#### Set jpeg as the output codec
For Each Codec As ImageCodecInfo In Codecs
If Codec.MimeType = "image/jpeg" Then
jpegParams = Codec
End If
Next
Response.Clear()
Response.ContentType = "image/jpeg"
d.Save(Response.OutputStream, jpegParams, jpegArgs)
End Using
End Using
Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With