Santhiya
Santhiya

Reputation: 301

How to capture the rotated image to stream?

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

Upvotes: 0

Views: 103

Answers (1)

YanGu
YanGu

Reputation: 3032

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.

Upvotes: 0

Related Questions