0

I am using the UWP image control.

I have rotated the image to 45 degrees by applying the Rotate transform(Angle = 45) now I want to convert the rendered rotated image to stream. So I have tried the RenderTargetBitmap to capture the image but it is not worked. It returns an actual image instead of a rotated image. Please provide any suggestions on this.

        var rendererShapeViewBitmap = new RenderTargetBitmap();
        InMemoryRandomAccessStream renderedStream = new InMemoryRandomAccessStream();
        await rendererShapeViewBitmap.RenderAsync(editorImage);
        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, renderedStream);
        IBuffer pixelBuffer = await rendererShapeViewBitmap.GetPixelsAsync();
        encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied,
           (uint)rendererShapeViewBitmap.PixelWidth, (uint)rendererShapeViewBitmap.PixelHeight, 96, 96, pixelBuffer.ToArray());
        await encoder.FlushAsync();
        renderedStream.Seek(0);

Before getting stream: enter image description here

After getting the stream

enter image description here

My requirement: enter image description here

Santhiya
  • 191
  • 2
  • 14

1 Answers1

0

You could let the Image control within a panel such as StackPanel or Grid, and convert the panel which includes your rotated image to stream by using RenderTargetBitmap class.

Update:

The size of Grid will adapt to the size of the Image control and the size of Grid is always bigger than the size of the Image control if the image is rotated.

You could check the following code as a sample.

<Grid x:Name="panel">
    <Image Source="Assets/YourImage.png"  Width="300" Height="300"
       x:Name="image" Margin="10">
        <Image.RenderTransform>
            <RotateTransform Angle="45" CenterX="150" CenterY="150"/>
        </Image.RenderTransform>
    </Image>
</Grid>

Code-behind

private async void button_Click(object sender, RoutedEventArgs e)
{
    var renderShapeViewBitmap = new RenderTargetBitmap();
    InMemoryRandomAccessStream renderedStream = new InMemoryRandomAccessStream();
    await renderShapeViewBitmap.RenderAsync(panel);
    BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, renderedStream);
    IBuffer pixelBuffer = await renderShapeViewBitmap.GetPixelsAsync();
    encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied,
        (uint)renderShapeViewBitmap.PixelWidth, (uint)renderShapeViewBitmap.PixelHeight,
            96, 96, pixelBuffer.ToArray());
    await encoder.FlushAsync();
    renderedStream.Seek(0);
}

Update:

The image stream captured by RenderTargetBitmap with an Image control does not include the rotation information. Therefore, you cannot get the rotated image stream only.

You could check the following code as a workaround:

    <Grid x:Name="panel" Background="Green" >
        <Image Source="Assets/2211.png"   Width="300" 
           x:Name="image" RenderTransformOrigin="0.5,0.5">
            <Image.RenderTransform>
                <RotateTransform Angle="45" CenterX="0" CenterY="0"/>
            </Image.RenderTransform>
        </Image>
    </Grid>

Code-behind:

    private async void button_Click(object sender, RoutedEventArgs e)
    {
        var width = panel.Width;
        var height = panel.Height;
         
//We can calculate the grid’size based on the size of image. Change the size of grid to wrap the image, then capture the grid which just surrounds the image
        panel.Height = image.ActualWidth / Math.Sqrt(2) + image.ActualHeight / Math.Sqrt(2);
        panel.Width = image.ActualWidth / Math.Sqrt(2) + image.ActualHeight / Math.Sqrt(2); 
        var renderShapeViewBitmap = new RenderTargetBitmap();
        InMemoryRandomAccessStream renderedStream = new InMemoryRandomAccessStream();
        await renderShapeViewBitmap.RenderAsync(panel);
        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, renderedStream);
        IBuffer pixelBuffer = await renderShapeViewBitmap.GetPixelsAsync();
        encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied,
            (uint)renderShapeViewBitmap.PixelWidth, (uint)renderShapeViewBitmap.PixelHeight,
            96, 96, pixelBuffer.ToArray());
        await encoder.FlushAsync();
        renderedStream.Seek(0);
       ……
        //panel.Width = width;  //If you want the panel to remain the original size, you can use the two line code.
        //panel.Height = height;
    }

Note, you need to rotate your image around its center with CenterX and CenterY as 0 and UIElement.RenderTransformOriginal as (0.5,0.5) for simple calculation.

YanGu
  • 3,006
  • 1
  • 3
  • 7
  • How to add the image inside the grid? Image size and grid size are different. – Santhiya Nov 19 '20 at 05:46
  • I update the answer and maybe you could check the update to see if it solves your question. – YanGu Nov 19 '20 at 08:33
  • Thanks.. It is meet my requirement partially. How to get the rotated image stream only currently I get the panel stream? I have added the images. – Santhiya Nov 19 '20 at 10:36
  • I update the answer and maybe you could check the update to see if it meets your requirements. – YanGu Nov 20 '20 at 06:16