Comment recadrer une image en utilisant C #?

239

Comment puis-je écrire une application qui recadrera des images en C #?

sandy101
la source

Réponses:

228

Vous pouvez utiliser Graphics.DrawImagepour dessiner une image recadrée sur l'objet graphique à partir d'une image bitmap.

Rectangle cropRect = new Rectangle(...);
Bitmap src = Image.FromFile(fileName) as Bitmap;
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);
}
Daniel LeCheminant
la source
3
Juste une note, la signature de DrawImage () n'est pas valide. Il manque le paramètre GraphicsUnit .
Nathan Taylor
2
Le deuxième argument est également le rect cible, pas le rect cadré.
axk
8
La méthode est-elle DrawImageUnscaledAndClippedplus efficace qu'à des DrawImagefins de culture?
Ivan Kochurkin
270

Consultez 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);
}
pseudo
la source
56
D'accord, mais notez que si le cropArea traverse la frontière img, il donne une exception "Mémoire insuffisante".
ChrisJJ
1
@KvanTTT, les deux sont assez lents si vous souhaitez recadrer une grande image en plus petites.
JBeurer
1
@ChrisJJ pouvez-vous expliquer plus? ou donner une solution à ce problème?
raym0nd
1
@ raym0nd Je suppose que la solution de contournement consiste à s'assurer que les dimensions de votre rectangle ne sont pas plus grandes que celles de l'image
stuartdotnet
4
Leur site est en panne. Quelqu'un a obtenu le code sur le site?
sangam
55

Plus simple que la réponse acceptée est la suivante:

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

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

Notez que Bitmapet Graphicssont IDisposabledonc les usingclauses.

EDIT : Je trouve que c'est bien avec les PNG enregistrés par Bitmap.Saveou Paint.exe, mais échoue avec les PNG enregistrés par exemple par Paint Shop Pro 6 - le contenu est déplacé. L'addition de GraphicsUnit.Pixeldonne un mauvais résultat différent. Peut-être que ces fichiers PNG défaillants sont défectueux.

ChrisJJ
la source
5
Meilleure réponse ici, cela devrait être attribué la réponse. J'éprouvais également le «manque de mémoire» sur d'autres solutions. Cela a fonctionné la première fois.
c0d3p03t
Je ne comprends pas pourquoi l'ajout de GraphicsUnit.Pixel donne le mauvais résultat, mais c'est certainement le cas.
DOKKA
Mes images étaient rognées avec la bonne taille mais à un X / Y incorrect jusqu'à ce que j'appelle SetResolution sur l'image cible comme suggéré dans la réponse de @IntellyDev.
Brent Keller
7
Cette réponse fuit l'objet Grphics.
TaW
2
Bitmapet Graphicssont IDisposable- ajouter une usingclause
dave thieben
7

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

cela peut être nécessaire même si vous implémentez la meilleure réponse ici, surtout si votre image est vraiment géniale et que les résolutions ne sont pas exactement 96,0

Mon exemple de test:

    static Bitmap LoadImage()
    {
        return (Bitmap)Bitmap.FromFile( @"e:\Tests\d_bigImage.bmp" ); // here is large image 9222x9222 pixels and 95.96 dpi resolutions
    }

    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");
            }
        }
    }
IntellyDev
la source
5

C'est assez simple:

  • Créez un nouvel Bitmapobjet avec la taille recadrée.
  • Utilisez Graphics.FromImagepour créer un Graphicsobjet pour le nouveau bitmap.
  • Utilisez la DrawImageméthode pour dessiner l'image sur le bitmap avec une coordonnée X et Y négative.
Guffa
la source
5

Voici un exemple simple sur le recadrage d'une image

public Image Crop(string img, int width, int height, int x, int y)
{
    try
    {
        Image image = Image.FromFile(img);
        Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
        bmp.SetResolution(80, 60);

        Graphics gfx = Graphics.FromImage(bmp);
        gfx.SmoothingMode = SmoothingMode.AntiAlias;
        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
        gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
        gfx.DrawImage(image, new Rectangle(0, 0, width, height), x, y, width, height, GraphicsUnit.Pixel);
        // Dispose to free up resources
        image.Dispose();
        bmp.Dispose();
        gfx.Dispose();

        return bmp;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return null;
    }            
}
PsychoCoder
la source
5
Il est le seul à avoir mentionné la résolution, toutes les méthodes ci-dessus échoueront si l'image source a une résolution non standard.
net_prog
1
utiliser bmp.SetResolution (image .HorizontalResolution, image .VerticalResolution); pour résoudre le problème de résolution.
Morbia
2
À l'exception, cela entraînera des fuites d'objets image, bmp et gfx. Pourquoi ne pas les envelopper dans des déclarations?
Darius Kucinskas
3

Si vous utilisez AForge.NET :

using(var croppedBitmap = new Crop(new Rectangle(10, 10, 10, 10)).Apply(bitmap))
{
    // ...
}
Mateen Ulhaq
la source
2

