'How to determine the height and width of a image after a rotation of x degrees with an offset?
I have a school project which involve in recreating the class Bitmap of C# without using any existing library to act on the images. The problem I face is for the rotation of an 24 bits bitmap image of a arbitrary θ° degrees angle, I have to increase the height and width of the resulting image to make sure the source image fits inside of it without being cropped. In doing so, I've found a way of increasing the height and width through trigonometric formulas which are :
new_width=|old_width×cosθ|+|old_height×sinθ|
new_height=|old_height×cosθ|+ |old_width×sinθ|
but when I tried for different angles some work and some don't work :
. I've successfully identified that if I would force the new_height and the new_width to be really large (1000 * 1000 pixels)
(so the code for the rotation is not the problem).
Regarding this problem, I've tried to identify by using the debug console which dimension was given for the image after rotation that cause a problem. I've found that for example, a source image of 512*512 pixels and a rotation of 30°, the new_height = new_width = 699, but if I add an "offset" of 1, so new_height = new_width = 700 it works ! The image appear normally. But, with a rotation of 10°, the new_height = new_width= 593, so I tried to add an offset of 1 like before, so new_height = new_witdh = 594 but it didn't work ! It only work with an offset of 3, so new_height = new_width = 596 and now it works.
But cannot get to understand why... I see no pattern here.
So, all my explanations for this question : How to calculate this offset ? Is there any formula ?
public void Rotation(int angle)
{
MyImage nouvelle_image = new MyImage(this.filename); //Creation of a new_image with the same properties as the original one
#region Variables
double angleRad = angle * Math.PI / 180;
double cos = Math.Cos(angleRad);
double sin = Math.Sin(angleRad);
int height = nouvelle_image.height; //height of the original image
int width = nouvelle_image.width ; //width of the original image
int new_height = (int)Math.Round(Math.Abs(cos * height ) + Math.Abs(sin * width ));
int new_width = (int)Math.Round(Math.Abs(cos * width ) + Math.Abs(sin * height ));
#endregion
if (angle == 0)
{
new_height = (int)Math.Round(Math.Abs(cos * hauteur) + Math.Abs(sin * largeur));
new_width = (int)Math.Round(Math.Abs(cos * largeur) + Math.Abs(sin * hauteur));
}
else if (angle % 15 == 0)
{
new_height = (int)Math.Round(Math.Abs(cos * hauteur) + Math.Abs(sin * largeur)) + 1;
new_width = (int)Math.Round(Math.Abs(cos * largeur) + Math.Abs(sin * hauteur)) + 1;
}
else
{
new_height = (int)Math.Round(Math.Abs(cos * hauteur) + Math.Abs(sin * largeur)) + 2;
new_width = (int)Math.Round(Math.Abs(cos * largeur) + Math.Abs(sin * hauteur)) + 2;
}
Pixel[,] new_mat = new Pixel[new_height , new_width ]; //Definition of the new matrix with the increased size so the source image fits inside after the rotation
int center_original_height = (int)Math.Round((double)((height + 1) / 2) - 1);
int center_original_width = (int)Math.Round((double)((width + 1) / 2) - 1);
int center_new_height = (int)Math.Round((double)((new_height + 1) / 2) - 1); //center of the new image : height
int center_new_width = (int)Math.Round((double)((new_width + 1) / 2) - 1); //center of the new image : width
//Some code that does the rotation through shearing
}
edit: adding some code regarding the center of rotation
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
