Comment puis-je redimensionner une image sans affecter la qualité de l'image?
Comment puis-je redimensionner une image sans affecter la qualité de l'image?
Réponses:
Comme le dit rcar , vous ne pouvez pas sans perdre de la qualité, le mieux que vous puissiez faire en c # est:
Bitmap newImage = new Bitmap(newWidth, newHeight);
using (Graphics gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight));
}
Sauf si vous faites des graphiques vectoriels, il n'y a aucun moyen de redimensionner une image sans potentiellement perdre une certaine qualité d'image.
private static Image resizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
Je pense que ce que vous cherchez à faire est de "redimensionner / rééchantillonner" vos images. Voici un bon site qui donne des instructions et fournit une classe d'utilité (que j'utilise aussi):
http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx
Sauf si vous redimensionnez, vous ne pouvez pas le faire avec des graphiques raster.
Ce que vous pouvez faire avec un bon filtrage et un bon lissage est de redimensionner sans perdre aucune qualité notable .
Vous pouvez également modifier les métadonnées DPI de l'image (en supposant qu'elle en possède) qui conserveront exactement le même nombre de pixels, mais modifieront la façon dont les éditeurs d'images la perçoivent dans des mesures «réelles».
Et juste pour couvrir toutes les bases, si vous ne parliez vraiment que de la taille de fichier de l'image et non des dimensions réelles de l'image, je vous suggère de regarder un encodage sans perte des données d'image. Ma suggestion pour cela serait de réenregistrer l'image sous forme de fichier .png (j'ai tendance à utiliser Paint comme transcodeur gratuit pour les images dans Windows. Charger l'image dans Paint, enregistrer sous le nouveau format)
Vous ne pouvez pas redimensionner une image sans perdre de la qualité, simplement parce que vous réduisez le nombre de pixels.
Ne réduisez pas la taille côté client, car les navigateurs ne font pas un bon travail de redimensionnement des images.
Ce que vous pouvez faire est de modifier la taille par programme avant de le rendre ou au fur et à mesure qu'un utilisateur la télécharge.
Voici un article qui explique une façon de faire cela en c #: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx
Voyez si vous aimez la qualité de redimensionnement d'image de ce module ASP.NET open source. Il y a une démo en direct, vous pouvez donc jouer avec vous-même. Cela donne des résultats qui sont (pour moi) impossibles à distinguer de la sortie Photoshop. Il a également des tailles de fichier similaires - MS a fait du bon travail sur son encodeur JPEG.
Il y a quelque chose là-bas, le redimensionnement sensible au contexte, je ne sais pas si vous pourrez l'utiliser, mais cela vaut la peine d'être examiné, c'est sûr
Une belle démo vidéo (l'agrandissement apparaît vers le milieu) http://www.youtube.com/watch?v=vIFCV2spKtg
Ici, il pourrait y avoir du code. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/
Était-ce exagéré? Peut-être qu'il existe des filtres simples que vous pouvez appliquer à une image agrandie pour brouiller un peu les pixels, vous pouvez vous pencher là-dessus.
Redimensionnez-vous plus ou moins? Par un petit% ou par un facteur plus grand comme 2x, 3x? Qu'entendez-vous par qualité pour votre application? Et quel type d'images - des photographies, des dessins au trait dur ou quoi? Écrire votre propre code de broyage de pixels de bas niveau ou essayer de le faire autant que possible avec des bibliothèques existantes (.net ou autre)?
Il existe un vaste corpus de connaissances sur ce sujet. Le concept clé est l'interpolation.
Recommandations de navigation:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* pour C #: https: //secure.codeproject.com/KB/GDI-plus/imageprocessing4.aspx?display=PrintAll&fid=3657&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&select=629945
* ceci est spécifique à Java mais peut être éducatif - http: //today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
Ici vous pouvez trouver également ajouter des codes de filigrane dans cette classe:
public class ImageProcessor
{
public Bitmap Resize(Bitmap image, int newWidth, int newHeight, string message)
{
try
{
Bitmap newImage = new Bitmap(newWidth, Calculations(image.Width, image.Height, newWidth));
using (Graphics gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.AntiAlias;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(image, new Rectangle(0, 0, newImage.Width, newImage.Height));
var myBrush = new SolidBrush(Color.FromArgb(70, 205, 205, 205));
double diagonal = Math.Sqrt(newImage.Width * newImage.Width + newImage.Height * newImage.Height);
Rectangle containerBox = new Rectangle();
containerBox.X = (int)(diagonal / 10);
float messageLength = (float)(diagonal / message.Length * 1);
containerBox.Y = -(int)(messageLength / 1.6);
Font stringFont = new Font("verdana", messageLength);
StringFormat sf = new StringFormat();
float slope = (float)(Math.Atan2(newImage.Height, newImage.Width) * 180 / Math.PI);
gr.RotateTransform(slope);
gr.DrawString(message, stringFont, myBrush, containerBox, sf);
return newImage;
}
}
catch (Exception exc)
{
throw exc;
}
}
public int Calculations(decimal w1, decimal h1, int newWidth)
{
decimal height = 0;
decimal ratio = 0;
if (newWidth < w1)
{
ratio = w1 / newWidth;
height = h1 / ratio;
return height.To<int>();
}
if (w1 < newWidth)
{
ratio = newWidth / w1;
height = h1 * ratio;
return height.To<int>();
}
return height.To<int>();
}
}
Voici un fil de discussion du forum qui fournit un exemple de code de redimensionnement d'image C #. Vous pouvez utiliser l'un des classeurs de bibliothèque GD pour effectuer un rééchantillonnage en C #.