Je cherchais une fonction facile et RAPIDE sans bibliothèque supplémentaire pour faire le travail. J'ai essayé la solution Nicks , mais j'avais besoin de 29,4 secondes pour "extraire" 1195 images d'un fichier atlas. Alors plus tard, j'ai réussi de cette façon et j'ai eu besoin de 2,43 secondes pour faire le même travail. Ce sera peut-être utile.

// content of the Texture class
public class Texture
{
    //name of the texture
    public string name { get; set; }
    //x position of the texture in the atlas image
    public int x { get; set; }
    //y position of the texture in the atlas image
    public int y { get; set; }
    //width of the texture in the atlas image
    public int width { get; set; }
    //height of the texture in the atlas image
    public int height { get; set; }
}

Bitmap atlasImage = new Bitmap(@"C:\somepicture.png");
PixelFormat pixelFormat = atlasImage.PixelFormat;

foreach (Texture t in textureList)
{
     try
     {
           CroppedImage = new Bitmap(t.width, t.height, pixelFormat);
           // copy pixels over to avoid antialiasing or any other side effects of drawing
           // the subimages to the output image using Graphics
           for (int x = 0; x < t.width; x++)
               for (int y = 0; y < t.height; y++)
                   CroppedImage.SetPixel(x, y, atlasImage.GetPixel(t.x + x, t.y + y));
           CroppedImage.Save(Path.Combine(workingFolder, t.name + ".png"), ImageFormat.Png);
     }
     catch (Exception ex)
     {
          // handle the exception
     }
}
GruMu
la source
1

Le recadrage d'une image est très simple en C #. Cependant, faire les choses comment allez-vous gérer le recadrage de votre image sera un peu plus difficile.

L'exemple ci-dessous montre comment recadrer une image en C #.

var filename = @"c:\personal\images\horizon.png";
var img = Image.FromFile(filename);
var rect = new Rectangle(new Point(0, 0), img.Size);
var cloned = new Bitmap(img).Clone(rect, img.PixelFormat);
var bitmap = new Bitmap(cloned, new Size(50, 50));
cloned.Dispose();
Mike
la source
1

Il existe un wrapper C # pour ce qui est open source, hébergé sur Codeplex appelé Web Image Cropping

Enregistrer le contrôle

<%@ Register Assembly="CS.Web.UI.CropImage" Namespace="CS.Web.UI" TagPrefix="cs" %>

Redimensionnement

<asp:Image ID="Image1" runat="server" ImageUrl="images/328.jpg" />
<cs:CropImage ID="wci1" runat="server" Image="Image1" 
     X="10" Y="10" X2="50" Y2="50" />

Recadrage dans le code derrière - Appelez la méthode Crop lorsque le bouton est cliqué par exemple;

wci1.Crop(Server.MapPath("images/sample1.jpg"));

Cem
la source
0

Seul cet exemple fonctionne sans problème:

var crop = new Rectangle(0, y, bitmap.Width, h);
var bmp = new Bitmap(bitmap.Width, h);
var tempfile = Application.StartupPath+"\\"+"TEMP"+"\\"+Path.GetRandomFileName();


using (var gr = Graphics.FromImage(bmp))
{
    try
    {
        var dest = new Rectangle(0, 0, bitmap.Width, h);
        gr.DrawImage(image,dest , crop, GraphicsUnit.Point);
        bmp.Save(tempfile,ImageFormat.Jpeg);
        bmp.Dispose();
    }
    catch (Exception)
    {


    }

}
user2757577
la source
0

C’est une autre façon. Dans mon cas, j'ai:

  • 2 contrôles numériques de mise à jour (appelés LeftMargin et TopMargin)
  • 1 Boîte à images (pictureBox1)
  • 1 bouton que j'ai appelé générer
  • 1 image sur C: \ imagenes \ myImage.gif

À l'intérieur du bouton, j'ai ce code:

Image myImage = Image.FromFile(@"C:\imagenes\myImage.gif");
Bitmap croppedBitmap = new Bitmap(myImage);
croppedBitmap = croppedBitmap.Clone(
            new Rectangle(
                (int)LeftMargin.Value, (int)TopMargin.Value,
                myImage.Width - (int)LeftMargin.Value,
                myImage.Height - (int)TopMargin.Value),
            System.Drawing.Imaging.PixelFormat.DontCare);
pictureBox1.Image = croppedBitmap;

Je l'ai essayé dans Visual studio 2012 en utilisant C #. J'ai trouvé cette solution sur cette page

user1981081
la source
0

ici ça marche démo sur github

https://github.com/SystematixIndore/Crop-SaveImageInCSharp

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
 <link href="css/jquery.Jcrop.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.Jcrop.js"></script>
