Bagaimana cara memotong gambar menggunakan C #?

239

Bagaimana saya bisa menulis aplikasi yang akan memotong gambar dalam C #?

sandy101
sumber

Jawaban:

228

Anda dapat menggunakan Graphics.DrawImageuntuk menggambar gambar yang dipotong ke objek grafik dari 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
sumber
3
Hanya sebuah catatan, tanda tangan DrawImage () tidak valid. Tidak ada parameter GraphicsUnit .
Nathan Taylor
2
Argumen kedua adalah target rect, bukan crop rect.
axk
8
Apakah metode DrawImageUnscaledAndClippedlebih efisien daripada DrawImageuntuk tujuan penanaman?
Ivan Kochurkin
270

Lihat tautan ini: 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
sumber
56
Setuju, tetapi perhatikan bahwa jika cropArea melintasi batas img, itu memberikan pengecualian "Kehabisan memori".
ChrisJJ
1
@VanTTT, keduanya cukup lambat jika Anda ingin memotong gambar besar menjadi yang lebih kecil.
JBeurer
1
@ ChrisJJ dapatkah Anda menjelaskan lebih lanjut? atau memberikan solusi untuk masalah itu?
raym0nd
1
@ raym0nd Saya kira solusinya adalah untuk memastikan dimensi persegi panjang Anda tidak lebih besar dari gambar
stuartdotnet
4
Situs mereka sedang down. Adakah yang mendapat kode dari situs?
sangam
55

Lebih sederhana daripada jawaban yang diterima adalah ini:

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

dan itu menghindari " Kehabisan memori risiko " dari jawaban paling sederhana.

Perhatikan bahwa Bitmapdan Graphicsadalah IDisposablekarenanyausing klausa.

EDIT : Saya menemukan ini baik-baik saja dengan PNG disimpan oleh Bitmap.Saveatau Paint.exe, tetapi gagal dengan PNG disimpan oleh misalnya Paint Shop Pro 6 - konten dipindahkan. Penambahan GraphicsUnit.Pixelmemberi hasil salah yang berbeda. Mungkin PNG yang gagal ini salah.

ChrisJJ
sumber
5
Jawaban terbaik di sini, ini harus diberikan jawabannya. Saya mengalami 'kehabisan memori' juga pada solusi lain. Ini bekerja pertama kali.
c0d3p03t
Saya tidak mengerti mengapa menambahkan GraphicsUnit.Pixel memberikan hasil yang salah, tetapi jelas tidak.
DOKKA
Gambar saya dipotong dengan ukuran yang benar tetapi pada X / Y yang salah sampai saya memanggil SetResolution pada gambar target seperti yang disarankan dalam jawaban oleh @IntellyDev.
Brent Keller
7
Jawaban ini bocor objek Grphics.
TaW
2
Bitmapdan Graphicsyang IDisposable- menambahkan usingklausul
dave thieben
7

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

ini mungkin perlu dilakukan bahkan jika Anda menerapkan jawaban terbaik di sini terutama jika gambar Anda benar-benar hebat dan resolusi tidak tepat 96.0

Contoh pengujian saya:

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

Cukup mudah:

  • Buat yang baru Bitmap objek dengan ukuran yang dipotong.
  • Gunakan Graphics.FromImageuntuk membuatGraphics objek untuk bitmap baru.
  • Gunakan DrawImagemetode untuk menggambar gambar ke bitmap dengan koordinat X dan Y negatif.
Guffa
sumber
5

Berikut adalah contoh sederhana tentang memotong gambar

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
sumber
5
Dia adalah satu-satunya yang menyebutkan resolusi, semua metode di atas akan gagal jika gambar sumber memiliki resolusi non-standar.
net_prog
1
gunakan bmp.SetResolution (image .HorizontalResolution, image .VerticalResolution); untuk memperbaiki masalah resolusi.
Morbia
2
Terkecuali ini akan membocorkan objek gambar, bmp dan gfx. Mengapa tidak membungkusnya dengan pernyataan?
Darius Kucinskas
3

Jika Anda menggunakan AForge.NET :

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

Saya mencari fungsi yang mudah dan CEPAT tanpa perpustakaan tambahan untuk melakukan pekerjaan itu. Saya mencoba solusi Nicks , tetapi saya membutuhkan 29,4 detik untuk "mengekstrak" 1195 gambar file atlas. Jadi kemudian saya berhasil dengan cara ini dan membutuhkan 2,43 detik untuk melakukan pekerjaan yang sama. Mungkin ini akan sangat membantu.

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

Memotong gambar sangat mudah di C #. Namun, melakukan hal-hal bagaimana Anda mengelola pemotongan gambar Anda akan sedikit lebih sulit.

Contoh di bawah ini adalah cara memotong gambar di 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
sumber
1

Ada pembungkus C # untuk apa yang merupakan open source, di-host di Codeplex yang disebut Web Image Cropping

Daftarkan kontrol

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

Mengubah ukuran

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

Pangkas kode di belakang - Metode Pangkas panggilan saat tombol diklik misalnya;

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

Cem
sumber
0

Dengan asumsi Anda bermaksud mengambil file gambar (JPEG, BMP, TIFF, dll) dan memotongnya kemudian menyimpannya sebagai file gambar yang lebih kecil, saya sarankan menggunakan alat pihak ketiga yang memiliki .NET API. Berikut adalah beberapa yang populer yang saya sukai:

LeadTools
Accusoft Pegasus Snowbound Imaging SDK

JohnFx
sumber
0

Hanya sampel ini yang berfungsi tanpa masalah:

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


    }

}
pengguna2757577
sumber
0

Ini cara lain. Dalam kasus saya, saya memiliki:

  • 2 kontrol pembaruan numerik (disebut LeftMargin dan TopMargin)
  • 1 kotak gambar (pictureBox1)
  • 1 tombol yang saya panggil menghasilkan
  • 1 gambar di C: \ imagenes \ myImage.gif

Di dalam tombol saya memiliki kode ini:

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;

Saya mencobanya di Visual studio 2012 menggunakan C #. Saya menemukan solusi ini dari halaman ini

pengguna1981081
sumber
0

ini dia demo bekerja di 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>

Logika kode C # untuk mengunggah dan memotong.

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
sumber