C# 高质量图像缩放库

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/249587/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:53:17  来源:igfitidea点击:

High Quality Image Scaling Library

c#imageimage-processingimage-manipulationimage-scaling

提问by Ramesh Soni

I want to scale an image in C# with quality level as good as Photoshop does. Is there any C# image processing library available to do this thing?

我想在 C# 中以与 Photoshop 一样好的质量级别缩放图像。是否有任何 C# 图像处理库可用于执行此操作?

采纳答案by Doctor Jones

Here's a nicely commented Image Manipulation helper class that you can look at and use. I wrote it as an example of how to perform certain image manipulation tasks in C#. You'll be interested in the ResizeImagefunction that takes a System.Drawing.Image, the width and the height as the arguments.

这是一个注释很好的 Image Manipulation 辅助类,您可以查看和使用它。我写它作为如何在 C# 中执行某些图像处理任务的示例。您会对ResizeImage函数感兴趣,该函数采用 System.Drawing.Image、宽度和高度作为参数。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;

namespace DoctaJonez.Drawing.Imaging
{
    /// <summary>
    /// Provides various image untilities, such as high quality resizing and the ability to save a JPEG.
    /// </summary>
    public static class ImageUtilities
    {    
        /// <summary>
        /// A quick lookup for getting image encoders
        /// </summary>
        private static Dictionary<string, ImageCodecInfo> encoders = null;

        /// <summary>
        /// A lock to prevent concurrency issues loading the encoders.
        /// </summary>
        private static object encodersLock = new object();

        /// <summary>
        /// A quick lookup for getting image encoders
        /// </summary>
        public static Dictionary<string, ImageCodecInfo> Encoders
        {
            //get accessor that creates the dictionary on demand
            get
            {
                //if the quick lookup isn't initialised, initialise it
                if (encoders == null)
                {
                    //protect against concurrency issues
                    lock (encodersLock)
                    {
                        //check again, we might not have been the first person to acquire the lock (see the double checked lock pattern)
                        if (encoders == null)
                        {
                            encoders = new Dictionary<string, ImageCodecInfo>();

                            //get all the codecs
                            foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders())
                            {
                                //add each codec to the quick lookup
                                encoders.Add(codec.MimeType.ToLower(), codec);
                            }
                        }
                    }
                }

                //return the lookup
                return encoders;
            }
        }

        /// <summary>
        /// Resize the image to the specified width and height.
        /// </summary>
        /// <param name="image">The image to resize.</param>
        /// <param name="width">The width to resize to.</param>
        /// <param name="height">The height to resize to.</param>
        /// <returns>The resized image.</returns>
        public static System.Drawing.Bitmap ResizeImage(System.Drawing.Image image, int width, int height)
        {
            //a holder for the result
            Bitmap result = new Bitmap(width, height);
            //set the resolutions the same to avoid cropping due to resolution differences
            result.SetResolution(image.HorizontalResolution, image.VerticalResolution);

            //use a graphics object to draw the resized image into the bitmap
            using (Graphics graphics = Graphics.FromImage(result))
            {
                //set the resize quality modes to high quality
                graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                //draw the image into the target bitmap
                graphics.DrawImage(image, 0, 0, result.Width, result.Height);
            }

            //return the resulting bitmap
            return result;
        }

        /// <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> 
        /// <exception cref="ArgumentOutOfRangeException">
        /// An invalid value was entered for image quality.
        /// </exception>
        public static void SaveJpeg(string path, Image image, int quality)
        {
            //ensure the quality is within the correct range
            if ((quality < 0) || (quality > 100))
            {
                //create the error message
                string error = string.Format("Jpeg image quality must be between 0 and 100, with 100 being the highest quality.  A value of {0} was specified.", quality);
                //throw a helpful exception
                throw new ArgumentOutOfRangeException(error);
            }

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

            //create a collection of all parameters that we will pass to the encoder
            EncoderParameters encoderParams = new EncoderParameters(1);
            //set the quality parameter for the codec
            encoderParams.Param[0] = qualityParam;
            //save the image using the codec and the parameters
            image.Save(path, jpegCodec, encoderParams);
        }

        /// <summary> 
        /// Returns the image codec with the given mime type 
        /// </summary> 
        public static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            //do a case insensitive search for the mime type
            string lookupKey = mimeType.ToLower();

            //the codec to return, default to null
            ImageCodecInfo foundCodec = null;

            //if we have the encoder, get it to return
            if (Encoders.ContainsKey(lookupKey))
            {
                //pull the codec from the lookup
                foundCodec = Encoders[lookupKey];
            }

            return foundCodec;
        } 
    }
}


Update

更新

A few people have been asking in the comments for samples of how to consume the ImageUtilities class, so here you go.

一些人一直在评论中询问如何使用 ImageUtilities 类的示例,所以你开始吧。

//resize the image to the specified height and width
using (var resized = ImageUtilities.ResizeImage(image, 50, 100))
{
    //save the resized image as a jpeg with a quality of 90
    ImageUtilities.SaveJpeg(@"C:\myimage.jpeg", resized, 90);
}

Note

笔记

