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

        


     

  • 相关阅读:
    E. Directing Edges 解析(思維、拓樸排序)
    E. Modular Stability 解析(思維、數論、組合)
    E1. Weights Division (easy version) 解析(思維、優先佇列、樹狀DP)
    D. Prefixes and Suffixes 解析(思維、字串、Z-Algo)
    B. Jzzhu and Cities 解析(思維、最短路)
    D. Captain Flint and Treasure 解析(拓樸排序、Stack)
    B. Suffix Operations
    SPOJ-COT Count on a tree(树上的可持久化线段树)
    UPC GCPC2019 K: Move & Meet
    F. x-prime Substrings(AC自动机 + dp)
  • 原文地址:https://www.cnblogs.com/hotcan/p/25646.html
Copyright © 2011-2022 走看看