rotating an image modifies the resolution and clarity
Consider the code below to rotate an image.
The problem is the resolution of the image is getting low and the image is getting unclear.
How can I avoid this problem?
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)this.Width / 2, (float)this.Height / 2);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
//rotate
g.RotateTransform(angle);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
g.TranslateTransform(-(float)this.Width / 2, -(float)this.Height / 2);
g.InterpolationMode = System.Drawing.Drawing2D.Interpolation开发者_开发问答Mode.HighQualityBilinear;
//draw passed in image onto graphics object
g.DrawImage(b, new Point(0, 0));
g.Dispose();
return returnBitmap;
}
Repeated rotations will cause quality to drop as the repeated interpolations take their toll on the image. The best way to avoid this is to only rotate the source image once. If you're building a system in which an image gets rotated multiple times simply rotate the source image by the total rotation amount instead of applying small delta rotations to an already rotated image each time.
I have a method that I use to do rotation and it works without reducing quality of image dramatically (that I have seen).
public static Bitmap RotateImage(Image image, float angle)
{
if(image == null)
throw new ArgumentNullException("image");
const double pi2 = Math.PI / 2.0;
double oldWidth = (double) image.Width;
double oldHeight = (double) image.Height;
// Convert degrees to radians
double theta = ((double) angle) * Math.PI / 180.0;
double locked_theta = theta;
// Ensure theta is now [0, 2pi)
while( locked_theta < 0.0 )
locked_theta += 2 * Math.PI;
double newWidth, newHeight;
int nWidth, nHeight; // The newWidth/newHeight expressed as ints
double adjacentTop, oppositeTop;
double adjacentBottom, oppositeBottom;
if( (locked_theta >= 0.0 && locked_theta < pi2) ||
(locked_theta >= Math.PI && locked_theta < (Math.PI + pi2) ) )
{
adjacentTop = Math.Abs(Math.Cos(locked_theta)) * oldWidth;
oppositeTop = Math.Abs(Math.Sin(locked_theta)) * oldWidth;
adjacentBottom = Math.Abs(Math.Cos(locked_theta)) * oldHeight;
oppositeBottom = Math.Abs(Math.Sin(locked_theta)) * oldHeight;
}
else
{
adjacentTop = Math.Abs(Math.Sin(locked_theta)) * oldHeight;
oppositeTop = Math.Abs(Math.Cos(locked_theta)) * oldHeight;
adjacentBottom = Math.Abs(Math.Sin(locked_theta)) * oldWidth;
oppositeBottom = Math.Abs(Math.Cos(locked_theta)) * oldWidth;
}
newWidth = adjacentTop + oppositeBottom;
newHeight = adjacentBottom + oppositeTop;
nWidth = (int) Math.Ceiling(newWidth);
nHeight = (int) Math.Ceiling(newHeight);
Bitmap rotatedBmp = new Bitmap(nWidth, nHeight);
using(Graphics g = Graphics.FromImage(rotatedBmp))
{
Point [] points;
if( locked_theta >= 0.0 && locked_theta < pi2 )
{
points = new Point[] {
new Point( (int) oppositeBottom, 0 ),
new Point( nWidth, (int) oppositeTop ),
new Point( 0, (int) adjacentBottom )
};
}
else if( locked_theta >= pi2 && locked_theta < Math.PI )
{
points = new Point[] {
new Point( nWidth, (int) oppositeTop ),
new Point( (int) adjacentTop, nHeight ),
new Point( (int) oppositeBottom, 0 )
};
}
else if( locked_theta >= Math.PI && locked_theta < (Math.PI + pi2) )
{
points = new Point[] {
new Point( (int) adjacentTop, nHeight ),
new Point( 0, (int) adjacentBottom ),
new Point( nWidth, (int) oppositeTop )
};
}
else
{
points = new Point[] {
new Point( 0, (int) adjacentBottom ),
new Point( (int) oppositeBottom, 0 ),
new Point( (int) adjacentTop, nHeight )
};
}
g.DrawImage(image, points);
}
return rotatedBmp;
}
sample code with RotateFlip:
Bitmap bitmap1;
private void InitializeBitmap()
{
try
{
bitmap1 = (Bitmap)Bitmap.FromFile(@"C:\test.bmp");
PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
PictureBox1.Image = bitmap1;
}
catch(System.IO.FileNotFoundException)
{
MessageBox.Show("There was an error." +
"Check the path to the bitmap.");
}
}
private void Button1_Click(System.Object sender, System.EventArgs e)
{
if (bitmap1 != null)
{
bitmap1.RotateFlip(RotateFlipType.Rotate180FlipNone);
PictureBox1.Image = bitmap1;
}
}
Specifies how much an image is rotated and the axis used to flip the image. http://msdn.microsoft.com/en-us/library/system.drawing.rotatefliptype.aspx
精彩评论