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

.net 相同的代码在不同的服务器上产生不一致的图像质量,.net,vb.net,image,.net-2.0,gd,.net,Vb.net,Image,.net 2.0,Gd,拍摄以下两张图片: 开发版本-IIS7 Windows 7 Pro 64位计算机 实时版本-IIS7 Windows Server 2008 64位计算机 请注意,实时版本是如何“像素化”的&看起来质量很低,而开发版本则是平滑的、抗锯齿的&看起来很好。它们都是由相同的代码生成的: ' Settings Dim MaxHeight As Integer = 140 Dim MaxWidth As Integer = 140 Dim WorkingFolderPath As String = "

拍摄以下两张图片:

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

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

请注意,实时版本是如何“像素化”的&看起来质量很低,而开发版本则是平滑的、抗锯齿的&看起来很好。它们都是由相同的代码生成的:

' 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
这背后的原因是什么&我如何解决这个问题?大概这是live web服务器上的GD问题-但我不知道是什么-我试图尽可能彻底地设置图形和编解码器设置,但它仍然不同


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

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


代理服务器通常具有谷歌页面速度或类似模块,对图像进行压缩以提高下载速度。在这种情况下,编写异常规则应该很简单。

您应该比较所有依赖项,并检查IIS是否使用相同的版本。Mor信息在此:

如果使用相同的配置,则可能与图形卡有关,通常服务器没有用于图像处理的特定图形卡。在这种情况下,您应该在开发机器中配置GDI+,使其不使用加速或特定于卡的指令。

可能正在使用其他引擎,并更改代码帮助作为解决方法:

我在这里回答了一个类似的问题:,但简而言之,似乎不同的平台使用不同的内部算法(或者可能是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

祝你好运

你能减少用于重现问题的代码吗?dev和live上使用了哪些编解码器?它们在同一个源图像上运行吗?@CodeCaster源图像在这两种情况下都是相同的-我还用源图像的链接编辑了我的问题。我将尝试使用较小的代码片段重新创建此代码,并在短期内进行更新。如果代码相同,则只能归结为您正在使用的GDI+版本,请检查每台计算机上的版本。编解码器如何?它们在两台机器上都是一样的吗?@James-我想是这样的,但接着看看这个问题:-他们能够通过在不同的对象上设置选项来防止同样的问题,而不管GDI+版本如何?不,有问题的图像直接从IIS7发送到用户浏览器-不涉及代理。我还可以确认,如果我们在web服务器上本地访问页面,会出现低质量图像。对不起,我已经在使用
PixelOffsetMode.HighQuality
(请参阅我问题中的代码)&将
InterpolationMode
设置为
InterpolationMode.Bilinear
似乎没有什么区别:'(啊,现在我明白了。你实际上从未使用过ReSizer图形…无论如何,我正在将我的示例更改为一个完整的示例,并调整大小并输出到客户端(很抱歉使用C#,但你应该能够轻松地将其转换为VB.NET)很好的转换,你试过了吗?我想你以前遇到的问题是你从未调用过Graphics().DrawImage()[因此从未使用图形中的设置]…无论如何,“Using”子句也应该可以让你避免将来位图永远不会释放文件句柄或内存的问题:)还没有试过,使用
.Where()
不会在.net 2中编译-现在就调整它。啊,您可以在“ImageCodeInfo.GetImageEncoders()”中迭代集合以找到正确的项:ImageCodeInfo.GetImageEncoders()中的foreach enc如果enc.FormatID=ImageFormat.Jpeg.Guid,则jpegParams=enc