點(diǎn)擊下載 Demo
注意??:內(nèi)存有泄露,暫時(shí)沒時(shí)間修復(fù)惧磺,使用需慎重哈
一颖对、獲取照片
1、開啟相冊(cè)權(quán)限
首先磨隘,需在工程對(duì)應(yīng)的plist文件內(nèi)添加“Privacy - Photo Library Usage Description”這個(gè)key缤底,同時(shí)設(shè)置其值為“App needs your permission to access the Photo”類似這樣的說明。
// 獲取當(dāng)前App的相冊(cè)授權(quán)狀態(tài)
PHAuthorizationStatus authorizationStatus = [PHPhotoLibrary authorizationStatus];
// 判斷授權(quán)狀態(tài)
if (authorizationStatus == PHAuthorizationStatusAuthorized) {
// 如果已經(jīng)授權(quán), 獲取圖片
[self getAllAsset];
}
// 如果沒決定, 彈出指示框, 讓用戶選擇
else if (authorizationStatus == PHAuthorizationStatusNotDetermined) {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
// 如果用戶選擇授權(quán), 則獲取圖片
if (status == PHAuthorizationStatusAuthorized) {
[self getAllAsset];
}
}];
} else {
[self noticeAlert];
}
2番捂、獲取相簿中的PHAsset對(duì)象
PHAsset: 代表照片庫中的一個(gè)資源个唧,跟 ALAsset 類似,通過 PHAsset 可以獲取和保存資源
PHFetchOptions: 獲取資源時(shí)的參數(shù)设预,可以傳 nil徙歼,即使用系統(tǒng)默認(rèn)值
PHFetchResult: 表示一系列的資源結(jié)果集合,也可以是相冊(cè)的集合鳖枕,從 PHCollection 的類方法中獲得
// 獲取所有資源的集合魄梯,并按資源的創(chuàng)建時(shí)間排序
PHFetchOptions *options = [[PHFetchOptions alloc] init];
options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate"
ascending:NO]];
PHFetchResult *result = [PHAsset fetchAssetsWithOptions:options];
3、獲取相片
PhotoKit 無法直接從 PHAsset 的實(shí)例中獲取圖像宾符,而是引入了一個(gè)管理器?PHImageManager 獲取圖像酿秸。PHImageManager 是通過請(qǐng)求的方式拉取圖像,并可以控制請(qǐng)求得到的圖像的尺寸吸奴、剪裁方式允扇、質(zhì)量缠局,緩存以及請(qǐng)求本身的管理(發(fā)出請(qǐng)求、取消請(qǐng)求)等考润。而請(qǐng)求圖像的方法是 ?PHImageManager 的一個(gè)實(shí)例方法狭园。
// 篩選本地圖片,過濾視頻糊治、iCloud圖片
PHAsset *asset = self.assetArr[index];
if (asset.mediaType != PHAssetMediaTypeImage || asset.sourceType != PHAssetSourceTypeUserLibrary) {
[self requestImageWithIndex:index+1];
return;
}
// 請(qǐng)求圖像的屬性
PHImageRequestOptions *imageOpt = [[PHImageRequestOptions alloc] init];
// resizeMode 屬性控制圖像的剪裁
imageOpt.resizeMode = PHImageRequestOptionsResizeModeNone;
// deliveryMode 則用于控制請(qǐng)求的圖片質(zhì)量
imageOpt.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
// 獲取縮率圖
PHImageManager *mgr = [PHImageManager defaultManager];
__weak typeof(self) weakSelf = self;
[mgr requestImageForAsset:asset
targetSize:CGSizeMake(125, 125)
contentMode:PHImageContentModeDefault
options:imageOpt
resultHandler:^(UIImage *result, NSDictionary *info) {
[weakSelf getImageSizeWithIndex:index
image:result];
}];
- asset唱矛,圖像對(duì)應(yīng)的 PHAsset。
- targetSize井辜,需要獲取的圖像的尺寸绎谦,如果輸入的尺寸大于資源原圖的尺寸,則只返回原圖粥脚。需要注意在 PHImageManager 中窃肠,所有的尺寸都是用 Pixel 作為單位(Note that all sizes are in pixels),因此這里想要獲得正確大小的圖像刷允,需要把輸入的尺寸轉(zhuǎn)換為 Pixel冤留。如果需要返回原圖尺寸,可以傳入 PhotoKit 中預(yù)先定義好的常量?PHImageManagerMaximumSize树灶,表示返回可選范圍內(nèi)的最大的尺寸纤怒,即原圖尺寸。
- contentMode天通,圖像的剪裁方式泊窘,與?UIView 的 contentMode 參數(shù)相似,控制照片應(yīng)該以按比例縮放還是按比例填充的方式放到最終展示的容器內(nèi)像寒。注意如果 targetSize 傳入?PHImageManagerMaximumSize烘豹,則 contentMode 無論傳入什么值都會(huì)被視為?PHImageContentModeDefault。
- options萝映,一個(gè)?PHImageRequestOptions 的實(shí)例吴叶,可以控制的內(nèi)容相當(dāng)豐富阐虚,包括圖像的質(zhì)量序臂、版本,也會(huì)有參數(shù)控制圖像的剪裁实束,下面再展開說明奥秆。
- resultHandler,請(qǐng)求結(jié)束后被調(diào)用的 block咸灿,返回一個(gè)包含資源對(duì)于圖像的 UIImage 和包含圖像信息的一個(gè) NSDictionary构订,在整個(gè)請(qǐng)求的周期中,這個(gè) block 可能會(huì)被多次調(diào)用避矢,關(guān)于這點(diǎn)連同 options 參數(shù)在下面展開說明悼瘾。
參考鏈接:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-two.html
3囊榜、獲取相片原圖大小
這里獲取的是相片原圖的數(shù)據(jù)大小,請(qǐng)求參數(shù)與獲取圖片類似亥宿,可參考上面
PHImageRequestOptions *sizeOpt = [[PHImageRequestOptions alloc] init];
sizeOpt.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
sizeOpt.resizeMode = PHImageRequestOptionsResizeModeExact;
__weak typeof(self) weakSelf = self;
PHImageManager *mgr = [PHImageManager defaultManager];
[mgr requestImageDataForAsset:self.assetArr[index]
options:sizeOpt
resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
[weakSelf dealImageWithIndex:index
image:image
imageData:imageData];
}];
二卸勺、存儲(chǔ)照片
1、保存圖片到系統(tǒng)相冊(cè)
此方法可以直接保存在系統(tǒng)相冊(cè)的"相機(jī)膠卷"中
- (void)save {
// 存儲(chǔ)圖片到"相機(jī)膠卷"
UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}
// 成功保存圖片到相冊(cè)中, 必須調(diào)用此方法, 否則會(huì)報(bào)參數(shù)越界錯(cuò)誤
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
if (error) {
NSLog(@"保存失敗");
} else {
NSLog(@"保存成功");
}
}
2烫扼、保存圖片到自定義相冊(cè)
首先根據(jù)相簿名獲取相簿曙求,然后將圖片存入到相簿中。詳情可參考:http://www.reibang.com/p/1b3616945fc3
三映企、刪除照片
/// 刪除照片
+ (void)deleteAssets:(NSArray<PHAsset *> *)assets completionHandler:(void (^)(BOOL success, NSError *error))completion {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetChangeRequest deleteAssets:assets];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(success, error);
});
}
}];
}
四悟狱、相似照片
判斷照片的相似度,可分為五步:
1堰氓、縮小尺寸
2挤渐、簡化色彩
3、計(jì)算平均值
4双絮、比較像素的灰度
5挣菲、計(jì)算哈希值
原理介紹參考:http://www.reibang.com/p/8c3296ba6522
使用opencv判斷相似度:http://www.qingpingshan.com/rjbc/ios/202983.html
iOS,OC,圖片相似度比較,圖片指紋:http://www.cnblogs.com/kongkaikai/p/5251543.html
五、壓縮照片
壓縮圖片不能壓縮到指定大小掷邦,有誤差白胀,只能計(jì)算近似值。這里通過遞歸的方法抚岗,壓縮到小于1.5M
// 壓縮圖片 小于1.5M -- 先壓縮大小再壓縮數(shù)據(jù)
+ (NSDictionary *)compressData:(NSData *)imageData {
NSUInteger imageSize = imageData.length;
UIImage *image = [UIImage imageWithData:imageData];
NSLog(@"圖片壓縮前 data: %.2fMB, size:%@", imageData.length / 1024.0 / 1024.0, NSStringFromCGSize(image.size));
// 壓縮率
CGFloat rate = 1024 * 1024.0 / imageSize;
// 大小壓縮
CGSize size = CGSizeMake(image.size.width * rate, image.size.height * rate);
UIImage *img2 = [self imageWithImage:image scaledToSize:size];
NSData *data2 = UIImageJPEGRepresentation(img2, 1);
NSLog(@"大小壓縮后 data: %.2fMB, size:%@", data2.length / 1024.0 / 1024.0, NSStringFromCGSize(size));
if (data2.length > 1024 * 1024 * 1.5) {
// 數(shù)據(jù)壓縮
NSData *data = UIImageJPEGRepresentation(img2, rate);
UIImage *img = [UIImage imageWithData:data];
NSLog(@"數(shù)據(jù)壓縮后 data: %.2fMB, size:%@", data.length / 1024.0 / 1024.0, NSStringFromCGSize(img.size));
if (data.length > 1024 * 1024 * 1.5) {
return [self compressData:data];
} else {
return @{@"image":img, @"length":@(data.length)};
}
} else {
return @{@"image":img2, @"length":@(data2.length)};
}
}