在 C# 中旋转图像时如何防止剪切?
题
我刚刚经历了很多事情,试图找出如何让图像旋转。这可行,但现在它正在剪辑,我不太确定如何让它停止......我正在使用这个rotateImage方法:
public static Image RotateImage(Image img, float rotationAngle)
{
//create an empty Bitmap image
Bitmap bmp = new Bitmap(img.Width, img.Height);
//turn the Bitmap into a Graphics object
Graphics gfx = Graphics.FromImage(bmp);
//now we set the rotation point to the center of our image
gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);
//now rotate the image
gfx.RotateTransform(rotationAngle);
gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);
//set the InterpolationMode to HighQualityBicubic so to ensure a high
//quality image once it is transformed to the specified size
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
//now draw our new image onto the graphics object
gfx.DrawImage(img, new System.Drawing.Point(0, 0));
//dispose of our Graphics object
gfx.Dispose();
//return the image
return bmp;
}
我尝试使空位图变大,但这仅适用于一侧,因为图像固定到位图的左上角。任何想法,将不胜感激!
解决方案
我发现从其他网站一些帮助。下面是我落得这样做对于那些你想知道谁:
// Rotates the input image by theta degrees around center.
public static Bitmap RotateImage(Bitmap bmpSrc, float theta)
{
Matrix mRotate = new Matrix();
mRotate.Translate(bmpSrc.Width / -2, bmpSrc.Height / -2, MatrixOrder.Append);
mRotate.RotateAt(theta, new System.Drawing.Point(0, 0), MatrixOrder.Append);
using (GraphicsPath gp = new GraphicsPath())
{ // transform image points by rotation matrix
gp.AddPolygon(new System.Drawing.Point[] { new System.Drawing.Point(0, 0), new System.Drawing.Point(bmpSrc.Width, 0), new System.Drawing.Point(0, bmpSrc.Height) });
gp.Transform(mRotate);
System.Drawing.PointF[] pts = gp.PathPoints;
// create destination bitmap sized to contain rotated source image
Rectangle bbox = boundingBox(bmpSrc, mRotate);
Bitmap bmpDest = new Bitmap(bbox.Width, bbox.Height);
using (Graphics gDest = Graphics.FromImage(bmpDest))
{ // draw source into dest
Matrix mDest = new Matrix();
mDest.Translate(bmpDest.Width / 2, bmpDest.Height / 2, MatrixOrder.Append);
gDest.Transform = mDest;
gDest.DrawImage(bmpSrc, pts);
return bmpDest;
}
}
}
private static Rectangle boundingBox(Image img, Matrix matrix)
{
GraphicsUnit gu = new GraphicsUnit();
Rectangle rImg = Rectangle.Round(img.GetBounds(ref gu));
// Transform the four points of the image, to get the resized bounding box.
System.Drawing.Point topLeft = new System.Drawing.Point(rImg.Left, rImg.Top);
System.Drawing.Point topRight = new System.Drawing.Point(rImg.Right, rImg.Top);
System.Drawing.Point bottomRight = new System.Drawing.Point(rImg.Right, rImg.Bottom);
System.Drawing.Point bottomLeft = new System.Drawing.Point(rImg.Left, rImg.Bottom);
System.Drawing.Point[] points = new System.Drawing.Point[] { topLeft, topRight, bottomRight, bottomLeft };
GraphicsPath gp = new GraphicsPath(points,
new byte[] { (byte)PathPointType.Start, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line });
gp.Transform(matrix);
return Rectangle.Round(gp.GetBounds());
}
其他提示
按着这些次序:
- 创建空的目标图像,其宽度和高度 = 旋转图像的边界框
- 将源图像绘制到目标图像上。源的 (0,0) 将映射到目标的 (ox,oy)
- 现在执行旋转目标图像的步骤。
完成上述步骤的详细信息:
W,H = 目的地的宽度和高度
w,h = 源的宽度和高度
c=|cos(θ)|
s=|sin(θ)|
w * c + h * s = W
w * s + h * c = H
ox = ( W - w ) / 2
oy = ( H - h ) / 2
public Bitmap rotateImage(Bitmap b, float angle)
{
if (angle > 0)
{
int l = b.Width;
int h = b.Height;
double an = angle * Math.PI / 180;
double cos = Math.Abs(Math.Cos(an));
double sin = Math.Abs(Math.Sin(an));
int nl = (int)(l * cos + h * sin);
int nh = (int)(l * sin + h * cos);
Bitmap returnBitmap = new Bitmap(nl, nh);
Graphics g = Graphics.FromImage(returnBitmap);
g.TranslateTransform((float)(nl-l) / 2, (float)(nh-h) / 2);
g.TranslateTransform((float)b.Width / 2, (float)b.Height / 2);
g.RotateTransform(angle);
g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
g.DrawImage(b, new Point(0, 0));
return returnBitmap;
}
else return b;
}
一个旋转的图像可能需要较大的位图被包含不削波。一个相当简单的方法来计算边界是变换矩阵向原边框的角落。由于新的位图较大时,原始图像必须被绘制为使得它的中心,而不是在(0,0)。
这证明在以下修订您的代码:
public static Image RotateImage(Image img, float rotationAngle)
{
int minx = int.MaxValue, maxx = int.MinValue, miny = int.MaxValue, maxy = int.MinValue;
using (Bitmap bmp = new Bitmap(1, 1)) // Dummy bitmap, so we can use TransformPoints to figure out the correct size.
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.TranslateTransform((float)img.Width / 2, (float)img.Height / 2);
g.RotateTransform(rotationAngle);
g.TranslateTransform(-(float)img.Width / 2, -(float)img.Height / 2);
Point[] pts = new Point[4];
pts[0] = new Point(0, 0);
pts[1] = new Point(img.Width, 0);
pts[2] = new Point(img.Width, img.Height);
pts[3] = new Point(0, img.Height);
g.TransformPoints(CoordinateSpace.Device, CoordinateSpace.World, pts);
foreach (Point pt in pts)
{
minx = Math.Min(minx, pt.X);
maxx = Math.Max(maxx, pt.X);
miny = Math.Min(miny, pt.Y);
maxy = Math.Max(maxy, pt.Y);
}
}
}
Bitmap bmp2 = new Bitmap(maxx - minx, maxy - miny);
using (Graphics g = Graphics.FromImage(bmp2))
{
g.TranslateTransform((float)bmp2.Width / 2, (float)bmp2.Height / 2);
g.RotateTransform(rotationAngle);
g.TranslateTransform(-(float)bmp2.Width / 2, -(float)bmp2.Height / 2);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(img, bmp2.Width / 2 - img.Width / 2, bmp2.Height / 2 - img.Height / 2);
}
return bmp2;
}
不隶属于 StackOverflow