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