在其中心旋转图形位图

时间:2014-10-23 10:18:25

标签: c# graphics

我正在为学校做一个项目,我们需要在不使用XNA的情况下在C#中进行基本的自上而下的比赛。 首先让我告诉你,到目前为止我们学到的关于编程的东西与制作甚至远程看起来像一场比赛的东西没什么关系。它没有比阵列,循环等更困难。 所以我们没有了解图形或类似的东西。

说完所有我有以下问题。

我们创建了一个Graphics对象,然后使用DrawImage并使用car.jpg中的位图。

graphics = e.Graphics;
graphics.RotateTransform(angle);
graphics.DrawImage(car, xPos, yPos, car.Width, car.Height);

然后我们等待按键,例如右键

case Keys.Right:
  if (angle != 360)
  {
    angle += 10;
  }
  else
  {
    angle = 0;
  }
  this.Refresh();
  break;

我们遇到的问题是旋转的枢轴点位于左上角。因此,只要我们将汽车移动到(20,25)之类并开始旋转它,它就会使用(0,0)作为旋转中心。我们想要实现的是将中心旋转点置于汽车的中心位置。

我们一直在尝试寻找更改centerX的{​​{1}}和centerY的方法,但我们得出的结论是,位图无法实现这一点。 我们一直在努力解决这个问题超过2天,似乎找不到任何解决方案来实现我们想要的东西。

我们在创建Graphics对象时遇到了什么问题,还是有一种完全不同的方式来改变汽车的RotateTransformcenterX

3 个答案:

答案 0 :(得分:5)

要绘制旋转的Bitmap,您需要执行几个步骤来准备Graphics对象:

  • 首先将原点移动到旋转的中点
  • 然后按所需角度旋转
  • 接下来你将其移回
  • 现在您可以绘制Bitmap
  • 最后重置了Graphics

这需要为每个位图完成。

以下是在位置(Bitmap bmp)处绘制xPos, yPos的代码中的步骤:

float moveX = bmp.Width / 2f + xPos;   
float moveY = bmp.Height / 2f+ xPosf;   
e.Graphics.TranslateTransform(moveX , moveY );
e.Graphics.RotateTransform(angle);
e.Graphics.TranslateTransform(-moveX , -moveY );
e.Graphics.DrawImage(bmp, xPos, yPos);  
e.Graphics.ResetTransform();

