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