Rectangle Rotation and Flipping
Question
I have a bitmap with a Rectangle object that is drawn on top of it. I want to be able to RotateFlip the bitmap and adjust the x, y, width, and height of the Rectangle so that it lines up with the bitmap after each rotation or flip.
For example, if I have a bitmap of 1000 x 800 pixels, I may have a Rectangle object being drawn on it with a specified point and size.
Sample code:
// A bitmap that's 1000x800 size
Bitmap bitmap = new Bitmap(fileName);
// Any arbitrary rectangle that can be drawn inside the bitmap boundaries
Rectangle rect = new Rectangle(200, 200, 100, 100);
bitmap.RotateFlip(rotateFlipType);
switch (rotateFlipType)
{
case Rotate90FlipNone:
// Adjust rectangle to match new bitmap orientation
rect = new Rectangle(?, ?, ?, ?);
break;
case RotateNoneFlip180:
rect = new Rectangle(?, ?, ?, ?);
break;
// ... etc.
}
Solution
I find it easiest to reason through each scenario by drawing a picture and labeling rect.Top
, rect.Bottom
, rect.Left
, and rect.Right
. Once that's done, I either mentally rotate the picture, or even physically rotate the paper. From there, it's as simple as figuring out where the new rect.Left
and rect.Top
live.
A few general tips:
- For 90 degree and 270 degree rotations,
rect.Width
andrect.Height
have to be swapped. - It's often easiest to compute the new top or the new left using
bitmap.Width-rect.Right
andbitmap.Height-rect.Bottom
.
Here are your two examples with the blanks filled in to get you started:
switch (rotateFlipType)
{
case Rotate90FlipNone:
// Adjust rectangle to match new bitmap orientation
rect = new Rectangle(bitmap.Height-rect.Bottom,
rect.Left,
rect.Height,
rect.Width);
break;
case RotateNoneFlipHorizontally:
rect = new Rectangle(bitmap.Width - rect.Right,
rect.Top,
rect.Width,
rect.Height);
break;
// ... etc.
}
OTHER TIPS
I faced exactly this problem.
Here are my results - perhaps they will save somebody else an hour of fiddling...
void RotateFlipRect(CRect & pRect, int pNewContainerWidth, int pNewContainerHeight, Gdiplus::RotateFlipType pCorrection)
{
CRect lTemp = pRect;
switch (pCorrection)
{
case RotateNoneFlipNone: // = Rotate180FlipXY
break;
case Rotate90FlipNone: // = Rotate270FlipXY
pRect.left = lTemp.top;
pRect.top = pNewContainerHeight - lTemp.right;
pRect.right = lTemp.bottom;
pRect.bottom = pNewContainerHeight - lTemp.left;
break;
case Rotate180FlipNone: // = RotateNoneFlipXY
pRect.left = pNewContainerWidth - lTemp.right;
pRect.top = pNewContainerHeight - lTemp.bottom;
pRect.right = pNewContainerWidth - lTemp.left;
pRect.bottom = pNewContainerHeight - lTemp.top;
break;
case Rotate270FlipNone: // = Rotate90FlipXY
pRect.left = pNewContainerWidth - lTemp.bottom;
pRect.top = lTemp.left;
pRect.right = pNewContainerWidth - lTemp.top;
pRect.bottom = lTemp.right;
break;
case RotateNoneFlipX: // = Rotate180FlipY
pRect.left = pNewContainerWidth - lTemp.right;
pRect.top = lTemp.top;
pRect.right = pNewContainerWidth - lTemp.left;
pRect.bottom = lTemp.bottom;
break;
case Rotate90FlipX: // = Rotate270FlipY
pRect.left = pNewContainerWidth - lTemp.bottom;
pRect.top = pNewContainerHeight - lTemp.right;
pRect.right = pNewContainerWidth - lTemp.top;
pRect.bottom = pNewContainerHeight - lTemp.left;
break;
case Rotate180FlipX: // = RotateNoneFlipY
pRect.left = lTemp.left;
pRect.top = pNewContainerHeight - lTemp.bottom;
pRect.right = lTemp.right;
pRect.bottom = pNewContainerHeight - lTemp.top;
break;
case Rotate270FlipX: // = Rotate90FlipY
pRect.left = lTemp.top;
pRect.top = lTemp.left;
pRect.right = lTemp.bottom;
pRect.bottom = lTemp.right;
break;
default:
// ?!??!
break;
}
}