Fix the scale factor issue on macOS using helper methods to match the behavior of UIKit. Also remove the unused API on NSImage category

This commit is contained in:
DreamPiggy 2018-04-08 14:53:14 +08:00
parent 1a3fb834a0
commit cbf8581696
14 changed files with 242 additions and 101 deletions

View File

@ -8,16 +8,50 @@
#import "SDWebImageCompat.h"
// This category is provided to easily write cross-platform code. For common usage, see `UIImage+WebCache`.
// This category is provided to easily write cross-platform(AppKit/UIKit) code. For common usage, see `UIImage+WebCache`.
#if SD_MAC
@interface NSImage (Additions)
/**
The underlying Core Graphics image object. This will actually `CGImageForProposedRect` with the image size.
*/
@property (nonatomic, readonly, nullable) CGImageRef CGImage;
@property (nonatomic, readonly, nullable) NSArray<NSImage *> *images;
/**
The scale factor of the image. This wil actually use image size, and its `CGImage`'s pixel size to calculate the scale factor. Should be greater than or equal to 1.0.
*/
@property (nonatomic, readonly) CGFloat scale;
@property (nonatomic, readonly, nullable) NSBitmapImageRep *bitmapImageRep;
// These are convenience methods to make AppKit's `NSImage` match UIKit's `UIImage` behavior. The scale factor should be greater than or equal to 1.0.
/**
Returns an image object with the scale factor. The representation is created from the Core Graphics image object.
@note The difference between this and `initWithCGImage:size` is that `initWithCGImage:size` will create a `NSCGImageSnapshotRep` but not `NSBitmapImageRep` instance. And it will always `backingScaleFactor` as scale factor.
@param cgImage A Core Graphics image object
@param scale The image scale factor
@return The image object
*/
- (nonnull instancetype)initWithCGImage:(nonnull CGImageRef)cgImage scale:(CGFloat)scale;
/**
Returns an image object with the scale factor. The representation is created from the image data.
@note The difference between these this and `initWithData:` is that `initWithData:` will always `backingScaleFactor` as scale factor.
@param data The image data
@param scale The image scale factor
@return The image object
*/
- (nullable instancetype)initWithData:(nonnull NSData *)data scale:(CGFloat)scale;
@end
@interface NSBitmapImageRep (Additions)
// These method's function is the same as `NSImage`'s function. For `NSBitmapImageRep`.
- (nonnull instancetype)initWithCGImage:(nonnull CGImageRef)cgImage scale:(CGFloat)scale;
- (nullable instancetype)initWithData:(nonnull NSData *)data scale:(CGFloat)scale;
@end

View File

@ -18,28 +18,72 @@
return cgImage;
}
- (NSArray<NSImage *> *)images {
return nil;
}
- (CGFloat)scale {
CGFloat scale = 1;
CGFloat width = self.size.width;
if (width > 0) {
// Use CGImage to get pixel width, NSImageRep.pixelsWide always double on Retina screen
// Use CGImage to get pixel width, NSImageRep.pixelsWide may be double on Retina screen
NSUInteger pixelWidth = CGImageGetWidth(self.CGImage);
scale = pixelWidth / width;
}
return scale;
}
- (NSBitmapImageRep *)bitmapImageRep {
NSRect imageRect = NSMakeRect(0, 0, self.size.width, self.size.height);
NSImageRep *imageRep = [self bestRepresentationForRect:imageRect context:nil hints:nil];
if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
return (NSBitmapImageRep *)imageRep;
- (instancetype)initWithCGImage:(CGImageRef)cgImage scale:(CGFloat)scale {
if (scale < 1) {
scale = 1;
}
return nil;
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage scale:scale];
NSSize size = NSMakeSize(imageRep.pixelsWide / scale, imageRep.pixelsHigh / scale);
self = [self initWithSize:size];
if (self) {
[self addRepresentation:imageRep];
}
return self;
}
- (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale {
if (scale < 1) {
scale = 1;
}
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithData:data scale:scale];
if (!imageRep) {
return nil;
}
NSSize size = NSMakeSize(imageRep.pixelsWide / scale, imageRep.pixelsHigh / scale);
self = [self initWithSize:size];
if (self) {
[self addRepresentation:imageRep];
}
return self;
}
@end
@implementation NSBitmapImageRep (Additions)
- (instancetype)initWithCGImage:(CGImageRef)cgImage scale:(CGFloat)scale {
self = [self initWithCGImage:cgImage];
if (self) {
if (scale < 1) {
scale = 1;
}
NSSize size = NSMakeSize(self.pixelsWide / scale, self.pixelsHigh / scale);
self.size = size;
}
return self;
}
- (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale {
self = [self initWithData:data];
if (self) {
if (scale < 1) {
scale = 1;
}
NSSize size = NSMakeSize(self.pixelsWide / scale, self.pixelsHigh / scale);
self.size = size;
}
return self;
}
@end

View File

@ -310,7 +310,7 @@ static NSArray *SDBundlePreferredScales() {
return nil;
}
#if SD_MAC
self = [super initWithCGImage:image.CGImage size:NSZeroSize];
self = [super initWithCGImage:image.CGImage scale:scale];
#else
self = [super initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
#endif
@ -353,7 +353,10 @@ static NSArray *SDBundlePreferredScales() {
NSNumber *scale = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(scale))];
NSData *animatedImageData = [aDecoder decodeObjectOfClass:[NSData class] forKey:NSStringFromSelector(@selector(animatedImageData))];
if (animatedImageData) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-designated-initializers"
return [self initWithData:animatedImageData scale:scale.doubleValue];
#pragma clang diagnostic pop
} else {
return [super initWithCoder:aDecoder];
}

