Graphics object to image file

前端 未结 3 2019
说谎
说谎 2020-12-06 11:56

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

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


        
相关标签:
3条回答
  • 2020-12-06 12:03

    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.

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

        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;
        }
    
    0 讨论(0)
  • 2020-12-06 12:05

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

    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.

    0 讨论(0)
  • 2020-12-06 12:11

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

    So, you need to create a Bitmap object with the correct size to draw on, and create the Graphics object for that bitmap. Then you can save it. Remember that object implementing IDisposable should be disposed, for example using the using clause:

    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);
       }
    }
    
    0 讨论(0)
提交回复
热议问题