github源碼學習之UIImage+YYWebImage,githubuiimage

來源:互聯網
上載者:User

github源碼學習之UIImage+YYWebImage,githubuiimage

UIImage+YYWebImage是YYWebImage(https://github.com/ibireme/YYWebImage)中的一個分類,這個分類封裝了一些image常用的變化方法,非常值得學習下源碼~(我看的版本是1.0.5) 預備知識:1,這裡大量使用了CoreGraphics的方法,第一個非常常用的的方法就是UIKIT_EXTERN void    UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) NS_AVAILABLE_IOS(4_0); 蘋果的官方文檔在這兒 https://developer.apple.com/reference/uikit/1623912-uigraphicsbeginimagecontextwitho  Parameters
size

The size (measured in points) of the new bitmap context. This represents the size of the image returned by the UIGraphicsGetImageFromCurrentImageContext() function. To get the size of the bitmap in pixels, you must multiply the width and height values by the value in thescale parameter.

opaque

A Boolean flag indicating whether the bitmap is opaque. If you know the bitmap is fully opaque, specify true to ignore the alpha channel and optimize the bitmap’s storage. Specifying false means that the bitmap must include an alpha channel to handle any partially transparent pixels.

scale

The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.

 考慮到UIColor是有透明度的,所以這個方法傳入的參數opaque一般傳NO;考慮到螢幕的的Scale,所以傳入的scale參數一般傳0,或者self.scale;文檔有寫“This function may be called from any thread of your app.” 所以在任何線程做都沒有問題~~  具體方法:1, + (UIImage *)yy_imageWithColor:(UIColor *)color size:(CGSize)size;產生一個指定大小的純色圖片;方法實現比較簡單,就是建立一個圖片上下文,拿到這個上下文,設定其為指定顏色,填充,取到圖片,關閉這個圖片上下文,就可以了;如最開始所說,opaque是NO,scale是0;如果是用來做背景用的圖片,可以直接將size設定為(1,1),然後用系統預設的展開效果來把圖片放大( UIViewContentModeScaleToFill),這樣效率比較高;YYImage也提供了 + (nullable UIImage *)yy_imageWithColor:(UIColor *)color;這個方法來實現這個功能。     2, - (void)yy_drawInRect:(CGRect)rect withContentMode:(UIViewContentMode)contentMode clipsToBounds:(BOOL)clips;這個方法我感覺應該算是個內部方法,個人感覺沒有必要放出來,可能有情境會用到我沒遇到過吧; 3, - (nullable UIImage *)yy_imageByResizeToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode;按指定的模式產生一個指定大小的圖片;size就是產生的圖片的大小,多出來的地方是透明的;這個方法是調用- (void)yy_drawInRect:(CGRect)rect withContentMode:(UIViewContentMode)contentMode clipsToBounds:(BOOL)clips;來實現的。裡面用到的 static CGRect _YYCGRectFitWithContentMode(CGRect rect, CGSize size, UIViewContentMode mode)這個方法得值得學習下。這個方法是用來得到按模式放大或者縮小後圖片完整的rect,比如:一張100*200的圖片,用 UIViewContentModeScaleAspectFit的模式,放到一個400*400的imageView中,那得到的rect就是(100,0,200,400);一張100*200的圖片,用 UIViewContentModeScaleAspectFill的模式,放到一個400*400的imageView中,那得到的rect就是(0,200,400,800);。。。。。。不同的模式會得到不同的rect,產生的圖片也會不一樣;具體rect的計算是根據圖片的寬高比和目標rect的寬高比來確定的,而不是具體的寬或者高,這個需要特別注意,這完全是為了達到縮放模式的效果而做的數學計算。這裡真的很佩服作者!!!- (UIImage *)yy_imageByResizeToSize:(CGSize)size;沒有調用這個方法,而是另外寫了一遍,效果跟用這個方法contentModel傳 UIViewContentModeScaleToFill是一樣的,不知道有啥用意~ 4, - (nullable UIImage *)yy_imageByCropToRect:(CGRect)rect;裁剪圖片中的某個地區注意裁剪範圍只跟image的size有關,跟imageView的大小無關;如果rect比image的size大,則沒有效果,如果rect比image的size小,會剪裁出指定的地區; 5, - (nullable UIImage *)yy_imageByInsetEdge:(UIEdgeInsets)insets withColor:(nullable UIColor *)color;根據insets來剪裁圖片;這個方法也很牛X~,注意insets是可以取負數的,如果取負數,就相當與給原來的圖片加上指定顏色的邊框;如果為正數,就是根據insets來剪裁圖片,這時候color參數無效 6, - (UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius
                                 corners:(UIRectCorner)corners
                             borderWidth:(CGFloat)borderWidth
                             borderColor:(UIColor *)borderColor                          borderLineJoin:(CGLineJoin)borderLineJoin;設定圓角的方法裡面用了 CGContextDrawImage(context, rect, self.CGImage);的方法;而CGContext的座標系與UIKit的座標系是不同的,所以需要特殊處理下;具體有什麼不同可以參考 http://blog.csdn.net/trandy/article/details/6617272 這裡他用了修改座標系的方法來解決,所以corners也是顛倒的,需要特殊處理下;注意這個方法只會設定圓角,如果原來的圖片不是正方形的,那怎麼設定頁不會得到正圓的圖片,需要預先把圖片裁成正方形的才行; 7, - (nullable UIImage *)yy_imageByRotate:(CGFloat)radians fitSize:(BOOL)fitSize;產生旋轉指定角度後的圖片fitSize傳yes,圖片會自動壓縮使圖片顯示完整,傳no圖片會被截斷;其中 CGRectApplyAffineTransform返回的是“包含旋轉後的rect的最小矩形的CGRect”,origin的值可能為負值;這個方法使用 CGBitmapContextCreate這個方法來繪製的,跟前面的直接用 UIGraphicsGetCurrentContext不太一樣,反正我是不太懂。。。我能看懂的就這麼幾句:    CGContextTranslateCTM(context, +(newRect.size.width * 0.5), +(newRect.size.height * 0.5));    CGContextRotateCTM(context, radians);
   
    CGContextDrawImage(context, CGRectMake(-(width * 0.5), -(height * 0.5), width, height), self.CGImage);
    CGImageRef imgRef = CGBitmapContextCreateImage(context);
    UIImage *img = [UIImageimageWithCGImage:imgRef scale:self.scaleorientation:self.imageOrientation];    CGImageRelease(imgRef);這裡比較巧妙,貌似CGContext的錨點是在(0,0)的,而image的錨點是在中心點的,所以先移動context到中心點,再從(-(width * 0.5), -(height * 0.5))開始繪圖,然後得到CGImageRef,用[UIImageimageWithCGImage:imgRef scale:self.scaleorientation:self.imageOrientation]這個方法來修正座標系的問題,也是非常值得學習~  8,- (nullable UIImage *)yy_imageByBlurRadius:(CGFloat)blurRadius                                 tintColor:(nullable UIColor *)tintColor                                  tintMode:(CGBlendMode)tintBlendMode                                saturation:(CGFloat)saturation                                 maskImage:(nullable UIImage *)maskImage;圖片模糊效果好用,但實現超出了目前的我的理解範圍,待研究。。。 9, + (nullableUIImage *)yy_imageWithSmallGIFData:(NSData *)data scale:(CGFloat)scale;文檔說是小型gif用,比如表情~實現沒有看懂,待研究。。。 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.