C# 如何旋转图像,然后移动到左上角0,0,而不切断图像

C# 如何旋转图像,然后移动到左上角0,0,而不切断图像,c#,gdi+,C#,Gdi+,如何旋转图像,然后移动到左上角0,0,而不切断图像 请阅读代码中的注释。我在第三步被卡住了 我认为用三角学应该能解决这个问题 谢谢 private Bitmap RotateImage(Bitmap b, float angle) { //create a new empty bitmap to hold rotated image Bitmap returnBitmap = new Bitmap(b.Width, b.Height); //make a graphics

如何旋转图像,然后移动到左上角0,0,而不切断图像

请阅读代码中的注释。我在第三步被卡住了 我认为用三角学应该能解决这个问题

谢谢

private Bitmap RotateImage(Bitmap b, float angle)
{
    //create a new empty bitmap to hold rotated image
    Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
    //make a graphics object from the empty bitmap
    Graphics g = Graphics.FromImage(returnBitmap);
    //STEP 1 move rotation point to top left
    g.TranslateTransform((float)0, (float)0);
    //STEP 2 rotate
    g.RotateTransform(angle);
    //STEP 3 move image back to top left without cutting off the image
    //SOME trigonometry calculation here
    int newY = b.Height;
    g.TranslateTransform(-(float)0, -newY);
    //draw passed in image onto graphics object
    g.DrawImage(b, new Point(0, 0));
    return returnBitmap;
}

这包括“三角学”吗?我已经做了第0步,因为我认为你需要先做。通过这种方式,您可以计算得到的位图的大小,它会更大-请参阅代码中的注释

    private Bitmap RotateImage(Bitmap b, float Angle) {
        // The original bitmap needs to be drawn onto a new bitmap which will probably be bigger 
        // because the corners of the original will move outside the original rectangle.
        // An easy way (OK slightly 'brute force') is to calculate the new bounding box is to calculate the positions of the 
        // corners after rotation and get the difference between the maximum and minimum x and y coordinates.
        float wOver2 = b.Width / 2.0f;
        float hOver2 = b.Height / 2.0f;
        float radians = -(float)(Angle / 180.0 * Math.PI);
        // Get the coordinates of the corners, taking the origin to be the centre of the bitmap.
        PointF[] corners = new PointF[]{
            new PointF(-wOver2, -hOver2),
            new PointF(+wOver2, -hOver2),
            new PointF(+wOver2, +hOver2),
            new PointF(-wOver2, +hOver2)
        };

        for (int i = 0; i < 4; i++) {
            PointF p = corners[i];
            PointF newP = new PointF((float)(p.X * Math.Cos(radians) - p.Y * Math.Sin(radians)), (float)(p.X * Math.Sin(radians) + p.Y * Math.Cos(radians)));
            corners[i] = newP;
        }

        // Find the min and max x and y coordinates.
        float minX = corners[0].X;
        float maxX = minX;
        float minY = corners[0].Y;
        float maxY = minY;
        for (int i = 1; i < 4; i++) {
            PointF p = corners[i];
            minX = Math.Min(minX, p.X);
            maxX = Math.Max(maxX, p.X);
            minY = Math.Min(minY, p.Y);
            maxY = Math.Max(maxY, p.Y);
        }

        // Get the size of the new bitmap.
        SizeF newSize = new SizeF(maxX - minX, maxY - minY);
        // ...and create it.
        Bitmap returnBitmap = new Bitmap((int)Math.Ceiling(newSize.Width), (int)Math.Ceiling(newSize.Height));
        // Now draw the old bitmap on it.
        using (Graphics g = Graphics.FromImage(returnBitmap)) {
            g.TranslateTransform(newSize.Width / 2.0f, newSize.Height / 2.0f);
            g.RotateTransform(Angle);
            g.TranslateTransform(-b.Width / 2.0f, -b.Height / 2.0f);

            g.DrawImage(b, 0, 0);
        }

        return returnBitmap;
    }
