c # Зміна розміру зображення до різного розміру при збереженні співвідношення сторін


81

Я намагаюся змінити розмір зображення, зберігаючи співвідношення сторін до вихідного, щоб нове зображення не виглядало зім'ятим.

наприклад:

Перетворіть зображення 150 * 100 на зображення 150 * 150.
Зайві 50 пікселів висоти потрібно заповнити білим кольором тла.

Це поточний код, який я використовую.

Це добре працює для зміни розміру, але зміна співвідношення сторін оригінального зображення стискає нове зображення.

private void resizeImage(string path, string originalFilename, 
                         int width, int height)
    {
        Image image = Image.FromFile(path + originalFilename);

        System.Drawing.Image thumbnail = new Bitmap(width, height);
        System.Drawing.Graphics graphic = 
                     System.Drawing.Graphics.FromImage(thumbnail);

        graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphic.SmoothingMode = SmoothingMode.HighQuality;
        graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
        graphic.CompositingQuality = CompositingQuality.HighQuality;

        graphic.DrawImage(image, 0, 0, width, height);

        System.Drawing.Imaging.ImageCodecInfo[] info =
                         ImageCodecInfo.GetImageEncoders();
        EncoderParameters encoderParameters;
        encoderParameters = new EncoderParameters(1);
        encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,
                         100L);            
        thumbnail.Save(path + width + "." + originalFilename, info[1], 
                         encoderParameters);
    }

EDIT: Я хотів би, щоб зображення було оббито замість обрізаного

Відповіді:


115

Це має зробити це.

private void resizeImage(string path, string originalFilename, 
                     /* note changed names */
                     int canvasWidth, int canvasHeight, 
                     /* new */
                     int originalWidth, int originalHeight)
{
    Image image = Image.FromFile(path + originalFilename);

    System.Drawing.Image thumbnail = 
        new Bitmap(canvasWidth, canvasHeight); // changed parm names
    System.Drawing.Graphics graphic = 
                 System.Drawing.Graphics.FromImage(thumbnail);

    graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
    graphic.SmoothingMode = SmoothingMode.HighQuality;
    graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
    graphic.CompositingQuality = CompositingQuality.HighQuality;

    /* ------------------ new code --------------- */

    // Figure out the ratio
    double ratioX = (double) canvasWidth / (double) originalWidth;
    double ratioY = (double) canvasHeight / (double) originalHeight;
    // use whichever multiplier is smaller
    double ratio = ratioX < ratioY ? ratioX : ratioY;

    // now we can get the new height and width
    int newHeight = Convert.ToInt32(originalHeight * ratio);
    int newWidth = Convert.ToInt32(originalWidth * ratio);

    // Now calculate the X,Y position of the upper-left corner 
    // (one of these will always be zero)
    int posX = Convert.ToInt32((canvasWidth - (originalWidth * ratio)) / 2);
    int posY = Convert.ToInt32((canvasHeight - (originalHeight * ratio)) / 2);

    graphic.Clear(Color.White); // white padding
    graphic.DrawImage(image, posX, posY, newWidth, newHeight);

    /* ------------- end new code ---------------- */

    System.Drawing.Imaging.ImageCodecInfo[] info =
                     ImageCodecInfo.GetImageEncoders();
    EncoderParameters encoderParameters;
    encoderParameters = new EncoderParameters(1);
    encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,
                     100L);            
    thumbnail.Save(path + newWidth + "." + originalFilename, info[1], 
                     encoderParameters);
}

Відредаговано, щоб додати:

Тим, хто хоче вдосконалити цей код, слід додати його до коментарів або до нової відповіді. Не редагуйте цей код безпосередньо.


2
Просто цікавлячись параметрами originalWidth і originalHeight, навіщо вони вам потрібні, коли ви можете просто отримати цю інформацію із зображення? (Я раніше редагував ваш код, перш ніж мав дозвіл коментувати, вибачаюся за це)
Мендель

@mendel - так, це теж спрацювало б. Але в оригінальному питанні він уже знав висоту та ширину, то навіщо їх перераховувати знову?
egrunin

1
я спробував це на зображенні 1024 * 768, щоб перетворити його на 500 * 500 - зображення спотворюється. Я шукаю такий алгоритм, як у wordpress CMS, де зображення не спотворюються, коли їх зменшують (проте деякі обрізки з боків є).
йогістінг

