旋转图像会修改分辨率和清晰度

时间:2010-12-01 01:49:17

标签: c# image

请考虑以下代码来旋转图像。

问题是图像的分辨率变低,图像变得不清晰。

我该如何避免这个问题?

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;
}

3 个答案:

答案 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