</head>
<body>
  <form id="form2" runat="server">
  <div>
    <asp:Panel ID="pnlUpload" runat="server">
      <asp:FileUpload ID="Upload" runat="server" />
      <br />
      <asp:Button ID="btnUpload" runat="server" OnClick="btnUpload_Click" Text="Upload" />
      <asp:Label ID="lblError" runat="server" Visible="false" />
    </asp:Panel>
    <asp:Panel ID="pnlCrop" runat="server" Visible="false">
      <asp:Image ID="imgCrop" runat="server" />
      <br />
      <asp:HiddenField ID="X" runat="server" />
      <asp:HiddenField ID="Y" runat="server" />
      <asp:HiddenField ID="W" runat="server" />
      <asp:HiddenField ID="H" runat="server" />
      <asp:Button ID="btnCrop" runat="server" Text="Crop" OnClick="btnCrop_Click" />
    </asp:Panel>
    <asp:Panel ID="pnlCropped" runat="server" Visible="false">
      <asp:Image ID="imgCropped" runat="server" />
    </asp:Panel>
  </div>
  </form>
    <script type="text/javascript">
  jQuery(document).ready(function() {
    jQuery('#imgCrop').Jcrop({
      onSelect: storeCoords
    });
  });

  function storeCoords(c) {
    jQuery('#X').val(c.x);
    jQuery('#Y').val(c.y);
    jQuery('#W').val(c.w);
    jQuery('#H').val(c.h);
  };

</script>
</body>
</html>

Logique de code C # pour le téléchargement et le recadrage.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using SD = System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace WebApplication1
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        String path = HttpContext.Current.Request.PhysicalApplicationPath + "images\\";
        protected void Page_Load(object sender, EventArgs e)
        {

        }
        protected void btnUpload_Click(object sender, EventArgs e)
        {
            Boolean FileOK = false;
            Boolean FileSaved = false;

            if (Upload.HasFile)
            {
                Session["WorkingImage"] = Upload.FileName;
                String FileExtension = Path.GetExtension(Session["WorkingImage"].ToString()).ToLower();
                String[] allowedExtensions = { ".png", ".jpeg", ".jpg", ".gif" };
                for (int i = 0; i < allowedExtensions.Length; i++)
                {
                    if (FileExtension == allowedExtensions[i])
                    {
                        FileOK = true;
                    }
                }
            }

            if (FileOK)
            {
                try
                {
                    Upload.PostedFile.SaveAs(path + Session["WorkingImage"]);
                    FileSaved = true;
                }
                catch (Exception ex)
                {
                    lblError.Text = "File could not be uploaded." + ex.Message.ToString();
                    lblError.Visible = true;
                    FileSaved = false;
                }
            }
            else
            {
                lblError.Text = "Cannot accept files of this type.";
                lblError.Visible = true;
            }

            if (FileSaved)
            {
                pnlUpload.Visible = false;
                pnlCrop.Visible = true;
                imgCrop.ImageUrl = "images/" + Session["WorkingImage"].ToString();
            }
        }

        protected void btnCrop_Click(object sender, EventArgs e)
        {
            string ImageName = Session["WorkingImage"].ToString();
            int w = Convert.ToInt32(W.Value);
            int h = Convert.ToInt32(H.Value);
            int x = Convert.ToInt32(X.Value);
            int y = Convert.ToInt32(Y.Value);

            byte[] CropImage = Crop(path + ImageName, w, h, x, y);
            using (MemoryStream ms = new MemoryStream(CropImage, 0, CropImage.Length))
            {
                ms.Write(CropImage, 0, CropImage.Length);
                using (SD.Image CroppedImage = SD.Image.FromStream(ms, true))
                {
                    string SaveTo = path + "crop" + ImageName;
                    CroppedImage.Save(SaveTo, CroppedImage.RawFormat);
                    pnlCrop.Visible = false;
                    pnlCropped.Visible = true;
                    imgCropped.ImageUrl = "images/crop" + ImageName;
                }
            }
        }

        static byte[] Crop(string Img, int Width, int Height, int X, int Y)
        {
            try
            {
                using (SD.Image OriginalImage = SD.Image.FromFile(Img))
                {
                    using (SD.Bitmap bmp = new SD.Bitmap(Width, Height))
                    {
                        bmp.SetResolution(OriginalImage.HorizontalResolution, OriginalImage.VerticalResolution);
                        using (SD.Graphics Graphic = SD.Graphics.FromImage(bmp))
                        {
                            Graphic.SmoothingMode = SmoothingMode.AntiAlias;
                            Graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
                            Graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
                            Graphic.DrawImage(OriginalImage, new SD.Rectangle(0, 0, Width, Height), X, Y, Width, Height, SD.GraphicsUnit.Pixel);
                            MemoryStream ms = new MemoryStream();
                            bmp.Save(ms, OriginalImage.RawFormat);
                            return ms.GetBuffer();
                        }
                    }
                }
            }
            catch (Exception Ex)
            {
                throw (Ex);
            }
        }
    }
}
Dev-Systematix
la source