@yogihosting опублікує питання з вашою проблемою, включаючи ваш код, можливо навіть посилання на тестове зображення. Це працює для інших людей, тому нам потрібно буде подивитися, що для вас відрізняється.
egrunin

1
@egrunin Я пропоную використовувати Path.Combine(path, originalFileName)при завантаженні оригінального зображення. Те саме при збереженні ескізу в кінці.
Пол Карам,

83

Я дізнався, як змінити розмір та заповнити зображення, вивчивши цю статтю CodeProject .

static Image FixedSize(Image imgPhoto, int Width, int Height)
    {
        int sourceWidth = imgPhoto.Width;
        int sourceHeight = imgPhoto.Height;
        int sourceX = 0;
        int sourceY = 0;
        int destX = 0;
        int destY = 0;

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

        nPercentW = ((float)Width / (float)sourceWidth);
        nPercentH = ((float)Height / (float)sourceHeight);
        if (nPercentH < nPercentW)
        {
            nPercent = nPercentH;
            destX = System.Convert.ToInt16((Width -
                          (sourceWidth * nPercent)) / 2);
        }
        else
        {
            nPercent = nPercentW;
            destY = System.Convert.ToInt16((Height -
                          (sourceHeight * nPercent)) / 2);
        }

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

        Bitmap bmPhoto = new Bitmap(Width, Height,
                          PixelFormat.Format24bppRgb);
        bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                         imgPhoto.VerticalResolution);

        Graphics grPhoto = Graphics.FromImage(bmPhoto);
        grPhoto.Clear(Color.Red);
        grPhoto.InterpolationMode =
                InterpolationMode.HighQualityBicubic;

        grPhoto.DrawImage(imgPhoto,
            new Rectangle(destX, destY, destWidth, destHeight),
            new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
            GraphicsUnit.Pixel);

        grPhoto.Dispose();
        return bmPhoto;
    }

1
@bobek просто закрийте оригінальне зображення imgPhoto.Dispose ();
грабувати

1
Хороший код! Ще чистіший, якщо для Graphics.FromImage (bmPhoto) використовується "використання шаблону"; і змінні sourceX та sourceY відкинуті та встановлені на 0 в буквальному значенні в 'new Rectangle (0, 0, sourceWidth, sourceHeight)'
Патрік з команди NDepend

саме те, що мені потрібно;) особливо корисно, коли вам потрібно передати параметр зображення замість фактичного шляху.
Pinte Dani

2
Хороший код, проте я пропоную використовувати Color.White, а не Color.Red
Ахмад

27

Я використовую наступний метод для обчислення бажаного розміру зображення:

using System.Drawing;
public static Size ResizeKeepAspect(this Size src, int maxWidth, int maxHeight, bool enlarge = false)
{
    maxWidth = enlarge ? maxWidth : Math.Min(maxWidth, src.Width);
    maxHeight = enlarge ? maxHeight : Math.Min(maxHeight, src.Height);

    decimal rnd = Math.Min(maxWidth / (decimal)src.Width, maxHeight / (decimal)src.Height);
    return new Size((int)Math.Round(src.Width * rnd), (int)Math.Round(src.Height * rnd));
}

Це ставить проблему співвідношення сторін та розмірів в окремий метод.


Що робити, якщо я хочу зробити "заливку"? Це щоenlarge робить?
Матіас Ліккегор Лоренцен

@MathiasLykkegaardLorenzen зазвичай ти робиш лише зменшення зображень, оскільки збільшення означає втрату якості - тому я додав цей необов’язковий параметр, якщо ти все одно хочеш це зробити
fubo

9

Щоб отримати швидший результат, функцію, яка отримує розмір, можна знайти в resultSize:

Size original = new Size(640, 480);

int maxSize = 100;

float percent = (new List<float> { (float)maxSize / (float)original.Width , (float)maxSize  / (float)original.Height }).Min();

Size resultSize = new Size((int)Math.Floor(original.Width * percent), (int)Math.Floor(original.Height * percent));

Використовує Linqдля мінімізації змінних та перерахунків, а також непотрібних if/elseтверджень