私有位图旋转图像(位图b,浮动角度){
//原始位图需要绘制到新位图上,新位图可能会更大
//因为原始矩形的角将移动到原始矩形之外。
//一种简单的方法(可以略带“蛮力”)是计算新的边界框,即计算
//旋转后的角点,并获得最大和最小x和y坐标之间的差值。
浮子宽度2=b.宽度/2.0f;
浮动悬停2=b.高度/2.0f;
浮动弧度=-(浮动)(角度/180.0*Math.PI);
//获取角点的坐标,将原点作为位图的中心。
PointF[]角点=新的PointF[]{
新的点F(-wOver2,-hOver2),
新点F(+wOver2,-hOver2),
新的PointF(+wOver2,+hOver2),
新点F(-wOver2,+hOver2)
};
对于(int i=0;i<4;i++){
点f p=角点[i];
PointF newP=新的PointF((浮点)(p.X*Math.Cos(弧度)-p.Y*Math.Sin(弧度)),(浮点)(p.X*Math.Sin(弧度)+p.Y*Math.Cos(弧度));
角[i]=newP;
}
//找到最小和最大x和y坐标。
float minX=角点[0].X;
浮点最大值=最小值;
float minY=角[0].Y;
浮动最大值=最小值;
对于(int i=1;i<4;i++){
点f p=角点[i];
minX=Math.Min(minX,p.X);
maxX=数学最大值(maxX,p.X);
minY=Math.Min(minY,p.Y);
maxY=Math.Max(maxY,p.Y);
}
//获取新位图的大小。
SizeF newSize=newsizef(maxX-minX,maxY-minY);
//…并创造它。
位图返回位图=新位图((int)数学天花板(newSize.Width),(int)数学天花板(newSize.Height));
//现在在其上绘制旧位图。
使用(Graphics g=Graphics.FromImage(返回位图)){
g、 TranslateTransform(newSize.Width/2.0f,newSize.Height/2.0f);
g、 旋转变换(角度);
g、 平移变换(-b.宽度/2.0f,-b.高度/2.0f);
g、 绘图图像(b,0,0);
}
返回位图;
}

这包括“三角学”吗?我已经做了第0步,因为我认为你需要先做。通过这种方式,您可以计算得到的位图的大小,它会更大-请参阅代码中的注释

    private Bitmap RotateImage(Bitmap b, float Angle) {
        // The original bitmap needs to be drawn onto a new bitmap which will probably be bigger 
        // because the corners of the original will move outside the original rectangle.
        // An easy way (OK slightly 'brute force') is to calculate the new bounding box is to calculate the positions of the 
        // corners after rotation and get the difference between the maximum and minimum x and y coordinates.
        float wOver2 = b.Width / 2.0f;
        float hOver2 = b.Height / 2.0f;
        float radians = -(float)(Angle / 180.0 * Math.PI);
        // Get the coordinates of the corners, taking the origin to be the centre of the bitmap.
        PointF[] corners = new PointF[]{
            new PointF(-wOver2, -hOver2),
            new PointF(+wOver2, -hOver2),
            new PointF(+wOver2, +hOver2),
            new PointF(-wOver2, +hOver2)
        };

        for (int i = 0; i < 4; i++) {
            PointF p = corners[i];
            PointF newP = new PointF((float)(p.X * Math.Cos(radians) - p.Y * Math.Sin(radians)), (float)(p.X * Math.Sin(radians) + p.Y * Math.Cos(radians)));
            corners[i] = newP;
        }

        // Find the min and max x and y coordinates.
        float minX = corners[0].X;
        float maxX = minX;
        float minY = corners[0].Y;
        float maxY = minY;
        for (int i = 1; i < 4; i++) {
            PointF p = corners[i];
            minX = Math.Min(minX, p.X);
            maxX = Math.Max(maxX, p.X);
            minY = Math.Min(minY, p.Y);
            maxY = Math.Max(maxY, p.Y);
        }

        // Get the size of the new bitmap.
        SizeF newSize = new SizeF(maxX - minX, maxY - minY);
        // ...and create it.
        Bitmap returnBitmap = new Bitmap((int)Math.Ceiling(newSize.Width), (int)Math.Ceiling(newSize.Height));
        // Now draw the old bitmap on it.
        using (Graphics g = Graphics.FromImage(returnBitmap)) {
            g.TranslateTransform(newSize.Width / 2.0f, newSize.Height / 2.0f);
            g.RotateTransform(Angle);
            g.TranslateTransform(-b.Width / 2.0f, -b.Height / 2.0f);

            g.DrawImage(b, 0, 0);
        }

        return returnBitmap;
    }
私有位图旋转图像(位图b,浮动角度){
//原始位图需要绘制到新位图上,新位图可能会更大
//因为原始矩形的角将移动到原始矩形之外。
//一种简单的方法(可以略带“蛮力”)是计算新的边界框,即计算
//旋转后的角点,并获得最大和最小x和y坐标之间的差值。
浮子宽度2=b.宽度/2.0f;
浮动悬停2=b.高度/2.0f;
浮动弧度=-(浮动)(角度/180.0*Math.PI);
//获取角点的坐标,将原点作为位图的中心。
PointF[]角点=新的PointF[]{
新的点F(-wOver2,-hOver2),
新点F(+wOver2,-hOver2),
新的PointF(+wOver2,+hOver2),
新点F(-wOver2,+hOver2)
};
对于(int i=0;i<4;i++){
点f p=角点[i];
PointF newP=新的PointF((浮点)(p.X*Math.Cos(弧度)-p.Y*Math.Sin(弧度)),(浮点)(p.X*Math.Sin(弧度)+p.Y*Math.Cos(弧度));
角[i]=newP;
}
//找到最小和最大x和y坐标。
float minX=角点[0].X;
浮点最大值=最小值;
float minY=角[0].Y;
浮动最大值=最小值;
对于(int i=1;i<4;i++){
点f p=角点[i];
minX=Math.Min(minX,p.X);
maxX=数学最大值(maxX,p.X);
minY=Math.Min(minY,p.Y);
maxY=Math.Max(maxY,p.Y);
}
//获取新位图的大小。
SizeF newSize=newsizef(maxX-minX,maxY-minY);
//…并创造它。
位图返回位图=新位图((int)数学天花板(newSize.Width),(int)数学天花板(newSize.Height));
//现在在其上绘制旧位图。
使用(Graphics g=Graphics.FromImage(返回位图)){
g、 TranslateTransform(newSize.Width/2.0f,newSize.Height/2.0f);
g、 旋转变换(角度);
g、 平移变换(-b.宽度/2.0f,-b.高度/2.0f);
g、 绘图图像(b,0,0);
}
返回位图;
}

TranslateTransform(0,0)
不会做你认为它会做的事情。您需要
TranslateTransform(b.Width/2,b.Height/2)
。这将使图像的中心位于原点。然而,剩下的我就不懂了。我想把所有的东西移到0,0坐标会使正弦,余弦,切线的事情变得容易得多。我的示例不需要移动到0,0,因为已经位于0,0
TranslateTransform(0,0)
的图像不符合您的想法。您需要
TranslateTransform(b.Width/2,b.Height/2)
。这将使图像的中心位于原点。然而,剩下的我就不懂了。我想把所有的东西移到0,0坐标会使正弦,co更容易