C# 围绕中心C旋转图像

C# 围绕中心C旋转图像,c#,rotation,picturebox,C#,Rotation,Picturebox,我在尝试旋转图片框中的图像时出现了一个小错误。 一切正常。但当旋转时,它不会围绕中心完美旋转。有点不明显,但有点烦人。这是我的密码: private readonly Bitmap _origPowerKnob = Properties.Resources.PowerKnob; //CODE WHERE ROTATE METHOD IS CALLED// using (Bitmap b = new Bitmap(_origPowerKnob)) {

我在尝试旋转图片框中的图像时出现了一个小错误。 一切正常。但当旋转时,它不会围绕中心完美旋转。有点不明显,但有点烦人。这是我的密码:

private readonly Bitmap _origPowerKnob = Properties.Resources.PowerKnob;

//CODE WHERE ROTATE METHOD IS CALLED//

using (Bitmap b = new Bitmap(_origPowerKnob))
                {
                    Bitmap newBmp = RotateImage(b, _powerAngle);
                    PowerKnob.BackgroundImage = newBmp;
                }

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);
            //move rotation point to center of image.
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.TranslateTransform((float) b.Width / 2, (float)b.Height / 2);
            //Rotate.        
            g.RotateTransform(angle);
            //Move image back.
            g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
            //Draw passed in image onto graphics object.
            g.DrawImage(b, new Point(0, 0));
            return returnBitmap;
        }
显示我的意思的图片:

它的旋转并不完美。有解决办法吗?我没有为我的picturebox属性设置什么?我试了很多


谢谢。

在这里,一个简单的测试表格会对您有很大帮助

将此代码放入新WinForms项目的Form1.cs文件中

using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace RotateImage {
    public partial class Form1 : Form {
        private readonly Graphics gfx;
        private readonly Bitmap originalBitmap;
        private readonly Bitmap redrawnBitmap;
        private readonly Stopwatch sw;

        private Timer timer;
        public Form1() {
            InitializeComponent();
            BackColor = Color.White;

            timer = new Timer();
            timer.Interval = 16;
            timer.Enabled = true;
            timer.Tick += timer_Tick;
            sw = new Stopwatch();
            sw.Start();

            gfx = CreateGraphics();

            originalBitmap = new Bitmap(256, 256);
            redrawnBitmap = new Bitmap(256, 256);
            using (var bmpGfx = Graphics.FromImage(originalBitmap)) {
                DrawCross(bmpGfx, new Point(128, 128), 128D, 0D);
            }
        }

        private void timer_Tick(object sender, EventArgs e) {
            // Rotate a full 90 degrees every 4 seconds.
            var angle = sw.Elapsed.TotalSeconds * 22.5D;

            var newBitmap = RotateImage(originalBitmap, (float)angle);

            // Clear the result of the last draw.
            gfx.FillRectangle(Brushes.White, new Rectangle(0, 0, 256, 256));

            gfx.DrawImageUnscaled(newBitmap, 0, 0);
            gfx.DrawEllipse(Pens.Blue, new Rectangle(124, 124, 8, 8));

            using (var redrawGfx = Graphics.FromImage(redrawnBitmap)) {
                // Clear what we have, we are redrawing on the same surface.
                redrawGfx.Clear(Color.White);
                DrawCross(redrawGfx, new Point(128, 128), 128D, angle);
            }
            gfx.DrawImageUnscaled(redrawnBitmap, 256, 0);
            gfx.DrawEllipse(Pens.Blue, new Rectangle(256+124, 124, 8, 8));
        }

        private void DrawCross(Graphics drawGfx, Point center, double radius, double angle) {
            // Turn our angle from degrees to radians.
            angle *= Math.PI / 180;

            // NOTE: Using PointF to lazily "fix" rounding errors and casting (flooring) double to int. When the result of the math below is say 127.9999999...
            // then it would get rounded down to 127. There is always Math.Round, which can round to nearest whole (away from .5) integer!
            // Draw one line of our cross.
            drawGfx.DrawLine(
                Pens.Red,
                new PointF((float)(Math.Cos(angle) * radius + center.X), (float)(Math.Sin(angle) * radius + center.Y)),
                new PointF((float)(Math.Cos(angle - Math.PI) * radius + center.X), (float)(Math.Sin(angle - Math.PI) * radius + center.Y)));

            // Rotate our angle 90 degrees.
            angle += Math.PI / 2D;

            // Draw the other line of our cross.
            drawGfx.DrawLine(
                Pens.Red,
                new PointF((float)(Math.Cos(angle) * radius + center.X), (float)(Math.Sin(angle) * radius + center.Y)),
                new PointF((float)(Math.Cos(angle - Math.PI) * radius + center.X), (float)(Math.Sin(angle - Math.PI) * radius + center.Y)));
        }

        // Your method, not mine.
        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);
            //move rotation point to center of image.
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.TranslateTransform((float) b.Width / 2, (float)b.Height / 2);
            //Rotate.        
            g.RotateTransform(angle);
            //Move image back.
            g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
            //Draw passed in image onto graphics object.
            g.DrawImage(b, new Point(0, 0));
            return returnBitmap;
        }
    }
}
观察两个十字围绕其中心旋转的情况。左一个是一个位图,它随方法旋转,右一个是每帧重绘一次。
也就是说,旋转代码没有问题,但源位图或显示容器可能有问题。

