How to rotate image x degrees in c#?

If I’ve understood your question correctly, you essentially want to work out the new size of an image once rotated, and how to position the rotated image in it’s new bitmap.

enter image description here

The diagram hopefully helps make clear the solution. Here is a bit of pseudo code:

sinVal = abs(sin(angle))
cosVal = abs(cos(angle))
newImgWidth = sinVal * oldImgHeight + cosVal * oldImgWidth
newImgHeight = sinVal * oldImgWidth + cosVal * oldImgHeight
originX = 0
originY = sinVal * oldImgWidth

You want to make the new image from the newImgWidth and newImgHeight, and then perform a rotation around the origin (originX, originY) and then render the image to this point. This will fall over if the angle (in degrees) isn’t between -90 and 0 degrees (depicted). If it is between 0 and 90 degrees, then you just change the origin:

originX = sinVal * oldImgHeight
originY = 0

If it is in the range 90 degrees to 270 degrees (-90 degrees) then it is a little tricker (see example code below).

Your code re-written (briefly tested) – it is slightly dodgy but seems to work:

public static Bitmap RotateImg(Bitmap bmp, float angle, Color bkColor)
{
    angle = angle % 360;
    if (angle > 180)
        angle -= 360;

    System.Drawing.Imaging.PixelFormat pf = default(System.Drawing.Imaging.PixelFormat);
    if (bkColor == Color.Transparent)
    {
        pf = System.Drawing.Imaging.PixelFormat.Format32bppArgb;
    }
    else
    {
        pf = bmp.PixelFormat;
    }

    float sin = (float)Math.Abs(Math.Sin(angle * Math.PI / 180.0)); // this function takes radians
    float cos = (float)Math.Abs(Math.Cos(angle * Math.PI / 180.0)); // this one too
    float newImgWidth = sin * bmp.Height + cos * bmp.Width;
    float newImgHeight = sin * bmp.Width + cos * bmp.Height;
    float originX = 0f;
    float originY = 0f;

    if (angle > 0)
    {
        if (angle <= 90)
            originX = sin * bmp.Height;
        else
        {
            originX = newImgWidth;
            originY = newImgHeight - sin * bmp.Width;
        }
    }
    else
    {
        if (angle >= -90)
        originY = sin * bmp.Width;
        else
        {
            originX = newImgWidth - sin * bmp.Height;
            originY = newImgHeight;
        }
    }

    Bitmap newImg = new Bitmap((int)newImgWidth, (int)newImgHeight, pf);
    Graphics g = Graphics.FromImage(newImg);
    g.Clear(bkColor);
    g.TranslateTransform(originX, originY); // offset the origin to our calculated values
    g.RotateTransform(angle); // set up rotate
    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
    g.DrawImageUnscaled(bmp, 0, 0); // draw the image at 0, 0
    g.Dispose();

    return newImg;
}

Note the Degrees to Radians Conversion (180 Degrees == Pi Radians) for the trig functions

Edit: big issue was negative sin values, and me getting width/height confused when calculating origin x/y – this should work fine now (tested)

Edit: modified code to handle any angle

Leave a Comment