【问题标题】:How to crop an image using C#?如何使用 C# 裁剪图像?
【发布时间】:2010-10-18 14:35:51
【问题描述】:

如何编写一个可以在 C# 中裁剪图像的应用程序?

【问题讨论】:

    标签: c# image-processing


    【解决方案1】:

    查看此链接: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);
    }
    

    【讨论】:

    • 同意,但请注意,如果cropArea 越过img 边界,则会出现“内存不足”异常。
    • @KvanTTT,如果您想将大图像裁剪成较小的图像,它们都非常慢。
    • @ChrisJJ 你能解释更多吗?或为该问题提供解决方法?
    • 他们的网站已关闭。有人从网站上得到代码吗?
    • 这是性能最差的解决方案。 Graphics.DrawImage 解决方案要好得多。
    【解决方案2】:

    您可以使用Graphics.DrawImage 从位图中将裁剪后的图像绘制到图形对象上。

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

    【讨论】:

    • 请注意,DrawImage() 的签名无效。 It's missing the GraphicsUnit parameter.
    • 第二个参数也是目标矩形,而不是裁剪矩形。
    • 方法DrawImageUnscaledAndClipped是否比DrawImage更有效?
    【解决方案3】:

    比公认的答案更简单的是:

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

    它避免了最简单答案的“内存不足”异常风险。

    请注意,BitmapGraphicsIDisposable,因此是 using 子句。

    编辑:我发现这对于Bitmap.Save 或 Paint.exe 保存的 PNG 来说很好,但对于通过例如保存的 PNG 则失败。 Paint Shop Pro 6 - 内容被替换。添加GraphicsUnit.Pixel 会给出不同的错误结果。也许只是这些失败的 PNG 是错误的。

    【讨论】:

    • 最佳回复在这里,这应该被授予答案。我在其他解决方案上也遇到了“内存不足”。这是第一次工作。
    • 我不明白为什么添加 GraphicsUnit.Pixel 会给出错误的结果,但它确实如此。
    • 这个答案泄露了 Grphics 对象。
    • BitmapGraphicsIDisposable - 添加 using 子句
    【解决方案4】:

    使用bmp.SetResolution(image.HorizontalResolution, image .VerticalResolution);

    即使您在此处实施最佳答案,也可能需要这样做 尤其是如果您的图像真的很棒并且分辨率不完全是 96.0

    我的测试示例:

        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】:

      这是一个关于裁剪图像的简单示例

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

      【讨论】:

      • 他是唯一一个提到分辨率的,如果源图像的分辨率不标准,上述所有方法都会失败。
      • 使用 bmp.SetResolution(image .Horizo​​ntalResolution, image .VerticalResolution);解决分辨率问题。
      • 在异常情况下,这将泄漏图像、bmp 和 gfx 对象。为什么不将它们包装在 using 语句中?
      【解决方案6】:

      很简单:

      • 使用裁剪后的大小创建一个新的Bitmap 对象。
      • 使用Graphics.FromImage 为新位图创建Graphics 对象。
      • 使用DrawImage 方法将图像绘制到具有负X 和Y 坐标的位图上。

      【讨论】:

      • 最好添加一些示例代码以供参考。不是每个人都像你我一样是编码专家!
      【解决方案7】:

      如果您使用的是AForge.NET

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

      【讨论】:

        【解决方案8】:

        我一直在寻找一个简单而快速的功能,无需额外的库来完成这项工作。我试过Nicks solution,但我需要 29.4 秒来“提取”1195 张图集文件的图像。所以后来我以这种方式进行了管理,需要 2.43 秒来完成同样的工作。也许这会有所帮助。

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

        【讨论】:

          【解决方案9】:

          在 C# 中裁剪图像非常简单。但是,您将如何管理图像的裁剪会有点困难。

          下面的示例是如何在 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();
          

          【讨论】:

            【解决方案10】:

            有一个开源的 C# 包装器,托管在 Codeplex 上,名为 Web Image Cropping

            注册控件

            &lt;%@ Register Assembly="CS.Web.UI.CropImage" Namespace="CS.Web.UI" TagPrefix="cs" %&gt;

            调整大小

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

            在后面的代码中裁剪 - 例如,单击按钮时调用裁剪方法;

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

            【讨论】:

              【解决方案11】:

              假设您的意思是要获取图像文件(JPEG、BMP、TIFF 等)并对其进行裁剪,然后将其保存为较小的图像文件,我建议使用具有 .NET API 的第三方工具。以下是我喜欢的一些流行的:

              LeadTools
              Accusoft Pegasus Snowbound Imaging SDK

              【讨论】:

                【解决方案12】:

                只有这个样本没有问题:

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

                【讨论】:

                  【解决方案13】:

                  这是另一种方式。就我而言,我有:

                  • 2 个数字上下控件(称为 LeftMargin 和 TopMargin)
                  • 1个图片框(pictureBox1)
                  • 我称之为 generate 的 1 个按钮
                  • C:\imagenes\myImage.gif 上有 1 张图片

                  在按钮里面我有这个代码:

                  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;
                  

                  我在 Visual Studio 2012 中使用 C# 进行了尝试。我从这个page找到了这个解决方案

                  【讨论】:

                    【解决方案14】:

                    这里是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# 代码逻辑。

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

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2020-10-18
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多