高品质的图像缩放库
我想在C#中调整图像的质量,就像Photoshop一样好。 有没有任何C#image processing库可用来做这件事情?
这里有一个很好的评论的图像操作助手类,你可以看看和使用。 我把它写成了一个如何在C#中执行某些image processing任务的例子。 你会对ResizeImage函数感兴趣,它以System.Drawing.Image,width和height作为参数。
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; } } }
更新
有几个人在评论中询问如何使用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); }
注意
请记住,图像是一次性的,所以你需要将你的resize的结果分配给一个使用声明(或者你可以最后使用一个尝试,并确保你最后调用处置)。
当你使用GDI +绘制图像时,在我看来它的缩放比例非常好。 您可以使用它来创build一个缩放图像。
如果你想用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)); }
如Imagemagick和GD的testing库可用于.NET
你也可以阅读诸如双三次插值之类的东西,然后自己写。
讨论和共享缩放图像的源代码的CodeProject文章:
- 使用filter的两个通道缩放
- 使用.NET GDI +在C#中对图像进行matrix转换
- 使用GDI + for .NET调整照片图像的大小
- Haar变换快速二进制图像缩放
使用这个库: http : //imageresizing.net
阅读图书馆作者的这篇文章: 20图像调整与.NET的陷阱
尝试Graphics.InterpolationMode的不同值。 在GDI +中有几种典型的缩放algorithm。 如果其中一个足以满足您的需要,您可以走这条路线,而不是依赖外部图书馆。
您可以尝试使用我公司产品之一的dotImage ,其中包含一个用于重新采样图像的对象 ,该对象具有各种质量级别的18种滤镜types 。
典型的用法是:
// BiCubic is one technique available in PhotoShop ResampleCommand resampler = new ResampleCommand(newSize, ResampleMethod.BiCubic); AtalaImage newImage = resampler.Apply(oldImage).Image;
另外,dotImage包含了140个奇怪的image processing命令,其中包括许多类似于PhotoShop的滤镜,如果这就是你正在寻找的。
这可能有帮助
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; }
注意InterpolationMode.HighQualityBicubic
– >这通常是性能和结果之间的良好折衷。
试试这个基本的代码片段:
private static Bitmap ResizeBitmap(Bitmap srcbmp, int width, int height ) { Bitmap newimage = new Bitmap(width, height); using (Graphics g = Graphics.FromImage(newimage)) g.DrawImage(srcbmp, 0, 0, width, height); return newimage; }
有一篇关于使用GDI + for .NET的代码项目的文章 ,例如使用双三次插值来进行照片大小调整。
在另一个博客上有另一篇关于这个话题的文章(MS员工,我认为),但是我找不到任何链接。 :(也许别人可以find它?
你可以尝试这一个,如果它是一个低分辨率的二维图像filter
这是一篇我看到在Paint.NET的图像重采样代码引用的文章:Paul Bourke的各种简单image processing技术 。
你可以试试魔术核心 。 它在缩放时产生比双三次重采样更less的像素化伪像,并且在缩小时也产生非常好的结果。 源代码在网站上以c#提供。
琼斯博士的回答我有了一些改进。
它适用于谁想要如何按比例调整图像大小。 它为我testing和工作。
我添加的类的方法:
public static System.Drawing.Bitmap ResizeImage(System.Drawing.Image image, Size size) { return ResizeImage(image, size.Width, size.Height); } public static Size GetProportionedSize(Image image, int maxWidth, int maxHeight, bool withProportion) { if (withProportion) { double sourceWidth = image.Width; double sourceHeight = image.Height; if (sourceWidth < maxWidth && sourceHeight < maxHeight) { maxWidth = (int)sourceWidth; maxHeight = (int)sourceHeight; } else { double aspect = sourceHeight / sourceWidth; if (sourceWidth < sourceHeight) { maxWidth = Convert.ToInt32(Math.Round((maxHeight / aspect), 0)); } else { maxHeight = Convert.ToInt32(Math.Round((maxWidth * aspect), 0)); } } } return new Size(maxWidth, maxHeight); }
和新的可用使用根据此代码:
using (var resized = ImageUtilities.ResizeImage(image, ImageUtilities.GetProportionedSize(image, 50, 100))) { ImageUtilities.SaveJpeg(@"C:\myimage.jpeg", resized, 90); }