这是一个简单的测试表单对您有很大帮助的地方

将此代码放入新WinForms项目的Form1.cs文件中

using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace RotateImage {
    public partial class Form1 : Form {
        private readonly Graphics gfx;
        private readonly Bitmap originalBitmap;
        private readonly Bitmap redrawnBitmap;
        private readonly Stopwatch sw;

        private Timer timer;
        public Form1() {
            InitializeComponent();
            BackColor = Color.White;

            timer = new Timer();
            timer.Interval = 16;
            timer.Enabled = true;
            timer.Tick += timer_Tick;
            sw = new Stopwatch();
            sw.Start();

            gfx = CreateGraphics();

            originalBitmap = new Bitmap(256, 256);
            redrawnBitmap = new Bitmap(256, 256);
            using (var bmpGfx = Graphics.FromImage(originalBitmap)) {
                DrawCross(bmpGfx, new Point(128, 128), 128D, 0D);
            }
        }

        private void timer_Tick(object sender, EventArgs e) {
            // Rotate a full 90 degrees every 4 seconds.
            var angle = sw.Elapsed.TotalSeconds * 22.5D;

            var newBitmap = RotateImage(originalBitmap, (float)angle);

            // Clear the result of the last draw.
            gfx.FillRectangle(Brushes.White, new Rectangle(0, 0, 256, 256));

            gfx.DrawImageUnscaled(newBitmap, 0, 0);
            gfx.DrawEllipse(Pens.Blue, new Rectangle(124, 124, 8, 8));

            using (var redrawGfx = Graphics.FromImage(redrawnBitmap)) {
                // Clear what we have, we are redrawing on the same surface.
                redrawGfx.Clear(Color.White);
                DrawCross(redrawGfx, new Point(128, 128), 128D, angle);
            }
            gfx.DrawImageUnscaled(redrawnBitmap, 256, 0);
            gfx.DrawEllipse(Pens.Blue, new Rectangle(256+124, 124, 8, 8));
        }

        private void DrawCross(Graphics drawGfx, Point center, double radius, double angle) {
            // Turn our angle from degrees to radians.
            angle *= Math.PI / 180;

            // NOTE: Using PointF to lazily "fix" rounding errors and casting (flooring) double to int. When the result of the math below is say 127.9999999...
            // then it would get rounded down to 127. There is always Math.Round, which can round to nearest whole (away from .5) integer!
            // Draw one line of our cross.
            drawGfx.DrawLine(
                Pens.Red,
                new PointF((float)(Math.Cos(angle) * radius + center.X), (float)(Math.Sin(angle) * radius + center.Y)),
                new PointF((float)(Math.Cos(angle - Math.PI) * radius + center.X), (float)(Math.Sin(angle - Math.PI) * radius + center.Y)));

            // Rotate our angle 90 degrees.
            angle += Math.PI / 2D;

            // Draw the other line of our cross.
            drawGfx.DrawLine(
                Pens.Red,
                new PointF((float)(Math.Cos(angle) * radius + center.X), (float)(Math.Sin(angle) * radius + center.Y)),
                new PointF((float)(Math.Cos(angle - Math.PI) * radius + center.X), (float)(Math.Sin(angle - Math.PI) * radius + center.Y)));
        }

        // Your method, not mine.
        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);
            //move rotation point to center of image.
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.TranslateTransform((float) b.Width / 2, (float)b.Height / 2);
            //Rotate.        
            g.RotateTransform(angle);
            //Move image back.
            g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
            //Draw passed in image onto graphics object.
            g.DrawImage(b, new Point(0, 0));
            return returnBitmap;
        }
    }
}
观察两个十字围绕其中心旋转的情况。左一个是一个位图,它随方法旋转,右一个是每帧重绘一次。
也就是说,您的旋转代码没有问题,但源位图或显示容器可能有问题。

