Do not convert images to JPEG when stored to disk for caching
This saves CPU and memory in all cases and alpha channel / image clearness if orignal format was PNG or GIF.
This commit is contained in:
parent
7f7dfbecd6
commit
d2dc4cbbac
|
@ -10,7 +10,7 @@
|
|||
|
||||
@interface SDImageCache : NSObject
|
||||
{
|
||||
NSMutableDictionary *memCache;
|
||||
NSMutableDictionary *memCache, *storeDataQueue;
|
||||
NSString *diskCachePath;
|
||||
NSOperationQueue *cacheInQueue;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
|||
+ (SDImageCache *)sharedImageCache;
|
||||
- (void)storeImage:(UIImage *)image forKey:(NSString *)key;
|
||||
- (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk;
|
||||
- (void)storeImage:(UIImage *)image imageData:(NSData *)data forKey:(NSString *)key toDisk:(BOOL)toDisk;
|
||||
- (UIImage *)imageFromKey:(NSString *)key;
|
||||
- (UIImage *)imageFromKey:(NSString *)key fromDisk:(BOOL)fromDisk;
|
||||
- (void)removeImageForKey:(NSString *)key;
|
||||
|
|
|
@ -25,6 +25,7 @@ static SDImageCache *instance;
|
|||
memCache = [[NSMutableDictionary alloc] init];
|
||||
|
||||
// Init the disk cache
|
||||
storeDataQueue = [[NSMutableDictionary alloc] init];
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
diskCachePath = [[[paths objectAtIndex:0] stringByAppendingPathComponent:@"ImageCache"] retain];
|
||||
|
||||
|
@ -72,6 +73,7 @@ static SDImageCache *instance;
|
|||
[memCache release], memCache = nil;
|
||||
[diskCachePath release], diskCachePath = nil;
|
||||
[cacheInQueue release], cacheInQueue = nil;
|
||||
[storeDataQueue release], storeDataQueue = nil;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
|
@ -105,25 +107,43 @@ static SDImageCache *instance;
|
|||
|
||||
- (void)storeKeyToDisk:(NSString *)key
|
||||
{
|
||||
UIImage *image = [[self imageFromKey:key fromDisk:YES] retain]; // be thread safe with no lock
|
||||
// Can't use defaultManager another thread
|
||||
NSFileManager *fileManager = [[NSFileManager alloc] init];
|
||||
|
||||
if (image != nil)
|
||||
NSData *data = [storeDataQueue objectForKey:key];
|
||||
if (data)
|
||||
{
|
||||
[[NSFileManager defaultManager] createFileAtPath:[self cachePathForKey:key] contents:UIImageJPEGRepresentation(image, (CGFloat)1.0) attributes:nil];
|
||||
[image release];
|
||||
[fileManager createFileAtPath:[self cachePathForKey:key] contents:data attributes:nil];
|
||||
@synchronized(storeDataQueue)
|
||||
{
|
||||
[storeDataQueue removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no data representation given, convert the UIImage in JPEG and store it
|
||||
// This trick is more CPU/memory intensive and doesn't preserve alpha channel
|
||||
UIImage *image = [[self imageFromKey:key fromDisk:YES] retain]; // be thread safe with no lock
|
||||
if (image)
|
||||
{
|
||||
[fileManager createFileAtPath:[self cachePathForKey:key] contents:UIImageJPEGRepresentation(image, (CGFloat)1.0) attributes:nil];
|
||||
[image release];
|
||||
}
|
||||
}
|
||||
|
||||
[fileManager release];
|
||||
}
|
||||
|
||||
#pragma mark ImageCache
|
||||
|
||||
- (void)storeImage:(UIImage *)image forKey:(NSString *)key
|
||||
- (void)storeImage:(UIImage *)image imageData:(NSData *)data forKey:(NSString *)key toDisk:(BOOL)toDisk
|
||||
{
|
||||
[self storeImage:image forKey:key toDisk:YES];
|
||||
}
|
||||
if (!image || !key)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
- (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk
|
||||
{
|
||||
if (image == nil || key == nil)
|
||||
if (toDisk && !data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -132,10 +152,23 @@ static SDImageCache *instance;
|
|||
|
||||
if (toDisk)
|
||||
{
|
||||
[storeDataQueue setObject:data forKey:key];
|
||||
[cacheInQueue addOperation:[[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(storeKeyToDisk:) object:key] autorelease]];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
- (void)storeImage:(UIImage *)image forKey:(NSString *)key
|
||||
{
|
||||
[self storeImage:image imageData:nil forKey:key toDisk:YES];
|
||||
}
|
||||
|
||||
- (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk
|
||||
{
|
||||
[self storeImage:image imageData:nil forKey:key toDisk:toDisk];
|
||||
}
|
||||
|
||||
|
||||
- (UIImage *)imageFromKey:(NSString *)key
|
||||
{
|
||||
return [self imageFromKey:key fromDisk:YES];
|
||||
|
@ -152,7 +185,7 @@ static SDImageCache *instance;
|
|||
|
||||
if (!image && fromDisk)
|
||||
{
|
||||
image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:[self cachePathForKey:key]]];
|
||||
image = [[UIImage alloc] initWithContentsOfFile:[self cachePathForKey:key]];
|
||||
if (image != nil)
|
||||
{
|
||||
[memCache setObject:image forKey:key];
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
@property (nonatomic, retain) NSURL *url;
|
||||
@property (nonatomic, assign) id<SDWebImageDownloaderDelegate> delegate;
|
||||
@property (nonatomic, retain) NSMutableData *imageData;
|
||||
|
||||
+ (id)downloaderWithURL:(NSURL *)url delegate:(id<SDWebImageDownloaderDelegate>)delegate;
|
||||
- (void)start;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
@interface SDWebImageDownloader ()
|
||||
@property (nonatomic, retain) NSURLConnection *connection;
|
||||
@property (nonatomic, retain) NSMutableData *imageData;
|
||||
@end
|
||||
|
||||
@implementation SDWebImageDownloader
|
||||
|
@ -73,16 +72,19 @@
|
|||
|
||||
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
|
||||
{
|
||||
UIImage *image = [[UIImage alloc] initWithData:imageData];
|
||||
self.imageData = nil;
|
||||
self.connection = nil;
|
||||
|
||||
if ([delegate respondsToSelector:@selector(imageDownloaderDidFinish:)])
|
||||
{
|
||||
[delegate performSelector:@selector(imageDownloaderDidFinish:) withObject:self];
|
||||
}
|
||||
|
||||
if ([delegate respondsToSelector:@selector(imageDownloader:didFinishWithImage:)])
|
||||
{
|
||||
UIImage *image = [[UIImage alloc] initWithData:imageData];
|
||||
[delegate performSelector:@selector(imageDownloader:didFinishWithImage:) withObject:self withObject:image];
|
||||
[image release];
|
||||
}
|
||||
|
||||
[image release];
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
@optional
|
||||
|
||||
- (void)imageDownloaderDidFinish:(SDWebImageDownloader *)downloader;
|
||||
- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithImage:(UIImage *)image;
|
||||
- (void)imageDownloader:(SDWebImageDownloader *)downloader didFailWithError:(NSError *)error;
|
||||
|
||||
|
|
|
@ -120,7 +120,10 @@ static SDWebImageManager *instance;
|
|||
if (image)
|
||||
{
|
||||
// Store the image in the cache
|
||||
[[SDImageCache sharedImageCache] storeImage:image forKey:[downloader.url absoluteString]];
|
||||
[[SDImageCache sharedImageCache] storeImage:image
|
||||
imageData:downloader.imageData
|
||||
forKey:[downloader.url absoluteString]
|
||||
toDisk:YES];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue