diff --git a/SDWebImage/SDWebImageDownloader.m b/SDWebImage/SDWebImageDownloader.m index 9a984ab9..24e5e0d6 100644 --- a/SDWebImage/SDWebImageDownloader.m +++ b/SDWebImage/SDWebImageDownloader.m @@ -8,7 +8,6 @@ #import "SDWebImageDownloader.h" #import "SDWebImageDownloaderOperation.h" -#import @implementation SDWebImageDownloadToken @end diff --git a/SDWebImage/SDWebImageDownloaderOperation.m b/SDWebImage/SDWebImageDownloaderOperation.m index 89d75ab9..c35ea1a8 100644 --- a/SDWebImage/SDWebImageDownloaderOperation.m +++ b/SDWebImage/SDWebImageDownloaderOperation.m @@ -48,10 +48,11 @@ typedef NSMutableDictionary SDCallbacksDictionary; @end @implementation SDWebImageDownloaderOperation { - size_t width, height; + size_t _width, _height; #if SD_UIKIT || SD_WATCH - UIImageOrientation orientation; + UIImageOrientation _orientation; #endif + CGImageSourceRef _imageSource; } @synthesize executing = _executing; @@ -80,6 +81,10 @@ typedef NSMutableDictionary SDCallbacksDictionary; - (void)dealloc { SDDispatchQueueRelease(_barrierQueue); + if (_imageSource) { + CFRelease(_imageSource); + _imageSource = NULL; + } } - (nullable id)addHandlersForProgress:(nullable SDWebImageDownloaderProgressBlock)progressBlock @@ -317,48 +322,55 @@ didReceiveResponse:(NSURLResponse *)response if ((self.options & SDWebImageDownloaderProgressiveDownload) && self.expectedSize > 0) { // The following code is from http://www.cocoaintheshell.com/2011/05/progressive-images-download-imageio/ // Thanks to the author @Nyx0uf - + + // Get the image data + NSData *imageData = [self.imageData copy]; // Get the total bytes downloaded - const NSInteger totalSize = self.imageData.length; - + const NSInteger totalSize = imageData.length; + // Get the finish status + BOOL finished = (self.expectedSize == totalSize); + + if (!_imageSource) { + _imageSource = CGImageSourceCreateIncremental(NULL); + } // Update the data source, we must pass ALL the data, not just the new bytes - CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)self.imageData, NULL); - - if (width + height == 0) { - CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); + CGImageSourceUpdateData(_imageSource, (__bridge CFDataRef)imageData, finished); + + if (_width + _height == 0) { + CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(_imageSource, 0, NULL); if (properties) { NSInteger orientationValue = -1; CFTypeRef val = CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight); - if (val) CFNumberGetValue(val, kCFNumberLongType, &height); + if (val) CFNumberGetValue(val, kCFNumberLongType, &_height); val = CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth); - if (val) CFNumberGetValue(val, kCFNumberLongType, &width); + if (val) CFNumberGetValue(val, kCFNumberLongType, &_width); val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation); if (val) CFNumberGetValue(val, kCFNumberNSIntegerType, &orientationValue); CFRelease(properties); - + // When we draw to Core Graphics, we lose orientation information, // which means the image below born of initWithCGIImage will be // oriented incorrectly sometimes. (Unlike the image born of initWithData // in didCompleteWithError.) So save it here and pass it on later. #if SD_UIKIT || SD_WATCH - orientation = [[self class] orientationFromPropertyValue:(orientationValue == -1 ? 1 : orientationValue)]; + _orientation = [[self class] orientationFromPropertyValue:(orientationValue == -1 ? 1 : orientationValue)]; #endif } } - - if (width + height > 0 && totalSize < self.expectedSize) { + + if (_width + _height > 0 && !finished) { // Create the image - CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL); - + CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(_imageSource, 0, NULL); + #if SD_UIKIT || SD_WATCH // Workaround for iOS anamorphic image if (partialImageRef) { const size_t partialHeight = CGImageGetHeight(partialImageRef); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGContextRef bmContext = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); + CGContextRef bmContext = CGBitmapContextCreate(NULL, _width, _height, 8, _width * 4, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); CGColorSpaceRelease(colorSpace); if (bmContext) { - CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = width, .size.height = partialHeight}, partialImageRef); + CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = _width, .size.height = partialHeight}, partialImageRef); CGImageRelease(partialImageRef); partialImageRef = CGBitmapContextCreateImage(bmContext); CGContextRelease(bmContext); @@ -369,13 +381,14 @@ didReceiveResponse:(NSURLResponse *)response } } #endif - + if (partialImageRef) { #if SD_UIKIT || SD_WATCH - UIImage *image = [UIImage imageWithCGImage:partialImageRef scale:1 orientation:orientation]; + UIImage *image = [UIImage imageWithCGImage:partialImageRef scale:1 orientation:_orientation]; #elif SD_MAC UIImage *image = [[UIImage alloc] initWithCGImage:partialImageRef size:NSZeroSize]; #endif + CGImageRelease(partialImageRef); NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL]; UIImage *scaledImage = [self scaledImageForKey:key image:image]; if (self.shouldDecompressImages) { @@ -384,14 +397,16 @@ didReceiveResponse:(NSURLResponse *)response else { image = scaledImage; } - CGImageRelease(partialImageRef); [self callCompletionBlocksWithImage:image imageData:nil error:nil finished:NO]; } } - - if (imageSource) { - CFRelease(imageSource); + + if (finished) { + if (_imageSource) { + CFRelease(_imageSource); + _imageSource = NULL; + } } }