2009-07-18 11 views
8

Me gustaría recortar y cambiar el tamaño de mi imagen. Aquí está mi código:Objeto de gráficos para el archivo de imagen

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

Ahora supongamos que mi recortada imagen resultante/cambiar de tamaño se almacena en los gráficos objeto. La pregunta es: ¿cómo la guardo en un archivo?

Respuesta

10

El objeto Graphics que obtienes de Graphics.FromImage es una superficie de dibujo para la imagen. Así que puedes simplemente guardar el objeto de imagen cuando hayas terminado.

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

Tenga en cuenta que hacer esto varias veces en una imagen jpg puede no ser una buena cosa; la imagen se vuelve a codificar cada vez y, como jpg usa un método de compresión destructivo, perderás calidad de imagen cada vez. Sin embargo, no me preocuparía si esto es una operación de una vez por imagen.

5

No, el objeto Graphics no contiene ningún dato de imagen, se usa para dibujar en un lienzo, que generalmente es la pantalla o un objeto Bitmap.

Por lo tanto, debe crear un objeto Bitmap con el tamaño correcto para dibujar y crear el objeto Graphics para ese mapa de bits. Entonces puedes guardarlo. Recuerde que el objeto que implementa IDisposable deben ser eliminados, por ejemplo mediante el using cláusula:

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

Ésta no es una respuesta directa a la pregunta de la OP, pero es una herramienta a menudo se pasa por alto que se permitirá acercarse cosas en una manera diferente, si eso resultara necesario.

A menudo se dice que no es posible acceder al contenido de un objeto Graphics. Esto no es cierto en absoluto. Con el enfoque correcto, puede acceder a los datos en un lienzo usando HDC y BitBlt. Aquí hay una manera de hacerlo usando 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; 
    } 
+2

¿Responde esto a la pregunta? Explique cómo responde esto a la pregunta – CocoNess

+0

Todo el mundo dice que no es posible copiar el contenido del objeto Graphics. Esto no es cierto en absoluto. Puede acceder a los datos en un lienzo utilizando es HDC y BitBlt. Aquí es cómo hacerlo usando C#. – user1830791

+0

Esto es lo que estaba buscando cuando mi búsqueda planteó la pregunta del OP, entre muchos otros :) –

Cuestiones relacionadas