Save an image by identifying it from FrameworkElement

0

I have this layout:

<StackPanel>
    <Button x:Name="button" Content="Button" Click="button_Click" Height="50" />
    <Image x:Name="image" Source="vermelho.jpg" />
</StackPanel>

The code I tested to write the image to a png file is as follows:

private void button_Click(object sender, RoutedEventArgs e)
{
    Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
    dlg.FileName = "imagem";
    dlg.DefaultExt = ".png";
    dlg.Filter = "Imagem PNG (.png)|*.png";
    Nullable<bool> result = dlg.ShowDialog();
    if (result == true)
    {
        var encoder = new PngBitmapEncoder();
        SaveUsingEncoder(image, dlg.FileName, encoder);
    }
}

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

Why is it that when I open the image recorded on the disc, the area corresponding to the button is also saved in transparent?

    
asked by anonymous 08.01.2017 / 11:08

2 answers

2

To help you reproduce your problem here and summarize what I understood.

SUMMARY: What seems to happen is that the RenderTargetBitmap class, even with the "Render" method containing the Visual specified its measures defined according to the target. it does not position correctly to turn the target into a Bitmap. It is as if he forms a square positioned at the beginning of the Window instead of standing on the image. I do not know why this is happening, I'm researching.

In addition, I was able to solve the problem by placing the image inside a DrawingVisual .

 public void SaveUsingEncoder(FrameworkElement visual, string fileName)
 {
        // SOLUÇÃO DO PROBLEMA: Colocar a imagem dentro de um DrawingVisual que é uma classe de desenho.
        DrawingVisual drawing = new DrawingVisual();
        using (DrawingContext ctx = drawing.RenderOpen())
        {
            VisualBrush vb = new VisualBrush(visual);
            ctx.DrawRectangle(vb, null, new Rect(new Point(0, 0), new Point(visual.Width, visual.Height)));
        }

        // Cria uma nova instância do RenderTargetBitmap onde será convertido um alvo visual para bitmap.
        RenderTargetBitmap bitmap = new RenderTargetBitmap((int)visual.Width, (int)visual.Height, 96, 96, PixelFormats.Pbgra32);
        // Converte o DrawingVisual com sua imagem em Bitmap
        bitmap.Render(drawing);

        // Cria instância do encode
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        // Transforma nosso BitmapSource em uma imagem
        BitmapFrame frame = BitmapFrame.Create(bitmap);
        // Adiciona a imagem ao encoder. Transformando ela em PNG...
        encoder.Frames.Add(frame);

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

I'm not sure if this is the ideal solution and even if what I said about RenderTargetBitmap is right. If someone has a better explanation, help us understand this situation.

    
16.01.2017 / 13:06
0

I have, however, abandoned this approach and solved it in a simpler way:

//Criar um ficheiro no disco correspondente à imagem exibida na área de preview
private void guardarImagemDiscoDoPreviewButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        //Converter source da imagem num byte array
        byte[] ImageData = getJPGFromImageControl(previewImage.Source as BitmapImage);

        //Save As Dialog ...
        Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
        dlg.FileName = "imagem";
        dlg.DefaultExt = ".jpg";
        dlg.Filter = "Imagem JPEG|*.jpg";
        Nullable<bool> result = dlg.ShowDialog();

        //Gravar a imagem no disco
        using (Image image = Image.FromStream(new MemoryStream(ImageData)))
        {
            image.Save(dlg.FileName, ImageFormat.Jpeg);  // Ou Png ...
        }
    }
    catch
    {
        MessageBox.Show("Nenhuma imagem foi ainda carregada.", "ERRO!", MessageBoxButton.OK, MessageBoxImage.Error);

    }
}

Of course this solves my problem but does not answer the initial question.

    
17.01.2017 / 09:41