2009-05-28 24 views
6

Estoy tratando de centrar una imagen girada en un búfer de destino usando GDI +. El buffer de origen y el buffer de destino son de diferentes tamaños.¿Cómo centro una imagen girada usando GDI +?

El búfer de origen es del tamaño de los datos de imagen: (ancho, alto).
El búfer de destino es el tamaño del rectángulo requerido para caber la imagen rota completa rotated image: (rotationAnchura, altura rotated).

Este es el código que estoy tratando:

// 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); 

Este casi obras. Está cerca - Estoy encontrando si altura es mayor que ancho, la posición izquierda de la imagen girada es incorrecta. Del mismo modo, si ancho es mayor que altura, la posición superior de la imagen girada es incorrecta.

Algunas notas:

  • IPMathUtilities es una clase de utilidad que escribí.
  • Estoy 100% seguro de que IPMathUtilities::CalculateRotatedImageSize() calcula el tamaño correcto del rectángulo requerido para adaptarse a toda la imagen girada. 100% seguro. Lo probé a fondo y funciona.
  • Hace poco hice una pregunta similar: Why is iplRotate() not giving me correct results?. Terminé renunciando a IPL/IPP y probando GDI +.

¿Alguna idea?

Respuesta

5

Después de la rotación, primero mueva la imagen de nuevo a la posición original, luego, además, a la mitad de la diferencia, el nuevo lienzo es más grande. Si su cálculo en CalculateRotatedImageSize es realmente correcto, debería ajustarse exactamente. Simplemente probado este código y parece que funciona:

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); 

Edit: Lo siento, por supuesto

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); 

es realmente lo mismo que

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

que es sólo el código que envió. Aunque parece funcionar bien para mí.

Edit2: tal vez el error es sólo

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

Trate

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

lugar

+0

Su primer bloque de código tenía algo que me estaba perdiendo - la traducción de vuelta desde el origen al espacio de la imagen fuente - Esa fue la clave que faltaba. Muchas gracias. Estoy tan aliviado de tener imágenes giradas centradas. ¡Gracias! –

+0

pero esto: g.TranslateTransform ((float) (org.Width/-2), (float) (org.Altura/-2)); g.RotateTransform (45, System.Drawing.Drawing2D.MatrixOrder.Append); g.TranslateTransform ((float) (rotation.Width/2), (float) (rotation.Height/2), System.Drawing.Drawing2D.MatrixOrder.Append); g.DrawImage (org, 0, 0); funciona para mí. ¿No es eso simplemente equivalente al código que publicaste? De todos modos, me alegro de que funcione ahora :) –

+0

No creo que sea equivalente: en mi código original, después de la rotación, me tradujeron directamente al espacio de la imagen de destino. En su código, primero está traduciendo al espacio de la imagen de origen, luego al espacio de la imagen de destino. Tienes una traducción extra, que es lo que me faltaba. :-) –

Cuestiones relacionadas