YYFrameImage.m
5.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//
// YYFrameImage.m
// YYImage <https://github.com/ibireme/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.
<table>
<tr><th>Path </th><th>Scale </th></tr>
<tr><td>"icon.png" </td><td>1 </td></tr>
<tr><td>"icon@2x.png" </td><td>2 </td></tr>
<tr><td>"icon@2.5x.png" </td><td>2.5 </td></tr>
<tr><td>"icon@2x" </td><td>1 </td></tr>
<tr><td>"icon@2x..png" </td><td>1 </td></tr>
<tr><td>"icon@2x.png/" </td><td>1 </td></tr>
</table>
*/
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