WPF: How to rotate a BitmapSource by any angle
Asked Answered
T

3

0

Ok, I tried this:

TransformedBitmap tbm = new TransformedBitmap(myBitmapSource, new RotateTransform(angle));
return tbm;

But this does not work with angles other than multiples of 90degrees.

New I tried to use a RenderTargetBitmap:

  var image = new Canvas();
  image.Width = myBitmapSource.PixelWidth;
  image.Height = myBitmapSource.PixelHeight;
  image.Background = new ImageBrush(myBitmapSource);
  image.RenderTransform = new RotateTransform(angle);
  RenderTargetBitmap rtb = new RenderTargetBitmap(myBitmapSource.PixelWidth, myBitmapSource.PixelHeight, myBitmapSource.DpiX, myBitmapSource.DpiY, myBitmapSource.Format);
  rtb.Render(image);
  return rtb;

But this gives me:

"The calling thread must be STA, because many UI components require this."

This runs in a service without a GUI.

Can somebody give me a working code sample on how to rotate a BitmapSource in WPF (without a GUI) by any angle?

update:

Vote for feature request: http://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/10870098-allow-rotation-of-bitmapsource-by-any-angle

Travancore answered 25/11, 2015 at 10:31 Comment(5)
It should work if you call SetApartmentState(ApartmentState.STA) on the thread that runs your code. Note however that you would somehow have to calculate the correct size of the resultimg bitmap. Otherwise parts of the source bitmap may be cut off. Moreover, you probably want to rotate around the image center, so you should set image.RenderTransformOrigin = new Point(0.5, 0.5). Finally, a layout must be done on the Canvas, i.e. you have to call its Measure and Arrange methods.Elane
problem is that I can't set that, as I'm a pluginTravancore
Then create a new thread, do the processing there and pass the result back to your plugin thread. Don't forget to call Freeze() on the result bitmap to make it accessible across threads.Elane
@Elane is it better to use RenderTransform or LayoutTransform? (where are the differences?)Travancore
You aren't doing any layout, so RenderTransform is sufficient. Read about the differences on MSDN.Elane
S
2

Well you can run that code in a separate thread. Just set the single-threaded apartment (STA).

Thread thread = new Thread(DoTheRotation);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();

Code for rotation in a method called by the thread:

public void DoTheRotation()
{
    var image = new Canvas();
    image.Width = myBitmapSource.PixelWidth;
    image.Height = myBitmapSource.PixelHeight;
    image.Background = new ImageBrush(myBitmapSource);
    image.RenderTransform = new RotateTransform(angle);
    RenderTargetBitmap rtb = new RenderTargetBitmap(myBitmapSource.PixelWidth, myBitmapSource.PixelHeight, myBitmapSource.DpiX, myBitmapSource.DpiY, myBitmapSource.Format);
    rtb.Render(image);
}

Then you just need to change the code to pass the object.

Somatology answered 25/11, 2015 at 11:7 Comment(1)
I also need to call .Freeze() !Travancore
P
9

just use a TransformedBitmap

var rotatedImage = new TransformedBitmap(image, new RotateTransform(180));
Pintle answered 17/2, 2017 at 14:3 Comment(1)
Slightly related: to flip horizontally you can use new ScaleTransform(-1, 1, 0.5, 0.5)Transalpine
S
2

Well you can run that code in a separate thread. Just set the single-threaded apartment (STA).

Thread thread = new Thread(DoTheRotation);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();

Code for rotation in a method called by the thread:

public void DoTheRotation()
{
    var image = new Canvas();
    image.Width = myBitmapSource.PixelWidth;
    image.Height = myBitmapSource.PixelHeight;
    image.Background = new ImageBrush(myBitmapSource);
    image.RenderTransform = new RotateTransform(angle);
    RenderTargetBitmap rtb = new RenderTargetBitmap(myBitmapSource.PixelWidth, myBitmapSource.PixelHeight, myBitmapSource.DpiX, myBitmapSource.DpiY, myBitmapSource.Format);
    rtb.Render(image);
}

Then you just need to change the code to pass the object.

Somatology answered 25/11, 2015 at 11:7 Comment(1)
I also need to call .Freeze() !Travancore
D
1

Be aware that TransformedBitmap supports only orthogonal transforms such as rotation transforms of 90° increments and scale transforms. Transforms that skew the image are not supported. So for the rotation you can only use 90, 180, 270 degrees! As already mentioned in the original question!

Dasyure answered 7/8, 2017 at 8:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.