To follow up on the earlier image editing tutorial, I will be going over an easy technique to rotate an image just like it is done in Adobe Photoshop.
To learn some more about the inner workings on the topic you can look up image transformation matrices. Let's create a method that takes a Bitmap object and a rotation angle and returns the new, rotated image.
private Bitmap rotateImage(Bitmap b, float angle)
We pass in the image to rotate (System.Drawing.Bitmap) and the the
angle to rotate it by in degrees. The image will be rotated clockwise.
The next step is to create the bitmap we are going to return and also
the graphics object (System.Drawing.Graphics) we use to rotate and
draw the image. First we create a blank Bitmap which is the same size at
the incoming one. Since we'll be drawing on this new Bitmap, the next
thing to do is to create a Graphics object from this Bitmap.
private Bitmap rotateImage(Bitmap b, float angle)
{
//create a new empty bitmap to hold rotated image
Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
//make a graphics object from the empty bitmap
Graphics g = Graphics.FromImage(returnBitmap);
}
The next part is the important part which does the actual rotation. First we move the image to the middle because the image rotates from the upper left corner. Next we tell the graphics object to rotate the picture by the requested degrees. And finally we move the image back to the correct position.
The way the graphics object rotates the image is by using a transformation matrix, which you can do a lot more with than just rotate the image. If you know more about transformation matrices, you can set g.Transform to a System.Drawing.Drawing2D.Matrix to perform any number of translations. We didn't use a transformation matrix in this tutorial because this technique is easier to understand.
private Bitmap rotateImage(Bitmap b, float angle)
{
//create a new empty bitmap to hold rotated image
Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
//make a graphics object from the empty bitmap
Graphics g = Graphics.FromImage(returnBitmap);
//move rotation point to center of image
g.TranslateTransform((float)b.Width/2,(float)b.Height / 2);
//rotate
g.RotateTransform(angle);
//move image back
g.TranslateTransform(-(float)b.Width/2,-(float)b.Height / 2);
}
The last thing to do is draw the return image and return it.
private Bitmap rotateImage(Bitmap b, float angle)
{
//create a new empty bitmap to hold rotated image
Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
//make a graphics object from the empty bitmap
Graphics g = Graphics.FromImage(returnBitmap);
//move rotation point to center of image
g.TranslateTransform((float)b.Width/2, (float)b.Height / 2);
//rotate
g.RotateTransform(angle);
//move image back
g.TranslateTransform(-(float)b.Width/2,-(float)b.Height / 2);
//draw passed in image onto graphics object
g.DrawImage(b, new Point(0, 0));
return returnBitmap;
}
Just like before, here is the source code and a C# VS2005 Express Edition solution with the needed methods and some test code.
Source Files:
Good example. Clear source codes :)
Great example to get me started - could sort the clipping out though?
Since the image is rotated inside its original bounds, the corners are most likely to be clipped. This can be fixed by increasing the size of
returnBitmapto account for this. You'll also have to adjust the transformation matrix to keep the image centered in the new, larger image.Thanks, I've had a go and it seems to work.
Any idea why RotateTransform seems to recolour the image? How do I stop it doing that?
Actually, have just found something that helps fix it:
This doesnt recolour the image so my palette now stays the same when i rotate apart from one extra colour - the black it fills the background with.
If you want the background to be a different color, you can clear the Graphics object after it's been created from the Bitmap.
I thought of increasing the size of the resulting bitmap by a factor of theta but it does nt seem to work. The image still gets clipped. Can u help me avoid the clipping?
Regards,
Vikas
solution for the corners clipped :
I am having problems implementing the updates cropped corners method above because of the PointF. Can I please have an example of what the method call should be?
I am using this rotateImage to rotate an image during acquire event during scanning. However, the image is saved very very small and hugs the right side of the page. Any ideas?
This occurs because you're rotating the bitmap result from a previous rotation. Each rotation induces anomalies into the result image.
You can avoid this by not re-rotating the bitmap result of a previous rotation. Instead, keep a copy of the original bitmap, and rotate it by theta. This way, you don't increasingly distort the source image with each successive rotation.
My reply was for the guy that said his image gets fuzzy with repeated rotations.
This fades the whole image and if you keep rotating, the image gets messed up.
Any one noticed?
Thank you
Thank for your sample code :)
Thanks for the good sample code.
Your code has saved me. If I weren't a Christian, I would ask you to me my Savior.
parto thero
This is most excellent. Thanks so much.
nice comment
Very helpful and nicely commented and explained :)
Good example with clear codes..Thanks to the author
God bless you man! ;-) thanks very much.
If you just need to rotate (and flip) by a multiple of 90 use
The graphics I get at the end are the wrong dimensions and the contents are pushed out to the side and mostly cut off.
Any suggestions?
hey help me to identify a circle in a image. it can be of any diameter.but i will have one of the pixel of that circle.
This code works well but there seem to be certain issues that i am facing.
1.one that a few people have mentioned about the rotated image being clipped as the bounding rectangle stays the same
?2. Rotating the image a lot, makes it blurry and unclear.
My approach would be to build a rotation matrix and apply the to the corners of the rectangle. Is there an easier way to do this.
Hello, could use some help plz //move image back g.TranslateTransform(-(float)b.Width/2,-(float)b.Height / 2);
i dont understand why cant I just write g.TranslateTransform(b.Width * 2, b.Height * 2);
thanks in advance
thanx bgt broo..makin cakep deh kamu..
Crap! Accidently submitted before I cleaned it up. This hack will rotate an input bitmap about its center. It returns a new bitmap, sized to bound the rotated input bitmap. As usual with my code, my style is "thick". I'm sure more than one person will shred this and show a very simple way to accomplish the same result. But this gave me fits until I worked it out. Your mileage may vary. - JMS - gojumpinthelake@comcast.net
Thanks for this code.... It is working like a charm..
I just commented out gDest.DrawRectangle(Pens.Red, bbox); and it worked perfectly! Thank you!
Im trying to rotate an image using this method but im using a back buffer and just want to rotate an image on it. When i try to use this it is rotating all my images. Can anyone help please.
very nice thanks
hey that really helped a lot.Thanks a lot...but how can this code be used for multiple images can u please tell...
hello i have 2 image i use surf descriptor to specify each picture i want for example i have two similar images, the second image is turned at x degrees in relation with first i would like to countdown the x degrees how can i do this with surf discriptor or can i use anything else ???
thanks
Hi, I adapted your code slightly to rotate a stretched/shrunk image within a C sharp pictureBox and to fix the ensuing bounding box issues.
Here is the new function:
private Bitmap rotateImage(Bitmap b, float angle) { Bitmap returnBitmap = new Bitmap(b.Width, b.Height + 1); Graphics g = Graphics.FromImage(returnBitmap); g.TranslateTransform((float)b.Width / 2, (float)b.Height / 2); g.RotateTransform(angle); g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2); g.DrawImage(b, b.Width / 2 - b.Height / 2, b.Height / 2 - b.Width / 2, b.Height, b.Width); return returnBitmap; }
And here's how I used that function to load an image locally, rotate it, and then stretch it to fit a pictureBox:
path = //path of filename goes here rotationAngle = //rotation angle you want goes here
pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage; pictureBox1.ImageLocation = path; pictureBox1.Load(); _BackBuffer = new Bitmap(pictureBox1.Image); pictureBox1.Image = rotateImage(_BackBuffer, rotationAngle); pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
I should have mentioned, that adapted code is for rotating an image on its side, IE. 90 or 270 degrees, and the pictureBox control must be sized correctly beforehand to accomodate the sideways image (i.e. width and height reversed.)
For flipping a pictureBox 180 degrees, the original code (without my adaptations) works fine without any bounding box issues. For all other angles, you will still have a bounding box that clips off parts of the image if you use the code I just gave.
Of course, by "for all other angles" I meant ones that are not 90, 180, or 270.
solution for the corners clipped :
Hi, I want to draw a lot of rectangles with different angles in one graphic object. Is it possible?
Yes, you can draw as many rectangles as you want at different angles. You'll want to use the RotateTransform and DrawRectangle methods to do the job.
Check out the Graphics class for more information.
Thank you so much, and one more question.. How can I calculate the minimum distance between two rectangles? It is easy for rectangles which have no angles(0 degrees) but with rotated rectangles I do not know how to do it.. Do you recommend any way?
WhiteFlare
That's actually a pretty complicated problem. Here's a result of a simple Google search.
I am having problems implementing the updates cropped corners method above because of the PointF. Can I please have an example of what the method call should be?
Hi there thank you so much your code has been very helpfull jst a question i'm not sure which classes i'm supposed to be using when i inserted your code it tells me that Matrix could not be found, So i must put using System.??? Thanks :)
Thanks to Anonymous for posting Rotates the input image by theta degrees around center.
I could not get this to work. I don't care about corner clipping because my images are round (have no corners). I have a second hand (clock) image where the hand points up (12 oclock). I want to rotate it by some positive or negative angle in degrees so I tried this, but the image also gets translated. Why?
Is it possible to make the space voided by rotating the image transparent?
hi, can anybody help me about plate recognition C# algorithm
please i want the source code of the images brightness
please
thank you
Hello, please I want a way to deal with the brightness images programmatically by using C# .. my darling please help me As soon as possible…. Best regards Thank You for Everything
I had some trouble as the resulting image would not be the right size and some clipping occured on the edges.
changing:
to:
took care of it though.
Thanks for the function, good work!
Here's a more flexible version that supports rotation with and without clipping and any angle between -180 to +180 degrees.
Thank You! Good solve. I was looking for something like this
thanks for your code man it really helped...
I have just made one change, for angle 270, the width and height is coming in negative so I added else { degrees -= 90; double radians = 0.0174532925 * degrees; double dSin = Math.Sin(radians); double dCos = Math.Cos(radians); if (dCos == -1) dCos = -1 * -1; W = (int)(dW * dSin + dH * dCos); H = (int)(dH * dSin + dW * dCos); X = (W - image.Width) / 2; Y = (H - image.Height) / 2; }
thank you brother God Bless You Jai SiyaRam
thanks....
Nice examples.... thank you,.
Thank You!!
my image is getting 1/3 smaller in bytes. does anyone know how to keep the image resolution after rotation?
var rotation = Math.PI * degrees / 180; var costheta = Math.Cos(rotation); var sintheta = Math.Sin(rotation); var newWidth = (float)(Math.Abs(costheta * b.Width) + Math.Abs(sintheta * b.Width)); var newHeight = (float)(Math.Abs(costheta * b.Height) + Math.Abs(sintheta * b.Height));
//Ceiling the height and width to the nearest even number if (b.Width % 2 == 0) newWidth = (Math.Ceiling(newWidth) % 2 == 1) ? (float)Math.Ceiling(newWidth + 1) : (float)Math.Ceiling(newWidth); if (b.Height % 2 == 0) newHeight = (Math.Ceiling(newHeight) % 2 == 1) ? (float)Math.Ceiling(newHeight + 1) : (float)Math.Ceiling(newHeight);
//offset var x = Math.Abs((newWidth - b.Width) / 2); var y = Math.Abs((newHeight - b.Height) / 2);
//create a new empty bitmap to hold rotated image Bitmap returnBitmap = new Bitmap((int)newWidth, (int)newHeight); returnBitmap.SetResolution(b.HorizontalResolution, b.VerticalResolution); //make a graphics object from the empty bitmap Graphics g = Graphics.FromImage(returnBitmap); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
var rotateXAt = newWidth / 2; var rotateYAt = newHeight / 2;
///move rotation point to center of image g.TranslateTransform(rotateXAt, rotateYAt); //rotate g.RotateTransform(degrees);
//move image back g.TranslateTransform(-rotateXAt, -rotateYAt);
//draw passed in image onto graphics object g.DrawImage(b, new PointF(x, y));
return returnBitmap;