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

这与他的相同,只是基于每个图像,而不是forms。

你正在挖掘自己更深的洞。 这很早就出错了,旋转位图的大小不是Width x Height。 这也是非常低效的。 您需要进行RotateTransform,重要的是还要使用TranslateTransform并选择正确的图像绘制位置。

下面是一个示例Windows窗体应用程序,它围绕其中心点旋转位图,偏移刚好足以在旋转时触摸窗体的内边缘。 在表单上删除一个Timer,并使用Project + Properties,Resource选项卡添加一个图像资源。 将其命名为SampleImage,它不必是方形的。 使代码看起来像这样:

 public partial class Form1 : Form { private float mDegrees; private Image mBmp; public Form1() { InitializeComponent(); mBmp = Properties.Resources.SampleImage; timer1.Enabled = true; timer1.Interval = 50; timer1.Tick += new System.EventHandler(this.timer1_Tick); this.DoubleBuffered = true; } private void timer1_Tick(object sender, EventArgs e) { mDegrees += 3.0F; this.Invalidate(); } protected override void OnPaint(PaintEventArgs e) { int center = (int)Math.Sqrt(mBmp.Width * mBmp.Width + mBmp.Height * mBmp.Height) / 2; e.Graphics.TranslateTransform(center, center); e.Graphics.RotateTransform(mDegrees); e.Graphics.DrawImage(mBmp, -mBmp.Width/2, -mBmp.Height/2); } } 

通过以32bppPArgb格式创建位图,您可以更快地绘制绘图,我跳过了这一步。