Це фантастичне рішення! Дуже лаконічний і маленький. Я використовував модифіковану версію цього разом із System.Web.Helpers.WebImage, щоб пропорційно змінювати розмір зображення на льоту. Чудова робота!
Halcyon

If/elseбуло б краще, ніж розподіляти список, Math.Minтеж був варіант
Суря Пратап

7

Просто узагальнивши його до пропорцій та розмірів, зображення можна робити поза цією функцією

public static d.RectangleF ScaleRect(d.RectangleF dest, d.RectangleF src, 
  bool keepWidth, bool keepHeight)  
{
    d.RectangleF destRect = new d.RectangleF();

    float sourceAspect = src.Width / src.Height;
    float destAspect = dest.Width / dest.Height;

    if (sourceAspect > destAspect)
    {
        // wider than high keep the width and scale the height
        destRect.Width = dest.Width;
        destRect.Height = dest.Width / sourceAspect;

        if (keepHeight)
        {
            float resizePerc = dest.Height / destRect.Height;
            destRect.Width = dest.Width * resizePerc;
            destRect.Height = dest.Height;
        }
    }
    else
    {
        // higher than wide – keep the height and scale the width
        destRect.Height = dest.Height;
        destRect.Width = dest.Height * sourceAspect;

        if (keepWidth)
        {
            float resizePerc = dest.Width / destRect.Width;
            destRect.Width = dest.Width;
            destRect.Height = dest.Height * resizePerc;
        }

    }

    return destRect;
}

Це чудова ідея, яка відокремлює цю проблему. Ви можете використовувати SizeF замість RectangleF.
Davi Fiamenghi

6

Я збираюся додати тут свій код. Цей код дозволить вам змінити розмір зображення з примусовим співвідношенням сторін або без нього, а також змінити розмір із заповненням. Це модифікована версія коду egrunin.

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var path = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
            ResizeImage(path, "large.jpg", path, "new.jpg", 100, 100, true, true);
        }

        /// <summary>Resizes an image to a new width and height.</summary>
        /// <param name="originalPath">The folder which holds the original image.</param>
        /// <param name="originalFileName">The file name of the original image.</param>
        /// <param name="newPath">The folder which will hold the resized image.</param>
        /// <param name="newFileName">The file name of the resized image.</param>
        /// <param name="maximumWidth">When resizing the image, this is the maximum width to resize the image to.</param>
        /// <param name="maximumHeight">When resizing the image, this is the maximum height to resize the image to.</param>
        /// <param name="enforceRatio">Indicates whether to keep the width/height ratio aspect or not. If set to false, images with an unequal width and height will be distorted and padding is disregarded. If set to true, the width/height ratio aspect is maintained and distortion does not occur.</param>
        /// <param name="addPadding">Indicates whether fill the smaller dimension of the image with a white background. If set to true, the white padding fills the smaller dimension until it reach the specified max width or height. This is used for maintaining a 1:1 ratio if the max width and height are the same.</param>
        private static void ResizeImage(string originalPath, string originalFileName, string newPath, string newFileName, int maximumWidth, int maximumHeight, bool enforceRatio, bool addPadding)
        {
            var image = Image.FromFile(originalPath + "\\" + originalFileName);
            var imageEncoders = ImageCodecInfo.GetImageEncoders();
            EncoderParameters encoderParameters = new EncoderParameters(1);
            encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
            var canvasWidth = maximumWidth;
            var canvasHeight = maximumHeight;
            var newImageWidth = maximumWidth;
            var newImageHeight = maximumHeight;
            var xPosition = 0;
            var yPosition = 0;


            if (enforceRatio)
            {
                var ratioX = maximumWidth / (double)image.Width;
                var ratioY = maximumHeight / (double)image.Height;
                var ratio = ratioX < ratioY ? ratioX : ratioY;
                newImageHeight = (int)(image.Height * ratio);
                newImageWidth = (int)(image.Width * ratio);

                if (addPadding)
                {
                    xPosition = (int)((maximumWidth - (image.Width * ratio)) / 2);
                    yPosition = (int)((maximumHeight - (image.Height * ratio)) / 2);
                }
                else
                {
                    canvasWidth = newImageWidth;
                    canvasHeight = newImageHeight;                  
                }
            }

            var thumbnail = new Bitmap(canvasWidth, canvasHeight);
            var graphic = Graphics.FromImage(thumbnail);

            if (enforceRatio && addPadding)
            {
                graphic.Clear(Color.White);
            }

            graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphic.SmoothingMode = SmoothingMode.HighQuality;
            graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
            graphic.CompositingQuality = CompositingQuality.HighQuality;
            graphic.DrawImage(image, xPosition, yPosition, newImageWidth, newImageHeight);

            thumbnail.Save(newPath + "\\" + newFileName, imageEncoders[1], encoderParameters);
        }
    }
}

