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);
 
 
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用,比如表情~实现没有看懂,待研究。。。 

github源码学习之UIImage+YYWebImage的更多相关文章

  1. 【 js 基础 】【 源码学习 】源码设计 (持续更新)

    学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析第二部分:undersc ...

  2. 【 js 基础 】【 源码学习 】源码设计 (更新了backbone分析)

    学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析 第二部分:unders ...

  3. ActiveMQ学习系列(三)----下载github源码并编译

    前记:坚持使用官网的资源去学习是挺痛苦的一个过程,昨天瞎溜达了一天,也没看到有系统性的学习文章,倒是发现了github上的ActiveMq项目. 地址:https://github.com/apach ...

  4. 在IDEA中搭建Java源码学习环境并上传到GitHub上

    打开IDEA新建一个项目 创建一个最简单的Java项目即可 在项目命名填写该项目的名称,我这里写的项目名为Java_Source_Study 点击Finished,然后在项目的src目录下新建源码文件 ...

  5. 05.ElementUI源码学习:项目发布配置(github pages&npm package)

    0x00.前言 书接上文.项目第一个组件已经封装好,说明文档也已编写好.下面需要将说明文档发布到外网上,以此来展示和推广项目,使用 Github Pages功能实现.同时将组件发布之 npm 上,方便 ...

  6. MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)

    前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...

  7. MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)

    前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...

  8. MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)

    前言:最近一段时间在学习MVC源码,说实话,研读源码真是一个痛苦的过程,好多晦涩的语法搞得人晕晕乎乎.这两天算是理解了一小部分,这里先记录下来,也给需要的园友一个参考,奈何博主技术有限,如有理解不妥之 ...

  9. 我的angularjs源码学习之旅2——依赖注入

    依赖注入起源于实现控制反转的典型框架Spring框架,用来削减计算机程序的耦合问题.简单来说,在定义方法的时候,方法所依赖的对象就被隐性的注入到该方法中,在方法中可以直接使用,而不需要在执行该函数的时 ...

随机推荐

  1. 机器指令翻译成 JavaScript —— 终极目标

    上一篇,我们顺利将 6502 指令翻译成 C 代码,并演示了一个案例. 现在,我们来完成最后的目标 -- 转换成 JavaScript. 中间码输出 我们之所以选择 C,就是为了使用 LLVM.现在来 ...

  2. 博客已经迁移至 http://barretlee.com/entry/,时而同步分享到这里

    博客园是一个十分好的写作平台,不过个人比较喜欢倒腾,所以将文章都做了搬迁. 博客已经迁移至 http://barretlee.com/entry/,感谢一直以来的关注和支持. 博客订阅地址: http ...

  3. [异常解决] windows用SSH和linux同步文件&linux开启SSH&ssh client 报 algorithm negotiation failed的解决方法之一

    1.安装.配置与启动 SSH分客户端openssh-client和openssh-server 如果你只是想登陆别的机器的SSH只需要安装openssh-client(ubuntu有默认安装,如果没有 ...

  4. ABP源码分析七:Setting 以及 Mail

    本文主要说明Setting的实现以及Mail这个功能模块如何使用Setting. 首先区分一下ABP中的Setting和Configuration. Setting一般用于需要通过外部配置文件(或数据 ...

  5. datepickerx设置默认日期

    datepicher插件是jQuery UI的一个插件,它提供一个日期弹出窗口(或直接显示在页面),供用户选择日期.在Web开发中,总会遇到需要用户输入日期的情况.一般都是提供一个text类型的inp ...

  6. PHP 高级编程(5/5) - SPL 数组重载

    ArrayAccess接口 ArrayAccess接口是对象的行为看起来像个数组,定义了四个方法.接口概要如下: ArrayAccess { /* Methods */ abstract public ...

  7. ASP.NET 5 WebApi 返回 HttpResponseMessage

    首先,ASP.NET 5 没有了 MVC 和 WebApi 的区分,都属于 ASP.NET 5,从 Controller 的继承就可以看出,原来 ASP.NET WebApi 2 ValuesCont ...

  8. NodeJs对Mysql封装

    之前在学习NodeJs的时候,每次操作数据库都需要连接数据库然后开始写Sql操作,这样非常麻烦,然后自己对Mysql进行了封装,一共100多行代码. github地址: Mysql操作 我在里面对My ...

  9. js实现StringBuffer

    实现 function StringBuffer() { this.__strings__ = []; }; StringBuffer.prototype.Append = function (str ...

  10. Python(六)面向对象、异常处理、反射、单例模式

    本章内容: 创建类和对象 面向对象三大特性(封装.继承.多态) 类的成员(字段.方法.属性) 类成员的修饰符(公有.私有) 类的特殊成员 isinstance(obj, cls) & issu ...