272 votes

Comment puis-je recadrer une image en utilisant C#?

Comment puis-je recadrer une image en utilisant C#?

0 votes

Je viens de créer une classe personnalisée pour simplement recadrer tout contrôle qui a une image ou une image de fond. Je l'ai téléchargée sur github.com : github.com/DwainSnickles/ControlCrop/blob/master/README.md

303voto

Nick Points 2964

Découvrez ce lien : http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing

private static Image cropImage(Image img, Rectangle cropArea)
{
   Bitmap bmpImage = new Bitmap(img);
   return bmpImage.Clone(cropArea, bmpImage.PixelFormat);
}

58 votes

D'accord, mais notez que si la cropArea traverse la frontière de l'image, cela génère une exception "Mémoire insuffisante".

0 votes

Est-ce que cette méthode est plus rapide que la méthode de @DanielLeCheminant?

1 votes

@KvanTTT, les deux sont assez lents si vous voulez recadrer une grande image en plusieurs petites.

251voto

Daniel LeCheminant Points 28101

Vous pouvez utiliser [Graphics.DrawImage][1] pour dessiner une image recadrée sur l'objet graphics à partir d'un bitmap.

Rectangle cropRect = new Rectangle(...);
using (Bitmap src = Image.FromFile("") as Bitmap)
{
    using (Bitmap target = new Bitmap(cropRect.Width, cropRect.Height))
    {
        using (Graphics g = Graphics.FromImage(target))
        {
            g.DrawImage(src, new Rectangle(0, 0, target.Width, target.Height),
                cropRect,
                GraphicsUnit.Pixel);
        }
    }
}

4 votes

Juste une note, la signature de DrawImage() n'est pas valide. Il manque le paramètre GraphicsUnit.

2 votes

Aussi, le deuxième argument est le rectangle cible, et non le rectangle de découpe.

10 votes

Est-ce que la méthode DrawImageUnscaledAndClipped est plus efficace que DrawImage pour recadrer une image ?

79voto

ChrisJJ Points 710

Plus simple que la réponse acceptée est celle-ci :

public static Bitmap cropAtRect(this Bitmap b, Rectangle r)
{
    using (var nb = new Bitmap(r.Width, r.Height))
    {
        using (Graphics g = Graphics.FromImage(nb))
        {
            g.DrawImage(b, -r.X, -r.Y);
            return nb;
        }
    }
}

et cela évite le risque d'exception "Out of memory" de la réponse la plus simple.

Notez que Bitmap et Graphics sont IDisposable donc les clauses using.

MODIFICATION : Je trouve que cela fonctionne bien avec les PNG enregistrés par Bitmap.Save ou Paint.exe, mais échoue avec les PNG enregistrés par exemple avec Paint Shop Pro 6 - le contenu est déplacé. L'ajout de GraphicsUnit.Pixel donne un résultat incorrect différent. Peut-être que juste ces PNG défaillants sont défectueux.

8 votes

Meilleure réponse ici, cela devrait être récompensé comme réponse. J'avais également rencontré le problème de 'mémoire insuffisante' avec d'autres solutions. Cela a fonctionné du premier coup.

0 votes

Je ne comprends pas pourquoi l'ajout de GraphicsUnit.Pixel donne le mauvais résultat, mais c'est certainement le cas.

2 votes

Mes images étaient rognées avec la bonne taille mais à un mauvais X/Y jusqu'à ce que j'appelle SetResolution sur l'image cible comme suggéré dans la réponse de @IntellyDev.

10voto

IntellyDev Points 36

utilisez bmp.SetResolution(image.HorizontalResolution, image.VerticalResolution);

cela peut être nécessaire à faire même si vous implémentez la meilleure réponse ici surtout si votre image est vraiment grande et que les résolutions ne sont pas exactement de 96.0

Mon exemple de test:

    static Bitmap LoadImage()
    {
        return (Bitmap)Bitmap.FromFile( @"e:\Tests\d_bigImage.bmp" ); // ici une grande image de 9222x9222 pixels et une résolution de 95.96 dpi
    }

    static void TestBigImagePartDrawing()
    {
        using( var absentRectangleImage = LoadImage() )
        {
            using( var currentTile = new Bitmap( 256, 256 ) )
            {
                currentTile.SetResolution(absentRectangleImage.HorizontalResolution, absentRectangleImage.VerticalResolution);

                using( var currentTileGraphics = Graphics.FromImage( currentTile ) )
                {
                    currentTileGraphics.Clear( Color.Black );
                    var absentRectangleArea = new Rectangle( 3, 8963, 256, 256 );
                    currentTileGraphics.DrawImage( absentRectangleImage, 0, 0, absentRectangleArea, GraphicsUnit.Pixel );
                }

                currentTile.Save(@"e:\Tests\Tile.bmp");
            }
        }
    }

5voto

Guffa Points 308133

C'est assez facile :

  • Créez un nouvel objet Bitmap avec la taille rognée.
  • Utilisez Graphics.FromImage pour créer un objet Graphics pour le nouveau bitmap.
  • Utilisez la méthode DrawImage pour dessiner l'image sur le bitmap avec une coordonnée X et Y négatives.

0 votes

Il est toujours préférable d'ajouter un peu de code d'exemple pour se référer. Tout le monde n'est pas un expert en codage comme toi et moi!

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