View File

@ -82,10 +82,19 @@ const CFStringRef kCGImagePropertyAPNGUnclampedDelayTime = (__bridge CFStringRef
if (!data) {
return nil;
}
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
if (scale < 1) {
scale = 1;
}
}
#if SD_MAC
SDAnimatedImageRep *imageRep = [[SDAnimatedImageRep alloc] initWithData:data];
NSImage *animatedImage = [[NSImage alloc] initWithSize:imageRep.size];
NSSize size = NSMakeSize(imageRep.pixelsWide / scale, imageRep.pixelsHigh / scale);
imageRep.size = size;
NSImage *animatedImage = [[NSImage alloc] initWithSize:size];
[animatedImage addRepresentation:imageRep];
return animatedImage;
#else
@ -95,13 +104,6 @@ const CFStringRef kCGImagePropertyAPNGUnclampedDelayTime = (__bridge CFStringRef
return nil;
}
size_t count = CGImageSourceGetCount(source);
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
if (scale < 1) {
scale = 1;
}
}
UIImage *animatedImage;
if (count <= 1) {
@ -277,10 +279,17 @@ const CFStringRef kCGImagePropertyAPNGUnclampedDelayTime = (__bridge CFStringRef
CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(_imageSource, 0, NULL);
if (partialImageRef) {
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
if (scale < 1) {
scale = 1;
}
}
#if SD_UIKIT || SD_WATCH
image = [[UIImage alloc] initWithCGImage:partialImageRef];
image = [[UIImage alloc] initWithCGImage:partialImageRef scale:scale orientation:UIImageOrientationUp];
#elif SD_MAC
image = [[UIImage alloc] initWithCGImage:partialImageRef size:NSZeroSize];
image = [[UIImage alloc] initWithCGImage:partialImageRef scale:scale];
#endif
CGImageRelease(partialImageRef);
}
@ -375,7 +384,7 @@ const CFStringRef kCGImagePropertyAPNGUnclampedDelayTime = (__bridge CFStringRef
CGImageRelease(imageRef);
}
#if SD_MAC
UIImage *image = [[UIImage alloc] initWithCGImage:newImageRef size:NSZeroSize];
UIImage *image = [[UIImage alloc] initWithCGImage:newImageRef scale:1];
#else
UIImage *image = [UIImage imageWithCGImage:newImageRef];
#endif

View File

@ -103,8 +103,14 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
return nil;
}
CFRelease(imageDestination);
CGFloat scale = frames.firstObject.image.scale;
if (scale < 1) {
scale = 1;
}
SDAnimatedImageRep *imageRep = [[SDAnimatedImageRep alloc] initWithData:imageData];
animatedImage = [[NSImage alloc] initWithSize:imageRep.size];
NSSize size = NSMakeSize(imageRep.pixelsWide / scale, imageRep.pixelsHigh / scale);
imageRep.size = size;
animatedImage = [[NSImage alloc] initWithSize:size];
[animatedImage addRepresentation:imageRep];
#endif
@ -157,27 +163,27 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
#else
NSBitmapImageRep *bitmapRep;
for (NSImageRep *imageRep in animatedImage.representations) {
if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
bitmapRep = (NSBitmapImageRep *)imageRep;
break;
}
NSRect imageRect = NSMakeRect(0, 0, animatedImage.size.width, animatedImage.size.height);
NSImageRep *imageRep = [animatedImage bestRepresentationForRect:imageRect context:nil hints:nil];
NSBitmapImageRep *bitmapImageRep;
if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
bitmapImageRep = (NSBitmapImageRep *)imageRep;
}
if (bitmapRep) {
frameCount = [[bitmapRep valueForProperty:NSImageFrameCount] unsignedIntegerValue];
if (!bitmapImageRep) {
return nil;
}
frameCount = [[bitmapImageRep valueForProperty:NSImageFrameCount] unsignedIntegerValue];
if (frameCount == 0) {
return nil;
}
CGFloat scale = animatedImage.scale;
for (size_t i = 0; i < frameCount; i++) {
@autoreleasepool {
// NSBitmapImageRep need to manually change frame. "Good taste" API
[bitmapRep setProperty:NSImageCurrentFrame withValue:@(i)];
float frameDuration = [[bitmapRep valueForProperty:NSImageCurrentFrameDuration] floatValue];
NSImage *frameImage = [[NSImage alloc] initWithCGImage:bitmapRep.CGImage size:NSZeroSize];
[bitmapImageRep setProperty:NSImageCurrentFrame withValue:@(i)];
float frameDuration = [[bitmapImageRep valueForProperty:NSImageCurrentFrameDuration] floatValue];
NSImage *frameImage = [[NSImage alloc] initWithCGImage:bitmapImageRep.CGImage scale:scale];
SDWebImageFrame *frame = [SDWebImageFrame frameWithImage:frameImage duration:frameDuration];
[frames addObject:frame];
}

View File

@ -100,14 +100,6 @@
if (!data) {
return nil;
}
BOOL decodeFirstFrame = [[options valueForKey:SDWebImageCoderDecodeFirstFrameOnly] boolValue];
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
if (scale < 1) {
scale = 1;
}
}
UIImage *image;
for (id<SDWebImageCoder> coder in self.coders) {
if ([coder canDecodeFromData:data]) {
@ -115,16 +107,6 @@
break;
}
}
if (image) {
// Check static image
if (decodeFirstFrame && image.images.count > 0) {
image = image.images.firstObject;
}
// Check image scale
if (scale > 1 && scale != image.scale) {
image = SDScaledImageForScaleFactor(scale, image);
}
}
return image;
}

