David Rector
David Rector

Reputation: 1026

Width and Height of the Image in RenderTargetBitmap.RenderAsync in UWP

I found this: Width and Height of the Image in RenderTargetBitmap in WPF but that is WPF and not UWP.

The RenderTargetBitmap class has an RenderAsync method that accepts no width and height and a method of the same name that takes a width and height. The width and height do not do anything that I expect. For instance,

So the numbers do something but I can't figure out what rule is used to pick the final PixelWidth and PixelHeight of the RenderTargetBitmap. They seem like minimums.

Here's my method for rendering in case it's something else that I'm doing wrong. Note that I try to take suggested input sizes and keep them proportional to the sizes I get when rendering without giving sizes. Also of note is that the input element is a Grid that is contained within a ViewBox element on screen...

    private async Task CreateSaveBitmapAsync( UIElement Element, int SuggestedWidth, int SuggestedHeight )
    {
        if (Element != null)
        {
            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
            await renderTargetBitmap.RenderAsync( Element );

            double WidthRatio = renderTargetBitmap.PixelWidth / (double)renderTargetBitmap.PixelHeight;

            if( WidthRatio >= 1 )
                SuggestedHeight = (int)( SuggestedWidth / WidthRatio );
            else
                SuggestedWidth = (int)( SuggestedHeight * WidthRatio );

            await renderTargetBitmap.RenderAsync( Element, SuggestedWidth, SuggestedHeight );

            var picker = new FileSavePicker();
            picker.FileTypeChoices.Add("PNG Image", new string[] { ".png" });
            StorageFile file = await picker.PickSaveFileAsync();
            if (file != null)
            {
                var pixels = await renderTargetBitmap.GetPixelsAsync();

                using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
                {
                    var encoder = await
                        BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
                    byte[] bytes = pixels.ToArray();
                    encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                                         BitmapAlphaMode.Ignore,
                                         (uint)renderTargetBitmap.PixelWidth, (uint)renderTargetBitmap.PixelHeight,
                                         96, 96, bytes);

                    await encoder.FlushAsync();
                }
            } 
        }
    }

After looking more closely at the documentation, I see that there is a built-in maximum size that can't be exceeded. So I am only confused about why the image is ever created bigger than the numbers I pass in. Are these minimums?

Upvotes: 0

Views: 946

Answers (2)

Enny
Enny

Reputation: 771

According to the following page it is a limitation of DirectX. MSDN

Upvotes: 1

AlexDrenea
AlexDrenea

Reputation: 8039

I've recently encountered this issue myself and discovered that RenderTargetBitmap is influenced by the current DPI setting of your monitor.

Based on the values you provided, I can assume that your DPI is at 150%. I didn't know about the max 4096x4096 size, but it looks like that's another parameter to be taken into consideration.

In my case I needed the image to be a specific size (for a live tile) so I check the Rendered bitmap size and if it does not match my expected size I will resize it in code. Let me know if you need the code for that.

Upvotes: 2

Related Questions