代码之家  ›  专栏  ›  技术社区  ›  niaher

图形对象到图像文件

  •  9
  • niaher  · 技术社区  · 15 年前

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

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

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

    3 回复  |  直到 6 年前
        1
  •  11
  •   Fredrik Mörk    15 年前

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

    尽管在JPG图像上重复这样做可能不是一件好事;图像每次都被重新编码,而且由于JPG使用破坏性压缩方法,每次都会丢失一些图像质量。不过,如果这是一个每图像一次的操作,我不会担心这个问题。

        2
  •  5
  •   Guffa    15 年前

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

    因此,您需要创建一个 位图 对象的大小正确,并创建 绘图 该位图的对象。然后你可以保存它。记住对象实现 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);
       }
    }
    
        3
  •  1
  •   Craig.Feied    6 年前

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

    人们常说,不可能获取图形对象的内容。这根本不是真的。使用正确的方法,您可以使用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;
        }