Wie schneide ich ein Bild mit C # zu?

239

Wie kann ich eine Anwendung schreiben, die Bilder in C # zuschneidet?

sandig101
quelle

Antworten:

228

Sie können Graphics.DrawImageein zugeschnittenes Bild aus einer Bitmap auf das Grafikobjekt zeichnen.

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
quelle
3
Nur eine Anmerkung, die Signatur von DrawImage () ist ungültig. Es fehlt der GraphicsUnit-Parameter .
Nathan Taylor
2
Auch das zweite Argument ist das Ziel-Rect, nicht das Crop-Rect.
Axk
8
Ist die Methode DrawImageUnscaledAndClippedeffizienter als DrawImagezum Zuschneiden?
Ivan Kochurkin
270

Schauen Sie sich diesen Link an: 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);
}
Nick
quelle
56
Einverstanden, aber beachten Sie, dass wenn die CropArea die IMG-Grenze überschreitet, eine Ausnahme "Nicht genügend Speicher" angezeigt wird.
ChrisJJ
1
@KvanTTT, beide sind ziemlich langsam, wenn Sie ein großes Bild in kleinere zuschneiden möchten.
JBeurer
1
@ ChrisJJ kannst du mehr erklären? oder eine Problemumgehung für dieses Problem geben?
Raym0nd
1
@ raym0nd Ich vermute, die Problemumgehung besteht darin, sicherzustellen, dass die Abmessungen Ihres Rechtecks ​​nicht größer sind als die des Bildes
stuartdotnet
4
Ihre Seite ist ausgefallen. Hat jemand den Code von der Seite bekommen?
Sangam
55

Einfacher als die akzeptierte Antwort ist dies:

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

und es vermeidet das Ausnahmerisiko "Nicht genügend Speicher " für die einfachste Antwort.

Beachten Sie, dass Bitmapund Graphicssind IDisposabledamit die usingKlauseln.

BEARBEITEN : Ich finde, dass dies bei PNGs, die von Bitmap.Saveoder Paint.exe gespeichert wurden, in Ordnung ist, aber bei PNGs, die von z. B. Paint Shop Pro 6 gespeichert wurden, fehlschlägt - der Inhalt wird verschoben. Das Hinzufügen von GraphicsUnit.Pixelergibt ein anderes falsches Ergebnis. Vielleicht sind nur diese fehlerhaften PNGs fehlerhaft.

ChrisJJ
quelle
5
Beste Antwort hier, dies sollte die Antwort erhalten. Ich habe auch bei anderen Lösungen das "Nicht-Gedächtnis" erlebt. Das hat beim ersten Mal funktioniert.
c0d3p03t
Ich verstehe nicht, warum das Hinzufügen von GraphicsUnit.Pixel das falsche Ergebnis liefert, aber es tut es definitiv.
DOKKA
Meine Bilder wurden mit der richtigen Größe, aber mit falschem X / Y zugeschnitten, bis ich SetResolution für das Zielbild aufrief, wie in der Antwort von @IntellyDev vorgeschlagen.
Brent Keller
6
Diese Antwort leckt das Grphics-Objekt.
TaW
2
Bitmapund Graphicssind IDisposable- eine usingKlausel hinzufügen
Dave Thieben
7

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

Dies kann auch dann erforderlich sein, wenn Sie hier die beste Antwort implementieren, insbesondere wenn Ihr Bild wirklich gut ist und die Auflösungen nicht genau 96,0 betragen

Mein Testbeispiel:

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

Es ist sehr leicht:

  • Erstellen Sie ein neues BitmapObjekt mit der zugeschnittenen Größe.
  • Verwenden Sie Graphics.FromImagediese Option , um ein GraphicsObjekt für die neue Bitmap zu erstellen .
  • Verwenden Sie die DrawImageMethode, um das Bild mit einer negativen X- und Y-Koordinate auf die Bitmap zu zeichnen.
Guffa
quelle
5

Hier ist ein einfaches Beispiel zum Zuschneiden eines Bildes

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
quelle
5
Er ist der einzige, der die Auflösung erwähnt hat. Alle oben genannten Methoden schlagen fehl, wenn das Quellbild eine nicht standardmäßige Auflösung aufweist.
net_prog
1
benutze bmp.SetResolution (image .HorizontalResolution, image .VerticalResolution); um das Problem mit der Auflösung zu beheben.
Morbia
2
In Ausnahmefällen werden Image-, BMP- und GFX-Objekte verloren gehen. Warum nicht diese mit Anweisungen einschließen?
Darius Kucinskas
3

Wenn Sie AForge.NET verwenden :

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

Ich suchte nach einer einfachen und SCHNELLEN Funktion ohne zusätzliche Bibliothek, um die Arbeit zu erledigen. Ich habe die Nicks-Lösung ausprobiert , aber ich brauchte 29,4 Sekunden, um 1195 Bilder einer Atlas-Datei zu "extrahieren". Also schaffte ich es später auf diese Weise und brauchte 2,43 Sekunden, um den gleichen Job zu machen. Vielleicht ist das hilfreich.

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

Das Zuschneiden eines Bildes ist in C # sehr einfach. Es wird jedoch etwas schwieriger sein, die Dinge zu tun, wie Sie das Zuschneiden Ihres Bildes verwalten.

Im folgenden Beispiel sehen Sie, wie Sie ein Bild in C # zuschneiden.

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
quelle
1

Es gibt einen C # -Wrapper für Open Source, der auf Codeplex gehostet wird und Web Image Cropping heißt

Registrieren Sie die Steuerung

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

Größenänderung

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

Code dahinter zuschneiden - Ruft die Crop-Methode auf, wenn Sie beispielsweise auf die Schaltfläche klicken.

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

Cem
quelle
0

Angenommen, Sie möchten eine Bilddatei (JPEG, BMP, TIFF usw.) aufnehmen und zuschneiden und dann als kleinere Bilddatei speichern, empfehle ich die Verwendung eines Drittanbieter-Tools mit einer .NET-API. Hier sind einige der beliebtesten, die ich mag:

LeadTools
Accusoft Pegasus Snowbound Imaging SDK

JohnFx
quelle
0

Nur dieses Beispiel funktioniert ohne Probleme:

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
quelle
0

Dies ist ein anderer Weg. In meinem Fall habe ich:

  • 2 numerische Updown-Steuerelemente (LeftMargin und TopMargin genannt)
  • 1 Bildbox (pictureBox1)
  • 1 Taste, die ich generiert habe, generieren
  • 1 Bild auf C: \ imagenes \ myImage.gif

Innerhalb der Schaltfläche habe ich diesen 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;

Ich habe es in Visual Studio 2012 mit C # versucht. Ich habe diese Lösung auf dieser Seite gefunden

user1981081
quelle
0

Hier arbeitet es Demo auf 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>

C # -Code-Logik zum Hochladen und Zuschneiden.

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
quelle