Изменение размера изображения с помощью GDI в .NET дает низкую насыщенность

Я борюсь с проблемой, когда мои измененные изображения теряют насыщенность цвета, когда я манипулирую ими с помощью GDI.

Я загружаю JPG как оригинал, изменяю его размер, и получившееся изображение имеет намного меньшую насыщенность (интенсивность цвета), чем исходное изображение. Что я могу сделать, чтобы улучшить это? это мой код:

using ( var original = System.Drawing.Image.FromStream( new MemoryStream( image.RawData ) ) )
{
    using ( var dst = new Bitmap( width, height, PixelFormat.Format32bppArgb ) )
    {
        using ( var g = Graphics.FromImage( dst ) )
        {
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            g.CompositingQuality = CompositingQuality.HighQuality;

            g.DrawImage( original, 0, 0, dst.Width, dst.Height );
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage( original, 0, 0, dst.Width, dst.Height );

            var jpgEncoder = GetEncoder( ImageFormat.Jpeg );
            var myEncoderParameters = new EncoderParameters( 1 );
            var quality = 95;
            var myEncoderParameter = new EncoderParameter( Encoder.Quality, quality );
            myEncoderParameters.Param[0] = myEncoderParameter;

            dst.Save( buffer, jpgEncoder, myEncoderParameters );
        }
    }
}

Я пробовал с разными пиксельными форматами, удаляя все фильтры и т.д., но всегда получаю тот же результат. Это какая-то известная проблема с GDI, или я что-то пропустил?

Addon: При открытии изображения в Paint.NET я получаю ту же проблему с низкой насыщенностью, даже без масштабирования, поэтому я предполагаю, что GDI + загружает изображения (jpg)?

Это изображение было сохранено из фотошопа с цветовым профилем sRGB, но у afaik JPG нет информации о встроенных цветовых профилях. И даже если это так, я считаю, что firefox не подчиняется им (это то, что я тестировал)

Больше тестирования показывает, что в IE8 он отличается от контраста Firefox. Кажется, что JPG поддерживает цветовые профили, но большинство приложений не подчиняется им. FF3.5 однако, похоже, делает это. И это было Adobe RGB, а не sRGB на изображении.

Ответ 1

Я сам нашел ответ. Это связано с тем, что по умолчанию в GDI + не применяются цветовые профили. Многие люди утверждают, что вы не можете автоматически применять цветовые профили с помощью GDI, но, видимо, единственное изменение, которое мне нужно было сделать, это следующее:

using ( var original = System.Drawing.Image.FromStream( new MemoryStream( image.RawData ) ) )

к

using ( var original = new Bitmap( new MemoryStream( image.RawData ), true ) )

По-видимому, Bitmap был производным классом Image, а конструктор для Bitmap может принимать как поток, так и булевский для "useIcm". Это сделало трюк для меня.

Ответ 2

У меня есть код масштабирования изображения, который я использую, и я не вижу эффекта, о котором вы упоминаете.

Основное отличие, которое я вижу, это то, что я использую Format24bppRgb, а не Format24bpp A Rgb

Имейте в виду, что JPG не имеет альфа-канала в любом случае (afaik)

Ответ 3

Подходя к этому под другим углом, я бы настоятельно рекомендовал http://nathanaeljones.com/products/asp-net-image-resizer/, если вы хотите избавиться от этой боли. Он даже заботится о кешировании диска!

Ответ 4

Был там, сделал это. Глубоко, как это звучит, это имеет значение:

var quality = 95;
var myEncoderParameter = new EncoderParameter( Encoder.Quality, (long)quality );

или

long quality = 95;
var myEncoderParameter = new EncoderParameter( Encoder.Quality, quality );

или

var quality = 95L;
var myEncoderParameter = new EncoderParameter( Encoder.Quality, quality );

Просто выберите один.