Jump to content

  • Log In with Google      Sign In   
  • Create Account

[.net] Rotating a Bitmap in C#


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 skauert   Members   -  Reputation: 100

Like
0Likes
Like

Posted 09 March 2010 - 03:18 AM

Hello fellow Gamedevs.

I'm preparing a basic engine setup for my game project that I'm going to do in C#. This is an assignment for university, and we've been instructed to not use APIs such as OpenGL and DirectX. I've made a basic image rendering class which is almost complete, I just haven't fully completed the method for rotating a Bitmap.

Personally, I don't feel like I'm 100% educated in terms of rotation logic and such. What I'm hoping is that the reponses to this, code samples or not, will help shed some light on the issue at hand. I'm aware of how rotation works for matrices and such, just not how to properly apply them to a bitmap.

The rotation function that I've used is courtesy of vcskicks.com.

       private System.Drawing.Image RotateImage(System.Drawing.Image inputImg, double degreeAngle)
        {
            //Corners of the image
            PointF[] rotationPoints = { new PointF(0, 0),
                                        new PointF(inputImg.Width, 0),
                                        new PointF(0, inputImg.Height),
                                        new PointF(inputImg.Width, inputImg.Height)};

            //Rotate the corners
            PointMath.RotatePoints(rotationPoints, new PointF(inputImg.Width / 2.0f, inputImg.Height / 2.0f), degreeAngle);

            //Get the new bounds given from the rotation of the corners
            //(avoid clipping of the image)
            Rectangle bounds = PointMath.GetBounds(rotationPoints);

            //An empy bitmap to draw the rotated image
            Bitmap rotatedBitmap = new Bitmap(bounds.Width, bounds.Height);

            using (Graphics g = Graphics.FromImage(rotatedBitmap))
            {
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;

                //Transformation matrix
                Matrix m = new Matrix();
                m.RotateAt((float)degreeAngle, new PointF(inputImg.Width / 2.0f, inputImg.Height / 2.0f));
                m.Translate(-bounds.Left, -bounds.Top, MatrixOrder.Append); //shift to compensate for the rotation

                g.Transform = m;
                g.Clear(Color.White);
                g.DrawImage(inputImg, 0, 0);
            }
            return (System.Drawing.Image)rotatedBitmap;
        }




    public static class PointMath
    {
        private static double DegreeToRadian(double angle)
        {
            return Math.PI * angle / 180.0;
        }

        public static PointF RotatePoint(PointF pnt, double degreeAngle)
        {
            return RotatePoint(pnt, new PointF(0, 0), degreeAngle);
        }

        public static PointF RotatePoint(PointF pnt, PointF origin, double degreeAngle)
        {
            double radAngle = DegreeToRadian(degreeAngle);

            PointF newPoint = new PointF();

            double deltaX = pnt.X - origin.X;
            double deltaY = pnt.Y - origin.Y;

            newPoint.X = (float)(origin.X + (Math.Cos(radAngle) * deltaX - Math.Sin(radAngle) * deltaY));
            newPoint.Y = (float)(origin.Y + (Math.Sin(radAngle) * deltaX + Math.Cos(radAngle) * deltaY));

            return newPoint;
        }

        public static void RotatePoints(PointF[] pnts, double degreeAngle)
        {
            for (int i = 0; i < pnts.Length; i++)
            {
                pnts[i] = RotatePoint(pnts[i], degreeAngle);
            }
        }

        public static void RotatePoints(PointF[] pnts, PointF origin, double degreeAngle)
        {
            for (int i = 0; i < pnts.Length; i++)
            {
                pnts[i] = RotatePoint(pnts[i], origin, degreeAngle);
            }
        }

        public static Rectangle GetBounds(PointF[] pnts)
        {
            RectangleF boundsF = GetBoundsF(pnts);
            return new Rectangle((int)Math.Round(boundsF.Left),
                                 (int)Math.Round(boundsF.Top),
                                 (int)Math.Round(boundsF.Width),
                                 (int)Math.Round(boundsF.Height));
        }

        public static RectangleF GetBoundsF(PointF[] pnts)
        {
            float left = pnts[0].X;
            float right = pnts[0].X;
            float top = pnts[0].Y;
            float bottom = pnts[0].Y;

            for (int i = 1; i < pnts.Length; i++)
            {
                if (pnts[i].X < left)
                    left = pnts[i].X;
                else if (pnts[i].X > right)
                    right = pnts[i].X;

                if (pnts[i].Y < top)
                    top = pnts[i].Y;
                else if (pnts[i].Y > bottom)
                    bottom = pnts[i].Y;
            }

            return new RectangleF(left,
                                  top,
                                 (float)Math.Abs(right - left),
                                 (float)Math.Abs(bottom - top));
        }
    }



This produces the following result:

0 degrees: http://i47.tinypic.com/r8cxhd.png
22.5 degrees: http://i46.tinypic.com/hsoxo9.png
45 degrees: http://i50.tinypic.com/vy6q8z.png

From what I can see, the produced Bitmap only extends its boundaries towards the right and the bottom, while it should also extend in the other 2 directions to make the image rotate properly around the center. I spent quite a while playing around with the method, and in the end I was unable to produce the desired result. The background of the produced Bitmap is colored white simply to be able to see its real size.

Any form of assistance is gladly appreciated. :)

Sponsor:

#2 skauert   Members   -  Reputation: 100

Like
0Likes
Like

Posted 09 March 2010 - 03:24 AM

Oh wow, just after posting this, I realized that I had made the stupid mistake of always drawing the top-left corner at a specific x,y position. This entire issue is fixed if I specify the location of the middle pixel, and then draw the top-left corner at mid_x - width/2, mid_y - height/2.

I feel kind of silly now. :(

This topic became useless pretty quick... I suppose if anyone has any tips in terms of this kind of coding practice and optimization around Bitmap transformations, I'll happily accept them.

#3 TheTroll   Members   -  Reputation: 882

Like
0Likes
Like

Posted 13 March 2010 - 12:12 PM

This is why they make XNA, you might want to look into it.

theTroll




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS