Identical code creating inconsistent image quality on different servers

Take the following two images:

Dev Version - IIS7 Windows 7 Pro 64-bit Machine

Dev copy

Current Version - Windows Server 2008 IIS7 64-bit Machine

Live copy

Please note that the Live Version is โ€œpixellyโ€ and looks poor quality, however the Dev version is smooth, smooth and looks great. They are generated by the 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 for this and how can I solve this problem? Presumably, this is a GD problem on a real web server, but I have no idea what - I tried to be as thorough as possible in setting up the graphics and codec settings, but still different?

Edit: The original image is identical in both examples (located on the central part of the share) - a copy of the original image here

+6
source share
3 answers

I had and answered a similar question: Graphic incorrect interpolation of images in .Net , but in short it seems that different platforms use different internal algorithms (or, perhaps, this is an internal rounding problem in GDI).

In any case, 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

+1
source

You should compare all the dependencies and verify that IIS uses the same versions. Mor info here: How do I compare if the configuration is different for IIS?

If the same configuration is used, then this may be due to the graphics card, usually the servers do not have specific graphics cards for image processing. In this case, you must configure GDI + in your development machine so that you do not use acceleration instructions or maps. Using a graphics card instead of GDI + for image manipulation

Another engine can be used and change the code help as a workaround: Replace GDI + DrawImage with PInvoked GDI and transparent PNG

0
source

Do you use a proxy cache web server in your production environment such as Apache, Nginex, Varnish ... between server and client?

It is very common that a proxy server with modules such as Google page speed or similar does compression over images to increase download speed. In this case, it should be trivial to write an exception rule.

-1
source

Source: https://habr.com/ru/post/958379/


All Articles