Click here to Skip to main content
15,890,438 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

To rotate image in picturebox i tried below code.

C#
public static Bitmap RotateImg(Bitmap bmp, float angle, Color bkColor)
        {
            int w = bmp.Width;
            int h = bmp.Height;
            PixelFormat pf = default(PixelFormat);
            if (bkColor == Color.Transparent)
            {
                pf = PixelFormat.Format32bppArgb;
            }
            else
            {
                pf = bmp.PixelFormat;
            }
            Bitmap tempImg = new Bitmap(w, h, pf);
            Graphics g = Graphics.FromImage(tempImg);
            g.Clear(bkColor);
            g.DrawImageUnscaled(bmp, 1, 1);
            g.Dispose();
            GraphicsPath path = new GraphicsPath();
            path.AddRectangle(new RectangleF(0f, 0f, w, h));
            Matrix mtrx = new Matrix();
            //Using System.Drawing.Drawing2D.Matrix class 
            mtrx.Rotate(angle);
            RectangleF rct = path.GetBounds(mtrx);
            Bitmap newImg = new Bitmap(Convert.ToInt32(rct.Width), Convert.ToInt32(rct.Height), pf);
            g = Graphics.FromImage(newImg);
            g.Clear(bkColor);
            g.TranslateTransform(-rct.X, -rct.Y);
            g.RotateTransform(angle);
            g.InterpolationMode = InterpolationMode.HighQualityBilinear;
            g.DrawImageUnscaled(tempImg, 0, 0);
            g.Dispose();
            tempImg.Dispose();
            return newImg;
        }

This code is referred from the link http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/a1e62e03-d732-444d-bb3d-6e7907fd5e16[^]

But it is not working. I have tried using RotateFlip method. I want similar type of behaviour using directly graphics object functions.
Please let me know what is not correct in above code.

Thanks on advance.
Posted
Updated 22-Jul-10 3:13am
v2

In your original post you didn't mention that you want to prevent clipping. So I decided to give you a link to article with simple and easy to understand approach. In that case (with your additional requirements) I will provide you a source which works fine for me. It may look a little bit complicated but I thoroughly commented the source. Here you go:
C#
// Rotates the input image by theta degrees around center
// and fills the background with specified color.
public static Bitmap RotateImage(Bitmap bmpSrc, float theta, Color bkColor)
{
    // Create a matrix for the geometric transformations.
    // Check out the documentation of this class
    Matrix mRotate = new Matrix();

    // Apply the transformations on the matrix:
    // 1) We will rotate around the center, so apply translation to the center of the image
    mRotate.Translate(bmpSrc.Width / -2, bmpSrc.Height / -2, MatrixOrder.Append);
    // 2) Apply the rotation after the translation
    mRotate.RotateAt(theta, new Point(0, 0), MatrixOrder.Append);

    using (GraphicsPath gp = new GraphicsPath())
    {
        // Transform image points by rotation matrix
        gp.AddPolygon(new Point[] { new Point(0, 0), new Point(bmpSrc.Width, 0), new Point(0, bmpSrc.Height) });
        gp.Transform(mRotate);

        // Get the points after transformation
        PointF[] pts = gp.PathPoints;

        // Ensure the selection of correct pixel format for the destination bitmap
        PixelFormat pfDest = default(PixelFormat);
        pfDest = (bkColor == Color.Transparent) ? PixelFormat.Format32bppArgb : bmpSrc.PixelFormat;

        // Create destination bitmap sized to contain rotated source image
        Rectangle bbox = BoundingBox(bmpSrc, mRotate);
        Bitmap bmpDest = new Bitmap(bbox.Width, bbox.Height, pfDest);

        // Create new graphics from the destination bitmap
        using (Graphics gDest = Graphics.FromImage(bmpDest))
        {
            // NOTE: The interpolation mode for gDest could be set for better quality.
            // For example:
            // gDest.InterpolationMode = InterpolationMode.HighQualityBicubic;

            // Draw the source into destination:
            Matrix mDest = new Matrix();
            mDest.Translate(bmpDest.Width / 2, bmpDest.Height / 2, MatrixOrder.Append);
            gDest.Clear(bkColor);
            gDest.Transform = mDest;
            gDest.DrawImage(bmpSrc, pts);
            return bmpDest;
        }
    }
}

// Returns the bounding box of the image after applying the
// transformations from the input matrix
private static Rectangle BoundingBox(Image img, Matrix matrix)
{
    // Get the bounding box of the input image
    GraphicsUnit gu = new GraphicsUnit();
    Rectangle rImg = Rectangle.Round(img.GetBounds(ref gu));

    // Create an array of points from the bounding box
    Point topLeft = new Point(rImg.Left, rImg.Top);
    Point topRight = new Point(rImg.Right, rImg.Top);
    Point bottomRight = new Point(rImg.Right, rImg.Bottom);
    Point bottomLeft = new Point(rImg.Left, rImg.Bottom);
    Point[] points = new Point[] { topLeft, topRight, bottomRight, bottomLeft };

    // Create a graphics path from the points.
    // We will apply transformations on graphics path, not on the input image
    GraphicsPath gp = new GraphicsPath
                                    (
                                    points,
                                    new byte[] {
                                                 (byte)PathPointType.Start,
                                                 (byte)PathPointType.Line,
                                                 (byte)PathPointType.Line,
                                                 (byte)PathPointType.Line
                                               }
                                    );

    // Apply the transformations from the input matrix to the graphics path
    gp.Transform(matrix);

    // Return the bounds of the graphics path after transformation
    return Rectangle.Round(gp.GetBounds());
}


You will need to add the following additional using statements in order to compile the code:
C#
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;


Now you can use the above code like this:
C#
private void btnRotateGraphics_Click(object sender, EventArgs e)
{
    pictureBox1.Image = RotateImage((Bitmap)pictureBox1.Image, 90.0f, Color.AliceBlue);
    pictureBox1.Invalidate();
}


I hope this helps. :)
 
Share this answer
 
If you want to rotate your image only on 90/180/270-degrees use the Image.RotateFlip[^] method because it is faster than using Graphics.
If you want to rotate your image on arbitrary angle, have a look at this[^] CodeProject article. It is not the fastest way to rotate an image, but it is simpler and easier to understand for you. :)
 
Share this answer
 
Comments
ISharda 23-Jul-10 0:34am    
I accept its easy to use the API and it would be faster. But I dont know what is this API internally doing.
e.g. Using Graphics I can set the InterpolationMode, I can ensure that the PixelFormat remain same as original.
Using RotateFlip API how do i ensure that the image quality remain same.

Also I tried the link suggested by you. When I rotate it 90 degree, the image is clipped. How to solve it.
Nuri Ismail 23-Jul-10 3:56am    
I've posted an additional answer, because it contains code snippets and I cannot paste all of this in a comment. Please see my next answer which is conformable to the comment posted by you. :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900