You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
9.0 KiB
295 lines
9.0 KiB
// |
|
// DBImageViewCache.m |
|
// DBImageView |
|
// |
|
// Created by iBo on 25/08/14. |
|
// Copyright (c) 2014 Daniele Bogo. All rights reserved. |
|
// |
|
|
|
#import "TYImageCache.h" |
|
#import <CommonCrypto/CommonDigest.h> |
|
|
|
@interface TYImageCache (){ |
|
NSFileManager *_fileManager; |
|
} |
|
|
|
@end |
|
|
|
@implementation TYImageCache |
|
|
|
static TYImageCache *_instance; |
|
|
|
+ (id)allocWithZone:(NSZone *)zone |
|
{ |
|
static dispatch_once_t onceToken; |
|
dispatch_once(&onceToken, ^{ |
|
_instance = [super allocWithZone:zone]; |
|
}); |
|
return _instance; |
|
} |
|
|
|
+ (instancetype)cache |
|
{ |
|
static dispatch_once_t onceToken; |
|
dispatch_once(&onceToken, ^{ |
|
_instance = [[self alloc] init]; |
|
}); |
|
return _instance; |
|
} |
|
|
|
#pragma mark - md5加密 |
|
+ (NSString *) md5:(NSString *)str |
|
{ |
|
const char *cStr = [str UTF8String]; |
|
if (cStr == NULL) { |
|
cStr = ""; |
|
} |
|
unsigned char result[CC_MD5_DIGEST_LENGTH]; |
|
CC_MD5( cStr, (CC_LONG)strlen(cStr), result ); |
|
return [NSString stringWithFormat: |
|
@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", |
|
result[0], result[1], result[2], result[3], |
|
result[4], result[5], result[6], result[7], |
|
result[8], result[9], result[10], result[11], |
|
result[12], result[13], result[14], result[15] |
|
]; |
|
} |
|
|
|
- (id) init |
|
{ |
|
self= [super init]; |
|
|
|
if ( self ) { |
|
_fileManager = [NSFileManager new]; |
|
[self createLocalDirectory]; |
|
} |
|
|
|
return self; |
|
} |
|
|
|
#pragma mark - 创建缓存图片文件目录 |
|
- (void) createLocalDirectory |
|
{ |
|
if ( ![_fileManager fileExistsAtPath:self.localDirectory] ) { |
|
NSError *error; |
|
|
|
if ( ![[NSFileManager defaultManager] createDirectoryAtPath:self.localDirectory withIntermediateDirectories:YES attributes:nil error:&error] ) { |
|
NSLog(@"[%@] ERROR: attempting to write create MyFolder directory", [self class]); |
|
NSAssert( FALSE, @"Failed to create directory maybe out of disk space?"); |
|
} |
|
} |
|
} |
|
|
|
#pragma mark - 存放image的文件夹路径 |
|
- (NSString *) localDirectory |
|
{ |
|
if (_localDirectory == nil) { |
|
_localDirectory = [NSString stringWithFormat:@"%@/ImageCache", NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]]; |
|
} |
|
|
|
return _localDirectory; |
|
} |
|
|
|
#pragma mark - image名字MD5加密后的路径 |
|
- (NSString *) pathOnDiskForName:(NSString *)imageName |
|
{ |
|
return [self.localDirectory stringByAppendingPathComponent:[TYImageCache md5:imageName]]; |
|
} |
|
|
|
#pragma mark - 保存image和缩略图 |
|
- (BOOL) saveImageFromURL:(NSString *)imageName thumbImageSize:(CGSize)thumbImageSize data:(NSData *)imageData |
|
{ |
|
// 转换gif 到 image |
|
UIImage *image = [UIImage imageWithData:imageData]; |
|
BOOL succeed = [self saveImageFromName:imageName image:image]; |
|
|
|
if (!CGSizeEqualToSize(thumbImageSize,CGSizeZero)) { |
|
// 保存thumbImage |
|
image = [self scaleImage:image ToSize:thumbImageSize]; |
|
succeed = [self saveImageFromName:[NSString stringWithFormat:@"Thumb%@",imageName] image:image]; |
|
} |
|
return succeed; |
|
} |
|
|
|
- (BOOL)saveImageFromURL:(NSString *)imageName data:(NSData *)imageData |
|
{ |
|
return [self saveImageFromURL:imageName thumbImageSize:CGSizeZero data:imageData]; |
|
} |
|
|
|
#pragma mark - 保存image根据UImage |
|
- (BOOL)saveImageFromName:(NSString *)imageName image:(UIImage *)image |
|
{ |
|
if (!image) { |
|
return NO; |
|
} |
|
if ([[imageName lowercaseString] hasSuffix:@".png"] || [[imageName lowercaseString] hasSuffix:@".bmp"]) { |
|
// png图片 |
|
[UIImagePNGRepresentation(image) writeToFile:[self pathOnDiskForName:imageName] options:NSAtomicWrite error:nil]; |
|
return YES; |
|
} else if ([[imageName lowercaseString] hasSuffix:@".jpg"] || [[imageName lowercaseString] hasSuffix:@".jpeg"] || [[imageName lowercaseString] hasSuffix:@".gif"]) |
|
{ |
|
//jpg图片 |
|
[UIImageJPEGRepresentation(image, 1.0) writeToFile:[self pathOnDiskForName:imageName] options:NSAtomicWrite error:nil]; |
|
return YES; |
|
} else { |
|
// 未知图片类型 |
|
NSLog(@"文件后缀名未知! CTImageCache "); |
|
return NO; |
|
} |
|
} |
|
|
|
#pragma mark - 从网络下载缓存image |
|
// 同步下载保存image |
|
- (BOOL)saveImageFromURL:(NSString *)imageName thumbImageSize:(CGSize)thumbImageSize |
|
{ |
|
// 从网络上加载图片 |
|
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageName]]; |
|
if (!data) { |
|
return NO; |
|
} |
|
// 缓存图片 |
|
return [self saveImageFromURL:imageName thumbImageSize:thumbImageSize data:data]; |
|
} |
|
|
|
// 异步下载保存image |
|
- (void)saveAsyncImageFromURL:(NSString *)imageURL thumbImageSize:(CGSize)thumbImageSize completion:(void(^)(BOOL isCache))completionBlock |
|
{ |
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ |
|
// 异步操作 |
|
// 从网络上 缓存图片 |
|
BOOL isCached = [self saveImageFromURL:imageURL thumbImageSize:thumbImageSize]; |
|
|
|
if (!completionBlock) { |
|
return ; |
|
} |
|
dispatch_async(dispatch_get_main_queue(), ^{ |
|
// 主线程更新 |
|
completionBlock(isCached); |
|
|
|
}); |
|
}); |
|
} |
|
|
|
- (void)saveAsyncImagesFromURLArray:(NSArray *)imageURLArray thumbImageSize:(CGSize)thumbImageSize completion:(void (^)(BOOL))completionBlock |
|
{ |
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ |
|
// 异步操作 |
|
// 从网络上 缓存图片 |
|
__block BOOL isCached = NO; |
|
[imageURLArray enumerateObjectsUsingBlock:^(NSString *imageURL, NSUInteger idx, BOOL *stop) { |
|
isCached = [self saveImageFromURL:imageURL thumbImageSize:thumbImageSize]; |
|
}]; |
|
|
|
if (!completionBlock) { |
|
return ; |
|
} |
|
dispatch_async(dispatch_get_main_queue(), ^{ |
|
// 主线程更新 |
|
completionBlock(isCached); |
|
|
|
}); |
|
}); |
|
|
|
} |
|
|
|
// 同步获取image |
|
- (UIImage *)imageForURL:(NSString *)imageURL |
|
{ |
|
NSString *path = [self pathOnDiskForName:imageURL]; |
|
return [[UIImage alloc] initWithContentsOfFile:path]; |
|
} |
|
|
|
#pragma mark - image是否存在 |
|
- (void) imageForURL:(NSString *)imageURL found:(void(^)(UIImage* image))found notFound:(void(^)(void))notFound |
|
{ |
|
[self imageForURL:imageURL needThumImage:NO found:found notFound:notFound]; |
|
} |
|
|
|
#pragma mark - image是否存在,是否需要缩略图,如果知道返回缩略图 否则返回原图 |
|
- (void) imageForURL:(NSString *)imageURL needThumImage:(BOOL)needThumImage found:(void(^)(UIImage* image))found notFound:(void(^)(void))notFound |
|
{ |
|
if ( !imageURL ) { |
|
return; |
|
} |
|
|
|
NSString *imageName = imageURL; |
|
if (needThumImage ) { |
|
imageName = [NSString stringWithFormat:@"Thumb%@",imageURL]; |
|
} |
|
|
|
// 图片路径 |
|
UIImage* image = [self imageForURL:imageName]; |
|
|
|
if (!image && needThumImage) { |
|
image = [self imageForURL:imageURL]; |
|
} |
|
|
|
if (image) { |
|
found(image); |
|
}else { |
|
notFound(); |
|
} |
|
} |
|
|
|
#pragma mark - 是否缓存图片 |
|
- (BOOL) imageIsCacheForURL:(NSString *)imageURL { |
|
|
|
return [_fileManager fileExistsAtPath:[self pathOnDiskForName:imageURL]]; |
|
} |
|
|
|
#pragma mark - 清除内存 |
|
- (void) clearCache |
|
{ |
|
NSError *error; |
|
|
|
[_fileManager removeItemAtPath:self.localDirectory error:&error]; |
|
|
|
if ( ![_fileManager createDirectoryAtPath:self.localDirectory withIntermediateDirectories:NO attributes:nil error:&error] ) |
|
return; |
|
} |
|
|
|
#pragma mark - scale image |
|
|
|
// 返回适应到targetSize的合适图片image |
|
- (UIImage *)scaleImage:(UIImage *)sourceImage ToSize:(CGSize)targetSize |
|
{ |
|
CGFloat width = sourceImage.size.width; |
|
CGFloat height = sourceImage.size.height; |
|
CGFloat targetWidth = targetSize.width; |
|
CGFloat targetHeight = targetSize.height; |
|
CGFloat scaleFactor = 0.0; |
|
CGFloat scaledWidth = targetWidth; |
|
CGFloat scaledHeight = targetHeight; |
|
CGPoint thumbnailPoint = CGPointMake(0.0,0.0); |
|
if (CGSizeEqualToSize(sourceImage.size, targetSize) == NO) { |
|
CGFloat widthFactor = targetWidth / width; |
|
CGFloat heightFactor = targetHeight / height; |
|
if (widthFactor < heightFactor) |
|
scaleFactor = widthFactor; |
|
else |
|
scaleFactor = heightFactor; |
|
scaledWidth = width * scaleFactor; |
|
scaledHeight = height * scaleFactor; |
|
// center the image |
|
if (widthFactor < heightFactor) { |
|
|
|
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; |
|
} else if (widthFactor > heightFactor) { |
|
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; |
|
} |
|
} |
|
// this is actually the interesting part: |
|
UIGraphicsBeginImageContext(targetSize); |
|
CGRect thumbnailRect = CGRectZero; |
|
thumbnailRect.origin = thumbnailPoint; |
|
thumbnailRect.size.width = scaledWidth; |
|
thumbnailRect.size.height = scaledHeight; |
|
[sourceImage drawInRect:thumbnailRect]; |
|
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); |
|
UIGraphicsEndImageContext(); |
|
if(newImage == nil) |
|
NSLog(@"could not scale image"); |
|
return newImage ; |
|
} |
|
|
|
@end
|
|
|