Rotate Picture without distortion.

My application needs to rotate a picture.

What works so far is to get a ref to the picture,
Create a PixmapShape with the picture as the image.
Rotate the PixmapShape,
Use .Graphics.DrawObject to return the rotated image.

This works but distorts the image. Although, if I rotate it back to it’s original position, it looks perfect again.

So see if you think I am on the right track.

Assume that the picture coming into the method is a rectangle.
If I take the longer side,
And make the new picture area a square of the longest side,
Now If I rotate, I won’t get any distortion as the area being used will not require distortion.

This may crop the PixmapShape if centered.
So I’ll take the longer side and multiply it by sqroot(2). This would give me a square larger than the longest side by the hypotenuse. I am assuming this:
TO rotate a square in another square, the outer square need only be the hypotenuse in length.
That is, take a leg of the inner square, and multiply it by root(2), and you’ll have a leg for the outer square large enough.
A leg large enough to rotate the inner square.

So …

  1. Find the longer side of a OriginalPicture to be rotated.
  2. Mul that by root 2.
  3. Make a NewPicture, square, of the size of the new leg,
  4. Use PixmapShape to draw the OriginalPicture into the NewPicture - centered.
    (to center use the width/2 and height/2 to center the PixmapShape)
    Graphics.DrawObject(PMap, Pic.Width/2, Pic.Height/2) - here PMap is my PixMapShpe.

With that all done, …
5) Rotate the image with PixMapShape.
6) Place the rotated PixMapShape into FinalPicture and return that from the routine.

I’m off to try this. … let’s see if it works …


Rotation will always distort to some degree. Anti-aliasing is used to mask some of the effects by blending colors, usually.
Having a larger area to do the rotation within just avoids losing some of the pixels from the corners

This might help…

Did you search the forum?

[quote=389517:@LangueR]Did you search the forum?
last I checked, there were more angles than just multiples of 90 :slight_smile:

@Dave S
You are correct. The post I reffered to has four options that allow rotation to whatever angle is desired. And it shows 4 different ways to skin the same cat, one which may provide better results to Eric (I’m thinking imageMagick, but Eric may find a better option).

Here is the solution I ended up with.

RotateSameSizeV2(Degrees as Integer, Pic as Picture)
// we pass the picture to be rotated and the desired rotation in degrees.

'Create a new picture with width and height of the picture passed to this routine.
Dim NewPic as Picture // this will hold the new picture in a bigger frame.
Dim NewPic2 as Picture // this will hold the rotated picture
Dim NewSide As Double // we need to calculate a value for a long side.

// Which side of the passed picture is the longest?
If Pic.Width > Pic.Height Then
Else // = or H is larger
// Now we have the longest side.

// if we make a new picture that is a square, with the longest side for each leg, we’ll end up cropping
// the picture as we rotate it. So we need to add some length.

'NewSide=NewSide*Sqrt(2) // find the diag of the square made of the longer side.
NewPic = new Picture(NewSide,NewSide) // make a picrure with this as it’s new width and height

’ create a pixmap shape to hold the rotation map
Dim PMap as PixmapShape
PMap = New PixmapShape
Pmap.SourceLeft=0 // not sure these are important.
PMap.SourceTop=0// not sure these are important.
Pmap.SourceHeight=Pic.Height // not sure these are important.
Pmap.SourceWidth=Pic.Width // not sure these are important.

PMap.Rotation=(Degrees/57.296) // rotate the passed picture

// you MUST center the object
NewPic.Graphics.DrawObject(PMap, NewSide/2, NewSide/2)
// draw the rotated picture cropped to the frame

// What’s odd is that I needed to center the PMap and
// I found the XOJO docs on Pixel Maps did not tell me why.

// But this works.

// now I return the rotated picture.
Return NewPic

// There is a little cropping but I think this is due to a rounding error and could be fixed by making
// NewSide a little longer to compensate.