View File

@ -88,18 +88,25 @@ inline UIImage * _Nullable SDScaledImageForScaleFactor(CGFloat scale, UIImage *
animatedImage = [UIImage animatedImageWithImages:scaledImages duration:image.duration];
animatedImage.sd_imageLoopCount = image.sd_imageLoopCount;
#else
// Animated GIF for `NSImage` need to grab `NSBitmapImageRep`
NSSize size = NSMakeSize(image.size.width / scale, image.size.height / scale);
animatedImage = [[NSImage alloc] initWithSize:size];
NSBitmapImageRep *bitmapImageRep = image.bitmapImageRep;
[animatedImage addRepresentation:bitmapImageRep];
// Animated GIF for `NSImage` need to grab `NSBitmapImageRep`;
NSRect imageRect = NSMakeRect(0, 0, image.size.width, image.size.height);
NSImageRep *imageRep = [image bestRepresentationForRect:imageRect context:nil hints:nil];
NSBitmapImageRep *bitmapImageRep;
if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
bitmapImageRep = (NSBitmapImageRep *)imageRep;
}
if (bitmapImageRep) {
NSSize size = NSMakeSize(image.size.width / scale, image.size.height / scale);
animatedImage = [[NSImage alloc] initWithSize:size];
[animatedImage addRepresentation:bitmapImageRep];
}
#endif
scaledImage = animatedImage;
} else {
#if SD_UIKIT || SD_WATCH
scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
#else
scaledImage = [[NSImage alloc] initWithCGImage:image.CGImage size:NSZeroSize];
scaledImage = [[NSImage alloc] initWithCGImage:image.CGImage scale:scale];
#endif
}
scaledImage.sd_isIncremental = image.sd_isIncremental;

View File

