问题
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
回答1:
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!
回答2:
You should compare all dependencies and check IIS are using same versions. Mor info here: How to compare if the configuration is different for IIS?
If the same configuration are used, then it could be somthing related to graphic card, usually servers don't have specific graphic cards for image proccessing. In that case, you should configure GDI+ in your develop machine to not use acceleration or card specific instructions. Using Graphics Card instead of GDI+ for Image Manipulation
May be using another engine, and change the code help as a workaround: Replace GDI+ DrawImage with PInvoked GDI and transparent PNG's
回答3:
Are you using a proxy-cache web server in your production enviroment like Apache, Nginex, Varnish... between server and client?
It's very common that proxy server having modules like google page speed or similar, making compression over images to improve download speed. I that case, it should be trivial to write an exception rule.
来源:https://stackoverflow.com/questions/20069100/identical-code-producing-inconsistent-image-quality-on-different-servers