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


109

Как я могу изменить размер изображения, не влияя на качество изображения?


Вы можете дать нам более подробную информацию? Насколько велики ваши изображения и какого размера они вам нужны?
Марк Рэнсом


6
imageresizing.net - Эта библиотека создает изображения высочайшего качества, которые вы можете получить с .NET
Лилит Ривер

Ответы:


218

Как говорит rcar , вы не можете не потерять качество, лучшее, что вы можете сделать в C #, это:

Bitmap newImage = new Bitmap(newWidth, newHeight);
using (Graphics gr = Graphics.FromImage(newImage))
{
    gr.SmoothingMode = SmoothingMode.HighQuality;
    gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
    gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
    gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
}

2
Я мог бы добавить, что (если возможно) пользователь должен начать с растрового изображения, которое, скажем, в два раза больше, чем необходимо, а затем уменьшить его масштаб. Полученное изображение должно быть довольно гладким.
Pretzel

2
gr.SmoothingMode = SmoothingMode.HighQuality - лучший код. В настоящее время HighQuality и AntiAlias ​​- это одно и то же, но, возможно, в будущем Microsoft изобретет что-то новое. Высокое качество всегда должно быть псевдонимом к лучшему.
Eyal

4
Метод System.Drawing.Image.Save (строковое имя файла, формат ImageFormat) сохраняет файлы JPG с качеством 75. Изображение было размытым и неприемлемо для клиента. Проблема качества была устранена путем использования Save (имя файла строки, кодировщик ImageCodecInfo, EncoderParameters encoderParams) и указание значения качества ближе к 100.
Рига,

3
Это иногда оставляет артефакты на границе изображения ...
jjxtra

1
У меня были артефакты на грани использования этого. Есть предложения?
Гопичандар

32

Если вы не занимаетесь векторной графикой, невозможно изменить размер изображения без потери качества изображения.


1
если вы не расширяете его ...
Блэр Конрад

Вы можете расширить его, не теряя никакой информации, но вы можете использовать разные типы фильтров, которые дают разные результаты - удержание нулевого порядка, фильтр нижних частот и т. Д.
Адам Розенфилд

24
private static Image resizeImage(Image imgToResize, Size size)
{
    int sourceWidth = imgToResize.Width;
    int sourceHeight = imgToResize.Height;

    float nPercent = 0;
    float nPercentW = 0;
    float nPercentH = 0;

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

    if (nPercentH < nPercentW)
        nPercent = nPercentH;
    else
        nPercent = nPercentW;

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

    Bitmap b = new Bitmap(destWidth, destHeight);
    Graphics g = Graphics.FromImage((Image)b);
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;

    g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
    g.Dispose();

    return (Image)b;
}

от сюда


Это работает, но возвращает идентичное качество ответу Криса Эриксо. Приятно видеть, что размер использован ...
Сэм Джонс


3

Если вы не измените размер, вы не сможете сделать это с растровой графикой.

Что вы можете сделать с хорошей фильтрацией и сглаживанием, так это изменить размер без какой-либо заметной потери качества.

Вы также можете изменить метаданные DPI изображения (при условии, что они есть), которые сохранят точно такое же количество пикселей, но изменит то, как редакторы изображений думают об этом в «реальных» измерениях.

И чтобы охватить все основы, если вы действительно имели в виду только размер файла изображения, а не фактические размеры изображения, я предлагаю вам взглянуть на кодирование данных изображения без потерь. Я предлагаю повторно сохранить изображение в виде файла .png (я обычно использую paint как бесплатный транскодер для изображений в Windows. Загрузите изображение в краске, сохраните как в новом формате)


3

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

Не уменьшайте размер на стороне клиента, потому что браузеры плохо меняют размер изображений.

Что вы можете сделать, так это программно изменить размер перед его визуализацией или по мере его загрузки пользователем.

Вот статья, в которой объясняется один из способов сделать это в C #: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx


«браузеры плохо справляются с изменением размеров изображений» - это могло быть правдой в '08, но, к счастью, сейчас мы далеко впереди в этой области (в значительной степени из-за того, что старые версии IE постепенно исчезают).
Камило Мартин

