相同的代码在不同的服务器上产生不一致的图像质量

时间:2013-11-19 10:33:06

标签: .net vb.net image .net-2.0 gd

拍摄以下两张照片:

开发版 - IIS7 Windows 7 Pro 64位计算机

Dev Copy

实时版本 - IIS7 Windows Server 2008 64位计算机

Live Copy

请注意实时版本是如何“像素化”&看起来质量低,Dev版本却是流畅的,抗锯齿的&看起来很好。这些都是由相同的代码生成的:

' 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

这个&的背后原因是什么?我该如何解决这个问题?大概是它在实时网络服务器上的GD问题 - 但我不知道是什么 - 我试图在设置图形和编解码器设置时尽可能彻底但仍然不同?

编辑:源图像在两个示例中也相同(位于中央unc共享位置) - 源图像的副本here

3 个答案:

答案 0 :(得分:1)

我已经并且在这里回答了类似的问题:Graphics wrong image interpolation in .Net,但简而言之,似乎不同的平台使用不同的内部算法(或者它可能是GDI中的内部舍入问题)

无论如何,问题出在设置中。请尝试以下方法:

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
祝你好运!

答案 1 :(得分:0)

您应该比较所有依赖项并检查IIS是否使用相同的版本。我在这里的信息:How to compare if the configuration is different for IIS?

如果使用相同的配置,那么它可能与图形卡有关,通常服务器没有用于图像处理的特定图形卡。在这种情况下,您应该在开发机器中配置GDI +以不使用加速或卡特定指令。 Using Graphics Card instead of GDI+ for Image Manipulation

可能正在使用其他引擎,并将代码帮助更改为变通方法: Replace GDI+ DrawImage with PInvoked GDI and transparent PNG's

答案 2 :(得分:-1)

您是否在生产环境中使用代理缓存Web服务器,如Apache,Nginex,Varnish ......服务器和客户端之间?

代理服务器具有谷歌页面速度或类似速度等模块,对图像进行压缩以提高下载速度是非常常见的。在这种情况下,编写例外规则应该是微不足道的。