有一种可能的复杂情况:如果您的Bitmap分辨率与屏幕不同dpi,而不是Graphics,则必须先调整Bitmap {{1}设置!

要使dpi适应常规Bitmap,您只需执行

即可
96dpi

为了准备未来类似视网膜的显示器,您可以创建一个在启动时设置的类变量:

bmp.SetResolution(96,96);

并在加载int ScreenDpi = 96; private void Form1_Load(object sender, EventArgs e) { using (Graphics G = this.CreateGraphics()) ScreenDpi = (int)G.DpiX; } 后使用它:

Bitmap

正常bmp.SetResolution(ScreenDpi , ScreenDpi ); 方法使用DrawImage的左上角。您可能需要使用不同的Bitmap作为旋转点,也可能需要使用不同的Points作为汽车的虚拟位置,可能位于其正面的中间位置。

答案 1 :(得分:2)

这是静态类,它将图像绘制在所需区域内的所需位置。更改rotationangle值以旋转图像。您还可以平移和缩放图像。

在Project中添加此类,并从Win Form调用静态函数。

public static class FullImage
{

    public static Image image;  
    public static RectangleF DisplayRect, SourceRect;
    public static Size ParentBoundry;
    public static float rotationangle=0;

    internal static void Paint(Graphics graphics)
    {
        if (image == null)
            return;
        float hw = DisplayRect.X + DisplayRect.Width / 2f;
        float hh = DisplayRect.Y + DisplayRect.Height / 2f;

        System.Drawing.Drawing2D.Matrix m = graphics.Transform;
        m.RotateAt(rotationangle, new PointF(hw, hh), System.Drawing.Drawing2D.MatrixOrder.Append);
        graphics.Transform = m;
        graphics.DrawImage(image, new RectangleF(DisplayRect.X, DisplayRect.Y, DisplayRect.Width, DisplayRect.Height), SourceRect, GraphicsUnit.Pixel);
        graphics.ResetTransform();
    }


    public static void LoadImage(Image img)
    {         
        image = img;
        SizeF s = GetResizedSize(image, ParentBoundry);
        SourceRect = new RectangleF(0, 0, image.Width, image.Height);
        DisplayRect =  new RectangleF(ParentBoundry.Width / 2 - s.Width / 2, ParentBoundry.Height / 2 - s.Height / 2, s.Width, s.Height);
    }

    public static Size GetResizedSize(Image ImageToResize, Size size)
    {
        int sourceWidth = ImageToResize.Width;
        int sourceHeight = ImageToResize.Height;

        float nPercent = 0;
        float nPercentW = 0;
        float nPercentH = 0;

        nPercentW = ((float)size.Width / (float)sourceWidth);
        nPercentH = ((float)size.Height / (float)sourceHeight);

        if (nPercentH < nPercentW)
            nPercent = nPercentH;
        else
            nPercent = nPercentW;

        int destWidth = (int)(sourceWidth * nPercent);
        int destHeight = (int)(sourceHeight * nPercent);

        return new Size(destWidth, destHeight);
    }

    internal static void MouseWheel(int delta)
    {

        if (delta > 0)
            DisplayRect = ZoomImage(DisplayRect,CurrentMouse, .1f);
        else
            DisplayRect = ZoomImage(DisplayRect, CurrentMouse, -.1f);

    }

private RectangleF ZoomImage(RectangleF ImageRectangle, PointF MouseLocation, float ScaleFactor)
    {

        /// Original Size and Location
        SizeF OriginalSize = ImageRectangle.Size;
        PointF OriginalPoint = ImageRectangle.Location;

        ///Mouse cursor location -located in width% and height% of totaloriginal image
        float mouse_widthpercent = System.Math.Abs(OriginalPoint.X - MouseLocation.X) / OriginalSize.Width * 100;
        float mouse_heightpercent = System.Math.Abs(OriginalPoint.Y - MouseLocation.Y) / OriginalSize.Height * 100;

        ///Zoomed Image by scalefactor
        SizeF FinalSize = new SizeF(OriginalSize.Width + OriginalSize.Width * ScaleFactor, OriginalSize.Height + OriginalSize.Height * ScaleFactor);
        if (FinalSize.Width < 15 || FinalSize.Height < 15)
            return ImageRectangle;
        if (FinalSize.Width > 60000 || FinalSize.Height > 60000)
            return ImageRectangle;
        /// How much width increases and height increases
        float widhtincrease = FinalSize.Width - OriginalSize.Width;
        float heightincrease = FinalSize.Height - OriginalSize.Height;

        /// Adjusting Image location after zooming the image
        PointF FinalLocation = new System.Drawing.PointF(OriginalPoint.X - widhtincrease * mouse_widthpercent / 100,
              OriginalPoint.Y - heightincrease * mouse_heightpercent / 100);
        ImageRectangle = new RectangleF(FinalLocation.X, FinalLocation.Y, FinalSize.Width, FinalSize.Height);

        return ImageRectangle;
    }

    static bool drag = false;
    static Point Initial, CurrentMouse;  

    internal static void MouseMove(Point location)
    {          
        CurrentMouse = location;
        if (drag)
        {
            DisplayRect = new RectangleF(DisplayRect.X + location.X - Initial.X, DisplayRect.Y + location.Y - Initial.Y, DisplayRect.Width, DisplayRect.Height);
            Initial = location;
        }

    }
    internal static void MouseDown(Point location)
    {       
        Initial = location;
        drag = true;
    }

    internal static void MouseUp(Point location)
    {
        drag = false;
    }        

}

在项目中添加此代码后(更好地添加单独的cs文件),从Win Form类(Form1.cs)调用函数。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.SetStyle(ControlStyles.ResizeRedraw, true);
        FullImage.ParentBoundry = new Size(this.Width, this.Height);
        // Enter the image path  
        FullImage.LoadImage(Image.FromFile(@"D:\a.jpg"));
    }

    //Create a paint event
    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        FullImage.Paint(e.Graphics);
    }

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        Vault.FullImage.MouseDown(e.Location);
        this.Invalidate();
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        Vault.FullImage.MouseMove(e.Location);
        this.Invalidate();
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        Vault.FullImage.MouseUp(e.Location);
        this.Invalidate();
    }
    protected override void OnMouseWheel(MouseEventArgs e)
    {
        Vault.FullImage.MouseWheel(e.Delta);
        this.Invalidate();
    }

现在,如果你想旋转图像,只需设置你想要的值(使用滑块,按钮或添加更多功能来检测鼠标移动然后旋转)

示例:添加一个按钮,每次单击按钮都会将值增加1。

  private void button1_clicked(object sender, EventArgs e)
  {
       FullImage.rotationangle++;
       this.invalidate();
  }

答案 2 :(得分:0)

要从中心旋转左上角,首先需要知道它的角度,然后按所需的角度调整它,并按新角度重新计算新的左上角:

var newXPos = (int)(xPos + car.Width / 2.0 + Math.Cos(Math.Atan2(-car.Height / 2, -car.Width / 2)
    + angle / 180.0 * Math.PI) * -car.Width / 2.0);
var newYPos = (int)(yPos + car.Height / 2.0 + Math.Sin(Math.Atan2(-car.Height / 2, -car.Width / 2)
    + angle / 180.0 * Math.PI) * -car.Height / 2.0);
graphics = e.Graphics;
graphics.RotateTransform(angle);
graphics.DrawImage(car, newXPos, newYPos, car.Width, car.Height);
相关问题