Je souhaite redimensionner une image en C # avec un niveau de qualité aussi bon que Photoshop. Existe-t-il une bibliothèque de traitement d’image C # disponible pour cette opération?
Voici une classe d'assistance de manipulation d'images bien commentée que vous pouvez regarder et utiliser. Je l'ai écrit à titre d'exemple pour effectuer certaines tâches de manipulation d'images en C #. Vous serez intéressé par la fonction ResizeImage qui prend comme arguments System.Drawing.Image, la largeur et la hauteur.
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;
}
}
}
Quelques personnes ont demandé dans les commentaires des exemples d'utilisation de la classe 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);
}
N'oubliez pas que les images sont jetables. Vous devez donc attribuer le résultat de votre redimensionnement à une déclaration d'utilisation (ou vous pouvez utiliser un essai et vous assurer que vous appelez disposer avec votre enfin).
Lorsque vous dessinez une image à l’aide de GDI +, elle s’échelonne assez bien à mon avis. Vous pouvez l'utiliser pour créer une image mise à l'échelle.
Si vous souhaitez redimensionner votre image avec GDI +, vous pouvez procéder de la manière suivante:
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));
}
Les bibliothèques testées telles que Imagemagick et Gd sont disponibles pour .NET
Vous pouvez également lire des articles sur l’interpolation bicubique et écrire le vôtre.
Articles CodeProject traitant et partageant le code source pour redimensionner des images:
Utilisez cette bibliothèque: http://imageresizing.net
Lisez cet article de l'auteur de la bibliothèque: 20 pièges de dimensionnement d'image avec .NET
Essayez les différentes valeurs pour Graphics.InterpolationMode. Plusieurs algorithmes de mise à l'échelle typiques sont disponibles dans GDI +. Si l’un de ceux-ci suffit à vos besoins, vous pouvez choisir cette voie au lieu de vous fier à une bibliothèque externe.
Vous pouvez essayer dotImage , l'un des produits de mon entreprise, qui inclut un objet à rééchantillonner images comportant 18 types de filtres pour différents niveaux de qualité.
L'utilisation typique est:
// BiCubic is one technique available in PhotoShop
ResampleCommand resampler = new ResampleCommand(newSize, ResampleMethod.BiCubic);
AtalaImage newImage = resampler.Apply(oldImage).Image;
en outre, dotImage inclut 140 commandes de traitement d'images impaires, y compris de nombreux filtres similaires à ceux de PhotoShop, si c'est ce que vous recherchez.
Cela pourrait aider
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;
}
Noter la InterpolationMode.HighQualityBicubic
-> il s’agit généralement d’un bon compromis entre performance et résultats.
Essayez cet extrait de code de base:
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;
}
Il y a un article sur Code Project sur l'utilisation de GDI + for .NET pour le redimensionnement des photos en utilisant, par exemple, une interpolation bicubique.
Il y avait aussi un autre article à ce sujet sur un autre blog (employé de MS, je pense), mais je ne trouve le lien nulle part. :( Peut-être que quelqu'un d'autre peut le trouver?
C'est un article que j'ai repéré en train d'être référencé dans le code de rééchantillonnage d'image de Paint.NET: Diverses techniques de traitement d'image simple de Paul Bourke.
Vous pouvez essayer le noyau magique . Il produit moins d'artefacts de pixelisation que le rééchantillonnage bicubique lors de la conversion ascendante et donne également de très bons résultats lors de la réduction de la résolution. Le code source est disponible en c # sur le site Web.
J'ai quelques améliorations à apporter à la réponse du docteur Jones.
Cela fonctionne pour qui a voulu comment redimensionner proportionnellement l'image. Il a testé et travaillé pour moi.
Les méthodes de cours que j'ai ajoutées:
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);
}
et nouveaux disponibles en fonction de ces codes:
using (var resized = ImageUtilities.ResizeImage(image, ImageUtilities.GetProportionedSize(image, 50, 100)))
{
ImageUtilities.SaveJpeg(@"C:\myimage.jpeg", resized, 90);
}
vous pouvez essayer celui-ci s'il s'agit d'un lowres cgi Filtre d'image 2D