@ -72,10 +72,19 @@
if (!data) {
return nil;
}
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
if (scale < 1) {
scale = 1;
}
}
#if SD_MAC
SDAnimatedImageRep *imageRep = [[SDAnimatedImageRep alloc] initWithData:data];
NSImage *animatedImage = [[NSImage alloc] initWithSize:imageRep.size];
NSSize size = NSMakeSize(imageRep.pixelsWide / scale, imageRep.pixelsHigh / scale);
imageRep.size = size;
NSImage *animatedImage = [[NSImage alloc] initWithSize:size];
[animatedImage addRepresentation:imageRep];
return animatedImage;
#else
@ -85,13 +94,6 @@
return nil;
}
size_t count = CGImageSourceGetCount(source);
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
if (scale < 1) {
scale = 1;
}
}
UIImage *animatedImage;
BOOL decodeFirstFrame = [options[SDWebImageCoderDecodeFirstFrameOnly] boolValue];
@ -224,10 +226,17 @@
CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(_imageSource, 0, NULL);
if (partialImageRef) {
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
if (scale < 1) {
scale = 1;
}
}
#if SD_UIKIT || SD_WATCH
image = [[UIImage alloc] initWithCGImage:partialImageRef];
image = [[UIImage alloc] initWithCGImage:partialImageRef scale:scale orientation:UIImageOrientationUp];
#elif SD_MAC
image = [[UIImage alloc] initWithCGImage:partialImageRef size:NSZeroSize];
image = [[UIImage alloc] initWithCGImage:partialImageRef scale:scale];
#endif
CGImageRelease(partialImageRef);
}
@ -375,7 +384,7 @@
CGImageRelease(imageRef);
}
#if SD_MAC
UIImage *image = [[UIImage alloc] initWithCGImage:newImageRef size:NSZeroSize];
UIImage *image = [[UIImage alloc] initWithCGImage:newImageRef scale:1];
#else
UIImage *image = [[UIImage alloc] initWithCGImage:newImageRef];
#endif

View File

@ -81,11 +81,6 @@
if (!data) {
return nil;
}
#if SD_MAC
UIImage *image = [[UIImage alloc] initWithData:data];
return image;
#else
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
@ -93,7 +88,11 @@
scale = 1;
}
}
UIImage *image = [[UIImage alloc] initWithData:data scale:scale];
#if SD_MAC
return image;
#else
if (!image) {
return nil;
}
@ -182,10 +181,17 @@
#endif
if (partialImageRef) {
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
if (scale < 1) {
scale = 1;
}
}
#if SD_UIKIT || SD_WATCH
image = [[UIImage alloc] initWithCGImage:partialImageRef scale:1 orientation:_orientation];
image = [[UIImage alloc] initWithCGImage:partialImageRef scale:scale orientation:_orientation];
#elif SD_MAC
image = [[UIImage alloc] initWithCGImage:partialImageRef size:NSZeroSize];
image = [[UIImage alloc] initWithCGImage:partialImageRef scale:scale];
#endif
CGImageRelease(partialImageRef);
}

View File

