LockBits 图像旋转方法不起作用?
嘿大家。在厌倦了 Get/Set Pixel 和 RotateTransfom 的缓慢性能和古怪行为后,我求助于使用 LockBits 进行 2d 位图图像旋转。这是我想出的代码,根据我的计算,它应该可以完美工作。事实并非如此。
private static void InternalRotateImage(Bitmap originalBitmap, Bitmap rotatedBitmap, PointF centerPoint, float theta)
{
BitmapData originalData = originalBitmap.LockBits(
new Rectangle(0, 0, originalBitmap.Width, originalBitmap.Height),
ImageLockMode.ReadOnly,
originalBitmap.PixelFormat);
BitmapData rotatedData = rotatedBitmap.LockBits(
new Rectangle(0, 0, rotatedBitmap.Width, rotatedBitmap.Height),
ImageLockMode.WriteOnly,
rotatedBitmap.PixelFormat);
unsafe
{
byte[,] A = new byte[originalData.Height * 2, originalBitmap.Width * 2];
byte[,] R = new byte[originalData.Height * 2, originalBitmap.Width * 2];
byte[,] G = new byte[originalData.Height * 2, originalBitmap.Width * 2];
byte[,] B = new byte[originalData.Height * 2, originalBitmap.Width * 2];
for (int y = 0; y < originalData.Height; y++)
{
byte* row = (byte*)originalData.Scan0 + (y * originalData.Stride);
for (int x = 0; x < originalData.Width; x++)
{
B[y, x] = row[x * 4];
G[y, x] = row[x * 4 + 1];
R[y, x] = row[x * 4 + 2];
A[y, x] = row[x * 4 + 3];
}
}
for (int y = 0; y < rotatedData.Height; y++)
{
byte* row = (byte*)rotatedData.Scan0 + (y * rotatedData.Stride);
for (int x = 0; x < rotatedData.Width; x++)
{
int newy = (int)Math.Abs((Math.Cos(theta) * (x - centerPoint.X) - Math.Sin(theta) * (y - centerPoint.Y) + centerPoint.X));
int newx = (int)Math.Abs((Math.Sin(theta) * (x - centerPoint.X) + Math.Cos(theta) * (y - centerPoint.Y) + centerPoint.Y));
row[x * 4] = B[newy, newx];
row[x * 4 + 1] = G[newy, newx];
row[x * 4 + 2] = R[newy, newx];
row[x * 4 + 3] = A[newy, newx];
}
}
}
originalBitmap.UnlockBits(originalData);
rotatedBitmap.UnlockBits(rotatedData);
}
有人有什么想法吗?我刚出来。提前致谢!
编辑: 这就是我最终使用的(非常感谢 Hans Passant):
private Image RotateImage(Image img, float rotationAngle)
{
Image image = new Bitmap(img.Width * 2, img.Height * 2);
Graphics gfx = Graphics.FromImage(image);
int center = (int)Math.Sqrt(img.Width * img.Width + img.Height * img.Height) / 2;
gfx.TranslateTransform(center, center);
gfx.RotateTransform(rotationAngle);
gfx.DrawImage(img, -img.Width / 2, -img.Height / 2);
return image;
}
它与他的相同,只是基于每个图像,而不是表单。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你正在给自己挖一个更深的坑。这很早就出错了,旋转位图的大小不是宽度 x 高度。这也是非常低效的。您需要启动 RotateTransform,重要的是还要使用 TranslateTransform 并选择正确的图像绘制位置。
下面是一个示例 Windows 窗体应用程序,它围绕其中心点旋转位图,偏移量刚好足以在旋转时接触窗体的内边缘。将计时器放在表单上,然后使用“项目 + 属性”、“资源”选项卡添加图像资源。将其命名为 SampleImage,它不必是方形的。使代码如下所示:
您可以通过创建 32bppPArgb 格式的位图来使绘制速度更快,我跳过了该步骤。
You are digging yourself a deeper hole. This goes wrong early, the size of the rotated bitmap is not Width x Height. It is also very inefficient. You need to get RotateTransform going, it is important to also use TranslateTransform and pick the correct image drawing location.
Here's a sample Windows Forms app that rotates a bitmap around its center point, offset just enough to touch the inner edge of the form when it rotates. Drop a Timer on the form and add an image resource with Project + Properties, Resource tab. Name it SampleImage, it doesn't have to be square. Make the code look like this:
You can make draw a lot faster by creating a bitmap in the 32bppPArgb format, I skipped that step.