Изменение размера изображения с помощью 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, или я что-то пропустил?

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

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

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


person jishi    schedule 16.10.2009    source источник
comment
image.RawData откуда это взялось?   -  person Andre    schedule 30.09.2014
comment
@Andre: Это всего лишь начальный массив байтов, содержащий изображение. В моем случае он был загружен из базы данных, но его можно было загрузить откуда угодно. Image.FromStream принимает поток, поэтому это может быть FileStream, сетевой поток или что-то еще. У меня был байтовый массив, поэтому я обернул его в MemoryStream.   -  person jishi    schedule 01.10.2014


Ответы (4)


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

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

to

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

Очевидно, Bitmap был производным классом Image, а конструктор Bitmap может принимать как поток, так и логическое значение для useIcm. Это помогло мне.

person jishi    schedule 16.10.2009
comment
Большое спасибо за объяснение! Я глубоко изучаю субдискретизацию цветности и другие возможные проблемы, вызывающие потерю цвета. После установки флага uselcm в значение true мои фотографии в формате jpeg становятся идеальными по цвету. - person jesperlind; 25.10.2009
comment
У меня такая же проблема, но вышесказанное не имело значения .. :( - person Sprintstar; 25.02.2011
comment
Может быть, в ваши изображения не встроена информация о цветокоррекции? Вы пробовали с разными изображениями? - person jishi; 25.02.2011

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

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

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

person Ken Egozi    schedule 16.10.2009

Подходя к этому с другой точки зрения, я настоятельно рекомендую ImageResizer, если вы хотите избавиться от боли, делая это самостоятельно. Он даже заботится о кэшировании диска.

person TimS    schedule 16.10.2009

Был там, сделал это. Как бы глупо это ни звучало, в этом есть разница:

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

or

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

or

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

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

person Dan Byström    schedule 16.10.2009
comment
У меня нет проблем с качеством сжатия, только с насыщенностью цвета. Пробовал ваше предложение, но, к сожалению, это не имело никакого значения ... - person jishi; 16.10.2009