@ -261,7 +261,7 @@
if (options & SDWebImageRefreshCached && cachedImage && !downloadedImage) {
// Image refresh hit the NSURLCache cache, do not call the completion block
} else if (downloadedImage && (!downloadedImage.images || (options & SDWebImageTransformAnimatedImage)) && transformer) {
} else if (downloadedImage && (!downloadedImage.sd_isAnimated || (options & SDWebImageTransformAnimatedImage)) && transformer) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *transformedImage = [transformer transformedImageWithImage:downloadedImage forKey:key];
if (transformedImage && finished) {

View File

@ -114,7 +114,6 @@ dispatch_semaphore_signal(self->_lock);
uint32_t flags = WebPDemuxGetI(demuxer, WEBP_FF_FORMAT_FLAGS);
BOOL hasAnimation = flags & ANIMATION_FLAG;
BOOL decodeFirstFrame = [[options valueForKey:SDWebImageCoderDecodeFirstFrameOnly] boolValue];
#if SD_UIKIT || SD_WATCH
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
@ -122,7 +121,6 @@ dispatch_semaphore_signal(self->_lock);
scale = 1;
}
}
#endif
if (!hasAnimation) {
// for static single webp image
CGImageRef imageRef = [self sd_createWebpImageWithData:webpData];
@ -132,7 +130,7 @@ dispatch_semaphore_signal(self->_lock);
#if SD_UIKIT || SD_WATCH
UIImage *staticImage = [[UIImage alloc] initWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
#else
UIImage *staticImage = [[UIImage alloc] initWithCGImage:imageRef size:NSZeroSize];
UIImage *staticImage = [[UIImage alloc] initWithCGImage:imageRef scale:scale];
#endif
CGImageRelease(imageRef);
WebPDemuxDelete(demuxer);
@ -154,7 +152,7 @@ dispatch_semaphore_signal(self->_lock);
#if SD_UIKIT || SD_WATCH
UIImage *firstFrameImage = [[UIImage alloc] initWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
#else
UIImage *firstFrameImage = [[UIImage alloc] initWithCGImage:imageRef size:NSZeroSize];
UIImage *firstFrameImage = [[UIImage alloc] initWithCGImage:imageRef scale:scale];
#endif
CGImageRelease(imageRef);
WebPDemuxReleaseIterator(&iter);
@ -185,7 +183,7 @@ dispatch_semaphore_signal(self->_lock);
#if SD_UIKIT || SD_WATCH
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
#else
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef size:NSZeroSize];
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:scale];
#endif
CGImageRelease(imageRef);
@ -279,11 +277,18 @@ dispatch_semaphore_signal(self->_lock);
CGContextRelease(canvas);
return nil;
}
CGFloat scale = 1;
if ([options valueForKey:SDWebImageCoderDecodeScaleFactor]) {
scale = [[options valueForKey:SDWebImageCoderDecodeScaleFactor] doubleValue];
if (scale < 1) {
scale = 1;
}
}
#if SD_UIKIT || SD_WATCH
image = [[UIImage alloc] initWithCGImage:newImageRef];
image = [[UIImage alloc] initWithCGImage:newImageRef scale:scale orientation:UIImageOrientationUp];
#else
image = [[UIImage alloc] initWithCGImage:newImageRef size:NSZeroSize];
image = [[UIImage alloc] initWithCGImage:newImageRef scale:scale];
#endif
CGImageRelease(newImageRef);
CGContextRelease(canvas);
@ -664,7 +669,7 @@ static void FreeImageData(void *info, const void *data, size_t size) {
#if SD_UIKIT || SD_WATCH
image = [[UIImage alloc] initWithCGImage:imageRef];
#else
image = [[UIImage alloc] initWithCGImage:imageRef size:NSZeroSize];
image = [[UIImage alloc] initWithCGImage:imageRef scale:1];
#endif
CGImageRelease(imageRef);
} else {
@ -694,7 +699,7 @@ static void FreeImageData(void *info, const void *data, size_t size) {
#if SD_UIKIT || SD_WATCH
image = [[UIImage alloc] initWithCGImage:imageRef];
#else
image = [[UIImage alloc] initWithCGImage:imageRef size:NSZeroSize];
image = [[UIImage alloc] initWithCGImage:imageRef scale:1];
#endif
CGImageRelease(imageRef);
}

View File

@ -24,6 +24,15 @@ static CGContextRef SDCGContextCreateARGBBitmapContext(CGSize size, BOOL opaque,
CGImageAlphaInfo alphaInfo = (opaque ? kCGImageAlphaNoneSkipFirst : kCGImageAlphaPremultipliedFirst);
CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, space, kCGBitmapByteOrderDefault | alphaInfo);
CGColorSpaceRelease(space);
if (!context) {
return NULL;
}
if (scale == 0) {
// Match `UIGraphicsBeginImageContextWithOptions`, reset to the scale factor of the devices main screen if scale is 0.
scale = [NSScreen mainScreen].backingScaleFactor;
}
CGContextScaleCTM(context, scale, scale);
return context;
}
#endif
@ -71,7 +80,17 @@ static UIImage * SDGraphicsGetImageFromCurrentImageContext(void) {
if (!imageRef) {
return nil;
}
NSImage *image = [[NSImage alloc] initWithCGImage:imageRef size:NSZeroSize];
CGAffineTransform transform = CGContextGetCTM(context);
CGFloat xs = transform.a;
CGFloat ys = transform.d;
CGFloat scale;
if (xs == ys && xs > 0) {
scale = xs;
} else {
// Protect if x/y axis scale factor not equal
scale = [NSScreen mainScreen].backingScaleFactor;
}
NSImage *image = [[NSImage alloc] initWithCGImage:imageRef scale:scale];
CGImageRelease(imageRef);
return image;
#endif
@ -303,7 +322,7 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
#if SD_UIKIT || SD_WATCH
UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
#else
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef size:NSZeroSize];
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:self.scale];
#endif
CGImageRelease(imageRef);
return image;
@ -381,7 +400,7 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
#if SD_UIKIT || SD_WATCH
UIImage *img = [UIImage imageWithCGImage:imgRef scale:self.scale orientation:self.imageOrientation];
#else
UIImage *img = [[UIImage alloc] initWithCGImage:imgRef size:NSZeroSize];
UIImage *img = [[UIImage alloc] initWithCGImage:imgRef scale:self.scale];
#endif
CGImageRelease(imgRef);
CGContextRelease(context);
@ -417,7 +436,7 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
#if SD_UIKIT || SD_WATCH
UIImage *img = [UIImage imageWithCGImage:imgRef scale:self.scale orientation:self.imageOrientation];
#else
UIImage *img = [[UIImage alloc] initWithCGImage:imgRef size:NSZeroSize];
UIImage *img = [[UIImage alloc] initWithCGImage:imgRef scale:self.scale];
#endif
CGImageRelease(imgRef);
return img;
@ -434,7 +453,7 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
#if SD_UIKIT || SD_WATCH
return [UIImage imageWithCGImage:self.CGImage scale:self.scale orientation:self.imageOrientation];
#else
return [[UIImage alloc] initWithCGImage:self.CGImage size:NSZeroSize];
return [[UIImage alloc] initWithCGImage:self.CGImage scale:self.scale];
#endif
}
@ -651,7 +670,7 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
#if SD_UIKIT || SD_WATCH
UIImage *outputImage = [UIImage imageWithCGImage:effectCGImage scale:self.scale orientation:self.imageOrientation];
#else
UIImage *outputImage = [[UIImage alloc] initWithCGImage:effectCGImage size:NSZeroSize];
UIImage *outputImage = [[UIImage alloc] initWithCGImage:effectCGImage scale:self.scale];
#endif
CGImageRelease(effectCGImage);
@ -676,7 +695,7 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
#if SD_UIKIT
UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
#else
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef size:NSZeroSize];
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:self.scale];
#endif
CGImageRelease(imageRef);

