开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