当您使用透明png时,例如,仅将图像的一部分填充颜色-代码将仅旋转变换png中包含数据的部分

我试着在png的顶部中心找到一个点,围绕图像的中心旋转500x500 px,它只识别出被着色的部分,所以它变成了反弹效果

我也试过用一个全彩色的500x500像素的图像,效果正常


希望对你有点帮助

例如,当使用透明png时,图像中只有一部分填充了颜色-代码将仅旋转变换png中包含数据的部分

我试着在png的顶部中心找到一个点,围绕图像的中心旋转500x500 px,它只识别出被着色的部分,所以它变成了反弹效果

我也试过用一个全彩色的500x500像素的图像,效果正常


希望对你有点帮助

我找到了一个解决方案,从它的中心获得旋转图像

[我的测试条件] 我正在用下一个考虑因素来测试它,如果它对你有效的话:3

1.-我使用的源图像是一个完美的正方形[LxL],取自png文件,正方形的大小不管,只要是LxL//宽度=高度=真

2.-我正在旋转的png源图像文件是透明的方形,我是从illustrator获得的

3.-我测试了大小为417x417、520x520和1024x1024的文件

[我可以分享给你的代码] 我刚刚给这个函数命名为RotateImageN,因为这是我尝试过的第五个解决方案:3我希望能有所帮助


对不起,我的英语和/或语法不好呵呵:3

我找到了一个解决方案,从旋转图像的中心获取旋转图像

[我的测试条件] 我正在用下一个考虑因素来测试它,如果它对你有效的话:3

1.-我使用的源图像是一个完美的正方形[LxL],取自png文件,正方形的大小不管,只要是LxL//宽度=高度=真

2.-我正在旋转的png源图像文件是透明的方形,我是从illustrator获得的

3.-我测试了大小为417x417、520x520和1024x1024的文件

[我可以分享给你的代码] 我刚刚给这个函数命名为RotateImageN,因为这是我尝试过的第五个解决方案:3我希望能有所帮助


对不起我的英语和/或语法呵呵:3

我在这里猜一下。这可能是因为您正在围绕像素旋转图像。如果图像的宽度或高度为偶数,则图像的正中心没有像素。从宽度/2或高度/2获得的像素不是图像的中心,因此不会围绕中心旋转图像。尝试使用奇数宽度和高度的图像,在图像的正中央有一个像素。我将在这里进行猜测。这可能是因为您正在围绕像素旋转图像。如果图像的宽度或高度为偶数,则图像的正中心没有像素。从宽度/2或高度/2获得的像素不是图像的中心,因此不会围绕中心旋转图像。试着用一张宽度和高度都很奇怪的图片,在图片的正中央有一个像素。我同意投了反对票,对不起!如果你做一个简单的编辑,我可以在向上投票中改变它。如果角度是90.0,这将失败。我不明白为什么?90.001有效,但不是90.0I一致否决,抱歉!如果你做一个简单的编辑,我可以在向上投票中改变它。如果角度是90.0,这将失败。我不明白为什么?90 1可以工作,但不是90.0