View File

@ -51,7 +51,12 @@
- (NSUInteger)sd_imageLoopCount {
NSUInteger imageLoopCount = 0;
NSBitmapImageRep *bitmapImageRep = self.bitmapImageRep;
NSRect imageRect = NSMakeRect(0, 0, self.size.width, self.size.height);
NSImageRep *imageRep = [self bestRepresentationForRect:imageRect context:nil hints:nil];
NSBitmapImageRep *bitmapImageRep;
if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
bitmapImageRep = (NSBitmapImageRep *)imageRep;
}
if (bitmapImageRep) {
imageLoopCount = [[bitmapImageRep valueForProperty:NSImageLoopCount] unsignedIntegerValue];
}
@ -59,7 +64,12 @@
}
- (void)setSd_imageLoopCount:(NSUInteger)sd_imageLoopCount {
NSBitmapImageRep *bitmapImageRep = self.bitmapImageRep;
NSRect imageRect = NSMakeRect(0, 0, self.size.width, self.size.height);
NSImageRep *imageRep = [self bestRepresentationForRect:imageRect context:nil hints:nil];
NSBitmapImageRep *bitmapImageRep;
if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
bitmapImageRep = (NSBitmapImageRep *)imageRep;
}
if (bitmapImageRep) {
[bitmapImageRep setProperty:NSImageLoopCount withValue:@(sd_imageLoopCount)];
}
@ -67,7 +77,12 @@
- (BOOL)sd_isAnimated {
BOOL isGIF = NO;
NSBitmapImageRep *bitmapImageRep = self.bitmapImageRep;
NSRect imageRect = NSMakeRect(0, 0, self.size.width, self.size.height);
NSImageRep *imageRep = [self bestRepresentationForRect:imageRect context:nil hints:nil];
NSBitmapImageRep *bitmapImageRep;
if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
bitmapImageRep = (NSBitmapImageRep *)imageRep;
}
if (bitmapImageRep) {
NSUInteger frameCount = [[bitmapImageRep valueForProperty:NSImageFrameCount] unsignedIntegerValue];
isGIF = frameCount > 1 ? YES : NO;

View File

@ -170,7 +170,9 @@
UIImage *outputImage = [coder decodedImageWithData:outputImageData options:nil];
expect(outputImage.size).to.equal(inputImage.size);
expect(outputImage.scale).to.equal(inputImage.scale);
#if SD_UIKIT
expect(outputImage.images.count).to.equal(inputImage.images.count);
#endif
}
@end