2013-11-19 3 views
6

Возьмите следующие два изображения:Идентичный код производит противоречивое качество изображения на разных серверах

Dev версия - IIS7 для Windows 7 Pro 64bit машина

Dev Copy

Живая версия - IIS7 Windows Server 2008 64-разрядная машина

Live Copy

Обратите внимание, что версия Live «pixelly» & выглядит низкое качество, версия 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 на реальном веб-сервере, но я понятия не имею, что - я старался быть настолько тщательным, насколько это было возможно при настройке графических и кодековых настроек, но все еще отличается?

Edit: Источник изображения идентичен в обоих примерах тоже (расположенных на центральной доли Unc) - копия исходного изображения here

+0

Можете ли вы уменьшить код, используемый для воспроизведения проблемы? Какие кодеки присутствуют и используются на dev и живут? Они работают с одним и тем же исходным изображением? – CodeCaster

+0

@CodeCaster Исходное изображение идентично в обоих сценариях - я также редактировал свой вопрос со ссылкой на исходное изображение. Я попытаюсь заново создать его с помощью небольшого фрагмента кода и обновить его в ближайшее время. – HeavenCore

+0

Если код идентичен, то он может перейти только к версии GDI +, которую вы используете, проверьте версии на каждой машине. – James

ответ

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 

Удачи вам!

+0

Извините, но я уже использовал 'PixelOffsetMode.HighQuality' (см. Код в моем вопросе) и установка' InterpolationMode' '' InterpolationMode.Bilinear', казалось, не имела значения: '( – HeavenCore

+0

А теперь я вижу. никогда не используя графику ReSizer ... Во всяком случае, я меняю свой образец на полный с изменением размера и выводом на клиент (извините за C#, но вы должны легко перевести это на VB.NET) –

+0

Отличное преобразование, вы уже пробовали это? Я думаю, что проблема, с которой вы столкнулись раньше, заключалась в том, что вы никогда не называли Graphics(). DrawImage() [таким образом никогда не использовал настройки в Graphics] ... Во всяком случае, фразы «Использование» также должны сэкономить вас будущие проблемы Bitmap никогда не выпускают дескрипторы файлов или память :) –

-1

Вы используете веб-сервер, прокси-кэша в производственной среде, как Apache, Nginex, Varnish ... между сервером и клиентом?

Очень распространено, что прокси-сервер с такими модулями, как скорость страницы Google или аналогичный, делает сжатие над изображениями для повышения скорости загрузки. В этом случае, должно быть тривиально написать правило исключения.

+0

Нет, изображение, о котором идет речь, подается прямо из IIS7 в браузер пользователей - никакой прокси-сервер не задействован. Я также могу подтвердить, что изображение низкого качества происходит, если мы посетим страницу локально на самом веб-сервере. – HeavenCore

0

Вы должны сравнить все зависимости и проверить, что IIS используют одни и те же версии. Mor info здесь: 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

Смежные вопросы