Remember that images are disposable, so you need to assign the result of your resize to a using declaration (or you could use a try finally and make sure you call dispose in your finally).

请记住,图像是一次性的,因此您需要将调整大小的结果分配给 using 声明(或者您可以使用 try finally 并确保您在 finally 中调用 dispose )。

回答by Hallgrim

When you draw the image using GDI+ it scales quite well in my opinion. You can use this to create a scaled image.

当您使用 GDI+ 绘制图像时,我认为它可以很好地缩放。您可以使用它来创建缩放图像。

If you want to scale your image with GDI+ you can do something like this:

如果要使用 GDI+ 缩放图像,可以执行以下操作:

Bitmap original = ...
Bitmap scaled = new Bitmap(new Size(original.Width * 4, original.Height * 4));
using (Graphics graphics = Graphics.FromImage(scaled)) {
  graphics.DrawImage(original, new Rectangle(0, 0, scaled.Width, scaled.Height));
}

回答by kitsune

Tested libraries like Imagemagickand GDare available for .NET

ImagemagickGD等经过测试的库可用于 .NET

You could also read up on things like bicubic interpolation and write your own.

您还可以阅读双三次插值之类的内容并编写自己的内容。

回答by OregonGhost

Try the different values for Graphics.InterpolationMode. There are several typical scaling algorithms available in GDI+. If one of these is sufficient for your need, you can go this route instead of relying on an external library.

尝试 Graphics.InterpolationMode 的不同值。GDI+ 中有几种典型的缩放算法可用。如果其中之一足以满足您的需要,您可以走这条路,而不是依赖外部库。

回答by OregonGhost

There's an article on Code Projectabout using GDI+ for .NET to do photo resizing using, say, Bicubic interpolation.

Code Project 上一篇关于使用 GDI+ for .NET 使用 Bicubic 插值调整照片大小的文章

There was also another article about this topic on another blog (MS employee, I think), but I can't find the link anywhere. :( Perhaps someone else can find it?

在另一个博客上还有另一篇关于这个主题的文章(我认为是 MS 员工),但我在任何地方都找不到链接。:( 也许其他人可以找到它?

回答by plinth

You can try dotImage, one of my company's products, which includes an object for resamplingimages that has 18 filter typesfor various levels of quality.

您可以尝试dotImage,我公司的产品之一,它包括一个用于重采样图像的对象,该对象具有18 种不同质量级别的过滤器类型

Typical usage is:

典型用法是:

// BiCubic is one technique available in PhotoShop
ResampleCommand resampler = new ResampleCommand(newSize, ResampleMethod.BiCubic);
AtalaImage newImage = resampler.Apply(oldImage).Image;

in addition, dotImage includes 140 some odd image processing commands including many filters similar to those in PhotoShop, if that's what you're looking for.

此外,dotImage 包含 140 个奇怪的图像处理命令,其中包括许多类似于 PhotoShop 中的过滤器,如果这就是您正在寻找的。

回答by Igor Brejc

This is an article I spotted being referenced in Paint.NET's code for image resampling: Various Simple Image Processing Techniquesby Paul Bourke.

这是我在 Paint.NET 的图像重采样代码中发现的一篇文章:Paul Bourke 的各种简单图像处理技术

回答by Cryx

you could try this one if it's a lowres cgi 2D Image Filter

如果它是低分辨率 cgi 2D 图像过滤器,你可以试试这个

回答by Leslie Marshall

This might help

这可能有帮助

    public Image ResizeImage(Image source, RectangleF destinationBounds)
    {
        RectangleF sourceBounds = new RectangleF(0.0f,0.0f,(float)source.Width, (float)source.Height);
        RectangleF scaleBounds = new RectangleF();

        Image destinationImage = new Bitmap((int)destinationBounds.Width, (int)destinationBounds.Height);
        Graphics graph = Graphics.FromImage(destinationImage);
        graph.InterpolationMode =
            System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

        // Fill with background color
        graph.FillRectangle(new SolidBrush(System.Drawing.Color.White), destinationBounds);

        float resizeRatio, sourceRatio;
        float scaleWidth, scaleHeight;

        sourceRatio = (float)source.Width / (float)source.Height;

        if (sourceRatio >= 1.0f)
        {
            //landscape
            resizeRatio = destinationBounds.Width / sourceBounds.Width;
            scaleWidth = destinationBounds.Width;
            scaleHeight = sourceBounds.Height * resizeRatio;
            float trimValue = destinationBounds.Height - scaleHeight;
            graph.DrawImage(source, 0, (trimValue / 2), destinationBounds.Width, scaleHeight);
        }
        else
        {
            //portrait
            resizeRatio = destinationBounds.Height/sourceBounds.Height;
            scaleWidth = sourceBounds.Width * resizeRatio;
            scaleHeight = destinationBounds.Height;
            float trimValue = destinationBounds.Width - scaleWidth;
            graph.DrawImage(source, (trimValue / 2), 0, scaleWidth, destinationBounds.Height);
        }

        return destinationImage;

    }

Note the InterpolationMode.HighQualityBicubic-> this is generally a good tradeoff between performance and results.

请注意InterpolationMode.HighQualityBicubic-> 这通常是性能和结果之间的良好折衷。