Не забудьте додати посилання на System.Drawing DLL.
Дуг

Цей код повертає зображення на 90 градусів - ескіз повертається порівняно з оригіналом - чому?
user2709214

5

Ось менш конкретний метод розширення, який працює з Image, а не завантажує та зберігає за вас. Це також дозволяє вказати метод інтерполяції та правильно відтворювати краї при використанні інтерполяції NedestNeighbour.

Зображення буде відтворюватися в межах вказаної області, щоб ви завжди знали свою вихідну ширину та висоту. наприклад:

Масштабовано в межах

namespace YourApp
{
    #region Namespaces
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Drawing.Drawing2D;
    #endregion

    /// <summary>Generic helper functions related to graphics.</summary>
    public static class ImageExtensions
    {
        /// <summary>Resizes an image to a new width and height value.</summary>
        /// <param name="image">The image to resize.</param>
        /// <param name="newWidth">The width of the new image.</param>
        /// <param name="newHeight">The height of the new image.</param>
        /// <param name="mode">Interpolation mode.</param>
        /// <param name="maintainAspectRatio">If true, the image is centered in the middle of the returned image, maintaining the aspect ratio of the original image.</param>
        /// <returns>The new image. The old image is unaffected.</returns>
        public static Image ResizeImage(this Image image, int newWidth, int newHeight, InterpolationMode mode = InterpolationMode.Default, bool maintainAspectRatio = false)
        {
            Bitmap output = new Bitmap(newWidth, newHeight, image.PixelFormat);

            using (Graphics gfx = Graphics.FromImage(output))
            {
                gfx.Clear(Color.FromArgb(0, 0, 0, 0));
                gfx.InterpolationMode = mode;
                if (mode == InterpolationMode.NearestNeighbor)
                {
                    gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    gfx.SmoothingMode = SmoothingMode.HighQuality;
                }

                double ratioW = (double)newWidth / (double)image.Width;
                double ratioH = (double)newHeight / (double)image.Height;
                double ratio = ratioW < ratioH ? ratioW : ratioH;
                int insideWidth = (int)(image.Width * ratio);
                int insideHeight = (int)(image.Height * ratio);

                gfx.DrawImage(image, new Rectangle((newWidth / 2) - (insideWidth / 2), (newHeight / 2) - (insideHeight / 2), insideWidth, insideHeight));
            }

            return output;
        }
    }
}

1
Параметр для maintenanceAspectRatio не використовується.
Хаукман,

4

