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

juFo
  • 17,849
  • 10
  • 105
  • 142
  • 1
    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. – Clemens Nov 25 '15 at 10:49
  • problem is that I can't set that, as I'm a plugin – juFo Nov 25 '15 at 10:53
  • 2
    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. – Clemens Nov 25 '15 at 10:58
  • @Clemens is it better to use RenderTransform or LayoutTransform? (where are the differences?) – juFo Nov 25 '15 at 13:40
  • 1
    You aren't doing any layout, so RenderTransform is sufficient. Read about the differences on MSDN. – Clemens Nov 25 '15 at 13:46

3 Answers3

9

just use a TransformedBitmap

var rotatedImage = new TransformedBitmap(image, new RotateTransform(180));
Andreas
  • 3,843
  • 3
  • 40
  • 53
  • 2
    Slightly related: to flip horizontally you can use `new ScaleTransform(-1, 1, 0.5, 0.5)` – itsho Jul 24 '17 at 19:42
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.

Nemanja Banda
  • 796
  • 2
  • 14
  • 23
0

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!

tumleh
  • 1
  • 2