問題
問題簡述: 使用SDWebImage下載圖片保存到相冊變大,原本8M圖片保存后變成20M.
問題代碼:
首先是使用SDWebImage的- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionWithFinishedBlock)completedBlock
方法進行下載圖片
NSURL *imageURL = [NSURL URLWithString:@"http://upload-images.jianshu.io/upload_images/259-7424a9a21a2cb81b.jpg"];
[[SDWebImageManager sharedManager]downloadImageWithURL:imageURL options:SDWebImageLowPriority progress:^(NSInteger receivedSize, NSInteger expectedSize) {
//此處是下載過程中的回調 expectedSize:總大小 receivedSize:當前已下載大小
NSLog(@"expectedSize:%.2fM", expectedSize/1024/1024.0);
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
//下載完成的回調
[self.imageView setImage:image];
//保存SDWebImage下載的圖片存到指定路徑
NSData *imageData = UIImagePNGRepresentation(image);
NSLog(@"imageData.length:%.2fM", imageData.length/1024/1024.0);
[UIImagePNGRepresentation(image) writeToFile:_imageModel.imagePath atomically:YES];
}];
保存圖片到本地后,在適當場景觸發保存圖片到手機相冊,保存到相冊使用的是PHPhotoLibrary
的creationRequestForAssetFromImage
保存到相冊方法如下:
- (void)loadImageFinished {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//寫入圖片到相冊
UIImage *image = [UIImage imageWithContentsOfFile:_imageModel.imagePath];
[PHAssetChangeRequest creationRequestForAssetFromImage:image];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
//保存成功
}];
}
也可以使用
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
方法來保存圖片到相冊,效果是一樣的,都會變大
整個一套下載保存的邏輯是沒有問題的,可以完成保存,在相冊也可以看到,但是當你再次看相冊中文件的大小時,你會發現圖片變大了
問題分析
不想看分析的可以直接跳到下一章 解決方法 看具體的解決方案
經過調試發現,在使用SDWebImage 方法下載圖片時,下載中回調的block打印的expectedSize(圖片總大小)的大小和下載完成回調的block打印的imageData.length的大小不一致,imageData.length偏大。
而下載完成后直接看沙盒中SDWebImage 存儲的圖片大小是正確的,
也就是說問題出在下載完成后將image存到指定路徑的過程中。
經Google發現將文件轉成UIImage 再轉成NSData ,這個過程會使圖片變大。
解決方法
解決方法就是不使用SDWebImage 下載完成block返回的UIImage,而是直接找到SDWebImage下載后的文件轉成NSData存儲到指定路徑。
在存儲圖片到相冊的過程中也摒棄使用UIImage存儲,使用PHPhotoLibrary
中的creationRequestForAssetFromImageAtFileURL:
方法,可以使用NSURL來存儲,而NSURL可以由文件路徑來初始化。
代碼如下
下載代碼:
NSURL *imageURL = [NSURL URLWithString:@"http://upload-images.jianshu.io/upload_images/259-7424a9a21a2cb81b.jpg"];
[[SDWebImageManager sharedManager]downloadImageWithURL:imageURL options:SDWebImageLowPriority progress:^(NSInteger receivedSize, NSInteger expectedSize) {
//此處是下載過程中的回調 expectedSize:總大小 receivedSize:當前已下載大小
NSLog(@"expectedSize:%.2fM", expectedSize/1024/1024.0);
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
//下載完成的回調
[self.imageView setImage:image];
//保存SDWebImage下載的圖片存到指定路徑
if (finished) {
//此處一定要延時之行才可以
[self performSelector:@selector(saveImageWithURL:) withObject: imageURL afterDelay:1];
}
}];
保存圖片存到指定路徑 的代碼
//保存SDWebImage下載的圖片存到指定路徑
- (void)saveImageWithURL:(NSURL *)imageURL {
if ([_imageModel.thumbUrl rangeOfString:_imageModel.originalImageUrl].location!=NSNotFound) {
//根據下載URL獲取圖片在SDWebImage中存儲對應的key
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:imageURL];
//根據key獲取到對應圖片的存儲路徑
NSString *imagePath = [[SDWebImageManager sharedManager].imageCache defaultCachePathForKey:key];
//根據路徑直接獲取NSData數據
NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
NSLog(@"imageData.length:%.2fM", imageData.length/1024/1024.0);
//將NSData數據存儲到指定路徑
[imageData writeToFile:_imageModel.originalImagePath atomically:YES];
}
}
保存圖片到相冊的代碼
//保存圖片到相冊
- (void)loadImageFinished {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//寫入圖片到相冊
NSString *pathStr = _imageModel.imagePath;
NSURL *imageUrl = [NSURL fileURLWithPath:pathStr];
[PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:imageUrl];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
//保存完成
}];
}