yogapriya shanmugam
yogapriya shanmugam

Reputation: 99

Saving the render target bitmap results in wrong size when background is set

I am saving the rendered image using render target bitmap, and it is saved properly in the given size, but when I set background to the grid in which image is placed, I am getting different output. Can any one explain this behavior?

    <Grid x:Name="grid1" Grid.Row="0" Background="Red">

        <Image x:Name="image1" Source="Images/butterfly.jpg"  >              
        </Image>

    </Grid>

Code behind

        RenderTargetBitmap result = GetImage(this.grid1);
        Stream imageStream = new MemoryStream();
        SaveAsPng(result, imageStream);

    public static RenderTargetBitmap GetImage(Grid view)
    {
        Size size = new Size(1122, 750);
        if (size.IsEmpty)
            return null;

        RenderTargetBitmap result = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32);

        DrawingVisual drawingvisual = new DrawingVisual();
        using (DrawingContext context = drawingvisual.RenderOpen())
        {
            context.DrawRectangle(new VisualBrush(view), null, new Rect(new Point(), size));
            context.Close();
        }

        result.Render(drawingvisual);
        return result;
    }

    public static void SaveAsPng(RenderTargetBitmap src, Stream outputStream)
    {
        var saveFileDialog = new SaveFileDialog()
        {
            Filter = "Image Files (*.bmp, *.png, *.jpg)|*.bmp;*.png;*.jpg"
        };
        if (saveFileDialog.ShowDialog() == true)
        {              
            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(src));
            using (FileStream stream = new FileStream(saveFileDialog.FileName, FileMode.Create))
                encoder.Save(stream);
        }
    }

Without Background With Background

Upvotes: 0

Views: 888

Answers (1)

Clemens
Clemens

Reputation: 128061

In order to retain the original element dimensions in the DrawingVisual, you should set the VisualBrush's Stretch to None. If necessary, you can also get precise control of the placement of the visual by setting the VisualBrush's Viewport, Viewbox, AlignmentX and AlignmentY properties.

Also consider passing the result size as an argument to your GetImage method, and use the most general type for the view argument:

public static BitmapSource GetImage(Visual view, Size size)
{
    var bitmap = new RenderTargetBitmap(
        (int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32);

    var visualBrush = new VisualBrush
    {
        Visual = view,
        Stretch = Stretch.None
    };

    var drawingvisual = new DrawingVisual();

    using (var context = drawingvisual.RenderOpen())
    {
        context.DrawRectangle(visualBrush, null, new Rect(size));
    }

    bitmap.Render(drawingvisual);

    return bitmap;
}

Also make the SaveAsPng method more flexible by changing the argument type. The outputStream argument isn't used at all, so remove it.

public static void SaveAsPng(BitmapSource src)

Then call both methods like this:

var result = GetImage(grid1, new Size(1122, 750));
SaveAsPng(result);

Upvotes: 3

Related Questions