Изменение размера изображения снижение качества

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

    public Image ResizeImage(Image imgToResize, Size size)
    {
        int sourceWidth = imgToResize.Width;
        int sourceHeight = imgToResize.Height;

        float nPercentW = (size.Width/(float) sourceWidth);
        float nPercentH = (size.Height/(float) sourceHeight);

        float nPercent = nPercentH < nPercentW ? nPercentH : nPercentW;

        var destWidth = (int) (sourceWidth*nPercent);
        var destHeight = (int) (sourceHeight*nPercent);

        var src = imgToResize;

        using (var dst = new Bitmap(destWidth, destHeight, imgToResize.PixelFormat))
        {
            dst.SetResolution(imgToResize.HorizontalResolution, imgToResize.VerticalResolution);

            using (var g = Graphics.FromImage(dst))
            {
                var mime = GetMimeType(imgToResize);
                ImageFormat format;
                if (mime == "image/gif" || mime == "image/png")
                {
                    //convert all gif to png, better resize quality
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    g.DrawImage(src, 0, 0, dst.Width, dst.Height);
                    format = ImageFormat.Png;
                }
                else
                {
                    //jpeg
                    g.CompositingQuality = CompositingQuality.HighQuality;
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    format = ImageFormat.Jpeg;
                }
                g.DrawImage(src, 0, 0, dst.Width, dst.Height);

                // At this point the new bitmap has no MimeType
                // Need to output to memory stream
                var m = new MemoryStream();
                dst.Save(m, format);

                var img = Image.FromStream(m);

                return img;
            }
        }
    }

Как вы видите, я использую предложенные настройки для интерполяции, сглаживания и т. Д. Я также сохраняю JPEG с качеством 100.

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

Bitmap NewImg = new Bitmap(original, new Size(387,257));
editor.SaveImage(@"C:\simpleResize.jpg", NewImg, ImageFormat.Jpeg);

Удивительно, но это дает гораздо более приятное изображение, хотя оно немного больше - на 30% больше занимаемой памяти.

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

Ваша помощь очень ценится. Это мой первый опыт в обработке изображений.

РЕДАКТИРОВАТЬ

Простое изменение размера (82 КБ)

http://img189.imageshack.us/img189/2137/simpleresize.jpg

Мой размер (55 КБ)

http://img12.imageshack.us/img12/4023/complexresize.jpg

2 ответа

Решение

Моей первой мыслью было, что jpeg-кодер.NET использует подвыборку цветности даже при максимальном качестве, поэтому информация о цвете сохраняется с половинным разрешением. Насколько я могу судить, настройка жестко запрограммирована. Но это не объясняет, почему вы получите лучшее качество во втором примере. Если, возможно, во 2-м году он не использовал сглаживание, давая более четкое (но более низкое качество) изображение, и артефакты остались незамеченными.

Изменить: Dst.Save (м, формат); похоже на твою проблему. Вы кодируете это как jpeg там с качеством по умолчанию (не 100%), а затем сразу же декодируете его обратно в изображение. dst уже является Image (класс Bitmap наследуется от Image), поэтому вы можете просто вернуть его как есть

Я нашел этот пример фрагмента кода (извините, я забыл источник), который может помочь вам:

// Create parameters
EncoderParameters params = new EncoderParameters (1);

// Set quality (100)
params.Param[0] = new EncoderParameter(Encoder.Quality, 100);

// Create encoder info
ImageCodecInfo codec = null;
foreach (ImageCodecInfo codectemp in ImageCodecInfo.GetImageDecoders())
{
    if (codectemp.MimeType == "image/jpeg")
    {
        codec = codectemp;
        break;
    }
}

// Check
if (codec == null)
    throw new Exception("Codec not found for image/jpeg");

// Save
image.Save(filename, codec, params);
Другие вопросы по тегам