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

2

Я написал простой вспомогательный класс 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;
            }
        }
    }

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

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

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

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

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

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

ИЗМЕНИТЬ

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

простой http://img189.imageshack.us/img189/2137/simpleresize.jpg

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

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

  • 1
    Dst.Save (м, формат); похоже на твою проблему. Вы кодируете это как jpeg там с качеством по умолчанию (не 100%), а затем сразу же декодируете его обратно в изображение. dst уже является Image (класс Bitmap наследуется от Image), поэтому вы можете просто вернуть его как есть.
  • 0
    Привет, Дэвид. Ты был прав. Мое рассуждение об этом шаге было таким, что mimetype был частью результирующего изображения. Я временно сохранил изображение в сеансе и хотел получить его позже. Если вы обновите свой ответ, пометьте его как ответивший.
Теги:
graphics
gdi
image-manipulation

2 ответа

2
Лучший ответ

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

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

  • 0
    Спасибо за быстрый ответ. Я попытался изменить настройки AA, чтобы увидеть, помогает ли это, но это не является причиной артефактов. Я переключаюсь назад и четвертый между простым изменением размера и комплексом, и артефакты присутствуют только в комплексе.
  • 0
    Кто-нибудь знает, каково качество по умолчанию?
4

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

// 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);
  • 0
    Приятно. Это сохраняет качество изображения и уменьшает размер изображения.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню