Изменение размера изображения с помощью 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 );
Просто выберите один.