Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the fastest method for rotating an image without clipping its edges with GDI+?

There are some looooong and hungry algorithms for doing so, but as of yet I haven't come up with or found anything particularly fast.

like image 473
Bloodyaugust Avatar asked Jan 22 '23 10:01

Bloodyaugust


2 Answers

The fastest way is to this is to use unsafe calls to manipulate the image memory directly using LockBits. It sounds scary but it's pretty straight forward. If you search for LockBits you'll find plently of examples such as here.

The interesting bit is:

BitmapData originalData = originalBitmap.LockBits(
     new Rectangle(0, 0, originalWidth, originalHeight), 
     ImageLockMode.ReadOnly, 
     PixelFormat.Format32bppRgb);

Once you have the BitmapData you can pass the pixels and map them into a new image (again using LockBits). This is significantly quicker than using the Graphics API.

like image 174
TheCodeKing Avatar answered Apr 28 '23 10:04

TheCodeKing


Here's what I ended up doing (after an extensive amount of continued research, and the helpful link provided by TheCodeKing):

public Image RotateImage(Image img, float rotationAngle)
    {
        // When drawing the returned image to a form, modify your points by 
        // (-(img.Width / 2) - 1, -(img.Height / 2) - 1) to draw for actual co-ordinates.

        //create an empty Bitmap image 
        Bitmap bmp = new Bitmap((img.Width * 2), (img.Height *2));

        //turn the Bitmap into a Graphics object
        Graphics gfx = Graphics.FromImage(bmp);

        //set the point system origin to the center of our image
        gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);

        //now rotate the image
        gfx.RotateTransform(rotationAngle);

        //move the point system origin back to 0,0
        gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);

        //set the InterpolationMode to HighQualityBicubic so to ensure a high
        //quality image once it is transformed to the specified size
        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

        //draw our new image onto the graphics object with its center on the center of rotation
        gfx.DrawImage(img, new PointF((img.Width / 2), (img.Height / 2)));

        //dispose of our Graphics object
        gfx.Dispose();

        //return the image
        return bmp;
    }

Cheers!

like image 44
Bloodyaugust Avatar answered Apr 28 '23 10:04

Bloodyaugust