Как центрировать повернутое изображение с помощью GDI +? - PullRequest
6 голосов
/ 28 мая 2009

Я пытаюсь центрировать повернутое изображение в буфере назначения, используя GDI +. Исходный буфер и целевой буфер имеют разные размеры.

Исходный буфер - это размер данных изображения: (ширина, высота) .
Целевой буфер - это размер прямоугольника, необходимый для размещения повернутого изображения всего : (rotatedWidth, rotatedHeight) .

Вот код, который я пытаюсь:

// Calculate the size needed for the image to be rotated into   
int width = /* some width */;
int height = /* some height */;
System::Windows::Size destSize 
  = IPMathUtilities::CalculateRotatedImageSize(rotateAreaBoundingPoints, 
    rotationDegree, width, height);

//
// Create source bitmap object
Bitmap^ sourceBitmap = gcnew Bitmap(width, height, width * 2, 
  PixelFormat::Format16bppRgb555, ptrSourceBuffer);

//
// Create destination bitmap object
int destBufferSize = destSize.Width * destSize.Height * 2;
BYTE* pDestBuffer = new BYTE[destBufferSize];
memset(pDestBuffer, 0, destBufferSize);
Bitmap^ destBitmap = gcnew Bitmap(destSize.Width, destSize.Height, 
  destSize.Width * 2, PixelFormat::Format16bppRgb555, (IntPtr)pDestBuffer);

//
// Draw rotated source image in destination image
Graphics^ g = Graphics::FromImage(destBitmap);
g->TranslateTransform(-width/2, -height/2);
g->RotateTransform(rotationDegree, MatrixOrder::Append);
g->TranslateTransform(destSize.Width / 2.0, destSize.Height / 2.0, 
  MatrixOrder::Append);
g->DrawImage(sourceBitmap, 0, 0, width, height);

Это почти работает. Это близко - я нахожу, если высота больше ширина , левая позиция повернутого изображения неверна. Аналогично, если ширина больше высота , верхнее положение повернутого изображения неверно.

Некоторые заметки:

  • IPMathUtilities - это служебный класс, который я написал.
  • Я на 100% уверен, что IPMathUtilities::CalculateRotatedImageSize() вычисляет правильный размер прямоугольника, необходимый для размещения всего повернутого изображения. 100% уверен. Я тщательно его проверил, и он работает.
  • Я недавно задал похожий вопрос: Почему iplRotate() не дает правильных результатов? . Я прекратил отказываться от IPL / IPP и пробовал GDI +.

Есть идеи?

1 Ответ

6 голосов
/ 28 мая 2009

После поворота сначала переместите изображение обратно в исходное положение, а затем вдвое больше нового холста. Если ваши вычисления в CalculateRotatedImageSize действительно верны, они должны соответствовать точно. Только что проверил этот код, и он, кажется, работает:

g.TranslateTransform((float)(org.Width / -2), (float)(org.Height / -2));
g.RotateTransform(45, System.Drawing.Drawing2D.MatrixOrder.Append );
g.TranslateTransform((float)(org.Width / 2), (float)(org.Height / 2), System.Drawing.Drawing2D.MatrixOrder.Append);
g.TranslateTransform((float)((rotated.Width - org.Width) / 2), (float)((rotated.Height - org.Height) / 2), System.Drawing.Drawing2D.MatrixOrder.Append);

РЕДАКТИРОВАТЬ: извините, конечно,

g.TranslateTransform((float)(org.Width / 2), (float)(org.Height / 2), System.Drawing.Drawing2D.MatrixOrder.Append);
g.TranslateTransform((float)((rotated.Width - org.Width) / 2), (float)((rotated.Height - org.Height) / 2), System.Drawing.Drawing2D.MatrixOrder.Append);

действительно так же, как

g.TranslateTransform((float)(rotated.Width / 2), (float)(rotated.Height / 2), System.Drawing.Drawing2D.MatrixOrder.Append);

это просто код, который вы опубликовали. Кажется, работает хорошо для меня, хотя.

EDIT2: возможно, ошибка просто

g->DrawImage(sourceBitmap, 0, 0, width, height);

Попробуйте

g->DrawImage(sourceBitmap, 0, 0);

вместо

...