【问题标题】:c# Image resizing to different size while preserving aspect ratioc# 在保持纵横比的同时将图像调整为不同大小
【发布时间】:2017-10-28 19:15:45
【问题描述】:

我正在尝试调整图像的大小,同时保留原始图像的宽高比,这样新图像就不会被压扁。

例如:

将 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);
    }

编辑:我想要填充而不是裁剪图像

【问题讨论】:

    标签: c# image-processing system.drawing image-scaling


    【解决方案1】:

    应该这样做。

    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);
    }
    

    编辑添加:

    那些想要改进这个代码的人应该把它放在 cmets 中,或者一个新的答案。不要直接编辑此代码。

    【讨论】:

    • 只是想知道参数 originalWidth 和 originalHeight,当您可以从图像中获取这些信息时,为什么需要它们? (在我获得评论权限之前,我确实编辑过你的代码,对此我深表歉意)
    • @mendel - 是的,这也可以。但是在最初的问题中他已经知道了高度和宽度,那为什么还要重新计算呢?
    • 我在一张 1024*768 的图像上尝试过这个转换为 500*500 的图像 - 图像失真了。我正在寻找类似 wordpress CMS 的算法,其中图像在缩小尺寸时不会失真(但是从侧面进行了一些裁剪)。
    • @yogihosting 发布有关您的问题的问题,包括您的代码,甚至可能是指向测试图像的链接。这对其他人有用,所以我们需要看看对你有什么不同。
    • @egrunin 我建议在加载原始图像时使用Path.Combine(path, originalFileName)。最后保存缩略图时相同。
    【解决方案2】:

    通过学习this CodeProject Article,我发现了如何调整图像大小和填充图像。

    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;
        }
    

    【讨论】:

    • @bobek 只关闭原图 imgPhoto.Dispose();
    • 不错的代码!如果对 Graphics.FromImage(bmPhoto); 使用“使用模式”,则更清洁。并且 sourceX 和 sourceY 变量被丢弃并在 'new Rectangle(0, 0, sourceWidth, sourceHeight)' 中设置为 0 字面量
    • 正是我需要的 ;) 当您需要传递图像参数而不是实际路径时特别有用。
    • 代码不错,但我建议使用 Color.White 而不是 Color.Red
    【解决方案3】:

    我使用以下方法来计算所需的图像尺寸:

    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));
    }
    

    这将纵横比和尺寸的问题放在一个单独的方法中。

    参数是什么 bool enlarge = false ?

    通常你只会缩小图像,因为放大意味着质量损失 - 所以如果你想这样做,我添加了这个可选参数

    【讨论】:

    • 如果我想做一个“填充”怎么办? enlarge 是这样做的吗?
    • @MathiasLykkegaardLorenzen 通常你只会缩小图像,因为放大意味着质量损失 - 所以如果你想这样做,我添加了这个可选参数
    【解决方案4】:

    为了得到更快的结果,获取大小的函数可以在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 一起使用,以即时按比例调整图像大小。干得好!
    • If/else 会比分配列表更好,Math.Min 也是一种选择
    【解决方案5】:

    只是将其概括为纵横比和尺寸,图像的东西可以在这个函数之外完成

    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
    【解决方案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 度 - 缩略图与原始图像相比旋转 - 为什么?
    【解决方案7】:

    这是一个不太具体的扩展方法,它适用于 Image 而不是为您进行加载和保存。它还允许您在使用 NearestNeighbour 插值时指定插值方法并正确渲染边缘。

    图像将在您指定的区域范围内呈现,因此您始终知道输出的宽度和高度。例如:

    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;
            }
        }
    }
    

    【讨论】:

    • 没有使用maintainAspectRatio的参数。
    【解决方案8】:

    注意:此代码调整大小并删除纵横比之外的所有内容,而不是填充它..

    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/…
    【解决方案9】:

    // 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 的示例?我想手动控制质量和其他设置。
    【解决方案10】:

    我创建了一个比发布的答案更简单的扩展方法。 并且在不裁剪图像的情况下应用纵横比。

    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
        }
    }
    

    【讨论】:

    • 最好不要使用 ThumbnailImage。请改用图片。
    • 图片的高度和宽度在 System.Drawing.Image 命名空间中是不可设置的,所以你不能只使用图片来代替。这只适用于旧的 Windows 窗体,它与这里讨论的命名空间不同。
    【解决方案11】:

    保持纵横比,消除信箱和邮筒。

    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;
        }
    

    【讨论】:

      【解决方案12】:
      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);
      
              }
          }
      

      【讨论】:

        【解决方案13】:

        我刚刚写了这篇文章,因为这里的答案都不够简单。您可以将硬编码的 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;
            }
        

        【讨论】:

          【解决方案14】:

          我知道这是一个较旧的线程。然而,这是谷歌搜索该主题的第一个结果。 没有一个答案符合我的要求。因此,这是我通过了解较旧的解决方案组合而成的解决方案,但将结果图像大小限制为最合适的高度和宽度。

                  double ratioW = (double)desiredWidthPixels / (double)originalImage.Width;
                  double ratioH = (double)desiredHeightPixels / (double)originalImage.Height;
                  double ratio = ratioW < ratioH ? ratioW : ratioH;
                  int suitableWidth = (int)(originalImage.Width * ratio);
                  int suitableHeight = (int)(originalImage.Height * ratio);
          
                  var resizedPhoto = new Bitmap((int)suitableWidth, (int)suitableHeight);
                  var graphicsSurface = Graphics.FromImage(resizedPhoto);
                  graphicsSurface.DrawImage(originalImage, new RectangleF(new PointF(0,0), new SizeF(suitableWidth, suitableHeight)));
          

          【讨论】:

            猜你喜欢
            • 2010-12-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-06-26
            • 2012-04-15
            相关资源
            最近更新 更多