【问题标题】:rotating an image modifies the resolution and clarity旋转图像会修改分辨率和清晰度
【发布时间】:2014-02-09 05:52:52
【问题描述】:

考虑下面的代码来旋转图像。

问题是图像的分辨率越来越低,图像越来越不清晰。

如何避免这个问题?

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

【问题讨论】:

    标签: c# image


    【解决方案1】:

    重复旋转会导致质量下降,因为重复插值会对图像造成影响。避免这种情况的最好方法是只旋转一次源图像。如果您正在构建一个图像多次旋转的系统,只需将源图像旋转总旋转量,而不是每次都对已旋转的图像应用小的增量旋转。

    【讨论】:

    • 他在哪里说他旋转了很多次?我错过了什么吗?
    • @Brian - 我的假设。他当前的代码不应该在一次旋转中将质量降低到任何明显的量。
    【解决方案2】:

    我有一种用于旋转的方法,它可以在不显着降低图像质量的情况下工作(我已经看到了)。

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

    【讨论】:

    • 即使使用这种方法也会失去质量
    • this solution 相比,这没有问题。谢谢。
    • 这在 90.0 度上失败
    【解决方案3】:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-07
      • 2021-04-28
      • 1970-01-01
      • 1970-01-01
      • 2013-07-27
      相关资源
      最近更新 更多