zoukankan      html  css  js  c++  java
  • 使用GDI+进行图像旋转

    以前总是用大段大段的cos/sin来写旋转图像的代码,而且旋转出来还经常因为插值的问题导致图像出错。后来稍微研究了一下GDI+,发现直接用GDI+来旋转效果比我自己写好太多了,网上搜到了关于旋转的代码,在这里和大家分享。

    /// <summary>
            
    /// Creates a new Image containing the same image only rotated
            
    /// </summary>
            
    /// <param name="image">The <see cref="System.Drawing.Image"/> to rotate</param>
            
    /// <param name="angle">The amount to rotate the image, clockwise, in degrees</param>
            
    /// <returns>A new <see cref="System.Drawing.Bitmap"/> that is just large enough
            
    /// to contain the rotated image without cutting any corners off.</returns>
            
    /// <exception cref="System.ArgumentNullException">Thrown if <see cref="image"/> is null.</exception>

            public static Bitmap RotateImage(Image image, float angle)
            
    {
                
    if(image == null)
                    
    throw new ArgumentNullException("image");

                
    const double pi2 = Math.PI / 2.0;

                
    // Why can't C# allow these to be const, or at least readonly
                
    // *sigh*  I'm starting to talk like Christian Graus :omg:
                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

                
    Explaination of the calculations

                
    double adjacentTop, oppositeTop;
                
    double adjacentBottom, oppositeBottom;

                
    // We need to calculate the sides of the triangles based
                
    // on how much rotation is being done to the bitmap.
                
    //   Refer to the first paragraph in the explaination above for 
                
    //   reasons why.
                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))
                
    {
                    
    // This array will be used to pass in the three points that 
                    
    // make up the rotated image
                    Point [] points;

                    
    /*
                     * The values of opposite/adjacentTop/Bottom are referring to 
                     * fixed locations instead of in relation to the
                     * rotating image so I need to change which values are used
                     * based on the how much the image is rotating.
                     * 
                     * For each point, one of the coordinates will always be 0, 
                     * nWidth, or nHeight.  This because the Bitmap we are drawing on
                     * is the bounding box for the rotated bitmap.  If both of the 
                     * corrdinates for any of the given points wasn't in the set above
                     * then the bitmap we are drawing on WOULDN'T be the bounding box
                     * as required.
                     
    */

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

        


     

  • 相关阅读:
    hdu 2647 Reward
    hdu 2094 产生冠军
    hdu 3342 Legal or Not
    hdu 1285 确定比赛名次
    hdu 3006 The Number of set
    hdu 1429 胜利大逃亡(续)
    UVA 146 ID Codes
    UVA 131 The Psychic Poker Player
    洛谷 P2491消防 解题报告
    洛谷 P2587 [ZJOI2008]泡泡堂 解题报告
  • 原文地址:https://www.cnblogs.com/hotcan/p/25646.html
Copyright © 2011-2022 走看看