Примітка: цей код змінює розмір і видаляє все, що не відповідає співвідношенню сторін, замість того щоб заповнювати його.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace MyPhotos.Common
{
    public class ThumbCreator
    {

        public enum VerticalAlign
        {
            Top,
            Middle,
            Bottom
        }

        public enum HorizontalAlign
        {
            Left,
            Middle,
            Right
        }

        public void Convert(string sourceFile, string targetFile, ImageFormat targetFormat, int height, int width, VerticalAlign valign, HorizontalAlign halign)
        {
            using (Image img = Image.FromFile(sourceFile))
            {
                using (Image targetImg = Convert(img, height, width, valign, halign))
                {
                    string directory = Path.GetDirectoryName(targetFile);
                    if (!Directory.Exists(directory))
                    {
                        Directory.CreateDirectory(directory);
                    }
                    if (targetFormat == ImageFormat.Jpeg)
                    {
                        SaveJpeg(targetFile, targetImg, 100);
                    }
                    else
                    {
                        targetImg.Save(targetFile, targetFormat);
                    }
                }
            }
        }

        /// <summary> 
        /// Saves an image as a jpeg image, with the given quality 
        /// </summary> 
        /// <param name="path">Path to which the image would be saved.</param> 
        // <param name="quality">An integer from 0 to 100, with 100 being the 
        /// highest quality</param> 
        public static void SaveJpeg(string path, Image img, int quality)
        {
            if (quality < 0 || quality > 100)
                throw new ArgumentOutOfRangeException("quality must be between 0 and 100.");


            // Encoder parameter for image quality 
            EncoderParameter qualityParam =
                new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            // Jpeg image codec 
            ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");

            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;

            img.Save(path, jpegCodec, encoderParams);
        }

        /// <summary> 
        /// Returns the image codec with the given mime type 
        /// </summary> 
        private static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            // Get image codecs for all image formats 
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

            // Find the correct image codec 
            for (int i = 0; i < codecs.Length; i++)
                if (codecs[i].MimeType == mimeType)
                    return codecs[i];
            return null;
        }

        public Image Convert(Image img, int height, int width, VerticalAlign valign, HorizontalAlign halign)
        {
            Bitmap result = new Bitmap(width, height);
            using (Graphics g = Graphics.FromImage(result))
            {
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                float ratio = (float)height / (float)img.Height;
                int temp = (int)((float)img.Width * ratio);
                if (temp == width)
                {
                    //no corrections are needed!
                    g.DrawImage(img, 0, 0, width, height);
                    return result;
                }
                else if (temp > width)
                {
                    //den e för bred!
                    int overFlow = (temp - width);
                    if (halign == HorizontalAlign.Middle)
                    {
                        g.DrawImage(img, 0 - overFlow / 2, 0, temp, height);
                    }
                    else if (halign == HorizontalAlign.Left)
                    {
                        g.DrawImage(img, 0, 0, temp, height);
                    }
                    else if (halign == HorizontalAlign.Right)
                    {
                        g.DrawImage(img, -overFlow, 0, temp, height);
                    }
                }
                else
                {
                    //den e för hög!
                    ratio = (float)width / (float)img.Width;
                    temp = (int)((float)img.Height * ratio);
                    int overFlow = (temp - height);
                    if (valign == VerticalAlign.Top)
                    {
                        g.DrawImage(img, 0, 0, width, temp);
                    }
                    else if (valign == VerticalAlign.Middle)
                    {
                        g.DrawImage(img, 0, -overFlow / 2, width, temp);
                    }
                    else if (valign == VerticalAlign.Bottom)
                    {
                        g.DrawImage(img, 0, -overFlow, width, temp);
                    }
                }
            }
            return result;
        }
    }
}

@Peter Це не відповідало початковому визначеному розміру ширини / висоти, який я передав функції. Натомість у мене вийшло дуже тонке і довге зображення, будь-яка ідея, як це виправити?
Ідан Шехтер,

@IdanShechter це стара стара стара відповідь (я не використовував цей код багато років), не могли б ви надати мені приклад, і я міг би вам допомогти.
Пітер,

@Peter Дякую, я фактично використовую ImageProcessor, але я отримую виняток: stackoverflow.com/questions/51280935/…
Айдан Шехтер,

4

// This allows us to resize the image. It prevents skewed images and 
// also vertically long images caused by trying to maintain the aspect 
// ratio on images who's height is larger than their width

public void ResizeImage(string OriginalFile, string NewFile, int NewWidth, int MaxHeight, bool OnlyResizeIfWider)

{
    System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(OriginalFile);

    // Prevent using images internal thumbnail
    FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
    FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);

    if (OnlyResizeIfWider)
    {
        if (FullsizeImage.Width <= NewWidth)
        {
            NewWidth = FullsizeImage.Width;
        }
    }

    int NewHeight = FullsizeImage.Height * NewWidth / FullsizeImage.Width;
    if (NewHeight > MaxHeight)
    {
        // Resize with height instead
        NewWidth = FullsizeImage.Width * MaxHeight / FullsizeImage.Height;
        NewHeight = MaxHeight;
    }

    System.Drawing.Image NewImage = FullsizeImage.GetThumbnailImage(NewWidth, NewHeight, null, IntPtr.Zero);

    // Clear handle to original file so that we can overwrite it if necessary
    FullsizeImage.Dispose();

    // Save resized picture
    NewImage.Save(NewFile);
}


