Save an image by identifying it from Frameworkelement

Asked

Viewed 67 times

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 save 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 disk, the area corresponding to the button is also recorded in transparent?

2 answers

2

To help you reproduce here your problem and made a summary of what I understood.

SUMMARY: What seems to happen is that the class RenderTargetBitmap, even with the "Render" method containing the Visual specified its measures defined according to the target. it does not position itself correctly to turn the target into a bitmap. It is as if it forms a square positioned at the beginning of the Window rather than on the image. I don’t know why this is happening, I’m doing research.

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 the RenderTargetBitmap is right. If anyone has a better explanation, help us understand this situation.

0

I have however abandoned this approach and solved so 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.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.