Обрезать часть изображения [дубликат]

Вы можете сделать это с помощью vba, создав определенную пользователем функцию в модуле:

Public Function applyFunction(functionName As Range, argument As Range) As Variant
    applyFunction = Evaluate(functionName & "(" & argument.Address & ")")
End Function

Если вы положите SUM в A1 и 1, 2, 3 в B1, B2, B3 , =applyFunction(A1,B1:B3) вернет 6. Это эквивалентно вызову =SUM(B1:B3).

EDIT

Если вы действительно не хотите использовать VBA, вы можете создать имя (вставить name in excel 2003 Я думаю, Define Name в Excel 2010):

  • Определите новое имя (допустим, eval1)
  • в области относится к области, введите =EVALUATE(A1&"(B1:B3)"), где A1 содержит SUM и B1: B3 - это диапазон с номерами
  • в пустой ячейке, тип =eval1 и он должен возвращать результат

Но этот подход менее гибкий.

210
задан Neil Barnwell 9 April 2009 в 17:24
поделиться

14 ответов

Вы можете использовать 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);
}
198
ответ дан axk 18 August 2018 в 10:27
поделиться

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

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;
    }            
}
2
ответ дан Bill the Lizard 18 August 2018 в 10:27
поделиться
  • 1
    Он единственный, кто упомянул о разрешении, все вышеперечисленные методы потерпят неудачу, если исходное изображение имеет нестандартное разрешение. – net_prog 2 January 2012 в 22:46
  • 2
    используйте bmp.SetResolution (изображение. HorizontalResolution, изображение. Вертикальное восстановление); для устранения проблемы с разрешением. – Morbia 23 May 2012 в 18:40
  • 3
    В случае исключения это приведет к утечке изображений, bmp и gfx объектов. Почему бы не обернуть их при использовании утверждений? – Darius Kucinskas 20 November 2013 в 22:30

Существует оболочка C # для открытого источника, размещенная на Codeplex, называемая Обрезка веб-изображений

Зарегистрируйте элемент управления

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

1
ответ дан Cem 18 August 2018 в 10:27
поделиться

Проверьте эту ссылку: http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing [& lt; == Ссылка - DEAD ]

private static Image cropImage(Image img, Rectangle cropArea)
{
   Bitmap bmpImage = new Bitmap(img);
   return bmpImage.Clone(cropArea, bmpImage.PixelFormat);
}
233
ответ дан Cyberherbalist 18 August 2018 в 10:27
поделиться
  • 1
    Согласовано, но обратите внимание, что если растение crop пересекает границу img, оно дает «Недостаточно памяти». исключение. – ChrisJJ 29 October 2011 в 15:41
  • 2
    @KvanTTT, оба из них довольно медленны, если вы хотите обрезать большое изображение на более мелкие. – JBeurer 1 February 2013 в 09:20
  • 3
    @ChrisJJ вы можете объяснить больше? или дать обходной путь для этой проблемы? – raym0nd 21 August 2013 в 20:32
  • 4
    @ raym0nd Я предполагаю, что обходным путем является обеспечение того, чтобы размеры вашего прямоугольника не превышали размеры изображения – stuartdotnet 28 May 2014 в 07:31
  • 5
    Их сайт не работает. Кто-нибудь получил код с сайта? – sangam 3 September 2015 в 19:58

здесь работает демо на 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
ответ дан Dev-Systematix 18 August 2018 в 10:27
поделиться

Более простым, чем принятый ответ, является следующее:

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

и он избегает исключения « Недостаточно памяти ». Самый простой ответ.

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

40
ответ дан Failed Scientist 18 August 2018 в 10:27
поделиться
  • 1
    Лучший ответ здесь, это должен быть награжден ответ. Я также переживал «из памяти» и других решений. Это сработало в первый раз. – c0d3p03t 15 October 2014 в 22:27
  • 2
    Я не понимаю, почему добавление GraphicsUnit.Pixel дает неверный результат, но это определенно делает. – DOKKA 30 June 2016 в 15:41
  • 3
    Мои изображения обрезались с правильным размером, но с неправильным X / Y, пока я не вызвал SetResolution на целевом изображении, как это было предложено в ответе @IntellyDev. – Brent Keller 10 May 2017 в 12:59
  • 4
    Этот ответ утечки объекта Graphics. – TaW 17 May 2018 в 15:35

Я искал легкую и функциональную функцию FAST без дополнительной библиотеки, чтобы выполнять эту работу. Я попробовал решение Nicks , но мне понадобилось 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
     }
}
0
ответ дан GruMu 18 August 2018 в 10:27
поделиться

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

  • Создайте новый объект Bitmap с обрезанным размером.
  • Используйте Graphics.FromImage для создания объекта Graphics для нового bitmap.
  • Используйте метод DrawImage для рисования изображения на растровом изображении с отрицательной координатой X и Y.
5
ответ дан Guffa 18 August 2018 в 10:27
поделиться

использовать bmp.SetResolution (image.HorizontalResolution, изображение .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");
            }
        }
    }
6
ответ дан IntellyDev 18 August 2018 в 10:27
поделиться

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

LeadTools Accusoft Pegasus SDG для снеговых изображений

0
ответ дан JohnFx 18 August 2018 в 10:27
поделиться

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

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
ответ дан kleopatra 18 August 2018 в 10:27
поделиться

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

using(var croppedBitmap = new Crop(new Rectangle(10, 10, 10, 10)).Apply(bitmap))
{
    // ...
}
3
ответ дан Mateen Ulhaq 18 August 2018 в 10:27
поделиться

Это другой способ. В моем случае у меня есть:

  • 2 числовых элемента управления updown (называемых LeftMargin и TopMargin)
  • 1 Поле изображения (pictureBox1)
  • 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;

I попробовал его в Visual Studio 2012 с помощью C #. Я нашел это решение на этой странице

0
ответ дан sikander 18 August 2018 в 10:27
поделиться

Обрезка изображения на 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
ответ дан Will 18 August 2018 в 10:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: