Question

I have a simple paiting app and I'm trying to render a canvas into a bitmap using the RenderTargetBitmap.RenderAsync() method. If a child element of the canvas exceeds canvas boundaries, the rendered bitmap is bigger than the canvas area... How can I avoid that and get only in-bounds elements rendered? I tried the clip property of the canvas but it only works for the UI , not for the rendering. ClipToBounds is not available in WinRT...

Was it helpful?

Solution

I've ran into same problem. Here is what worked for me:

        Rect r = new Rect(new Point(0, 0), new Point(canvas.Width, canvas.Height));
        foreach (var c in canvas.Children)
            c.Clip = new RectangleGeometry() { Rect = r };


        RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
        await renderTargetBitmap.RenderAsync(canvas, (int)canvas.Width, (int)canvas.Height);

        FileSavePicker picker = new FileSavePicker();
        picker.FileTypeChoices.Add("JPEG Image", new string[] { ".jpg" });
        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.JpegEncoderId, stream);
                byte[] bytes = pixels.ToArray();
                encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                    BitmapAlphaMode.Ignore,
                    (uint)canvas.Width, (uint)canvas.Height,
                    96, 96, bytes);

                await encoder.FlushAsync();
            }
        }

Basically, you just add Clip to all Canvas's children, so everything what is out of bounds won't be rendered by RenderTargetBitmap.


ClipToBounds functionality can be easily added via AttachedProperty: details

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top