// // YYFrameImage.m // YYImage // // Created by ibireme on 14/12/9. // Copyright (c) 2015 ibireme. // // This source code is licensed under the MIT-style license found in the // LICENSE file in the root directory of this source tree. // #import "YYFrameImage.h" #import "YYImageCoder.h" /** Return the path scale. e.g.
Path Scale
"icon.png" 1
"icon@2x.png" 2
"icon@2.5x.png" 2.5
"icon@2x" 1
"icon@2x..png" 1
"icon@2x.png/" 1
*/ static CGFloat _NSStringPathScale(NSString *string) { if (string.length == 0 || [string hasSuffix:@"/"]) return 1; NSString *name = string.stringByDeletingPathExtension; __block CGFloat scale = 1; NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:@"@[0-9]+\\.?[0-9]*x$" options:NSRegularExpressionAnchorsMatchLines error:nil]; [pattern enumerateMatchesInString:name options:kNilOptions range:NSMakeRange(0, name.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { if (result.range.location >= 3) { scale = [string substringWithRange:NSMakeRange(result.range.location + 1, result.range.length - 2)].doubleValue; } }]; return scale; } @implementation YYFrameImage { NSUInteger _loopCount; NSUInteger _oneFrameBytes; NSArray *_imagePaths; NSArray *_imageDatas; NSArray *_frameDurations; } - (instancetype)initWithImagePaths:(NSArray *)paths oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount { NSMutableArray *durations = [NSMutableArray new]; for (int i = 0, max = (int)paths.count; i < max; i++) { [durations addObject:@(oneFrameDuration)]; } return [self initWithImagePaths:paths frameDurations:durations loopCount:loopCount]; } - (instancetype)initWithImagePaths:(NSArray *)paths frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount { if (paths.count == 0) return nil; if (paths.count != frameDurations.count) return nil; NSString *firstPath = paths[0]; NSData *firstData = [NSData dataWithContentsOfFile:firstPath]; CGFloat scale = _NSStringPathScale(firstPath); UIImage *firstCG = [[[UIImage alloc] initWithData:firstData] yy_imageByDecoded]; self = [self initWithCGImage:firstCG.CGImage scale:scale orientation:UIImageOrientationUp]; if (!self) return nil; long frameByte = CGImageGetBytesPerRow(firstCG.CGImage) * CGImageGetHeight(firstCG.CGImage); _oneFrameBytes = (NSUInteger)frameByte; _imagePaths = paths.copy; _frameDurations = frameDurations.copy; _loopCount = loopCount; return self; } - (instancetype)initWithImageDataArray:(NSArray *)dataArray oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount { NSMutableArray *durations = [NSMutableArray new]; for (int i = 0, max = (int)dataArray.count; i < max; i++) { [durations addObject:@(oneFrameDuration)]; } return [self initWithImageDataArray:dataArray frameDurations:durations loopCount:loopCount]; } - (instancetype)initWithImageDataArray:(NSArray *)dataArray frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount { if (dataArray.count == 0) return nil; if (dataArray.count != frameDurations.count) return nil; NSData *firstData = dataArray[0]; CGFloat scale = [UIScreen mainScreen].scale; UIImage *firstCG = [[[UIImage alloc] initWithData:firstData] yy_imageByDecoded]; self = [self initWithCGImage:firstCG.CGImage scale:scale orientation:UIImageOrientationUp]; if (!self) return nil; long frameByte = CGImageGetBytesPerRow(firstCG.CGImage) * CGImageGetHeight(firstCG.CGImage); _oneFrameBytes = (NSUInteger)frameByte; _imageDatas = dataArray.copy; _frameDurations = frameDurations.copy; _loopCount = loopCount; return self; } #pragma mark - YYAnimtedImage - (NSUInteger)animatedImageFrameCount { if (_imagePaths) { return _imagePaths.count; } else if (_imageDatas) { return _imageDatas.count; } else { return 1; } } - (NSUInteger)animatedImageLoopCount { return _loopCount; } - (NSUInteger)animatedImageBytesPerFrame { return _oneFrameBytes; } - (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index { if (_imagePaths) { if (index >= _imagePaths.count) return nil; NSString *path = _imagePaths[index]; CGFloat scale = _NSStringPathScale(path); NSData *data = [NSData dataWithContentsOfFile:path]; return [[UIImage imageWithData:data scale:scale] yy_imageByDecoded]; } else if (_imageDatas) { if (index >= _imageDatas.count) return nil; NSData *data = _imageDatas[index]; return [[UIImage imageWithData:data scale:[UIScreen mainScreen].scale] yy_imageByDecoded]; } else { return index == 0 ? self : nil; } } - (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index { if (index >= _frameDurations.count) return 0; NSNumber *num = _frameDurations[index]; return [num doubleValue]; } @end