У вас був приклад, у якому не використовується GetThumbnailImage? Я хотів би контролювати якість та інші налаштування вручну.
sf.

1

Зберігайте аспект норми та усувайте поштову скриньку та Pillarbox.

static Image FixedSize(Image imgPhoto, int Width, int Height)
    {
        int sourceWidth = imgPhoto.Width;
        int sourceHeight = imgPhoto.Height;
        int X = 0;
        int Y = 0;

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

        nPercentW = ((float)Width / (float)sourceWidth);
        nPercentH = ((float)Height / (float)sourceHeight);
        if (nPercentH < nPercentW)
        {
            nPercent = nPercentH;
        }
        else
        {
            nPercent = nPercentW;
        }

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

        Bitmap bmPhoto = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);

        bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                                         imgPhoto.VerticalResolution);

        Graphics grPhoto = Graphics.FromImage(bmPhoto);

        grPhoto.DrawImage(imgPhoto,
                new Rectangle(X, Y, destWidth, destHeight),
                new Rectangle(X, Y, sourceWidth, sourceHeight),
                GraphicsUnit.Pixel);

        grPhoto.Dispose();
        return bmPhoto;
    }

1
public static void resizeImage_n_save(Stream sourcePath, string targetPath, int requiredSize)
    {
        using (var image = System.Drawing.Image.FromStream(sourcePath))
        {
            double ratio = 0;

            var newWidth = 0;
            var newHeight = 0;
            double w = Convert.ToInt32(image.Width);
            double h = Convert.ToInt32(image.Height);
            if (w > h)
            {
                ratio = h / w * 100;
                newWidth = requiredSize;
                newHeight = Convert.ToInt32(requiredSize * ratio / 100);
            }
            else
            {
                ratio = w / h * 100;
                newHeight = requiredSize;
                newWidth = Convert.ToInt32(requiredSize * ratio / 100);
            }

            //   var newWidth = (int)(image.Width * scaleFactor);
            // var newHeight = (int)(image.Height * scaleFactor);
            var thumbnailImg = new Bitmap(newWidth, newHeight);
            var thumbGraph = Graphics.FromImage(thumbnailImg);
            thumbGraph.CompositingQuality = CompositingQuality.HighQuality;
            thumbGraph.SmoothingMode = SmoothingMode.HighQuality;
            thumbGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
            var imageRectangle = new Rectangle(0, 0, newWidth, newHeight);

            thumbGraph.DrawImage(image, imageRectangle);
            thumbnailImg.Save(targetPath, image.RawFormat);

            //var img = FixedSize(image, requiredSize, requiredSize);
            //img.Save(targetPath, image.RawFormat);

        }
    }

1

Я створив метод розширення, який набагато простіший, ніж відповіді, які розміщені. і пропорція зображення застосовується без обрізання зображення.

public static Image Resize(this Image image, int width, int height) {
     var scale = Math.Min(height / (float)image.Height, width / (float)image.Width);
     return image.GetThumbnailImage((int)(image.Width * scale), (int)(image.Height * scale), () => false, IntPtr.Zero);
}

Приклад використання:

using (var img = Image.FromFile(pathToOriginalImage)) {
    using (var thumbnail = img.Resize(60, 60)){
        // Here you can do whatever you need to do with thumnail
    }
}

0

Я щойно написав це, тому що жодна з відповідей, які вже були тут, не була досить простою. Ви можете замінити твердокодовані 128 на будь-що, що завгодно, або встановити їх за розміром оригінального зображення. Все, що я хотів, - це масштабувати зображення на зображення розміром 128x128, зберігаючи пропорції та центруючи результат у новому зображенні.

    private Bitmap CreateLargeIconForImage(Bitmap src)
    {
        Bitmap bmp = new Bitmap(128, 128);
        Graphics g = Graphics.FromImage(bmp);

        float scale = Math.Max((float)src.Width / 128.0f, (float)src.Height / 128.0f);
        PointF p = new PointF(128.0f - ((float)src.Width / scale), 128.0f - ((float)src.Height / scale));
        SizeF size = new SizeF((float)src.Width / scale, (float)src.Height / scale);

        g.DrawImage(src, new RectangleF(p, size));

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