C# 图形对象到图像文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1147156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 09:21:28  来源:igfitidea点击:

Graphics object to image file

c#asp.netsystem.drawing

提问by niaher

I would like to crop and resize my image. Here is my code:

我想裁剪和调整我的图像。这是我的代码:

Image image = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "Cropper/tests/castle.jpg");

// Crop and resize the image.
Rectangle destination = new Rectangle(0, 0, 200, 120);
Graphics graphic = Graphics.FromImage(image);
graphic.DrawImage(image, destination, int.Parse(X1.Value), int.Parse(Y1.Value), int.Parse(Width.Value), int.Parse(Height.Value), GraphicsUnit.Pixel);

Now I assume that my resulting cropped/resized image is stored in the graphicsobject. The question is - how do I save it to a file?

现在我假设我得到的裁剪/调整大小的图像存储在图形对象中。问题是 - 如何将其保存到文件中?

采纳答案by Fredrik M?rk

The Graphicsobject that you get from Graphics.FromImageis a drawing surface for the image. So you can simply save the image object when you are done.

Graphics您从中获得的对象Graphics.FromImage是图像的绘图表面。因此,您可以在完成后简单地保存图像对象。

string fileName = AppDomain.CurrentDomain.BaseDirectory + "Cropper/tests/castle.jpg");
using (Image image = Image.FromFile(fileName)
{
    using (Graphics graphic = Graphics.FromImage(image))
    {
        // Crop and resize the image.
        Rectangle destination = new Rectangle(0, 0, 200, 120);
        graphic.DrawImage(image, destination, int.Parse(X1.Value), int.Parse(Y1.Value), int.Parse(Width.Value), int.Parse(Height.Value), GraphicsUnit.Pixel);
    }
    image.Save(fileName);
}

Beware though that doing this repeatedly on a jpg image may not be a good thing; the image is re-encoded each time and since jpg uses a destructive compression method you will lose some image quality each time. I wouldn't worry about that if this is a once-per-image operation though.

请注意,在 jpg 图像上重复执行此操作可能不是一件好事;图像每次都会重新编码,由于 jpg 使用破坏性压缩方法,因此每次都会损失一些图像质量。不过,如果这是每个图像一次的操作,我不会担心。

回答by Guffa

No, the Graphicsobject doesn't contain any image data, it's used to draw on a canvas, which usually is the screen or a Bitmapobject.

不,Graphics对象不包含任何图像数据,它用于在画布上绘制,通常是屏幕或Bitmap对象。

So, you need to create a Bitmapobject with the correct size to draw on, and create the Graphicsobject for that bitmap. Then you can save it. Remember that object implementing IDisposableshould be disposed, for example using the usingclause:

因此,您需要创建一个Bitmap具有正确大小的对象以供绘制,并Graphics为该位图创建对象。然后你可以保存它。请记住,IDisposable应该处理对象实现,例如使用using子句:

using (Image image = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "Cropper/tests/castle.jpg")) {

   // Create bitmap
   using (Bitmap newImage = new Bitmap(200, 120)) {

      // Crop and resize the image.
      Rectangle destination = new Rectangle(0, 0, 200, 120);
      using (Graphics graphic = Graphics.FromImage(newImage)) {
         graphic.DrawImage(image, destination, int.Parse(X1.Value), int.Parse(Y1.Value), int.Parse(Width.Value), int.Parse(Height.Value), GraphicsUnit.Pixel);
      }
      newImage.Save(AppDomain.CurrentDomain.BaseDirectory + "Cropper/tests/castle_icon.jpg", ImageFormat.Jpeg);
   }
}

回答by user1830791

This is not a direct answer to the OP's question, but it is an often-overlooked tool that can allow you to approach things in a different way, should that prove necessary.

这不是对 OP 问题的直接回答,但它是一个经常被忽视的工具,如果证明有必要,它可以让您以不同的方式处理事情。

It is often said that it's not possible to get at the content of a Graphics object. This is not true at all. With the right approach you can access data on a canvas using HDC and BitBlt. Here is one way to do it using C#:

人们常说不可能获得 Graphics 对象的内容。这根本不是真的。通过正确的方法,您可以使用 HDC 和 BitBlt 访问画布上的数据。这是使用 C# 执行此操作的一种方法:

    enum TernaryRasterOperations : uint
    {
        /// <summary>dest = source</summary>
        SRCCOPY = 0x00CC0020,
        /// <summary>dest = source OR dest</summary>
        SRCPAINT = 0x00EE0086,
        /// <summary>dest = source AND dest</summary>
        SRCAND = 0x008800C6,
        /// <summary>dest = source XOR dest</summary>
        SRCINVERT = 0x00660046,
        /// <summary>dest = source AND (NOT dest)</summary>
        SRCERASE = 0x00440328,
        /// <summary>dest = (NOT source)</summary>
        NOTSRCCOPY = 0x00330008,
        /// <summary>dest = (NOT src) AND (NOT dest)</summary>
        NOTSRCERASE = 0x001100A6,
        /// <summary>dest = (source AND pattern)</summary>
        MERGECOPY = 0x00C000CA,
        /// <summary>dest = (NOT source) OR dest</summary>
        MERGEPAINT = 0x00BB0226,
        /// <summary>dest = pattern</summary>
        PATCOPY = 0x00F00021,
        /// <summary>dest = DPSnoo</summary>
        PATPAINT = 0x00FB0A09,
        /// <summary>dest = pattern XOR dest</summary>
        PATINVERT = 0x005A0049,
        /// <summary>dest = (NOT dest)</summary>
        DSTINVERT = 0x00550009,
        /// <summary>dest = BLACK</summary>
        BLACKNESS = 0x00000042,
        /// <summary>dest = WHITE</summary>
        WHITENESS = 0x00FF0062,
        /// <summary>
        /// Capture window as seen on screen.  This includes layered windows 
        /// such as WPF windows with AllowsTransparency="true"
        /// </summary>
        CAPTUREBLT = 0x40000000
    }

    [DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);

    public static Bitmap CopyGraphicsContent(Graphics source, Rectangle rect)
    {
        Bitmap bmp = new Bitmap(rect.Width, rect.Height);

        using (Graphics dest = Graphics.FromImage(bmp))
        {
            IntPtr hdcSource = source.GetHdc();
            IntPtr hdcDest = dest.GetHdc();

            BitBlt(hdcDest, 0, 0, rect.Width, rect.Height, hdcSource, rect.X, rect.Y, TernaryRasterOperations.SRCCOPY);

            source.ReleaseHdc(hdcSource);
            dest.ReleaseHdc(hdcDest);
        }

        return bmp;
    }