C# WinApp: Math: Rotate & Strech Bitmap according to mouse

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • ShadowLocke
    New Member
    • Jan 2008
    • 116

    C# WinApp: Math: Rotate & Strech Bitmap according to mouse

    Alright..the idea im trying to create is this:

    The user would click to set an initial point which would start drawing an image at said point. From this point the user would drag the mouse in order to strech the image plus drag up/down changing the rotation the image.

    Think about mspaint, the line tool, only with a bitmap.

    Im pretty good with C#, but for the life of me I cant figure out the math behind this.

    Any help/pointers would be very much appreciated.

    thanks in advance!
  • ShadowLocke
    New Member
    • Jan 2008
    • 116

    #2
    (the whole rotating part is where im at a loss)

    Comment

    • ShadowLocke
      New Member
      • Jan 2008
      • 116

      #3
      Okay so this is what i got so far..

      Code:
              public Bitmap RotateImage(Image bmp, float angle)
              {
      
                  Bitmap returnBitmap = new Bitmap(bmp.Width * 5, bmp.Height * 5);
                  Graphics g = Graphics.FromImage(returnBitmap);
      
                  g.RotateTransform(angle);
                  g.DrawImage(bmp, new Point(0, 0));
      
                  return returnBitmap;
              }
      
              public Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
              {
                  Bitmap result = new Bitmap(nWidth, nHeight);
                  using (Graphics g = Graphics.FromImage((Image)result))
                      g.DrawImage(b, 0, 0, nWidth, nHeight);
                  return result;
              }
      
              public double Distance(Point a, Point b)
              {
                  double xdiff = a.X - b.X;
                  double ydiff = a.Y - b.Y;
                  return Math.Sqrt(xdiff * xdiff + ydiff * ydiff);
              }  
      
              OnMouseDown(MouseEventArgs e)
              {
                  initialPoint = e.Location;
                  this.previewRenderer.InitialPoint = initialPoint;
                  mouseDown = true;
               }
      
              OnMouseMove(MouseEventArgs e)
              {
                  if (mouseDown)
                  {
                      double angle = Math.Atan2(e.Y - initialPoint.Y, e.X - initialPoint.X) * 180 / Math.PI;
                      
                      Bitmap b = ResizeBitmap(new Bitmap(bmp), Math.Max(5,(int)Distance(initialPoint, e.Location)) + 30, 25);
                      
                      b = RotateImage(b, (float)angle);
      
                     //This draws it
                     this.previewRenderer.BmpStamp = Icon.FromHandle(b.GetHicon());
                  }
              }
      So, my problem is now that once the Bitmap is rotated, it gets clipped with the old bitmaps rectangle. How can I get the rotated rectangle?

      Comment

      • ShadowLocke
        New Member
        • Jan 2008
        • 116

        #4
        Ahh, worked it all out

        here is the full example application:

        (Note: Rotation code modified from original found at http://www.devasp.net/net/articles/display/391.html)

        Code:
        using System;
        using System.Drawing;
        using System.Windows.Forms;
        using System.Drawing.Drawing2D;
        
        namespace WindowsApplication1
        {
            public partial class Form1 : Form
            {
        
                public Form1()
                {
                    InitializeComponent();
                    pictureBox1.MouseDown += new MouseEventHandler(pictureBox1_MouseDown);
                    pictureBox1.MouseMove += new MouseEventHandler(pictureBox1_MouseMove);
                    pictureBox1.MouseUp += new MouseEventHandler(pictureBox1_MouseUp);
        
                    Bitmap b = (Bitmap)pictureBox1.InitialImage;
                    b.MakeTransparent(Color.White);
                    pictureBox1.InitialImage = b;
                }
        
                Boolean mouseDown = false;
                Point initialP;
        
                void pictureBox1_MouseUp(object sender, MouseEventArgs e)
                {
                    mouseDown = false;
                }
                        
                void pictureBox1_MouseMove(object sender, MouseEventArgs e)
                {
                    if (mouseDown)
                    {
                        double angle = Math.Atan2(e.Y - initialP.Y, e.X - initialP.X) * 180 / Math.PI;
                        this.Text = angle.ToString();
        
                        Bitmap b = ResizeBitmap((Bitmap)pictureBox1.Image, Math.Max(5, (int)Distance(initialP, e.Location)), 25);
                        b.MakeTransparent(Color.White);
        
                        b = RotateImage(b, (float)-angle);
                        
                        Graphics g = pictureBox1.CreateGraphics();
        
                        g.Clear(Color.White);
        
                        if (angle < -90)
                            g.DrawImage(b, initialP.X - (b.Width - 25), initialP.Y - (b.Height - 25));
                        else if (angle < 0 && angle > -90)
                            g.DrawImage(b, initialP.X, initialP.Y - (b.Height - 25));
                        else if (angle > 90)
                            g.DrawImage(b, initialP.X - (b.Width - 25), initialP.Y);
                        else
                            g.DrawImage(b, initialP);
                        
                        g.Dispose();
        
        
                        b.Dispose();
                        this.Text += " -- " + pictureBox1.Image.Width.ToString() + ", " + pictureBox1.Image.Height.ToString();
                        
                    }
                }
        
                void pictureBox1_MouseDown(object sender, MouseEventArgs e)
                {
                    mouseDown = true;
                    initialP = e.Location;
                }
        
                public double Distance(Point a, Point b)
                {
                    double xdiff = a.X - b.X;
                    double ydiff = a.Y - b.Y;
                    return Math.Sqrt(xdiff * xdiff + ydiff * ydiff);
                }  
        
                public Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight) 
                { 
                    Bitmap result = new Bitmap(nWidth, nHeight);
                    using (Graphics g = Graphics.FromImage((Image)result))
                    {
                        g.InterpolationMode = InterpolationMode.NearestNeighbor;
                        g.DrawImage(b, 0, 0, nWidth, nHeight);
                    }
                    return result; 
                }
        
                private Bitmap RotateImage(Image bmp, float angle)
                { 
                    Bitmap bm_in = new Bitmap(bmp);
                    int wid = bm_in.Width;
                    int hgt = bm_in.Height;
                    Point[] corners = new Point[] {  new Point(0, 0),  new Point(wid, 0),  new Point(0, hgt), new Point(wid, hgt)};
        
                    int cx = wid / 2;
                    int cy = hgt / 2;
        
        
                    for (int i = 0; i < 4; i++)
                    {
                        corners[i].X -= cx;
                        corners[i].Y -= cy;
                    }
        
                    double theta = angle * Math.PI / 180.0;
                    double sin_theta = Math.Sin(theta);
                    double cos_theta = Math.Cos(theta);
                    int X;
                    int Y;
        
                    for (int i = 0; i < 4; i++)
                    {
                        X = corners[i].X;
                        Y = corners[i].Y;
        
                        corners[i].X = (int)(X * cos_theta + Y * sin_theta);
                        corners[i].Y = (int)(-X * sin_theta + Y * cos_theta);
                    }
        
                    int xmin = corners[0].X;
                    int ymin = corners[0].Y;
        
                    for (int i = 0; i < 4; i++)
                    {
                        if (xmin > corners[i].X)
                            xmin = corners[i].X;
        
                        if (ymin > corners[i].Y)
                            ymin = corners[i].Y;
                    }
        
                    for (int i = 0; i < 4; i++)
                    {
                        corners[i].X -= xmin;
                        corners[i].Y -= ymin;
                    }
        
                    Bitmap bm_out = new Bitmap((int)Math.Max(Math.Abs(-2 * xmin), 5), (int)Math.Max(Math.Abs(-2 * ymin), 5));
                    Graphics gr_out = Graphics.FromImage(bm_out);
                    Point[] newCorners = new Point[] { corners[0], corners[1], corners[2] };
        
                    gr_out.DrawImage(bm_in, newCorners);
        
                    return bm_out;
                }
            }
        }

        Comment

        Working...