public unsafe void Rotate(Bitmap bmp, float angle) { int width=bmp.Width; int height=bmp.Height; /* * right, down = positive * p1------------p2 * | | * p4------------p3 * * p1(0,0), p2(width-1,0), p3(width-1,height-1), p4(0,height-1) * * In this coordinate system(left-handed coordinate system), clockwise rotation matrix (theta): (cos -sin * sin cos) * */ //Calculate new vertex Point p1 = RotatePoint(new Point(0, 0), angle); Point p2 = RotatePoint(new Point(width - 1, 0), angle); Point p3 = RotatePoint(new Point(width - 1, height - 1), angle); Point p4 = RotatePoint(new Point(0, height - 1), angle); //Calculate new size int dstWidth = Math.Max(Math.Abs(p3.X - p1.X) + 1, Math.Abs(p4.X - p2.X) + 1); int dstHeight = Math.Max(Math.Abs(p3.Y - p1.X) + 1, Math.Abs(p4.Y - p2.Y) + 1); /* * Calculate offset between old and new coordinate system * left-top point in new coordiante system -> (0,0) * */ int offsetX = -new int[4] { p1.X, p2.X, p3.X, p4.X }.Min(); int offsetY = -new int[4] { p1.Y, p2.Y, p3.Y, p4.Y }.Min(); //create bmp Bitmap dstBitmap = new Bitmap(dstWidth, dstHeight, PixelFormat.Format32bppArgb); Rectangle srcRect = new Rectangle(0, 0, width, height); Rectangle dstRect = new Rectangle(0, 0, dstWidth, dstHeight); BitmapData srcBmpData = bmp.LockBits(srcRect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); BitmapData dstBmpData = dstBitmap.LockBits(dstRect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); //define sin and cos double sin = Math.Sin(angle * Math.PI / 180); double cos = Math.Cos(angle * Math.PI / 180); int srcStride = srcBmpData.Stride; int dstStride = dstBmpData.Stride; //define pointer byte* srcP = (byte*)srcBmpData.Scan0.ToPointer(); byte* dstP = (byte*)dstBmpData.Scan0.ToPointer(); Parallel.For(0,dstHeight,i=> { Parallel.For(0, dstWidth, j => { int k = 4 * j + i * dstStride; //Calculate corresponding point in old coordinate system Point oldPoint = RotatePoint(new Point(j - offsetX, i - offsetY), -angle); if (oldPoint.X >= 0 && oldPoint.X < width && oldPoint.Y >= 0 && oldPoint.Y < height) { dstP[k] = srcP[4 * oldPoint.X + srcStride * oldPoint.Y]; dstP[k + 1] = srcP[4 * oldPoint.X + srcStride * oldPoint.Y + 1]; dstP[k + 2] = srcP[4 * oldPoint.X + srcStride * oldPoint.Y + 2]; dstP[k + 3] = srcP[4 * oldPoint.X + srcStride * oldPoint.Y + 3]; } else { dstP[k] = dstP[k + 1] = dstP[k + 2] = 0xff; dstP[k + 3] = 0x0; } }); }); bmp.UnlockBits(srcBmpData); dstBitmap.UnlockBits(dstBmpData); bmp = (Bitmap)dstBitmap.Clone(); dstBitmap.Dispose(); width = bmp.Width; height = bmp.Height; }
上色
Code Block
2015年7月22日 星期三
[C#] Rotate bitmap with a special angle
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言