Змінення розміру зображення без втрати якості [закрито]


108

Як я можу змінити розмір зображення, не змінюючи якість зображення?


Чи можете ви надати більше деталей? Наскільки великі ваші зображення, і якого розміру вам потрібно, щоб вони були?
Марк Рансом


6
imageresizing.net - Ця бібліотека створює зображення найвищої якості, які ви можете отримати .NET
Річка Ліліт

Відповіді:


217

Як каже 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
Я можу додати, що (якщо можливо) користувач повинен починати з зображення Bitmap, яке, скажімо, вдвічі більше, ніж потрібно, а потім масштабувати вниз. Отримане зображення повинно бути досить рівним.
Кредзель

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 (я, як правило, використовую фарбу як безкоштовний транскодер для зображень у 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

Ви змінюєте розмір більше, чи менше? На невеликий% або на більший коефіцієнт, наприклад, 2x, 3x? Що ви розумієте під якістю своєї заявки? А який тип зображень - фотографії, жорсткі обриси ліній, чи які? Написати власний піксельний шліфувальний код низького рівня або намагатися зробити це максимально за допомогою існуючих бібліотек (.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 : //today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstan.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>();
        }

    }

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.