Я хочу масштабировать изображение на C # с таким же уровнем качества, как в Photoshop. Есть ли для этого доступная библиотека обработки изображений C #?
c#
image
image-processing
image-manipulation
image-scaling
Рамеш Сони
источник
источник
Ответы:
Вот хорошо прокомментированный вспомогательный класс для обработки изображений, который вы можете посмотреть и использовать. Я написал это как пример того, как выполнять определенные задачи по работе с изображениями на 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; } } }
Обновить
Несколько человек просили в комментариях образцы того, как использовать класс 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); }
Заметка
Помните, что изображения одноразовые, поэтому вам нужно назначить результат вашего изменения размера объявлению using (или вы можете использовать try finally и убедиться, что вы вызываете dispose в своем finally).
источник
На мой взгляд, когда вы рисуете изображение с помощью GDI +, оно хорошо масштабируется. Вы можете использовать это для создания масштабированного изображения.
Если вы хотите масштабировать изображение с помощью 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)); }
источник
new Size
в объявленииscaled
:new Bitmap(original.Width * 4, original.Height * 4);
Протестированные библиотеки, такие как Imagemagick и GD , доступны для .NET.
Вы также можете прочитать о таких вещах, как бикубическая интерполяция, и написать свои собственные.
источник
Статьи CodeProject, в которых обсуждается и публикуется исходный код для масштабирования изображений:
источник
Используйте эту библиотеку: http://imageresizing.net
Прочтите эту статью автора библиотеки: 20 ловушек для изменения размера изображения с .NET
источник
Попробуйте разные значения для Graphics.InterpolationMode. В GDI + доступно несколько типичных алгоритмов масштабирования. Если одного из них достаточно для ваших нужд, вы можете пойти по этому пути вместо того, чтобы полагаться на внешнюю библиотеку.
источник
Вы можете попробовать dotImage , один из продуктов моей компании, который включает объект для передискретизации изображений, имеющий 18 типов фильтров для различных уровней качества.
Типичное использование:
// BiCubic is one technique available in PhotoShop ResampleCommand resampler = new ResampleCommand(newSize, ResampleMethod.BiCubic); AtalaImage newImage = resampler.Apply(oldImage).Image;
Кроме того, dotImage включает 140 некоторых команд обработки нечетных изображений, включая множество фильтров, подобных тем, что есть в 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; }
источник
В Code Project есть статья об использовании GDI + для .NET для изменения размера фотографий с использованием, скажем, бикубической интерполяции.
Еще одна статья на эту тему была в другом блоге (кажется, сотрудник MS), но я нигде не могу найти ссылку. :( Может еще кто-нибудь найдет?
источник
вы можете попробовать это, если это фильтр 2D-изображений lowres cgi
источник
Я заметил, что эта статья упоминается в коде Paint.NET для передискретизации изображения: « Различные простые методы обработки изображений» Пола Бурка.
источник
Вы можете попробовать волшебное ядро . Он создает меньше артефактов пикселизации, чем бикубическая передискретизация при апскейлинге, а также дает очень хорошие результаты при уменьшении. Исходный код доступен на C # с веб-сайта.
источник
У меня есть некоторые улучшения для ответа доктора Джонса.
Это работает для тех, кто хотел, как пропорционально изменить размер изображения. Он протестировал и работал у меня.
Методы класса я добавил:
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); }
источник