2012-05-06 12 views
11

Tengo un control de imagen dentro de mi aplicación wpf, que tiene una imagen grande dentro de ella, pero el control en sí es solo 60x150, esto significa que solo muestra una cierta porción de esto imagen. ¿Cuál es la forma más fácil de guardar la parte visible de un archivo?La manera más fácil de guardar wpf Control de imagen en un archivo

Gracias por su ayuda.

[EDIT] Terminé usando código que se encuentra here (que yo no he sido capaz de localizar antes de publicar aquí) ...

Grid r = new Grid(); 
     r.Background = new ImageBrush(image2.Source); 


    System.Windows.Size sz = new System.Windows.Size(image2.Source.Width, image2.Source.Height); 
    r.Measure(sz); 
    r.Arrange(new Rect(sz)); 

    RenderTargetBitmap rtb = new RenderTargetBitmap((int)image2.Source.Width, (int)image2.Source.Height, 96d, 96d, PixelFormats.Default); 
    rtb.Render(r); 

    BmpBitmapEncoder encoder = new BmpBitmapEncoder(); 
    encoder.Frames.Add(BitmapFrame.Create(rtb)); 

    FileStream fs = File.Open(@"C:\lol.png", FileMode.Create); 
    encoder.Save(fs); 
    fs.Close(); 
+0

¿Qué es image2.Source.Width? En cambio, es image2.ActualWidth, solo use mi código. – gliderkite

Respuesta

16

Usted podría utilizar RenderTargetBitmap clase y BitmapEncoder.

definir estos métodos:

void SaveToBmp(FrameworkElement visual, string fileName) 
{ 
    var encoder = new BmpBitmapEncoder(); 
    SaveUsingEncoder(visual, fileName, encoder); 
} 

void SaveToPng(FrameworkElement visual, string fileName) 
{ 
    var encoder = new PngBitmapEncoder(); 
    SaveUsingEncoder(visual, fileName, encoder); 
} 

// and so on for other encoders (if you want) 


void SaveUsingEncoder(FrameworkElement visual, string fileName, BitmapEncoder encoder) 
{ 
    RenderTargetBitmap bitmap = new RenderTargetBitmap((int)visual.ActualWidth, (int)visual.ActualHeight, 96, 96, PixelFormats.Pbgra32); 
    bitmap.Render(visual); 
    BitmapFrame frame = BitmapFrame.Create(bitmap); 
    encoder.Frames.Add(frame); 

    using (var stream = File.Create(fileName)) 
    { 
     encoder.Save(stream); 
    } 
} 

Si usted tiene su control de Image dentro de un contenedor de esta manera:

<Grid x:Name="MyGrid"> 
    <Image Name="MyImage" Stretch="None"></Image> 
</Grid> 

sólo tiene que hacerlo:

SaveToPng(MyGrid, "image.png"); 

De lo contrario, puede simplemente pasar las dimensiones que desea cuando usa RenderTargetBitmap:

SaveToPng(MyImage, "image.png"); 

... 

RenderTargetBitmap bitmap = new RenderTargetBitmap(YourWidth, YourHeight, 96, 96, PixelFormats.Pbgra32); 
+4

Gracias por esto, sería fantástico si no fuera por un pequeño problema ... La imagen guardada es completamente negra ... ¿Alguna idea de cómo sucedió eso o cómo solucionarla? – Meh

+0

Cuando ejecuto mi código funciona, ¿qué has intentado? con "MyGrid" o "MyImage"? – gliderkite

+0

He realizado un proyecto de prueba en VB.NET: [aquí hay una muestra] (http://ideone.com/wZH72) si puede ayudar; y [aquí] (http://ideone.com/CJrJA) el XAML. – gliderkite

2

Me encontré con el mismo problema de imagen 'negro' que el otro al usar la solución de gliderkite. La imagen 'negra' parece deberse al margen de FrameworkElement que hace que se renderice fuera de la imagen capturada. Encontré la solución en un comment on Rick Stahl's blog

Específicamente, medir y organizar antes de renderizar le da la oportunidad de ajustarse al hecho de que no hay márgenes en la imagen. La siguiente es una clase estática que ahora volveré a usar para capturas de pantalla. Esto se basa en la respuesta de gliderkite y la información en el blog de Rick Stahl.

public static class ScreenCapture 
{ 
    public static void SaveToBmp(FrameworkElement visual, string fileName) 
    { 
     var encoder = new BmpBitmapEncoder(); 
     SaveUsingEncoder(visual, fileName, encoder); 
    } 

    public static void SaveToPng(FrameworkElement visual, string fileName) 
    { 
     var encoder = new PngBitmapEncoder(); 
     SaveUsingEncoder(visual, fileName, encoder); 
    } 

    public static void SaveToJpeg(FrameworkElement visual, string fileName) 
    { 
     var encoder = new JpegBitmapEncoder(); 
     SaveUsingEncoder(visual, fileName, encoder); 
    } 

    private static void SaveUsingEncoder(FrameworkElement visual, string fileName, BitmapEncoder encoder) 
    { 
     RenderTargetBitmap bitmap = new RenderTargetBitmap((int)visual.ActualWidth, (int)visual.ActualHeight, 96, 96, PixelFormats.Pbgra32); 
     Size visualSize = new Size(visual.ActualWidth, visual.ActualHeight); 
     visual.Measure(visualSize); 
     visual.Arrange(new Rect(visualSize)); 
     bitmap.Render(visual); 
     BitmapFrame frame = BitmapFrame.Create(bitmap); 
     encoder.Frames.Add(frame); 

     using (var stream = File.Create(fileName)) 
     { 
      encoder.Save(stream); 
     } 
    } 
} 
Cuestiones relacionadas