¿Cómo recortar una imagen usando C #?

Respuestas:

228

Puede usar Graphics.DrawImagepara dibujar una imagen recortada en el objeto gráfico desde un mapa de bits.

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
fuente
3
Solo una nota, la firma de DrawImage () no es válida. Le falta el parámetro GraphicsUnit .
Nathan Taylor el
2
También el segundo argumento es el rect de destino, no el rect de cultivo.
axk
8
¿Es el método DrawImageUnscaledAndClippedmás eficiente que DrawImagepara fines de cultivo?
Ivan Kochurkin
270

Echa un vistazo a este enlace: 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);
}
Mella
fuente
56
De acuerdo, pero tenga en cuenta que si cropArea cruza el límite de img, da una excepción de "Memoria insuficiente".
ChrisJJ
1
@KvanTTT, ambos son bastante lentos si desea recortar una imagen grande en otras más pequeñas.
JBeurer
1
@ChrisJJ ¿puedes explicar más? o dar una solución para ese problema?
raym0nd
1
@ raym0nd Supongo que la solución es garantizar que las dimensiones de su rectángulo no sean más grandes que las de la imagen
stuartdotnet
44
Su sitio está caído. ¿Alguien obtuvo el código del sitio?
sangam
55

Más simple que la respuesta aceptada es esta:

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;
    }
}

y evita el riesgo de excepción "Sin memoria " de la respuesta más simple.

Tenga en cuenta que Bitmapy por lo tanto Graphicsson IDisposablelas usingcláusulas.

EDITAR : Creo que esto está bien con PNG guardados por Bitmap.Saveo Paint.exe, pero falla con PNG guardados por ejemplo, Paint Shop Pro 6 : el contenido se desplaza. La adición de GraphicsUnit.Pixelda un resultado incorrecto diferente. Quizás solo estos PNG defectuosos son defectuosos.

ChrisJJ
fuente
55
La mejor respuesta aquí, esta debería recibir la respuesta. Estaba experimentando la falta de memoria también en otras soluciones. Esto funcionó por primera vez.
c0d3p03t
No entiendo por qué agregar GraphicsUnit.Pixel da el resultado incorrecto, pero definitivamente lo hace.
DOKKA
Mis imágenes estaban recortando con el tamaño correcto pero a X / Y incorrectas hasta que llamé a SetResolution en la imagen de destino como se sugiere en la respuesta de @IntellyDev.
Brent Keller
77
Esta respuesta filtra el objeto Grphics.
TaW
2
Bitmapy Graphicsson IDisposable- agregue una usingcláusula
dave thieben
7

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

Esto puede ser necesario incluso si implementa la mejor respuesta aquí, especialmente si su imagen es realmente excelente y las resoluciones no son exactamente 96.0

Mi ejemplo de prueba:

    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
fuente
5

Es bastante fácil:

  • Crear un nuevo Bitmap objeto con el tamaño recortado.
  • Use Graphics.FromImagepara crear unGraphics objeto para el nuevo mapa de bits.
  • Utilice el DrawImagemétodo para dibujar la imagen en el mapa de bits con una coordenada X e Y negativa.
Guffa
fuente
5

Aquí hay un ejemplo simple sobre cómo recortar una imagen

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
fuente
55
Él es el único que mencionó la resolución, todos los métodos anteriores fallarán si la imagen de origen tiene una resolución no estándar.
net_prog
1
use bmp.SetResolution (imagen .Resolución horizontal, imagen .Resolución vertical); para solucionar el problema de resolución.
Morbia
2
A excepción de esto, se filtrarán objetos de imagen, bmp y gfx. ¿Por qué no envolverlos en el uso de declaraciones?
Darius Kucinskas
3

Si está utilizando AForge.NET :

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

Estaba buscando una función fácil y RÁPIDA sin una biblioteca adicional para hacer el trabajo. Intenté la solución Nicks , pero necesité 29,4 segundos para "extraer" 1195 imágenes de un archivo atlas. Así que más tarde me las arreglé de esta manera y necesité 2,43 segundos para hacer el mismo trabajo. Quizás esto sea útil.

// 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
fuente
1

Recortar una imagen es muy fácil en C #. Sin embargo, hacer las cosas como vas a manejar el recorte de tu imagen será un poco más difícil.

El siguiente ejemplo es la forma de recortar una imagen 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();
Miguel
fuente
1

Hay un contenedor de C # para el código abierto, alojado en Codeplex llamado Recorte de imágenes web

Registrar el control

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

Redimensionando

<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" />

Recorte en el código detrás : llame al método de recorte cuando se hace clic en un botón, por ejemplo;

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

Cem
fuente
0

Suponiendo que quiere decir que desea tomar un archivo de imagen (JPEG, BMP, TIFF, etc.) y recortarlo y luego guardarlo como un archivo de imagen más pequeño, sugiero usar una herramienta de terceros que tenga una API .NET. Estos son algunos de los más populares que me gustan:

LeadTools
Accusoft Pegasus Snowbound Imaging SDK

JohnFx
fuente
0

Solo esta muestra funciona sin problema:

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)
    {


    }

}
usuario2757577
fuente
0

Esta es otra forma. En mi caso tengo:

  • 2 controles numéricos ascendentes (llamados LeftMargin y TopMargin)
  • 1 cuadro de imagen (pictureBox1)
  • 1 botón que llamé generar
  • 1 imagen en C: \ imagenes \ myImage.gif

Dentro del botón tengo este código:

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;

Lo probé en Visual Studio 2012 usando C #. Encontré esta solución desde esta página

user1981081
fuente
0

aquí está trabajando demo en 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>

Lógica de código C # para cargar y recortar.

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
fuente