Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotating an image according to two points

Tags:

c#

math

geometry

I have two points on my form, and a picturebox, like this:

*

   [^]
   [ ]

          *

I would like to align the picturebox with the points, so that it looks like this:

*

   \^\
    \ \

          *

How would I calculate the angle and how would I rotate the PictureBox?

Currently I'm using this:

double xDifference = Math.Abs(point2.X - point1.X);
double yDifference = Math.Abs(point2.Y - point1.Y);

double angle = Math.Atan(yDifference / xDifference) * 180 / Math.PI;

But that doesn't work since the x and y values are absolute, and thus they can't calculate it if point 2 is left of point 1.

To rotate the image, I found the following function:

    public Bitmap rotateImage(Image image, PointF offset, float angle) {
        // Create a new empty bitmap to hold rotated image
        Bitmap rotatedBmp = new Bitmap(image.Width, image.Height);
        rotatedBmp.SetResolution(image.HorizontalResolution, image.VerticalResolution);

        // Make a graphics object from the empty bitmap
        Graphics g = Graphics.FromImage(rotatedBmp);

        // Put the rotation point in the center of the image
        g.TranslateTransform(offset.X, offset.Y);

        // Rotate the image
        g.RotateTransform(angle);

        // Move the image back
        g.TranslateTransform(-offset.X, -offset.Y);

        // Draw passed in image onto graphics object
        g.DrawImage(image, new PointF(0, 0));

        return rotatedBmp;
    }

How would I use that function? I'm not sure what values to insert for offset.

Thanks

like image 454
Qub1 Avatar asked Dec 18 '14 13:12

Qub1


People also ask

How to rotate an image?

How To Rotate An Image? 1 1. Click the “Select Image” to load an image. 2 2. Click on the rotate buttons to rotate the image. 3 3. Click the “Rotate Image” button to download the image.

How do you rotate an object to match the angle?

You want to rotate an object to match the angle of an object in your drawing. You can rotate an object based on a known angle or the angle of two points you select. In the following example, you want to rotate the chair and desk on the right to match the chair and table on the left.

How to rotate the image by 30⁰ in clockwise direction using imutils?

Script: Rotate the image by 30⁰ in clockwise direction using Imutils. The imutils.rotate function is called to rotate the image in the desired direction by passing the image and angle of rotation as arguments.

Is there a way to separate 2D image rotation?

You can separate 2D image rotation into skews and scalings, which preserve the image quality. Show activity on this post. It seems like the example you've provided is some edge detection kernel.


1 Answers

I do not like to use angle when it is not necessary.

Here, you just want to change of orthonormal basis.

From {X;Y} you want to move to {U;V} where V (of norm 1) is parallel to AB (or point1 point2).

Because {U;V} is an orthonormal basis, Ux = Vy and Uy = -Vx.

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

namespace CsiChart
{
    public partial class CustomControl1 : Control
    {
        private const float EPSILON = 1e-6f;

        private Image _image;
        private ImageLayout _imageLayout = ImageLayout.Center;
        private PointF _pointA = new PointF(0, 100);
        private PointF _pointB = new PointF(100, 0);

        public CustomControl1()
        {
            InitializeComponent();
        }

        public Image Image
        {
            get { return _image; }
            set
            {
                if (Equals(_image, value)) return;
                _image = value;
                Invalidate();
                OnImageChanged(EventArgs.Empty);
            }
        }

        public event EventHandler ImageChanged;

        public ImageLayout ImageLayout
        {
            get { return _imageLayout; }
            set
            {
                if (Equals(_imageLayout, value)) return;
                _imageLayout = value;
                Invalidate();
                OnImageLayoutChanged(EventArgs.Empty);
            }
        }

        public event EventHandler ImageLayoutChanged;

        public PointF PointA
        {
            get { return _pointA; }
            set
            {
                if (Equals(_pointA, value)) return;
                _pointA = value;
                Invalidate();
                OnPointAChanged(EventArgs.Empty);
            }
        }

        public event EventHandler PointAChanged;

        public PointF PointB
        {
            get { return _pointB; }
            set
            {
                if (Equals(_pointB, value)) return;
                _pointB = value;
                Invalidate();
                OnPointBChanged(EventArgs.Empty);
            }
        }

        public event EventHandler PointBChanged;

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
            if (DesignMode) return;

            var g = pe.Graphics;
            g.Clear(BackColor);         

            var image = Image;
            if (image == null) return;

            var clientRectangle = ClientRectangle;
            var centerX = clientRectangle.X + clientRectangle.Width / 2;
            var centerY = clientRectangle.Y + clientRectangle.Height / 2;

            var srcRect = new Rectangle(new Point(0, 0), image.Size);

            var pointA = PointA;
            var pointB = PointB;

            // Compute U, AB vector normalized.
            var vx = pointB.X - pointA.X;
            var vy = pointB.Y - pointA.Y;
            var vLength = (float) Math.Sqrt(vx*vx + vy*vy);
            if (vLength < EPSILON)
            {
                vx = 0;
                vy = 1;
            }
            else
            {
                vx /= vLength;
                vy /= vLength;
            }

            var oldTransform = g.Transform;

            // Change basis to U,V
            // We also take into acount the inverted on screen Y.
            g.Transform = new Matrix(-vy, vx, -vx, -vy, centerX, centerY);

            var imageWidth = image.Width;
            var imageHeight = image.Height;

            RectangleF destRect;
            switch (ImageLayout)
            {
                case ImageLayout.None:
                    destRect = new Rectangle(0, 0, imageWidth, imageHeight);
                    break;
                case ImageLayout.Center:
                    destRect = new Rectangle(-imageWidth/2, -imageHeight/2, imageWidth, imageHeight);
                    break;
                case ImageLayout.Zoom:
                    // XY aligned bounds size of the image.
                    var imageXSize = imageWidth*Math.Abs(vy) + imageHeight*Math.Abs(vx);
                    var imageYSize = imageWidth*Math.Abs(vx) + imageHeight*Math.Abs(vy);

                    // Get best scale to fit.
                    var s = Math.Min(clientRectangle.Width/imageXSize, clientRectangle.Height/imageYSize);
                    destRect = new RectangleF(-imageWidth*s/2, -imageHeight*s/2, imageWidth*s, imageHeight*s);
                    break;
                default:
                    throw new InvalidOperationException();
            }

            g.DrawImage(image, destRect, srcRect, GraphicsUnit.Pixel);
            g.Transform = oldTransform;
        }

        protected virtual void OnImageChanged(EventArgs eventArgs)
        {
            var handler = ImageChanged;
            if (handler == null) return;
            handler(this, eventArgs);
        }

        protected virtual void OnImageLayoutChanged(EventArgs eventArgs)
        {
            var handler = ImageLayoutChanged;
            if (handler == null) return;
            handler(this, eventArgs);
        }

        private void OnPointAChanged(EventArgs eventArgs)
        {
            var handler = PointAChanged;
            if (handler == null) return;
            handler(this, eventArgs);
        }

        private void OnPointBChanged(EventArgs eventArgs)
        {
            var handler = PointBChanged;
            if (handler == null) return;
            handler(this, eventArgs);
        }
    }
}
like image 125
Orace Avatar answered Sep 28 '22 12:09

Orace