123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- /*
- * This file is part of the SDWebImage package.
- * (c) Olivier Poitrey <rs@dailymotion.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- #import "SDAnimatedImageRep.h"
- #if SD_MAC
- #import "SDImageGIFCoderInternal.h"
- #import "SDImageAPNGCoderInternal.h"
- @interface SDAnimatedImageRep ()
- @property (nonatomic, assign, readonly, nullable) CGImageSourceRef imageSource;
- @end
- @implementation SDAnimatedImageRep
- // `NSBitmapImageRep`'s `imageRepWithData:` is not designed initlizer
- + (instancetype)imageRepWithData:(NSData *)data {
- SDAnimatedImageRep *imageRep = [[SDAnimatedImageRep alloc] initWithData:data];
- return imageRep;
- }
- // We should override init method for `NSBitmapImageRep` to do initlize about animated image format
- - (instancetype)initWithData:(NSData *)data {
- self = [super initWithData:data];
- if (self) {
- CGImageSourceRef imageSource = self.imageSource;
- if (!imageSource) {
- return self;
- }
- NSUInteger frameCount = CGImageSourceGetCount(imageSource);
- if (frameCount <= 1) {
- return self;
- }
- CFStringRef type = CGImageSourceGetType(imageSource);
- if (!type) {
- return self;
- }
- if (CFStringCompare(type, kUTTypeGIF, 0) == kCFCompareEqualTo) {
- // GIF
- // Do nothing because NSBitmapImageRep support it
- } else if (CFStringCompare(type, kUTTypePNG, 0) == kCFCompareEqualTo) {
- // APNG
- // Do initilize about frame count, current frame/duration and loop count
- [self setProperty:NSImageFrameCount withValue:@(frameCount)];
- [self setProperty:NSImageCurrentFrame withValue:@(0)];
- NSUInteger loopCount = [[SDImageAPNGCoder sharedCoder] sd_imageLoopCountWithSource:imageSource];
- [self setProperty:NSImageLoopCount withValue:@(loopCount)];
- }
- }
- return self;
- }
- // `NSBitmapImageRep` will use `kCGImagePropertyGIFDelayTime` whenever you call `setProperty:withValue:` with `NSImageCurrentFrame` to change the current frame. We override it and use the actual `kCGImagePropertyGIFUnclampedDelayTime` if need.
- - (void)setProperty:(NSBitmapImageRepPropertyKey)property withValue:(id)value {
- [super setProperty:property withValue:value];
- if ([property isEqualToString:NSImageCurrentFrame]) {
- // Access the image source
- CGImageSourceRef imageSource = self.imageSource;
- if (!imageSource) {
- return;
- }
- // Check format type
- CFStringRef type = CGImageSourceGetType(imageSource);
- if (!type) {
- return;
- }
- NSUInteger index = [value unsignedIntegerValue];
- float frameDuration = 0;
- if (CFStringCompare(type, kUTTypeGIF, 0) == kCFCompareEqualTo) {
- // GIF
- frameDuration = [[SDImageGIFCoder sharedCoder] sd_frameDurationAtIndex:index source:imageSource];
- } else if (CFStringCompare(type, kUTTypePNG, 0) == kCFCompareEqualTo) {
- // APNG
- frameDuration = [[SDImageAPNGCoder sharedCoder] sd_frameDurationAtIndex:index source:imageSource];
- }
- if (!frameDuration) {
- return;
- }
- // Reset super frame duration with the actual frame duration
- [super setProperty:NSImageCurrentFrameDuration withValue:@(frameDuration)];
- }
- }
- - (CGImageSourceRef)imageSource {
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- if (_tiffData) {
- return (__bridge CGImageSourceRef)(_tiffData);
- }
- #pragma GCC diagnostic pop
- return NULL;
- }
- @end
- #endif
|