342 votes

Comment redimensionner une image en C#

Como Size , Width y Height sont Get() les propriétés de System.Drawing.Image ;
Comment puis-je redimensionner un objet Image au moment de l'exécution en C# ?

Pour l'instant, je crée juste un nouveau Image en utilisant :

// objImage is the original Image
Bitmap objBitmap = new Bitmap(objImage, new Size(227, 171));

0 votes

Vérifiez este dehors.

0 votes

C'est ce qu'il faut faire... Le constructeur surchargé de Bitmap accepte également deux paramètres pour la largeur et la hauteur.

0 votes

Vous pouvez également consulter cette question sur stackoverflow : < stackoverflow.com/questions/87753/ >

590voto

Mark Points 49079

Cela permettra d'effectuer un redimensionnement de haute qualité :

/// <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 Bitmap ResizeImage(Image image, int width, int height)
{
    var destRect = new Rectangle(0, 0, width, height);
    var destImage = new Bitmap(width, height);

    destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

    using (var graphics = Graphics.FromImage(destImage))
    {
        graphics.CompositingMode = CompositingMode.SourceCopy;
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = SmoothingMode.HighQuality;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

        using (var wrapMode = new ImageAttributes())
        {
            wrapMode.SetWrapMode(WrapMode.TileFlipXY);
            graphics.DrawImage(image, destRect, 0, 0, image.Width,image.Height, GraphicsUnit.Pixel, wrapMode);
        }
    }

    return destImage;
}
  • wrapMode.SetWrapMode(WrapMode.TileFlipXY) empêche les images fantômes autour des frontières de l'image -- un redimensionnement naïf échantillonnera les pixels transparents au-delà des frontières de l'image, mais en reflétant l'image nous pouvons obtenir un meilleur échantillon (ce paramètre est très visible)
  • destImage.SetResolution maintient le DPI indépendamment de la taille physique -- peut augmenter la qualité lors de la réduction des dimensions de l'image ou lors de l'impression
  • La composition contrôle la façon dont les pixels sont mélangés à l'arrière-plan. Elle n'est peut-être pas nécessaire puisque nous ne dessinons qu'une seule chose.
    • graphics.CompositingMode détermine si les pixels d'une image source remplacent ou sont combinés avec les pixels de l'arrière-plan. SourceCopy spécifie que lorsqu'une couleur est rendue, elle écrase la couleur d'arrière-plan.
    • graphics.CompositingQuality détermine le niveau de qualité du rendu des images en couches.
  • graphics.InterpolationMode détermine le mode de calcul des valeurs intermédiaires entre deux points d'extrémité
  • graphics.SmoothingMode spécifie si les lignes, les courbes et les bords des zones remplies utilisent le lissage (également appelé anti-crénelage) -- ne fonctionne probablement que sur les vecteurs.
  • graphics.PixelOffsetMode affecte la qualité du rendu lors du dessin de la nouvelle image

Le maintien du ratio d'aspect est laissé comme un exercice pour le lecteur (en fait, je ne pense pas que ce soit le rôle de cette fonction de le faire pour vous).

Aussi, c'est un bon article décrivant certains des pièges du redimensionnement des images. La fonction ci-dessus couvre la plupart d'entre eux, mais vous devez toujours vous préoccuper de ce qui suit sauver .

4 votes

Le code a fonctionné parfaitement lors du redimensionnement de l'image mais a augmenté la taille de 66KB à 132 KB. Comment puis-je la réduire ?

3 votes

@chamara C'est probablement dû à la qualité de sauvegarde que vous avez choisie. Voir msdn.microsoft.com/fr/us/library/bb882583(v=vs.110).aspx Essayez la qualité = 90

0 votes

@mpen pouvez-vous regarder stackoverflow.com/questions/33865130/

164voto

Matt Points 559

Je ne vois pas ce qui est si difficile, faites ce que vous faisiez, utilisez le constructeur Bitmap surchargé pour créer une image redimensionnée, la seule chose qui vous manquait était un transfert vers le type de données Image :

public static Image resizeImage(Image imgToResize, Size size)
{
    return (Image)(new Bitmap(imgToResize, size));
}

yourImage = resizeImage(yourImage, new Size(50,50));

3 votes

Ne devriez-vous pas vous débarrasser yourImage avant de l'attribuer à la nouvelle image ?

4 votes

