Come ritagliare un'immagine usando C #?


Risposte:


228

È possibile utilizzare Graphics.DrawImageper disegnare un'immagine ritagliata sull'oggetto grafico da una 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);
}

3
Solo una nota, la firma di DrawImage () non è valida. Manca il parametro GraphicsUnit .
Nathan Taylor,

2
Anche il secondo argomento è il retto bersaglio, non il retto raccolto.
axk,

8
Il metodo è DrawImageUnscaledAndClippedpiù efficiente rispetto DrawImageallo scopo del ritaglio?
Ivan Kochurkin,

270

Dai un'occhiata a questo link: 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);
}

56
D'accordo, ma nota che se il cropArea attraversa il confine img, si ottiene un'eccezione "Memoria insufficiente".
ChrisJJ,

1
@KvanTTT, entrambi sono piuttosto lenti se vuoi ritagliare un'immagine grande in immagini più piccole.
JBeurer,

1
@ChrisJJ puoi spiegare di più? o dare una soluzione alternativa per quel problema?
raym0nd

1
@ raym0nd Immagino che la soluzione alternativa sia quella di garantire che le dimensioni del tuo rettangolo non siano più grandi di quelle dell'immagine
stuartdotnet,

4
Il loro sito è inattivo. Qualcuno ha ricevuto il codice dal sito?
sangam,

55

Più semplice della risposta accettata è questa:

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

ed evita il rischio di eccezione " Memoria insufficiente" della risposta più semplice.

Si noti che Bitmape Graphicssono IDisposablequindi le usingclausole.

EDIT : Trovo che Bitmap.Savevada bene con i PNG salvati da o Paint.exe, ma fallisca con i PNG salvati ad esempio da Paint Shop Pro 6 - il contenuto viene spostato. L'aggiunta di GraphicsUnit.Pixeldà un risultato errato diverso. Forse proprio questi PNG non funzionanti sono difettosi.


5
Migliore risposta qui, questo dovrebbe essere assegnato la risposta. Stavo sperimentando la "memoria insufficiente" anche su altre soluzioni. Questo ha funzionato per la prima volta.
c0d3p03t,

Non capisco perché l'aggiunta di GraphicsUnit.Pixel dia il risultato sbagliato, ma sicuramente lo fa.
DOKKA,

Le mie immagini venivano ritagliate con le dimensioni corrette ma con una X / Y errata fino a quando non ho chiamato SetResolution sull'immagine di destinazione, come suggerito nella risposta di @IntellyDev.
Brent Keller,

7
Questa risposta perde l'oggetto Grphics.
Ho visto

2
Bitmape Graphicssono IDisposable- aggiungi una usingclausola
dave thieben il

7

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

questo può essere necessario fare anche se qui si implementa la migliore risposta, specialmente se l'immagine è davvero eccezionale e le risoluzioni non sono esattamente 96.0

Il mio esempio di 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");
            }
        }
    }

5

È abbastanza facile:

  • Crea un nuovo Bitmapoggetto con le dimensioni ritagliate.
  • Utilizzare Graphics.FromImageper creare un Graphicsoggetto per la nuova bitmap.
  • Utilizzare il DrawImagemetodo per disegnare l'immagine sulla bitmap con una coordinata X e Y negativa.

5

Ecco un semplice esempio sul ritaglio di un'immagine

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

5
È l'unico che ha menzionato la risoluzione, tutti i metodi di cui sopra falliranno se l'immagine di origine ha una risoluzione non standard.
net_prog

1
usa bmp.SetResolution (image .HorizontalResolution, image .VerticalResolution); per risolvere il problema di risoluzione.
Morbia,

2
In via eccezionale, ciò perderà oggetti immagine, bmp e gfx. Perché non concludere quelli usando le dichiarazioni?
Darius Kucinskas,

3

Se stai usando AForge.NET :

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

2

Stavo cercando una funzione facile e VELOCE senza ulteriori libary per fare il lavoro. Ho provato la soluzione Nicks , ma ho impiegato 29,4 secondi per "estrarre" 1195 immagini di un file atlante. Quindi più tardi sono riuscito in questo modo e ho avuto bisogno di 2,43 secondi per fare lo stesso lavoro. Forse questo sarà 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
     }
}

1

Il ritaglio di un'immagine è molto semplice in C #. Tuttavia, fare le cose su come gestire il ritaglio della tua immagine sarà un po 'più difficile.

L'esempio seguente mostra come ritagliare un'immagine in 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();

1

Esiste un wrapper C # per ciò che è open source, ospitato su Codeplex chiamato Web Image Cropping

Registra il controllo

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

Ridimensionamento

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

Ritaglio del codice dietro : chiamare il metodo Ritaglia quando si fa clic sul pulsante, ad esempio;

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


0

Supponendo che tu voglia prendere un file di immagine (JPEG, BMP, TIFF, ecc.) E ritagliarlo, quindi salvarlo come un file di immagine più piccolo, ti suggerisco di utilizzare uno strumento di terze parti che ha un'API .NET. Ecco alcuni dei popolari che mi piacciono:

SDK di Imaging Snowbound di LeadTools
Accusoft Pegasus


0

Solo questo esempio funziona senza problemi:

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


    }

}

0

Questo è un altro modo. Nel mio caso ho:

  • 2 controlli numerici di aggiornamento (chiamati LeftMargin e TopMargin)
  • 1 Picture box (pictureBox1)
  • 1 pulsante che ho chiamato genera
  • 1 immagine su C: \ imagenes \ myImage.gif

All'interno del pulsante ho questo codice:

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;

L'ho provato in Visual Studio 2012 usando C #. Ho trovato questa soluzione da questa pagina


0

qui funziona demo su 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>

Logica del codice C # per upload e ritaglio.

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);
            }
        }
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.