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

发布于 2024-07-23 11:35:30 字数 1919 浏览 8 评论 0原文

我正在尝试使用 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()< /code> 没有给我正确的结果?。 我最终放弃了 IPL/IPP 并尝试了 GDI+。

有任何想法吗?

I'm trying to center a rotated image into a destination buffer using GDI+. The source buffer and the destination buffer are different sizes.

The source buffer is the size of the image data: (width, height).
The destination buffer is the size of the rectangle required to fit the entire rotated image: (rotatedWidth, rotatedHeight).

This is the code I'm trying:

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

This almost works. It's close - I'm finding if height is greater than width, the left position of the rotated image is incorrect. Similarly, if width is greater than height, the top position of the rotated image is incorrect.

Some notes:

  • IPMathUtilities is a utility class I wrote.
  • I'm 100% positive that IPMathUtilities::CalculateRotatedImageSize() calculates the correct size of the rectangle required to fit the entire rotated image. 100% certain. I've tested it thoroughly and it works.
  • I recently asked a similar question: Why is iplRotate() not giving me correct results?. I ended giving up on IPL/IPP and trying GDI+.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

筱武穆 2024-07-30 11:35:30

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

与您发布的代码 。 不过似乎对我来说效果很好。

错误只是

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

尝试

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

EDIT2:也许

After the rotate, first move the image back to the original position, then additionally by half the difference the new canvas is larger. If your calculation in CalculateRotatedImageSize is indeed correct, it should then fit exactly. Just tested this code and it seems to work:

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: sorry, of course

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

is really the same as

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

which is just the code you posted. Seems to work fine for me though.

EDIT2: perhaps the error is just

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

Try

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

instead

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文