Reputation: 1026
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,
Using no width and height, my Grid is rendered at 2342 x 1262 and the output file has the same proportions as what I see on the screen.
Using width and height of 20000 x 10777, my Grid is rendered at 4096 x 2208.
Using width and height of 3000 x 1616, my Grid is still rendered at 4096 x 2207.
Using a width and height of 3000 x 4000, my Grid is rendered at 3072 x 4096.
Using a width and height of 1000 x 538, my Grid is rendered at 1500 x 807.
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
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