OC UIImage基礎

韋家冰發表於2017-12-13

參考: 談談 iOS 中圖片的解壓縮

#####imageNamed:載入bundle圖片 通過 imageNamed 建立 UIImage 時,系統實際上只是在 Bundle 內查詢到檔名,然後把這個檔名放到 UIImage 裡返回,並沒有進行實際的檔案讀取和解碼。當 UIImage 第一次顯示到螢幕上時,其內部的解碼方法才會被呼叫,同時解碼結果會儲存到一個全域性快取去。

+ (nullable UIImage *)imageNamed:(NSString *)name;      // load from main bundle
複製程式碼
UIImage *image = [UIImage imageNamed:@"XXX.png"];
複製程式碼

快取:首先去系統快取中查詢是否有圖片,找到返回;找不到則從bundle中載入圖片並返回,同時將圖片快取到系統中。快取的圖片只有在收到記憶體警告時才會釋放。

執行緒安全性:iOS 9.0之前不是執行緒安全的,iOS 9.0之後Apple作了優化處理,將其改為執行緒安全的方法。

#####通過路徑載入圖片

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"logo" ofType:@"png"];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];

// 但是在開發中,筆者通常會定義成巨集,簡化呼叫
#define kResourcePath(name, type) ([[NSBundle mainBundle] pathForResource:name ofType:type])
#define kImgFromFile(name, type) [UIImage imageWithContentsOfFile:kResourcePath(name, type)]

// 然後,呼叫也變得很簡化了~
UIImage *image = kImgFromFile(@"logo", @"png");

複製程式碼

#####NSDate轉成UIImage,scale縮放引數

+ (nullable UIImage *)imageWithData:(NSData *)data;
+ (nullable UIImage *)imageWithData:(NSData *)data scale:(CGFloat)scale NS_AVAILABLE_IOS(6_0);
- (nullable instancetype)initWithData:(NSData *)data;
- (nullable instancetype)initWithData:(NSData *)data scale:(CGFloat)scale NS_AVAILABLE_IOS(6_0);

複製程式碼
// 以為是放大十倍,結果是縮小了十倍。但是image.cgImage大小不變
UIImage *image = [UIImage imageWithData:data scale:10]; // po image.size: (width = 64, height = 38.6)
UIImage *image = [UIImage imageWithData:data scale:1]; //  po image.size: (width = 640, height = 386)

複製程式碼

#####UIImage轉成NSData

UIImage *image = [UIImage imageWithData: imageData];

// 方法1
NSData *imageData = UIImagePNGRepresentation(image);
// 方法2
NSData *imageData = UIImageJPEGRepresentation(image,1);// 0到1
複製程式碼

#####拉伸、平鋪圖片,指定UIEdgeInsets區域

typedef NS_ENUM(NSInteger, UIImageResizingMode) {
    UIImageResizingModeTile,// 平鋪模式
    UIImageResizingModeStretch,// 拉伸模式
};
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(5_0); 
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode NS_AVAILABLE_IOS(6_0);

@property(nonatomic,readonly) UIEdgeInsets capInsets               NS_AVAILABLE_IOS(5_0);   // default is UIEdgeInsetsZero for non resizable images
@property(nonatomic,readonly) UIImageResizingMode resizingMode NS_AVAILABLE_IOS(6_0); // default is UIImageResizingModeTile


// 定義可拉伸的圖片
#define kResizableImage(name,top,left,bottom,right) [[UIImage imageNamed:name] resizableImageWithCapInsets:UIEdgeInsetsMake(top,left,bottom,right)]
複製程式碼

UIEdgeInsets區域

#####CGImage和UIImage相互轉換

// UIImage ->CGimageRef
UIImage *image = [UIImage imageNamed:@"xxx.png"];
CGImageRef ciRef = [image CGImage];
// CGImage ->UIImage
CGImageRef ciRef ...
UIImage *image = [UIImage imageWithCGImage:ciRef];

複製程式碼

iOS 處理圖片的一些小 Tip

#####儲存圖片到相簿

UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);//儲存圖片到照片庫(PNG格式)
複製程式碼
[ALAssetsLibrary writeImageDataToSavedPhotosAlbum:metadata:completionBlock] 可以直接把 APNG、GIF 的資料寫入相簿
// 從相簿獲取圖片時,直接去讀 data 二進位制資料,就能原封不動的取出來。
複製程式碼

####UIImage儲存到磁碟,用什麼方式最好? 儲存 UIImage 有三種方式: 1.直接用 NSKeyedArchiver 把 UIImage 序列化儲存(內部是UIImagePNGRepresentation)(消耗最大), 2.用 UIImagePNGRepresentation() 先把圖片轉為 PNG 儲存, 3.用 UIImageJPEGRepresentation() 把圖片壓縮成 JPEG 儲存(圖片不包含透明畫素時,最佳)。

相關文章