Vous pouvez l'éliminer manuellement ou laisser le ramasseur de déchets faire son travail. Peu importe.

32 votes

Ce code ne donne aucun contrôle sur la qualité du redimensionnement, ce qui est très important. Jetez un coup d'œil à la réponse de Mark.

48voto

Vinzz Points 1850

Sur cette question vous aurez des réponses, y compris les miennes :

public Image resizeImage(int newWidth, int newHeight, string stPhotoPath)
 {
     Image imgPhoto = Image.FromFile(stPhotoPath); 

     int sourceWidth = imgPhoto.Width;
     int sourceHeight = imgPhoto.Height;

     //Consider vertical pics
    if (sourceWidth < sourceHeight)
    {
        int buff = newWidth;

        newWidth = newHeight;
        newHeight = buff;
    }

    int sourceX = 0, sourceY = 0, destX = 0, destY = 0;
    float nPercent = 0, nPercentW = 0, nPercentH = 0;

    nPercentW = ((float)newWidth / (float)sourceWidth);
    nPercentH = ((float)newHeight / (float)sourceHeight);
    if (nPercentH < nPercentW)
    {
        nPercent = nPercentH;
        destX = System.Convert.ToInt16((newWidth -
                  (sourceWidth * nPercent)) / 2);
    }
    else
    {
        nPercent = nPercentW;
        destY = System.Convert.ToInt16((newHeight -
                  (sourceHeight * nPercent)) / 2);
    }

    int destWidth = (int)(sourceWidth * nPercent);
    int destHeight = (int)(sourceHeight * nPercent);

    Bitmap bmPhoto = new Bitmap(newWidth, newHeight,
                  PixelFormat.Format24bppRgb);

    bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                 imgPhoto.VerticalResolution);

    Graphics grPhoto = Graphics.FromImage(bmPhoto);
    grPhoto.Clear(Color.Black);
    grPhoto.InterpolationMode =
        System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

    grPhoto.DrawImage(imgPhoto,
        new Rectangle(destX, destY, destWidth, destHeight),
        new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
        GraphicsUnit.Pixel);

    grPhoto.Dispose();
    imgPhoto.Dispose();
    return bmPhoto;
}

5 votes

Vous avez oublié imgPhoto.Dispose() ; le fichier est gardé en utilisation.

1 votes

C'est très utile, et je l'utilise dans mon application. Cependant, il est important de noter que cet algorithme ne fonctionne pas avec les images transparentes. Il transforme tous les pixels transparents en noir. C'est probablement facile à corriger, mais c'est juste une note pour les utilisateurs :)

1 votes

N'êtes-vous pas censé enregistrer l'image ? imgPhoto.Save() ?

28voto

Lino Silva Points 146

Pourquoi ne pas utiliser le System.Drawing.Image.GetThumbnailImage méthode ?

public Image GetThumbnailImage(
    int thumbWidth, 
    int thumbHeight, 
    Image.GetThumbnailImageAbort callback, 
    IntPtr callbackData)

Ejemplo:

Image originalImage = System.Drawing.Image.FromStream(inputStream, true, true);
Image resizedImage = originalImage.GetThumbnailImage(newWidth, (newWidth * originalImage.Height) / originalWidth, null, IntPtr.Zero);
resizedImage.Save(imagePath, ImageFormat.Png);

Source : http://msdn.microsoft.com/en-us/library/system.drawing.image.getthumbnailimage.aspx

7 votes

Ce n'est pas la bonne façon de redimensionner une image. Cela tire une vignette du jpg si elle existe. Si elle n'existe pas, vous n'avez aucun contrôle sur la qualité ou la nouvelle image. De plus, ce code, tel quel, présente des fuites de mémoire.

1 votes

@Bobrot Pourquoi cela provoquera-t-il des fuites de mémoire ?

2 votes

Tout ce qui est dans la bibliothèque GDI fonctionne toujours sans être géré. Si l'on n'utilise pas de déclaration d'utilisation ou si l'on ne dispose pas des objets par la suite, le système peut prendre beaucoup de temps pour collecter ces objets et rendre la mémoire à nouveau disponible.

22voto

Lasse V. Karlsen Points 148037

Créer un nouveau Bitmap dans la nouvelle taille, obtenez un Graphiques de l'objet, définissez InterpolationMode et utiliser DrawImage pour peindre l'image originale dans la nouvelle image à la nouvelle taille.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X