酷店

YYFrameImage.m 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. //
  2. // YYFrameImage.m
  3. // YYImage <https://github.com/ibireme/YYImage>
  4. //
  5. // Created by ibireme on 14/12/9.
  6. // Copyright (c) 2015 ibireme.
  7. //
  8. // This source code is licensed under the MIT-style license found in the
  9. // LICENSE file in the root directory of this source tree.
  10. //
  11. #import "YYFrameImage.h"
  12. #import "YYImageCoder.h"
  13. /**
  14. Return the path scale.
  15. e.g.
  16. <table>
  17. <tr><th>Path </th><th>Scale </th></tr>
  18. <tr><td>"icon.png" </td><td>1 </td></tr>
  19. <tr><td>"icon@2x.png" </td><td>2 </td></tr>
  20. <tr><td>"icon@2.5x.png" </td><td>2.5 </td></tr>
  21. <tr><td>"icon@2x" </td><td>1 </td></tr>
  22. <tr><td>"icon@2x..png" </td><td>1 </td></tr>
  23. <tr><td>"icon@2x.png/" </td><td>1 </td></tr>
  24. </table>
  25. */
  26. static CGFloat _NSStringPathScale(NSString *string) {
  27. if (string.length == 0 || [string hasSuffix:@"/"]) return 1;
  28. NSString *name = string.stringByDeletingPathExtension;
  29. __block CGFloat scale = 1;
  30. NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:@"@[0-9]+\\.?[0-9]*x$" options:NSRegularExpressionAnchorsMatchLines error:nil];
  31. [pattern enumerateMatchesInString:name options:kNilOptions range:NSMakeRange(0, name.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
  32. if (result.range.location >= 3) {
  33. scale = [string substringWithRange:NSMakeRange(result.range.location + 1, result.range.length - 2)].doubleValue;
  34. }
  35. }];
  36. return scale;
  37. }
  38. @implementation YYFrameImage {
  39. NSUInteger _loopCount;
  40. NSUInteger _oneFrameBytes;
  41. NSArray *_imagePaths;
  42. NSArray *_imageDatas;
  43. NSArray *_frameDurations;
  44. }
  45. - (instancetype)initWithImagePaths:(NSArray *)paths oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount {
  46. NSMutableArray *durations = [NSMutableArray new];
  47. for (int i = 0, max = (int)paths.count; i < max; i++) {
  48. [durations addObject:@(oneFrameDuration)];
  49. }
  50. return [self initWithImagePaths:paths frameDurations:durations loopCount:loopCount];
  51. }
  52. - (instancetype)initWithImagePaths:(NSArray *)paths frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount {
  53. if (paths.count == 0) return nil;
  54. if (paths.count != frameDurations.count) return nil;
  55. NSString *firstPath = paths[0];
  56. NSData *firstData = [NSData dataWithContentsOfFile:firstPath];
  57. CGFloat scale = _NSStringPathScale(firstPath);
  58. UIImage *firstCG = [[[UIImage alloc] initWithData:firstData] yy_imageByDecoded];
  59. self = [self initWithCGImage:firstCG.CGImage scale:scale orientation:UIImageOrientationUp];
  60. if (!self) return nil;
  61. long frameByte = CGImageGetBytesPerRow(firstCG.CGImage) * CGImageGetHeight(firstCG.CGImage);
  62. _oneFrameBytes = (NSUInteger)frameByte;
  63. _imagePaths = paths.copy;
  64. _frameDurations = frameDurations.copy;
  65. _loopCount = loopCount;
  66. return self;
  67. }
  68. - (instancetype)initWithImageDataArray:(NSArray *)dataArray oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount {
  69. NSMutableArray *durations = [NSMutableArray new];
  70. for (int i = 0, max = (int)dataArray.count; i < max; i++) {
  71. [durations addObject:@(oneFrameDuration)];
  72. }
  73. return [self initWithImageDataArray:dataArray frameDurations:durations loopCount:loopCount];
  74. }
  75. - (instancetype)initWithImageDataArray:(NSArray *)dataArray frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount {
  76. if (dataArray.count == 0) return nil;
  77. if (dataArray.count != frameDurations.count) return nil;
  78. NSData *firstData = dataArray[0];
  79. CGFloat scale = [UIScreen mainScreen].scale;
  80. UIImage *firstCG = [[[UIImage alloc] initWithData:firstData] yy_imageByDecoded];
  81. self = [self initWithCGImage:firstCG.CGImage scale:scale orientation:UIImageOrientationUp];
  82. if (!self) return nil;
  83. long frameByte = CGImageGetBytesPerRow(firstCG.CGImage) * CGImageGetHeight(firstCG.CGImage);
  84. _oneFrameBytes = (NSUInteger)frameByte;
  85. _imageDatas = dataArray.copy;
  86. _frameDurations = frameDurations.copy;
  87. _loopCount = loopCount;
  88. return self;
  89. }
  90. #pragma mark - YYAnimtedImage
  91. - (NSUInteger)animatedImageFrameCount {
  92. if (_imagePaths) {
  93. return _imagePaths.count;
  94. } else if (_imageDatas) {
  95. return _imageDatas.count;
  96. } else {
  97. return 1;
  98. }
  99. }
  100. - (NSUInteger)animatedImageLoopCount {
  101. return _loopCount;
  102. }
  103. - (NSUInteger)animatedImageBytesPerFrame {
  104. return _oneFrameBytes;
  105. }
  106. - (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index {
  107. if (_imagePaths) {
  108. if (index >= _imagePaths.count) return nil;
  109. NSString *path = _imagePaths[index];
  110. CGFloat scale = _NSStringPathScale(path);
  111. NSData *data = [NSData dataWithContentsOfFile:path];
  112. return [[UIImage imageWithData:data scale:scale] yy_imageByDecoded];
  113. } else if (_imageDatas) {
  114. if (index >= _imageDatas.count) return nil;
  115. NSData *data = _imageDatas[index];
  116. return [[UIImage imageWithData:data scale:[UIScreen mainScreen].scale] yy_imageByDecoded];
  117. } else {
  118. return index == 0 ? self : nil;
  119. }
  120. }
  121. - (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index {
  122. if (index >= _frameDurations.count) return 0;
  123. NSNumber *num = _frameDurations[index];
  124. return [num doubleValue];
  125. }
  126. @end