2009-04-09 20 views

ответ

191

Вы можете использовать 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); 
} 
+2

Только примечание, подпись DrawImage() недействительна. [Отсутствует параметр GraphicsUnit] (http://msdn.microsoft.com/en-us/library/ms142040.aspx). –

+2

Также второй аргумент - это прямой, а не прямой. – axk

+6

Является ли метод 'DrawImageUnscaledAndClipped' более эффективным, чем' DrawImage' для целей обрезки? –

224

Проверить эту ссылку: 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); 
} 
+8

+1 Эта ссылка показывает самый простой способ обрезки, с которым я столкнулся. –

+47

Согласен, но обратите внимание, что если cropArea пересекает границу img, он дает исключение «Out of memory». – ChrisJJ

+0

Этот метод быстрее, чем метод @DanielLeCheminant? –

5

Это довольно просто:

  • Создать новый объект Bitmap с обрезанным размером.
  • Используйте Graphics.FromImage для создания объекта Graphics для нового растрового изображения.
  • Используйте метод DrawImage для рисования изображения на растровое изображение с отрицательной координатой X и Y.
-1

Предполагая, что вы хотите взять файл изображения (JPEG, BMP, TIFF и т. Д.) И обрезать его, а затем сохранить его как файл меньшего размера, я предлагаю использовать сторонний инструмент с именем. NET API. Вот некоторые из популярных те, которые мне нравятся:

LeadTools
Accusoft Pegasus Snowbound Imaging SDK

1

Вот простой пример на обрезке изображения

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

Он единственный, кто упомянул разрешение, все вышеперечисленные методы потерпят неудачу, если исходное изображение имеет нестандартное разрешение. –

+1

Использование bmp.SetResolution (изображение. Горизонтальное разрешение, изображение. Вертикальное восстановление); для устранения проблемы с разрешением. – Morbia

+1

В случае исключения это приведет к утечке изображений, bmp и gfx объектов. Почему бы не обернуть их при использовании утверждений? –

38

Simpler, чем принятый ответ таков:

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

и это av oids "Недостаточно памяти" исключение - риск простейшего ответа.

EDIT: Я считаю, что это хорошо с PNG файлов, сохраненных на Bitmap.Save или Paint.exe, но терпит неудачу с сохраненными в формате PNG, например, посредством Paint Shop Pro 6 - содержимое смещено. Добавление GraphicsUnit.Pixel дает другой неправильный результат. Возможно, эти неисправные PNG неисправны.

+4

Лучший ответ здесь, это должен быть награжден ответ. Я также переживал «из памяти» и других решений. Это сработало в первый раз. – c0d3p03t

+0

Я не понимаю, почему добавление GraphicsUnit.Pixel дает неверный результат, но это определенно делает. – DOKKA

+0

Мои изображения обрезались с правильным размером, но с неправильным X/Y, пока я не назвал SetResolution на целевом изображении, как это было предложено в ответе @IntellyDev. –

6

использование bmp.SetResolution (изображение.Хоризонтальное разрешение, изображение .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"); 
      } 
     } 
    } 
0

кадрирование в 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(); 
0

Существует С # обертка для того, что является открытым исходным кодом, размещенный на Codeplex называется Web Image Cropping

Регистрация контроль

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

Изменение размера

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

0

Только этот пример работает без проблем:

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

Это еще один способ. В моем случае у меня есть:

  • 2 числового программного управления Updown (так называемые LeftMargin и TopMargin)
  • 1 фото коробка
  • Кнопка
  • 1, что я назвал генерировать
  • 1 изображение на C (pictureBox1): \ IMAGENES \ myImage.gif

Внутри кнопки у меня есть этот код:

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

2

Если вы используете AForge.NET:

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

здесь работает демо на 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); 
      } 
     } 
    } 
} 
0

Я искал легкую и функциональную функцию FAST без дополнительной библиотеки, чтобы выполнить эту работу. Я попробовал 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 
    } 
}