如何使用GDI+将旋转的图像居中?

7

我正在尝试使用GDI+将旋转的图像居中到目标缓冲区。源缓冲区和目标缓冲区的大小不同。

源缓冲区的大小为图像数据的大小:(宽度,高度)
目标缓冲区的大小是适合整个旋转图像的矩形大小:(旋转后的宽度,旋转后的高度)

这是我正在尝试的代码:

// 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是我编写的实用程序类。 - 我非常确定IPMathUtilities :: CalculateRotatedImageSize()计算出了适合整个旋转图像所需的矩形的正确大小。我百分之百确定。我已经彻底测试过它,它有效。 - 我最近问了一个类似的问题:为什么iplRotate()没有给我正确的结果?。最后我放弃了IPL / IPP并尝试使用GDI +。
有什么想法吗?
1个回答

6

旋转后,首先将图像移回原始位置,然后再额外增加一半的差值来扩大新画布的大小。如果您在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);

这只是您发布的代码。不过,对我来说似乎工作正常。

编辑2:也许错误只是

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

请尝试

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

替代


你的第一个代码块有我所缺失的东西 - 从原始图像空间到源图像空间的转换 - 这是缺失的关键。非常感谢。我很高兴能够得到居中旋转的图像。谢谢! - Rob
但是这个代码:g.TranslateTransform((float)(org.Width / -2), (float)(org.Height / -2)); g.RotateTransform(45, System.Drawing.Drawing2D.MatrixOrder.Append); g.TranslateTransform((float)(rotated.Width / 2), (float)(rotated.Height / 2), System.Drawing.Drawing2D.MatrixOrder.Append); g.DrawImage(org, 0, 0);对我来说可以工作。这不就等同于你发布的代码吗?无论如何,很高兴现在它可以工作了 :) - Ben Schwehn
不幸的是,这对于矩形源图像没有用...它们仍然偏离中心 :-( - Rob
我认为代码是等价的。然而,在我的测试中它确实可以在更大的画布中正确居中。我还没有实现CalculateRotatedImageSize,所以它只是一个更大的框架,但是对于不同的角度和不同的画布大小,它绝对是居中的。我可以发布一个C#示例项目,这可能有助于你了解与你的代码的差异? - Ben Schwehn
太好了,我很想看一下这个示例项目! - Rob
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接