SDWebImage源码阅读前的准备(三)UIImage.h
UIKit/UIImage.h
UIImage 继承自NSObject,且遵守NSSecureCoding 协议,UIImage 实例是在应用程序中管理图像数据的对象。
下面逐行阅读UIImage.h 里面的代码:
(一):__has_include
1 #if __has_include(<CoreImage/CoreImage.h>) 2 3 #import <CoreImage/CoreImage.h> 4 5 #endif
__has_include 此宏传入一个你想引入文件的名称作为参数,如果该文件能够被引入则返回1,否则返回0,用于判断文件是否存在,存在了再导入使用,避免文件不存在的情况下导入文件。
参考链接:http://www.cnblogs.com/machao/p/5514921.html
(二):NS_ASSUME_NONNULL_BEGIN/NS_ASSUME_NONNULL_END
是NSObjCRuntime.h 里面的两个宏:
1 #define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") 2 #define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
主要用于: Nonnull的区域设置(Audited Regions).
nullability annotations 是Xcode 6.3的一个新特性。
在swift中,可以使用!和?来表示一个对象是optional的还是non-optional,如view?和view!。而在Objective-C中则没有这一区分,view即可表示这个对象是optional,也可表示是non-optioanl。这样就会造成一个问题:在Swift与Objective-C混编时,Swift编译器并不知道一个Objective-C对象到底是optional还是non-optional,因此这种情况下编译器会隐式地将Objective-C的对象当成是non-optional。
为了解决这个问题,苹果在Xcode 6.3引入了一个Objective-C的新特性:nullability annotations。这一新特性的核心是两个新的类型注释:__nullable和__nonnull。从字面上我们可以猜到,__nullable表示对象可以是NULL或nil,而__nonnull表示对象不应该为空。当我们不遵循这一规则时,编译器就会给出警告。在 Xcode 7 中,为了避免与第三方库潜在的冲突,苹果把 __nonnull/__nullable
改成 _Nonnull/_Nullable
。实例:
1 TestNullabilityClass.h 2 3 #import <Foundation/Foundation.h> 4 5 @interface TestNullabilityClass : NSObject 6 7 @property (nonatomic, copy) NSArray *items; // Pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified) 8 9 - (id)itemWithName:(NSString * __nonnull)name; 10 11 @end 12 13 TestNullabilityClass.m 14 15 #import "TestNullabilityClass.h" 16 17 @implementation TestNullabilityClass 18 19 - (void)testNullability { 20 [self itemWithName:nil]; // Null passed to a callee that requires a non-null argument 传给调用者需要一个非空的参数 21 } 22 23 - (id)itemWithName:(NSString * __nonnull)name { 24 return nil; 25 } 26 27 @end
不过这只是一个警告,程序还是能编译通过并运行。
事实上,在任何可以使用const关键字的地方都可以使用__nullable和__nonnull,不过这两个关键字仅限于使用在指针类型上。而在方法的声明中,我们还可以使用不带下划线的nullable和nonnull.
1 - (nonnull id)itemWithName:(NSString * __nonnull)name;
在属性声明中,也增加了两个相应的特性:
1 @property (nonatomic, copy, nonnull) NSArray *items;
也可使用:
1 @property (nonatomic, copy) NSArray * __nonnull itemTwo;
苹果同样支持了没有下划线的写法 nonnull/nullable
,于是就造成现在有三种写法这样混乱的局面。但是这三种写法本质上都是互通的,只是放的位置不同,举例如下:
1 // 方法返回值修饰: 2 3 - (nullableNSString*)method; 4 - (NSString* __nullable)method; 5 - (NSString* _Nullable)method; 6 7 // 声明属性的修饰: 8 9 @property(nonatomic,copy,nullable)NSString*aString; 10 @property(nonatomic,copy)NSString* __nullableaString; 11 @property(nonatomic,copy)NSString* _Nullable aString; 12 13 // 方法参数修饰: 14 15 - (void)methodWithString:(nullableNSString*)aString; 16 - (void)methodWithString:(NSString* _Nullable)aString; 17 - (void)methodWithString:(NSString* __nullable)aString;
而对于双指针类型对象
、 Block 的返回值
、 Block 的参数
等,这时候就不能用 nonnull/nullable
修饰,只能用带下划线的 __nonnull/__nullable
或者 _Nonnull/_Nullable
:
1 - (void)methodWithError:(NSError* _Nullable * _Nullable)error 2 - (void)methodWithError:(NSError* __nullable* __null_unspecified)error; 3 // 以及其他的组合方式 4 5 - (void)methodWithBlock:(nullablevoid(^)())block; 6 // 注意上面的 nullable 用于修饰方法传入的参数 Block 可以为空,而不是修饰 Block 返回值; 7 - (void)methodWithBlock:(void(^ _Nullable)())block; 8 - (void)methodWithBlock:(void(^ __nullable)())block; 9 - (void)methodWithBlock:(nullableid__nonnull(^)(id__nullableparams))block; 10 // 注意上面的 nullable 用于修饰方法传入的参数 Block 可以为空,而 __nonnull 用于修饰 Block 返回值 id 不能为空; 11 - (void)methodWithBlock:(id__nonnull(^ __nullable)(id__nullableparams))block; 12 - (void)methodWithBlock:(id_Nonnull (^ _Nullable)(id_Nullable params))block;
- 对于属性、方法返回值、方法参数的修饰,使用:
nonnull/nullable
; - 对于 C 函数的参数、Block 的参数、Block 返回值的修饰,使用:
_Nonnull/_Nullable
, 建议弃用。__nonnull/__nullable
Nonnull的区域设置(Audited Regions):
如果需要每个属性或每个方法都去指定nonnull和nullable,是一件非常繁琐的事。苹果为了减轻我们的工作量,专门提供了两个宏:NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END。在这两个宏之间的代码,所有简单指针对象都被假定为nonnull,因此我们只需要去指定那些nullable的指针。TestNullabilityClass.h 可改为如下:
1 #import <Foundation/Foundation.h> 2 3 NS_ASSUME_NONNULL_BEGIN 4 5 @interface TestNullabilityClass : NSObject 6 7 @property (nonatomic, copy) NSArray *items; 8 @property (nonatomic, copy) NSArray *itemTwo; 9 10 - (id)itemWithName:(nullable NSString *)name; 11 12 @end 13 14 NS_ASSUME_NONNULL_END
在上面的代码中,items属性默认是nonnull的,itemWithName:方法的返回值也是nonnull,而参数是指定为nullable的。
不过,为了安全起见,苹果还制定了几条规则:
- 1.typedef定义的类型的nullability特性通常依赖于上下文,即使是在Audited Regions中,也不能假定它为nonnull。
- 2.复杂的指针类型(如id *)必须显示去指定是nonnull还是nullable。例如,指定一个指向nullable对象的nonnull指针,可以使用”__nullable id * __nonnull”。
- 3.我们经常使用的NSError **通常是被假定为一个指向nullable NSError对象的nullable指针。
兼容性
因为Nullability Annotations是Xcode 6.3新加入的,所以我们需要考虑之前的老代码。实际上,苹果已以帮我们处理好了这种兼容问题,我们可以安全地使用它们:
-
老代码仍然能正常工作, 即使对nonnull对象使用了nil也没有问题。
-
老代码在需要和swift混编时,在新的swift编译器下会给出一个警告。
-
nonnull不会影响性能。事实上,我们仍然可以在运行时去判断我们的对象是否为nil。
事实上,我们可以将nonnull/nullable与我们的断言和异常一起看待,其需要处理的问题都是同一个:违反约定是一个程序员的错误。特别是,返回值是我们可控的东西,如果返回值是nonnull的,则我们不应该返回nil,除非是为了向后兼容。
参考链接:http://blog.sina.com.cn/s/blog_5c91824f0102vxpd.html
http://blog.csdn.net/bravegogo/article/details/52458403
(三):UIImageOrientation 枚举
UIImage有一个imageOrientation的属性,主要作用是控制image的绘制方向,它的值对应一个枚举:
1 typedef NS_ENUM(NSInteger, UIImageOrientation) { 2 UIImageOrientationUp, // default orientation 默认 3 UIImageOrientationDown, // 180 deg rotation 180度旋转 4 UIImageOrientationLeft, // 90 deg CCW 5 UIImageOrientationRight, // 90 deg CW 6 UIImageOrientationUpMirrored, // as above but image mirrored along other axis. horizontal flip 7 UIImageOrientationDownMirrored, // horizontal flip 8 UIImageOrientationLeftMirrored, // vertical flip 9 UIImageOrientationRightMirrored, // vertical flip 10 };
默认的方向是UIImageOrientationUp,这8种方向对应的绘制方如上面所示。我们在日常使用中经常会碰到把手机相册中的照片导入到应用中,发现方向不对的问题就是与这个属性有关,因为导出照片的时候,写exif中的方向信息时候没有考虑该方向的原因。利用imageWithCGImage:scale:orientation:方法,指定不同的orientation可完成图像不同方向的旋转。
参考链接:http://blog.csdn.net/z997756128/article/details/42297871
http://feihu.me/blog/2015/how-to-handle-image-orientation-on-iOS/#exifexchangeable-image-file-format
(四):UIImageResizingMode 枚举
用来指定图像拉伸的模式:
1 // 在iOS6.0中,UIImage提供了一个新方法处理图片拉伸: 2 3 - (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode; 4 5 typedef NS_ENUM(NSInteger, UIImageResizingMode) { 6 UIImageResizingModeTile, // 平铺模式,通过重复显示UIEdgeInsets指定的矩形区域来填充图片 进行区域复制模式拉伸
7 UIImageResizingModeStretch, // 拉伸模式,通过拉伸UIEdgeInsets指定的矩形区域来填充图片 进行渐变复制模式拉伸
};
参考链接:http://blog.csdn.net/mamong/article/details/45011009
(五):UIImageRenderingMode 枚举
iOS 7 中可设置在渲染一个UIImage时是否使用当前view 的tintColor。
1 // iOS 7 新增的,使用指定的渲染模式创建图像,默认的使用 UIImageRenderingModeAutomatic. 2 - (UIImage *)imageWithRenderingMode:(UIImageRenderingMode)renderingMode NS_AVAILABLE_IOS(7_0); 3 @property(nonatomic, readonly) UIImageRenderingMode renderingMode NS_AVAILABLE_IOS(7_0);
UIImageRenderingMode枚举值用来设置图片的renderingMode属性的:
1 typedef NS_ENUM(NSInteger, UIImageRenderingMode) { 2 UIImageRenderingModeAutomatic, // 根据图片的使用环境和所处的绘图上下文自动调整渲染模式 3 4 UIImageRenderingModeAlwaysOriginal, // 始终绘制图片原始状态,不使用Tint Color 5 UIImageRenderingModeAlwaysTemplate, // 始终根据Tint Color绘制图片,忽略图片的颜色信息 6 } NS_ENUM_AVAILABLE_IOS(7_0);
参考链接:http://www.tuicool.com/articles/AFrAJr
http://www.jianshu.com/p/b884766554ad
http://www.jianshu.com/p/d8e31684146d
(六):加载和创建UIImage 的类方法和实例方法:
1 + (nullable UIImage *)imageNamed:(NSString *)name; // 通过图片的文件名从bundle 获取这个图片,注意该图片已经导入到工程中 2 #if __has_include(<UIKit/UITraitCollection.h>) 3 + (nullable UIImage *)imageNamed:(NSString *)name inBundle:(nullable NSBundle *)bundle compatibleWithTraitCollection:(nullable UITraitCollection *)traitCollection NS_AVAILABLE_IOS(8_0); 4 #endif 5 6 + (nullable UIImage *)imageWithContentsOfFile:(NSString *)path; // 通过文件加载指定路径下的文件内容创建图片 7 + (nullable UIImage *)imageWithData:(NSData *)data; // 使用一个NSData对象来创建图片 8 + (nullable UIImage *)imageWithData:(NSData *)data scale:(CGFloat)scale NS_AVAILABLE_IOS(6_0); // 加上scale 参数,指定图片的大小 9 + (UIImage *)imageWithCGImage:(CGImageRef)cgImage; // 使用CGImage 对象创建图片 10 + (UIImage *)imageWithCGImage:(CGImageRef)cgImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation NS_AVAILABLE_IOS(4_0); // 指定图片大小和方向 11 #if __has_include(<CoreImage/CoreImage.h>) 12 + (UIImage *)imageWithCIImage:(CIImage *)ciImage NS_AVAILABLE_IOS(5_0); // 使用CIImage 对象创建图片 13 + (UIImage *)imageWithCIImage:(CIImage *)ciImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation NS_AVAILABLE_IOS(6_0); // 指定图片大小和方向 14 #endif 15 16 - (nullable instancetype)initWithContentsOfFile:(NSString *)path; // 从文件路径初始化图片 17 - (nullable instancetype)initWithData:(NSData *)data; // 使用NSData 对象初始化图片 18 - (nullable instancetype)initWithData:(NSData *)data scale:(CGFloat)scale NS_AVAILABLE_IOS(6_0); // 指定大小 19 - (instancetype)initWithCGImage:(CGImageRef)cgImage; // 使用CGImage 对象初始化图片 20 - (instancetype)initWithCGImage:(CGImageRef)cgImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation NS_AVAILABLE_IOS(4_0); // 指定大小和方向 21 #if __has_include(<CoreImage/CoreImage.h>) 22 - (instancetype)initWithCIImage:(CIImage *)ciImage NS_AVAILABLE_IOS(5_0); // 使用CIImage 对象初始化图片 23 - (instancetype)initWithCIImage:(CIImage *)ciImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation NS_AVAILABLE_IOS(6_0); // 指定大小和方向 24 #endif
UIImage 加载方式
1.+ (nullable UIImage *)imageNamed:(NSString *)name;
2.+ (nullable UIImage *)imageWithContentsOfFile:(NSString *)path;/- (nullable instancetype)initWithContentsOfFile:(NSString *)path;/+ (nullable UIImage *)imageWithData:(NSData *)data;/- (nullable instancetype)initWithData:(NSData *)data;
加载过程:
用imageNamed的方式加载时,系统会把图像Cache到内存。如果图像比较大,或者图像比较多,用这种方式会消耗很大的内存,而且释放图像的内存是一件相对来说比较麻烦的事情。
+ (nullable UIImage *)imageNamed:(NSString *)name;这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象如果它存在的话。
如果缓存中没有找到相应的图片,这个方法从指定的文档中加载然后缓存并返回这个对象,通常是加载bundle中的图片资源!因此+ (nullable UIImage *)imageNamed:(NSString *)name;的优点是当加载时会缓存图片。所以当图片会频繁的重复使用时,那么用+ (nullable UIImage *)imageNamed:(NSString *)name;的方法会比较好。
使用场景:
例如:如果利用imageNamed的方式加载图像到一个动态数组NSMutableArray,然后将将数组赋予一 个UIView的对象的animationImages进行逐帧动画,那么这将会很有可能造成内存泄露,并且释放图像所占据的内存也不会那么简单。
但是利用imageNamed加载图像也有自己的优势。对于同一个图像系统只会把它Cache到内存一次,如果是第二次调用,它不是从文件中取,而是直接从缓存中拿,也就是说读的不同的图片越多内存会越来越大,但是直接从内存中取图片,速度肯定快一点,性能高一点。so这对于图像的重复利用是非常有优势的。
例如:你需要在一个TableView里重复加载同样一个图标,那么用imageNamed加载图像,系统会把那个图标Cache到内存,在Table里每次利用那个图像的时候,只会把图片指针指向同一块内存。这种情况使用imageNamed加载图像就会变得非常有效。
利用NSData或imageWithContentOfFile方式加载时,图像会被系统以数据方式加载到程序。当你不需要重用该图像,或者你需要将图像以数据方式存储到数据库,又或者你要通过网络下载一个很大的图像时,请尽量使用imageWithData的方式加载图像,仅仅加载图片而不在内存中缓存下来,那么每次获取时都会重新去加载。
无论用哪种方式加载图像,图像使用结束后,一定要记得显示释放内存(MRC下)。
两种方式各有利弊,imageNamed性能高一点,但是前提是图片占用的内存较小,且该图被多个地方或频繁使用,但是如果,图片存储空间大,内存吃不消,就用(+ (nullable UIImage *)imageWithContentsOfFile:(NSString *)path;/- (nullable instancetype)initWithContentsOfFile:(NSString *)path;/+ (nullable UIImage *)imageWithData:(NSData *)data;/- (nullable instancetype)initWithData:(NSData *)data;)从路径加载图片。
- -imageNamed: 是读取到内存后会缓存下来,下次再读取时直接从缓存中获取,因此访问效率要比较高。对于图片资源比较小,使用比较频繁的图片,通常会选择使用此种方式来加载。当然,若不需要考虑性能时,直接使用此种方式也是可以的。
- -initWithContentsOfFile: 当图片资源比较大,或者图片资源只使用一次就不再使用了,那么使用此种方式是最佳方式。当应用程序需要加载一张比较大的图片并且是一次性使用的,那么是没有必要去缓存这个图片的,用-imageWithContentsOfFile:是最为经济的方式,这样不会因为UIImage元素较多情况下,CPU会被逐个分散在不必要的缓存上而浪费过多CPU时间。另外,当我们的图片不是PNG图片时,我们通常会选择此种方式来加载。
代码使用:
1 UIImage *image = [UIImageimageNamed:@"logo"]; 2 3 // 在开发中,通常都定义了快捷调用的宏 4 #define kImgName(name) [UIImage imageNamed:name] 5 6 // 使用时就更简化了 7 UIImage *image = kImgName(@"logo");
1 NSString *filePath = [[NSBundle mainBundle]pathForResource:@"logo"ofType:@"png"]; 2 UIImage *image = [[UIImage alloc]initWithContentsOfFile:filePath]; 3 4 // 定义成宏,简化调用 5 #define kResourcePath(name, type) ([[NSBundle mainBundle] pathForResource:name ofType:type]) 6 #define kImgFromFile(name, type) [[UIImage alloc] initWithContentsOfFile:kResourcePath(name, type)] 7 8 // 调用也变得很简化了 9 UIImage *image = kImgFromFile(@"logo", @"png");
注意:
图片格式及NSBundle加载全路径:
1.xcode或者说苹果官方是极力推荐使用的图片格式是png
2.所有如果项目中用得是png的图片,则不用写后缀名
3.其他格式要求后缀名,特别是用UIImage加载图片时
摘录:
1.加载Assets.xcassets这里面的图片:
1> 打包后变成Assets.car
2> 拿不到路径
3> 只能通过imageNamed:来加载图片
4> 不能通过imageWithContentsOfFile:来加载图片
2.放到bundle 中的图片:
1> 可以拿到路径
2> 能通过imageNamed:来加载图片
3> 也能通过imageWithContentsOfFile:来加载图片
1> imageNamed:
a.就算指向它的指针被销毁,该资源也不会被从内存中干掉
b.放到Assets.xcassets的图片,默认就有缓存
c.图片经常被使用 (需要缓存)
2> imageWithContentsOfFile:
a.指向它的指针被销毁,该资源会被从内存中干掉
b.放到项目中的图片就不带有缓存
c.不经常用,大批量的图片
参考链接:http://www.jianshu.com/p/28a8ab8bb143
http://blog.sina.com.cn/s/blog_6291e42d0101grr4.html
http://www.cnblogs.com/cxbblog/p/3746824.html?utm_source=tuicool&utm_medium=referral
http://blog.csdn.net/dqjyong/article/details/26969355
http://www.open-open.com/lib/view/open1456017576980.html
http://www.jianshu.com/p/f0530a75c7af
(七):属性 size (CGSize)
1 @property(nonatomic,readonly) CGSize size; // reflects orientation setting. In iOS 4.0 and later, this is measured in points. In 3.x and earlier, measured in pixels
一个图像的尺寸到底是多大呢?
第一反应可能就是image.size,恭喜你答错了,正确的答案是图像的实际的尺寸(像 素)等于image.size乘以image.scale。如果做过界面贴图的话你可能经常会需要准备至少两套图,一套1倍图,一套图已@2x命名的二倍 图。这样当我们的程序运行在retina屏幕的时候系统就会自动的去加载@2x的图片,它的size将和一倍图加载进来的size相等,但是scale却 置为2,这点大家可以做个简单的小测试验证一下。然我们再深入一点儿为什么不直接加载到成二倍的尺寸呢,原因很简单因为我们在界面布局中逻辑坐标系中的 (单位是point),而实际的绘制都是在设备坐标系(单位是pixel)进行的,系统会自动帮我们完成从point到pixel之间的转化。其实这个比 例也就刚好和UIScreen中的scale对应,这样整条scale的线就可以串通了。
参考链接:http://mobile.51cto.com/hot-442118.htm
(八):属性 CGImage (CGImageRef)/CIImage(CIImage)
1 @property(nullable, nonatomic,readonly) CGImageRef CGImage; // returns underlying CGImageRef or nil if CIImage based 2 - (nullable CGImageRef)CGImage NS_RETURNS_INNER_POINTER CF_RETURNS_NOT_RETAINED; 3 #if __has_include(<CoreImage/CoreImage.h>) 4 @property(nullable,nonatomic,readonly) CIImage *CIImage NS_AVAILABLE_IOS(5_0); // returns underlying CIImage or nil if CGImageRef based 5 #endif
以及在UIImage 初始化里面未提及的CGImage/CIImage 相关的初始化
1 + (UIImage *)imageWithCGImage:(CGImageRef)cgImage; 2 + (UIImage *)imageWithCGImage:(CGImageRef)cgImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation NS_AVAILABLE_IOS(4_0);
3 #if __has_include(<CoreImage/CoreImage.h>) 4 + (UIImage *)imageWithCIImage:(CIImage *)ciImage NS_AVAILABLE_IOS(5_0); 5 + (UIImage *)imageWithCIImage:(CIImage *)ciImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation NS_AVAILABLE_IOS(6_0); 6 #endif 7 8 - (instancetype)initWithCGImage:(CGImageRef)cgImage; 9 - (instancetype)initWithCGImage:(CGImageRef)cgImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation NS_AVAILABLE_IOS(4_0);
10 #if __has_include(<CoreImage/CoreImage.h>) 11 - (instancetype)initWithCIImage:(CIImage *)ciImage NS_AVAILABLE_IOS(5_0); 12 - (instancetype)initWithCIImage:(CIImage *)ciImage scale:(CGFloat)scale orientation:(UIImageOrientation)orientation NS_AVAILABLE_IOS(6_0); 13 #endif
UIImage 类的Core Graphics 版本是CGImage(CGImageRef)这两个类之间很容易进行转换,因为一个UIImage类有一个CGImage的属性。
CGImage.h 是CoreGraphics 框架中类。
CGImageRef 在CGImage.h 中定义的一个结构体指针,用C 语言编写:
1 typedef struct CGImage *CGImageRef;
CGImageRef 和 struct CGImage * 是完全等价的。这个结构体用来创建像素位图,可以通过操作存储的像素位来编辑图片。QuartzCore这个框架是可移植的。
先跳过CGImage.h 中定义的枚举,先看下面的C 函数(都用CG_EXTERN 做了前缀修饰):
1.CFTypeID CGImageGetTypeID(void)
1 /* Return the CFTypeID for CGImageRefs. */ 2 3 CG_EXTERN CFTypeID CGImageGetTypeID(void) 4 CG_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_2_0);
这个方法返回的是一个编号,在Core Foundation框架CFTypeID 定义如下:
1 #if __LLP64__ 2 typedef unsigned long long CFTypeID; 3 typedef unsigned long long CFOptionFlags; 4 typedef unsigned long long CFHashCode; 5 typedef signed long long CFIndex; 6 #else 7 typedef unsigned long CFTypeID; 8 typedef unsigned long CFOptionFlags; 9 typedef unsigned long CFHashCode; 10 typedef signed long CFIndex; 11 #endif
这个方法没有特殊的意义,只是获得一个标识符。
2.CGImageRef __nullable CGImageCreate(size_t width, size_t height,
size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow,
CGColorSpaceRef cg_nullable space, CGBitmapInfo bitmapInfo,
CGDataProviderRef cg_nullable provider,
const CGFloat * __nullable decode, bool shouldInterpolate,
CGColorRenderingIntent intent) (提示:这个函数有11 个参数)
1 /* Create an image. */ 2 3 CG_EXTERN CGImageRef __nullable CGImageCreate(size_t width, size_t height, 4 size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow, 5 CGColorSpaceRef cg_nullable space, CGBitmapInfo bitmapInfo, 6 CGDataProviderRef cg_nullable provider, 7 const CGFloat * __nullable decode, bool shouldInterpolate, 8 CGColorRenderingIntent intent) 9 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
通过这个方法,可以创建出一个CGImageRef 类型的对象,下面分别对参数进行解释:
size_t 是定义的一个可移植性的单位,在64位机器中为8字节,32位位4字节。
1 #ifndef _SIZE_T 2 #define _SIZE_T 3 typedef __darwin_size_t size_t; 4 #endif /* _SIZE_T */ 5 6 #if defined(__SIZE_TYPE__) 7 typedef __SIZE_TYPE__ __darwin_size_t; /* sizeof() */ 8 #else 9 typedef unsigned long __darwin_size_t; /* sizeof() */ 10 #endif
参数列表:
size_t width : 图片宽度像素
size_t height : 图片高度像素
size_t bitsPerComponent : 每个颜色的比特数,例如在rgba-32 模式下是8
size_t bitsPerPixel : 每个像素的总比特数
size_t bytesPerRow : 每一行占用的字节数,注意这里的单位是字节
CGColorSpaceRef cg_nullable space : 颜色空间模式,例如const CFStringRef kCGColorSpaceGenericRGB 这个函数可以返回一个颜色空间对象。
CGBitmapInfo bitmapInfo : 位图像素布局 枚举值如下:
1 typedef CF_OPTIONS(uint32_t, CGBitmapInfo) { 2 kCGBitmapAlphaInfoMask = 0x1F, // Aplha通道信息遮罩。用这个值来提取alpha信息。这个值明确了位图是否包含了alpha通道和alpha通道是如何生成的 3 4 kCGBitmapFloatInfoMask = 0xF00, // 5 kCGBitmapFloatComponents = (1 << 8), 6 7 kCGBitmapByteOrderMask = kCGImageByteOrderMask, 8 kCGBitmapByteOrderDefault = (0 << 12), // 默认的字节序 9 kCGBitmapByteOrder16Little = kCGImageByteOrder16Little, // 16位小字节序格式 10 kCGBitmapByteOrder32Little = kCGImageByteOrder32Little, // 32位小字节序格式 11 kCGBitmapByteOrder16Big = kCGImageByteOrder16Big, // 16位大字节序格式 12 kCGBitmapByteOrder32Big = kCGImageByteOrder32Big // 32位大字节序格式 13 } CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
CGDataProviderRef cg_nullable provider : 数据源提供者
const CGFloat * __nullable decode : 解码渲染
bool shouldInterpolate : 是否抗锯齿
CGColorRenderingIntent intent : 图片相关参数
3.CGImageRef __nullable CGImageMaskCreate(size_t width, size_t height,
size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow,
CGDataProviderRef cg_nullable provider, const CGFloat * __nullable decode,
bool shouldInterpolate)
1 /* Create an image mask. */ 2 3 CG_EXTERN CGImageRef __nullable CGImageMaskCreate(size_t width, size_t height, 4 size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow, 5 CGDataProviderRef cg_nullable provider, const CGFloat * __nullable decode, 6 bool shouldInterpolate) 7 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
这个方法用于创建mask 图片图层,可以设置其显示部分与不显示部分达到特殊的效果,参数意义同CGImageCreate。
4.CGImageRef __nullable CGImageCreateCopy(CGImageRef cg_nullable image)
1 /* Return a copy of `image'. Only the image structure itself is copied; the 2 underlying data is not. */ 3 4 CG_EXTERN CGImageRef __nullable CGImageCreateCopy(CGImageRef cg_nullable image) 5 CG_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
复制一个CGImageRef对象
5.CGImageRef __nullable CGImageCreateWithJPEGDataProvider(
CGDataProviderRef cg_nullable source, const CGFloat * __nullable decode,
bool shouldInterpolate,
CGColorRenderingIntent intent)
1 /* Create an image from `source', a data provider of JPEG-encoded data. */ 2 3 CG_EXTERN CGImageRef __nullable CGImageCreateWithJPEGDataProvider( 4 CGDataProviderRef cg_nullable source, const CGFloat * __nullable decode, 5 bool shouldInterpolate, 6 CGColorRenderingIntent intent) 7 CG_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0);
通过JPEG数据源获取图像
6.CGImageRef __nullable CGImageCreateWithPNGDataProvider(
CGDataProviderRef cg_nullable source, const CGFloat * __nullable decode,
bool shouldInterpolate,
CGColorRenderingIntent intent)
1 /* Create an image using `source', a data provider for PNG-encoded data. */ 2 3 CG_EXTERN CGImageRef __nullable CGImageCreateWithPNGDataProvider( 4 CGDataProviderRef cg_nullable source, const CGFloat * __nullable decode, 5 bool shouldInterpolate, 6 CGColorRenderingIntent intent) 7 CG_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_2_0);
通过PNG数据源获取图像
7.CGImageRef __nullable CGImageCreateWithImageInRect(
CGImageRef cg_nullable image, CGRect rect)
1 CG_EXTERN CGImageRef __nullable CGImageCreateWithImageInRect( 2 CGImageRef cg_nullable image, CGRect rect) 3 CG_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
截取图像的一个区域重绘图像
8. CGImageRef __nullable CGImageCreateWithMask(
CGImageRef cg_nullable image, CGImageRef cg_nullable mask)
1 CG_EXTERN CGImageRef __nullable CGImageCreateWithMask( 2 CGImageRef cg_nullable image, CGImageRef cg_nullable mask) 3 CG_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
截取mask图像的某一区域重绘
9.CGImageRef __nullable CGImageCreateWithMaskingColors(
CGImageRef cg_nullable image, const CGFloat * cg_nullable components)
1 CG_EXTERN CGImageRef __nullable CGImageCreateWithMaskingColors( 2 CGImageRef cg_nullable image, const CGFloat * cg_nullable components) 3 CG_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
通过颜色分量数组创建位图
10.CGImageRef __nullable CGImageCreateCopyWithColorSpace(
CGImageRef cg_nullable image, CGColorSpaceRef cg_nullable space)
1 CG_EXTERN CGImageRef __nullable CGImageCreateCopyWithColorSpace( 2 CGImageRef cg_nullable image, CGColorSpaceRef cg_nullable space) 3 CG_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0);
通过颜色空间模式复制位图
11. CGImageRef cg_nullable CGImageRetain(CGImageRef cg_nullable image)
1 CG_EXTERN CGImageRef cg_nullable CGImageRetain(CGImageRef cg_nullable image) 2 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
引用+1
12. void CGImageRelease(CGImageRef cg_nullable image)
1 CG_EXTERN void CGImageRelease(CGImageRef cg_nullable image) 2 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
引用-1
13. bool CGImageIsMask(CGImageRef cg_nullable image)
1 CG_EXTERN bool CGImageIsMask(CGImageRef cg_nullable image) 2 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
返回是否为Mask图层
14. size_t CGImageGetWidth(CGImageRef cg_nullable image)
1 CG_EXTERN size_t CGImageGetWidth(CGImageRef cg_nullable image) 2 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
获取宽度像素
15. size_t CGImageGetHeight(CGImageRef cg_nullable image)
1 CG_EXTERN size_t CGImageGetHeight(CGImageRef cg_nullable image) 2 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
获取高度像素
16.下面这些方法分别获取相应属性
1 /* Return the number of bits/component of `image'. */ 2 3 CG_EXTERN size_t CGImageGetBitsPerComponent(CGImageRef cg_nullable image) 4 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 5 6 /* Return the number of bits/pixel of `image'. */ 7 8 CG_EXTERN size_t CGImageGetBitsPerPixel(CGImageRef cg_nullable image) 9 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 10 11 /* Return the number of bytes/row of `image'. */ 12 13 CG_EXTERN size_t CGImageGetBytesPerRow(CGImageRef cg_nullable image) 14 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 15 16 /* Return the color space of `image', or NULL if `image' is an image 17 mask. */ 18 19 CG_EXTERN CGColorSpaceRef __nullable CGImageGetColorSpace(CGImageRef cg_nullable image) 20 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 21 22 /* Return the alpha info of `image'. */ 23 24 CG_EXTERN CGImageAlphaInfo CGImageGetAlphaInfo(CGImageRef cg_nullable image) 25 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 26 27 /* Return the data provider of `image'. */ 28 29 CG_EXTERN CGDataProviderRef __nullable CGImageGetDataProvider(CGImageRef cg_nullable image) 30 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 31 32 /* Return the decode array of `image'. */ 33 34 CG_EXTERN const CGFloat * __nullable CGImageGetDecode(CGImageRef cg_nullable image) 35 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 36 37 /* Return the interpolation parameter of `image'. */ 38 39 CG_EXTERN bool CGImageGetShouldInterpolate(CGImageRef cg_nullable image) 40 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 41 42 /* Return the rendering intent of `image'. */ 43 44 CG_EXTERN CGColorRenderingIntent CGImageGetRenderingIntent(cg_nullable CGImageRef image) 45 CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0); 46 47 /* Return the bitmap info of `image'. */ 48 49 CG_EXTERN CGBitmapInfo CGImageGetBitmapInfo(CGImageRef cg_nullable image) 50 CG_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0); 51 52 /* Return the UTType of `image'. */ 53 54 CG_EXTERN CFStringRef __nullable CGImageGetUTType(cg_nullable CGImageRef image) 55 CG_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0);
举例:
1 //使用CGImageRef进行图片截取 2 3 //原图片 4 UIImage *img = [UIImage imageNamed:@"11.11.52.png"]; 5 //转化为位图 6 CGImageRef temImg = img.CGImage; 7 //根据范围截图 8 temImg = CGImageCreateWithImageInRect(temImg, CGRectMake(0, 0, 100, 100)); 9 //得到新的图片 10 UIImage *newImg = [UIImage imageWithCGImage:temImg]; 11 //释放位图对象 12 CGImageRelease(temImg); 13 // 注意:最后必须要调用这个函数,否则会造成内存泄露 14 15 CGImageRelease(temImg)
CIImage 包含了创建图片的所有必要的数据,但其本身没有渲染成图片,它代表的是图像数据或者生成图像数据的流程(如滤镜)
CGImage是基于像素的矩阵,每个点都对应了图片中点的像素信息
UIImage 管理图片数据,主要用来展现,如 UIImageView 中,控件中等,也可以用来直接在 view 或其他的 context 中绘制
参考链接:http://blog.csdn.net/hero82748274/article/details/46839265
原文链接:https://my.oschina.net/u/2340880/blog/406437?p=%7B%7BcurrentPage-1%7D%7D
原文链接:http://www.jianshu.com/p/8ab86ce103dd
http://www.jianshu.com/p/b30bd7c69c50
http://blog.csdn.net/xiaolinyeyi/article/details/51436163
(九):属性 imageOrientation(UIImageOrientation)
1 @property(nonatomic,readonly) UIImageOrientation imageOrientation; // this will affect how the image is composited
图片的方向,主要影响图片的合成
(十):属性 scale(CGFloat)
1 @property(nonatomic,readonly) CGFloat scale NS_AVAILABLE_IOS(4_0);
一个图像的尺寸到底有多大呢?
第一反应可能就是image.size,恭喜你答错了,正确的答案是图像的实际的尺寸(像素)等于image.size * image.scale。如果做过界面贴图的话你可能经常会需要准备至少两套图,一套1倍图,一套图已@2x命名的二倍图。这样当我们的程序运行在retina屏幕的时候系统就会自动的去加载@2x的图片,它的size将和一倍图加载进来的size相等,但是scale却置为2,这点大家可以做个简单的小测试验证一下。然我们再深入一点儿为什么不直接加载到成二倍的尺寸呢,原因很简单因为我们在界面布局中逻辑坐标系中的(单位是point),而实际的绘制都是在设备坐标系(单位是pixel)进行的,系统会自动帮我们完成从point到pixel之间的转化。其实这个比例也就刚好和UIScreen中的scale对应,这样整条scale的线就可以串通了。
在使用Core Image中的滤镜效果时,需要注意,滤镜之后的UIImage的尺寸是图片的真实尺寸。
当使用滤镜时,需要将尺寸还原为@2x的效果。
1 UIImage *img = [UIImage imageNamed:@"dog"]; 2 //...滤镜代码 3 CGImageRef imgRef = [context createCGImage: result fromRect: CGRectMake(0, 0, img.size.width * img.scale, img.size.height * img.scale)]; 4 UIImage *tempImg = [UIImage imageWithCGImage:imgRef scale:2 orientation:UIImageOrientationUp];
还有一些图片处理的延伸:
图片的处理大概分 截图(capture), 缩放(scale), 设定大小(resize), 存储(save):
1 // 等比例缩放 2 - (UIImage *)scaleImage:(UIImage *)image toScale:(float)scaleSize { 3 UIGraphicsBeginImageContext(CGSizeMake(image.size.width * scaleSize, image.size.height * scaleSize)); 4 [image drawInRect:CGRectMake(0, 0, image.size.width * scaleSize, image.size.height * scaleSize)]; 5 UIImage *scaleImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
6 return scaleImage; 7 }
1 // 自定义长宽 2 - (UIImage *)reSizeImage:(UIImage *)image toSize:(CGSize)reSize { 3 UIGraphicsBeginImageContext(CGSizeMake(reSize.width, reSize.height)); 4 [image drawInRect:CGRectMake(0, 0, reSize.width, reSize.height)]; 5 UIImage *reSizeImage = UIGraphicsGetImageFromCurrentImageContext(); 6 UIGraphicsEndImageContext(); 7 return reSizeImage; 8 }
1 // 处理某个特定View 2 // 只要是继承UIView 的object 都可以处理 3 // 必须先引入 QuzrtzCore.framework 4 - (UIImage *)captureView:(UIView *)theView { 5 CGRect rect = theView.frame; 6 UIGraphicsBeginImageContext(rect.size); 7 CGContextRef context = UIGraphicsGetCurrentContext(); 8 [theView.layer renderInContext:context]; 9 UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); 10 UIGraphicsEndImageContext(); 11 return img; 12 }
1 // 储存图片 2 UIImage *image = [UIImage imageNamed:@"imageName"]; 3 NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:@"image.png"]; 4 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1 // 对于指定的UIView 截屏 2 // 把当前的View 的layer,输出到一个ImageContext 中,然后利用这个ImageContext 得到UIImage 3 - (UIImage *)captureView:(UIView *)theView { 4 CGRect rect = theView.frame; 5 UIGraphicsBeginImageContext(rect.size); 6 CGContextRef context = UIGraphicsGetCurrentContext(); 7 [theView.layer renderInContext:context]; 8 UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); 9 UIGraphicsEndImageContext(); 10 return img; 11 }
原文链接:http://blog.csdn.net/sxh1234567/article/details/44884713
参考链接:https://www.douban.com/note/77384858/
http://blog.csdn.net/xuhuan_wh/article/details/6434055
http://www.cnblogs.com/xvewuzhijing/p/5003832.html
http://www.cocoachina.com/ios/20150803/12873.html
http://blog.sina.com.cn/s/blog_65de54500101hsm5.html
http://xbiii3s.iteye.com/blog/1188008
https://blog.0xbbc.com/2014/12/ios中正确的截屏姿势/
(十一):动效图片
1 // animated images. When set as UIImageView.image, animation will play in an infinite loop until removed. Drawing will render the first image 2 3 + (nullable UIImage *)animatedImageNamed:(NSString *)name duration:(NSTimeInterval)duration NS_AVAILABLE_IOS(5_0); // read sequence of files with suffix starting at 0 or 1 4 + (nullable UIImage *)animatedResizableImageNamed:(NSString *)name capInsets:(UIEdgeInsets)capInsets duration:(NSTimeInterval)duration NS_AVAILABLE_IOS(5_0); // sequence of files 5 + (nullable UIImage *)animatedResizableImageNamed:(NSString *)name capInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode duration:(NSTimeInterval)duration NS_AVAILABLE_IOS(6_0); 6 + (nullable UIImage *)animatedImageWithImages:(NSArray<UIImage *> *)images duration:(NSTimeInterval)duration NS_AVAILABLE_IOS(5_0); 7 8 @property(nullable, nonatomic,readonly) NSArray<UIImage *> *images NS_AVAILABLE_IOS(5_0); // default is nil for non-animated images 9 @property(nonatomic,readonly) NSTimeInterval duration NS_AVAILABLE_IOS(5_0); // total duration for all frames. default is 0 for non-animated images
这是UIImage.h 中所有和动效图片相关的属性和方法。
如果我们有一组大小和缩放因子相同的图片,就可以将这些图片加载到同一个UIImage对象中,形成一个动态的UIImage对象。为此,UIImage提供了以下方法:
1 + (nullable UIImage *)animatedImageNamed:(NSString *)name duration:(NSTimeInterval)duration NS_AVAILABLE_IOS(5_0); // read sequence of files with suffix starting at 0 or 1
这个方法会加载以name为基准文件名的一系列文件。如,假设我们的name参数值为”swift”,则这个方法会加载诸如”swift0.png”, “swift1.png”,…, “swift1024.png”这样的一系列的文件。
这里有两个问题需要注意:
-
文件的序号必须是从0开始的连续数字,如果不从0开始,则在Playground中是会报错的。而如果中间序号有断,而中断后的图片是不会被加载的。
-
所有文件的大小和缩放因子应该是相同的,否则显示时会有不可预期的结果,这种结果主要表现为播放的顺序可能是杂乱的。
- name 只是一个base name,UIImage 会添加0~1024后缀拼成完整文件名。从bundle 中loadUIImage 中的所有UIImage共享同一个size 和scale ,取images 中第一张图片的size 和scale。images 中所有UIImage 使用同一个capInsets 和resizingMod。
如果我们有一组基准文件名不同的文件,但其大小和缩放因子相同,则可能使用以下方法:
1 + (nullable UIImage *)animatedImageWithImages:(NSArray<UIImage *> *)images duration:(NSTimeInterval)duration NS_AVAILABLE_IOS(5_0);
传入一个UIImage数组来拼装一个动效UIImage对象。
另外,UIImage也提供了resizable 版本的动效方法,如下所示:
1 + (nullable UIImage *)animatedResizableImageNamed:(NSString *)name capInsets:(UIEdgeInsets)capInsets duration:(NSTimeInterval)duration NS_AVAILABLE_IOS(5_0); // sequence of files 2 + (nullable UIImage *)animatedResizableImageNamed:(NSString *)name capInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode duration:(NSTimeInterval)duration NS_AVAILABLE_IOS(6_0);
第一个方法的UIImageResizingMode默认是UIImageResizingModeTile,所以如果想对图片做拉伸处理,可以使用第二个的方法,并传入UIImageResizingModeStretch。
你并不能告诉一个动画形象开始执行动画,也不能告诉它你想要动画重复多久。相反,只要它出现在你的界面上,动画图像就始终在执行动画,每隔1秒的时间重复这个图片序列;为了控制动画,你可以从你的界面中添加或者删除这个图像,这样可能会让动画图像转变为一个没有动画的图像。此外,动画图像可以出现在任何一个UIImage会出现的一些界面对象的属性界面上。
参考链接:http://www.cocoachina.com/ios/20151123/14376.html
http://blog.csdn.net/mardax/article/details/52352872
http://www.cnblogs.com/YungMing/p/4016517.html
http://www.cnblogs.com/ndyBlog/p/3956804.html?utm_source=tuicool&utm_medium=referral
http://www.oschina.net/question/262659_142325
(十二):绘画图片
1 // the these draw the image 'right side up' in the usual coordinate system with 'point' being the top-left. 2 3 - (void)drawAtPoint:(CGPoint)point; // mode = kCGBlendModeNormal, alpha = 1.0 // 在指定的点绘画图片,这个点就是图片的左上角顶点 4 - (void)drawAtPoint:(CGPoint)point blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha; // 在指定的点绘制整个图片,并使用自定义图片复合模式,并设置透明度 5 - (void)drawInRect:(CGRect)rect; // 在指定区域内绘制图片,可根据需要缩放图片 // mode = kCGBlendModeNormal, alpha = 1.0 6 - (void)drawInRect:(CGRect)rect blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha; // 在指定区域绘制图片,并使用自定义图片复合模式,并设置透明度 7 8 - (void)drawAsPatternInRect:(CGRect)rect; // draws the image as a CGPattern // 在指定区域内,平铺图片
这些方法,只有在UIview的drawRect方法中使用,将image绘制到这个UIview之中。
参考链接:http://www.cnblogs.com/ndyBlog/p/3956804.html?utm_source=tuicool&utm_medium=referral
http://blog.csdn.net/daiyelang/article/details/40682531
(十三):拉伸图片
// 返回值是UIImage 类型的对象,返回该方法拉伸后的图像
// 参数capinsets 是UIEdgeInsets 类型的数据,即原图像要保护的区域
//该参数的意思是被保护的区域到原始图像外轮廓的上部,左部,底部,右部的直线距离,
// UIEdgeInsets 结构体
typedef struct UIEdgeInsets {
CGFloat top, left, bottom, right; // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
} UIEdgeInsets;
1 - (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(5_0); // create a resizable version of this image. the interior is tiled when drawn. // 默认是平铺的模式 UIImageResizingModeTile
2 - (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode NS_AVAILABLE_IOS(6_0); // the interior is resized according to the resizingMode // 多了一个 resizingMode 参数 可设置平铺或者拉伸 UIImageResizingModeTile /
UIImageResizingModeStretch
3 4 @property(nonatomic,readonly) UIEdgeInsets capInsets NS_AVAILABLE_IOS(5_0); // default is UIEdgeInsetsZero for non resizable images 5 @property(nonatomic,readonly) UIImageResizingMode resizingMode NS_AVAILABLE_IOS(6_0); // default is UIImageResizingModeTile
参考链接:http://blog.csdn.net/q199109106q/article/details/8615661
http://www.jianshu.com/p/a577023677c1
http://www.jianshu.com/p/25eded09ebac
http://www.cnblogs.com/geek6/p/3930668.html?utm_source=tuicool&utm_medium=referral
UIImage 已经弃用的之前的图片拉伸相关的方法和属性:
1 @interface UIImage(UIImageDeprecated) 2 3 // use resizableImageWithCapInsets: and capInsets. 4 5 - (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight __TVOS_PROHIBITED; 6 @property(nonatomic,readonly) NSInteger leftCapWidth __TVOS_PROHIBITED; // default is 0. if non-zero, horiz. stretchable. right cap is calculated as width - leftCapWidth - 1 7 @property(nonatomic,readonly) NSInteger topCapHeight __TVOS_PROHIBITED; // default is 0. if non-zero, vert. stretchable. bottom cap is calculated as height - topCapWidth - 1 8 9 @end
(十四):对齐inset
1 // Support for constraint-based layout (auto layout) 2 // The alignmentRectInsets of a UIImage are used by UIImageView and other UIView and UIControl 3 // subclasses that take custom images to determine the view's alignment rect insets for 4 // constraint-based layout. 5 // The default alignmentRectInsets are UIEdgeInsetsZero. 6 - (UIImage *)imageWithAlignmentRectInsets:(UIEdgeInsets)alignmentInsets NS_AVAILABLE_IOS(6_0); 7 @property(nonatomic,readonly) UIEdgeInsets alignmentRectInsets NS_AVAILABLE_IOS(6_0);
1 UIImage *image = [[UIImage imageNamed:@"imageName"] 2 imageWithAlignmentRectInsets:UIEdgeInsetsMake(0, 0, 20, 20)]; 3 UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
alignmentInsets 定义了距离矩形的顶边、左边、底边和右边的间隙,用来描述从矩形的边移进(使用正值)或移出(使用负值)多远。即使图像内放置了绘制好的装饰效果,这些alignmentInsets 也能确保对齐矩形的正确性。
参考链接:http://book.51cto.com/art/201502/464877.htm
(十五):属性 traitCollection (UITraitCollection)
1 #if __has_include(<UIKit/UITraitCollection.h>) 2 @property (nonatomic, readonly, copy) UITraitCollection *traitCollection NS_AVAILABLE_IOS(8_0); // describes the image in terms of its traits 3 @property (nullable, nonatomic, readonly) UIImageAsset *imageAsset NS_AVAILABLE_IOS(8_0); // The asset is not encoded along with the image. Returns nil if the image is not CGImage based. 4 #endif
参考链接:http://www.cnblogs.com/imock/p/6525277.html
(十六): 图片翻转
1 // Creates a version of this image that, when assigned to a UIImageView’s image property, draws its underlying image contents horizontally mirrored when running under a right-to-left language. Affects the flipsForRightToLeftLayoutDirection property; does not affect the imageOrientation property. 2 // This method cannot be used to create a left-to-right version of a right-to-left source image, and will be deprecated in a future release. New code should instead use -imageWithHorizontallyFlippedOrientation to construct a UIImageAsset. 3 - (UIImage *)imageFlippedForRightToLeftLayoutDirection NS_AVAILABLE_IOS(9_0); 4 @property (nonatomic, readonly) BOOL flipsForRightToLeftLayoutDirection NS_AVAILABLE_IOS(9_0);
iOS 9.0 新添加imageFlippedForRightToLeftLayoutDirection 方法,该方法可以很容易地在适当时候以编程方式的翻转图像。
参考链接:http://www.jianshu.com/p/2d457c7f5729
1 // Creates a version of this image with an imageOrientation property that is horizontally mirrored from this image’s. Does not affect the flipsForRightToLeftLayoutDirection property. 2 - (UIImage *)imageWithHorizontallyFlippedOrientation NS_AVAILABLE_IOS(10_0);
(十七):CIImag 的分类 UIKitAdditions
1 #if __has_include(<CoreImage/CoreImage.h>) 2 @interface CIImage(UIKitAdditions) 3 4 - (nullable instancetype)initWithImage:(UIImage *)image NS_AVAILABLE_IOS(5_0); 5 - (nullable instancetype)initWithImage:(UIImage *)image options:(nullable NSDictionary *)options NS_AVAILABLE_IOS(5_0); 6 7 @end 8 #endif
(十八):UIImagePNGRepresentation 和 UIImageJPEGRepresentation
1 UIKIT_EXTERN NSData * __nullable UIImagePNGRepresentation(UIImage * __nonnull image); // return image as PNG. May return nil if image has no CGImageRef or invalid bitmap format // 返回图片PNG,如果图像没有CGImageRef 或者无效的位图格式则返回nil 2 UIKIT_EXTERN NSData * __nullable UIImageJPEGRepresentation(UIImage * __nonnull image, CGFloat compressionQuality); // return image as JPEG. May return nil if image has no CGImageRef or invalid bitmap format. compression is 0(most)..1(least) // 返回图片JPEG,如果图像没有CGImageRef 或者无效的位图格式则返回nil
UIImageJPEGRepresentation方法在耗时上比较少 而UIImagePNGRepresentation耗时操作时间比较长。
UIImageJPEGRepresentation函数需要两个参数:图片的引用和压缩系数。而UIImagePNGRepresentation只需要图片引用作为参数。
通过在实际使用过程中,比较发现: UIImagePNGRepresentation(UIImage* image) 要比UIImageJPEGRepresentation(UIImage* image, 1.0) 返回的图片数据量大很多。譬如,同样是读取摄像头拍摄的同样景色的照片, UIImagePNGRepresentation()返回的数据量大小为199K,而 UIImageJPEGRepresentation(UIImage* image, 1.0)返回的数据量大小只为140KB,比前者少了50多KB。
如果对图片的清晰度要求不高,还可以通过设置 UIImageJPEGRepresentation函数的第二个参数,大幅度降低图片数据量。譬如,刚才拍摄的图片,通过调用UIImageJPEGRepresentation(UIImage* image, 1.0)读取数据时,返回的数据大小为140KB,但更改压缩系数后,通过调用UIImageJPEGRepresentation(UIImage* image, 0.5)读取数据时,返回的数据大小只有11KB多,大大压缩了图片的数据量 ,而且从视角角度看,图片的质量并没有明显的降低。因此,在读取图片数据内容时,建议优先使用UIImageJPEGRepresentation,并可根据自己的实际使用场景,设置压缩系数,进一步降低图片数据量大小。
之前在做上传头像的时候由于服务器只能解析指定类型的图片,所以要在JPEG 和 PNG 之间做出选择,可视服务器的不同情况选择UIImagePNGRepresentation 或 UIImageJPEGRepresentation。
参考链接:http://blog.csdn.net/mideveloper/article/details/11473627