Skip to content

Commit

Permalink
Merge pull request SDWebImage#1217 from mythodeia/master
Browse files Browse the repository at this point in the history
Import fixes from @mythodeia 's fork
  • Loading branch information
bpoplauschi committed Jul 15, 2015
2 parents ae11cf7 + df751e7 commit be560a4
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 54 deletions.
3 changes: 3 additions & 0 deletions Examples/SDWebImage Demo/MasterViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,9 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

[cell.imageView setShowActivityIndicatorView:YES];
[cell.imageView setIndicatorStyle:UIActivityIndicatorViewStyleGray];

cell.textLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row];
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:[_objects objectAtIndex:indexPath.row]]
Expand Down
10 changes: 10 additions & 0 deletions SDWebImage/SDImageCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
*/
@property (assign, nonatomic) BOOL shouldDecompressImages;

/**
* disable iCloud backup [defaults to YES]
*/
@property (assign, nonatomic) BOOL shouldDisableiCloud;

/**
* use memory cache [defaults to YES]
*/
@property (assign, nonatomic) BOOL shouldCacheImagesInMemory;

/**
* The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory.
*/
Expand Down
39 changes: 30 additions & 9 deletions SDWebImage/SDImageCache.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ - (id)initWithNamespace:(NSString *)ns diskCacheDirectory:(NSString *)directory
// Set decompression to YES
_shouldDecompressImages = YES;

// memory cache enabled
_shouldCacheImagesInMemory = YES;

// Disable iCloud
_shouldDisableiCloud = YES;

dispatch_sync(_ioQueue, ^{
_fileManager = [NSFileManager new];
});
Expand Down Expand Up @@ -193,9 +199,11 @@ - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate image
if (!image || !key) {
return;
}

NSUInteger cost = SDCacheCostForImage(image);
[self.memCache setObject:image forKey:key cost:cost];
// if memory cache is enabled
if (self.shouldCacheImagesInMemory) {
NSUInteger cost = SDCacheCostForImage(image);
[self.memCache setObject:image forKey:key cost:cost];
}

if (toDisk) {
dispatch_async(self.ioQueue, ^{
Expand Down Expand Up @@ -237,7 +245,17 @@ - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate image
[_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
}

[_fileManager createFileAtPath:[self defaultCachePathForKey:key] contents:data attributes:nil];
// get cache Path for image key
NSString *cachePathForKey = [self defaultCachePathForKey:key];
// transform to NSUrl
NSURL *fileURL = [NSURL fileURLWithPath:cachePathForKey];

[_fileManager createFileAtPath:cachePathForKey contents:data attributes:nil];

// disable iCloud backup
if (self.shouldDisableiCloud) {
[fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:nil];
}
}
});
}
Expand Down Expand Up @@ -277,6 +295,7 @@ - (UIImage *)imageFromMemoryCacheForKey:(NSString *)key {
}