2

Посмотрите, нравится ли вам качество изменения размера изображения этого модуля ASP.NET с открытым исходным кодом. Есть живая демонстрация, так что вы можете повозиться с ней самостоятельно. Это дает результаты, которые (на мой взгляд) невозможно отличить от результатов Photoshop. Он также имеет аналогичные размеры файлов - MS хорошо поработала над своим кодировщиком JPEG.


Что ж, JPEG - относительно простой формат. Вы мало что можете сделать, чтобы превзойти эталонные реализации с точки зрения качества / размера файла, потому что в конечном итоге это просто коэффициенты DCT с общим сжатием.
Камило Мартин

1

Есть что-то там, контекстно-зависимое изменение размера, не знаю, сможете ли вы его использовать, но на это стоит посмотреть, это точно

Хорошая видеодемонстрация (ближе к середине появляется увеличение) http://www.youtube.com/watch?v=vIFCV2spKtg

Здесь может быть какой-то код. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/

Это было излишним? Возможно, есть несколько простых фильтров, которые вы можете применить к увеличенному изображению, чтобы немного размыть пиксели, вы могли бы изучить это.


Я подозреваю, что это не имеет ничего общего с исходным вопросом, но мне нравится эта техника.
Мэтт Крукшанк,

1

Вы изменяете размер больше или меньше? На небольшой процент или больший коэффициент, например, в 2 раза, 3 раза? Что вы подразумеваете под качеством вашего приложения? А что за изображения - фотографии, резкие штриховые рисунки или что? Писать свой собственный низкоуровневый код шлифовки пикселей или пытаться сделать это как можно больше с помощью существующих библиотек (.net или что-то еще)?

По этой теме накоплен большой объем знаний. Ключевое понятие - интерполяция.

Рекомендации по просмотру:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* для C #: https: //secure.codeproject.com/KB/GDI-plus/imageprocessing4.aspx?display=PrintAll&fid=3657&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&select=629945 * это специфично для java, но может быть образовательным - http: //today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html


1

Здесь вы также можете найти коды водяных знаков этого класса:

public class ImageProcessor
    {
        public Bitmap Resize(Bitmap image, int newWidth, int newHeight, string message)
        {
            try
            {
                Bitmap newImage = new Bitmap(newWidth, Calculations(image.Width, image.Height, newWidth));

                using (Graphics gr = Graphics.FromImage(newImage))
                {
                    gr.SmoothingMode = SmoothingMode.AntiAlias;
                    gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    gr.DrawImage(image, new Rectangle(0, 0, newImage.Width, newImage.Height));

                    var myBrush = new SolidBrush(Color.FromArgb(70, 205, 205, 205));

                    double diagonal = Math.Sqrt(newImage.Width * newImage.Width + newImage.Height * newImage.Height);

                    Rectangle containerBox = new Rectangle();

                    containerBox.X = (int)(diagonal / 10);
                    float messageLength = (float)(diagonal / message.Length * 1);
                    containerBox.Y = -(int)(messageLength / 1.6);

                    Font stringFont = new Font("verdana", messageLength);

                    StringFormat sf = new StringFormat();

                    float slope = (float)(Math.Atan2(newImage.Height, newImage.Width) * 180 / Math.PI);

                    gr.RotateTransform(slope);
                    gr.DrawString(message, stringFont, myBrush, containerBox, sf);
                    return newImage;
                }
            }
            catch (Exception exc)
            {
                throw exc;
            }
        }

        public int Calculations(decimal w1, decimal h1, int newWidth)
        {
            decimal height = 0;
            decimal ratio = 0;


            if (newWidth < w1)
            {
                ratio = w1 / newWidth;
                height = h1 / ratio;

                return height.To<int>();
            }

            if (w1 < newWidth)
            {
                ratio = newWidth / w1;
                height = h1 * ratio;
                return height.To<int>();
            }

            return height.To<int>();
        }

    }

0

Вот ветка форума, которая предоставляет пример кода C # для изменения размера изображения. Вы можете использовать одно из связывателей библиотеки GD для повторной выборки в C #.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.