请考虑以下代码来旋转图像。
问题是图像的分辨率变低,图像变得不清晰。
我该如何避免这个问题?
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.InterpolationMode.HighQualityBilinear;
//draw passed in image onto graphics object
g.DrawImage(b, new Point(0, 0));
g.Dispose();
return returnBitmap;
}
答案 0 :(得分:4)
重复旋转会导致质量下降,因为重复插值会对图像产生影响。避免这种情况的最佳方法是仅旋转源图像一次。如果您正在构建一个图像旋转多次的系统,只需将源图像旋转总旋转量,而不是每次都对已经旋转的图像应用小的增量旋转。
答案 1 :(得分:3)
我有一种方法可以用来进行旋转,它可以在不显着降低图像质量的情况下工作(我已经看过)。
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;
}
答案 2 :(得分:1)
使用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;
}
}
指定图像旋转的程度以及用于翻转图像的轴。 http://msdn.microsoft.com/en-us/library/system.drawing.rotatefliptype.aspx