- (UIImage *)imageFromDiskCacheForKey:(NSString *)key {

// First check the in-memory cache...
UIImage *image = [self imageFromMemoryCacheForKey:key];
if (image) {
Expand All @@ -285,7 +304,7 @@ - (UIImage *)imageFromDiskCacheForKey:(NSString *)key {

// Second check the disk cache...
UIImage *diskImage = [self diskImageForKey:key];
if (diskImage) {
if (diskImage && self.shouldCacheImagesInMemory) {
NSUInteger cost = SDCacheCostForImage(diskImage);
[self.memCache setObject:diskImage forKey:key cost:cost];
}
Expand Down Expand Up @@ -356,7 +375,7 @@ - (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompl

@autoreleasepool {
UIImage *diskImage = [self diskImageForKey:key];
if (diskImage) {
if (diskImage && self.shouldCacheImagesInMemory) {
NSUInteger cost = SDCacheCostForImage(diskImage);
[self.memCache setObject:diskImage forKey:key cost:cost];
}
Expand Down Expand Up @@ -387,9 +406,11 @@ - (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion
if (key == nil) {
return;
}

[self.memCache removeObjectForKey:key];


if (self.shouldCacheImagesInMemory) {
[self.memCache removeObjectForKey:key];
}

if (fromDisk) {
dispatch_async(self.ioQueue, ^{
[_fileManager removeItemAtPath:[self defaultCachePathForKey:key] error:nil];
Expand Down
2 changes: 1 addition & 1 deletion SDWebImage/SDWebImageCompat.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
}
else {
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
CGFloat scale = 1.0;
CGFloat scale = [UIScreen mainScreen].scale;
if (key.length >= 8) {
NSRange range = [key rangeOfString:@"@2x."];
if (range.location != NSNotFound) {
Expand Down
66 changes: 22 additions & 44 deletions SDWebImage/SDWebImageDecoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,60 +13,38 @@
@implementation UIImage (ForceDecode)

+ (UIImage *)decodedImageWithImage:(UIImage *)image {
if (image.images) {
// Do not decode animated images
return image;
}
// do not decode animated images
if (image.images) { return image; }

CGImageRef imageRef = image.CGImage;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
CGRect imageRect = (CGRect){.origin = CGPointZero, .size = imageSize};

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef);
BOOL anyAlpha = (alpha == kCGImageAlphaFirst ||
alpha == kCGImageAlphaLast ||
alpha == kCGImageAlphaPremultipliedFirst ||
alpha == kCGImageAlphaPremultipliedLast);

int infoMask = (bitmapInfo & kCGBitmapAlphaInfoMask);
BOOL anyNonAlpha = (infoMask == kCGImageAlphaNone ||
infoMask == kCGImageAlphaNoneSkipFirst ||
infoMask == kCGImageAlphaNoneSkipLast);
if (anyAlpha) { return image; }

// CGBitmapContextCreate doesn't support kCGImageAlphaNone with RGB.
// https://developer.apple.com/library/mac/#qa/qa1037/_index.html
if (infoMask == kCGImageAlphaNone && CGColorSpaceGetNumberOfComponents(colorSpace) > 1) {
// Unset the old alpha info.
bitmapInfo &= ~kCGBitmapAlphaInfoMask;
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);

// Set noneSkipFirst.
bitmapInfo |= kCGImageAlphaNoneSkipFirst;
}
// Some PNGs tell us they have alpha but only 3 components. Odd.
else if (!anyNonAlpha && CGColorSpaceGetNumberOfComponents(colorSpace) == 3) {
// Unset the old alpha info.
bitmapInfo &= ~kCGBitmapAlphaInfoMask;
bitmapInfo |= kCGImageAlphaPremultipliedFirst;
}
CGContextRef context = CGBitmapContextCreate(NULL, width,
height,
CGImageGetBitsPerComponent(imageRef),
0,
CGImageGetColorSpace(imageRef),
kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);

// It calculates the bytes-per-row based on the bitsPerComponent and width arguments.
CGContextRef context = CGBitmapContextCreate(NULL,
imageSize.width,
imageSize.height,
CGImageGetBitsPerComponent(imageRef),
0,
colorSpace,
bitmapInfo);
CGColorSpaceRelease(colorSpace);

// If failed, return undecompressed image
if (!context) return image;

CGContextDrawImage(context, imageRect, imageRef);
CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
// Draw the image into the context and retrieve the new image, which will now have an alpha layer
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGImageRef imageRefWithAlpha = CGBitmapContextCreateImage(context);
UIImage *imageWithAlpha = [UIImage imageWithCGImage:imageRefWithAlpha];

CGContextRelease(context);
CGImageRelease(imageRefWithAlpha);

UIImage *decompressedImage = [UIImage imageWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation];
CGImageRelease(decompressedImageRef);
return decompressedImage;
return imageWithAlpha;
}

@end
12 changes: 12 additions & 0 deletions SDWebImage/UIImageView+WebCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,18 @@

- (void)sd_cancelCurrentAnimationImagesLoad;

/**
* Show activity UIActivityIndicatorView
*/
- (void)setShowActivityIndicatorView:(BOOL)show;

/**
* set desired UIActivityIndicatorViewStyle
*
* @param style The style of the UIActivityIndicatorView
*/
- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style;

@end


Expand Down
75 changes: 75 additions & 0 deletions SDWebImage/UIImageView+WebCache.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#import "UIView+WebCacheOperation.h"

static char imageURLKey;
static char TAG_ACTIVITY_INDICATOR;
static char TAG_ACTIVITY_STYLE;
static char TAG_ACTIVITY_SHOW;

@implementation UIImageView (WebCache)

Expand Down Expand Up @@ -49,8 +52,15 @@ - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder
}

if (url) {

// check if activityView is enabled or not
if ([self showActivityIndicatorView]) {
[self addActivityIndicator];
}

__weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
[wself removeActivityIndicator];
if (!wself) return;
dispatch_main_sync_safe(^{
if (!wself) return;
Expand All @@ -76,6 +86,7 @@ - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder
[self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
} else {
dispatch_main_async_safe(^{
[self removeActivityIndicator];
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
if (completedBlock) {
completedBlock(nil, error, SDImageCacheTypeNone, url);
Expand Down Expand Up @@ -134,6 +145,70 @@ - (void)sd_cancelCurrentAnimationImagesLoad {
[self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"];
}


#pragma mark -
- (UIActivityIndicatorView *)activityIndicator {
return (UIActivityIndicatorView *)objc_getAssociatedObject(self, &TAG_ACTIVITY_INDICATOR);
}

- (void)setActivityIndicator:(UIActivityIndicatorView *)activityIndicator {
objc_setAssociatedObject(self, &TAG_ACTIVITY_INDICATOR, activityIndicator, OBJC_ASSOCIATION_RETAIN);
}

- (void)setShowActivityIndicatorView:(BOOL)show{
objc_setAssociatedObject(self, &TAG_ACTIVITY_SHOW, [NSNumber numberWithBool:show], OBJC_ASSOCIATION_RETAIN);
}

- (BOOL)showActivityIndicatorView{
return [objc_getAssociatedObject(self, &TAG_ACTIVITY_SHOW) boolValue];
}

- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style{
objc_setAssociatedObject(self, &TAG_ACTIVITY_STYLE, [NSNumber numberWithInt:style], OBJC_ASSOCIATION_RETAIN);
}

- (int)getIndicatorStyle{
return [objc_getAssociatedObject(self, &TAG_ACTIVITY_STYLE) intValue];
}

- (void)addActivityIndicator {
if (!self.activityIndicator) {
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:[self getIndicatorStyle]];
self.activityIndicator.translatesAutoresizingMaskIntoConstraints = NO;

dispatch_main_async_safe(^{
[self addSubview:self.activityIndicator];

[self addConstraint:[NSLayoutConstraint constraintWithItem:self.activityIndicator
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self.activityIndicator
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0.0]];
});
}

dispatch_main_async_safe(^{
[self.activityIndicator startAnimating];
});

}

- (void)removeActivityIndicator {
if (self.activityIndicator) {
[self.activityIndicator removeFromSuperview];
self.activityIndicator = nil;
}
}

@end


Expand Down

0 comments on commit be560a4

Please sign in to comment.