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.
}
Was it helpful?

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 and rect.Height have to be swapped.
  • It's often easiest to compute the new top or the new left using bitmap.Width-rect.Right and bitmap.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;
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top