diff options
author | marinofaggiana <marino@marinofaggiana.com> | 2020-05-18 10:54:41 +0300 |
---|---|---|
committer | marinofaggiana <marino@marinofaggiana.com> | 2020-05-18 10:54:41 +0300 |
commit | 750bee9a483581a5bb3dde1676683210ca81511a (patch) | |
tree | 703de4984aa614ef9a9d3508502e683f4fac6fc5 /Libraries external | |
parent | 69fd855c4eec152b143d2d73ec041737427f4886 (diff) |
coding
Diffstat (limited to 'Libraries external')
-rwxr-xr-x | Libraries external/UIImage+animatedGIF/UIImage+animatedGIF.h | 32 | ||||
-rwxr-xr-x | Libraries external/UIImage+animatedGIF/UIImage+animatedGIF.m | 119 |
2 files changed, 0 insertions, 151 deletions
diff --git a/Libraries external/UIImage+animatedGIF/UIImage+animatedGIF.h b/Libraries external/UIImage+animatedGIF/UIImage+animatedGIF.h deleted file mode 100755 index 324d8141f..000000000 --- a/Libraries external/UIImage+animatedGIF/UIImage+animatedGIF.h +++ /dev/null @@ -1,32 +0,0 @@ -#import <UIKit/UIKit.h> - -/** - UIImage (animatedGIF) - - This category adds class methods to `UIImage` to create an animated `UIImage` from an animated GIF. -*/ -@interface UIImage (animatedGIF) - -/* - UIImage *animation = [UIImage animatedImageWithAnimatedGIFData:theData]; - - I interpret `theData` as a GIF. I create an animated `UIImage` using the source images in the GIF. - - The GIF stores a separate duration for each frame, in units of centiseconds (hundredths of a second). However, a `UIImage` only has a single, total `duration` property, which is a floating-point number. - - To handle this mismatch, I add each source image (from the GIF) to `animation` a varying number of times to match the ratios between the frame durations in the GIF. - - For example, suppose the GIF contains three frames. Frame 0 has duration 3. Frame 1 has duration 9. Frame 2 has duration 15. I divide each duration by the greatest common denominator of all the durations, which is 3, and add each frame the resulting number of times. Thus `animation` will contain frame 0 3/3 = 1 time, then frame 1 9/3 = 3 times, then frame 2 15/3 = 5 times. I set `animation.duration` to (3+9+15)/100 = 0.27 seconds. -*/ -+ (UIImage *)animatedImageWithAnimatedGIFData:(NSData *)theData; - -/* - UIImage *image = [UIImage animatedImageWithAnimatedGIFURL:theURL]; - - I interpret the contents of `theURL` as a GIF. I create an animated `UIImage` using the source images in the GIF. - - I operate exactly like `+[UIImage animatedImageWithAnimatedGIFData:]`, except that I read the data from `theURL`. If `theURL` is not a `file:` URL, you probably want to call me on a background thread or GCD queue to avoid blocking the main thread. -*/ -+ (UIImage *)animatedImageWithAnimatedGIFURL:(NSURL *)theURL; - -@end diff --git a/Libraries external/UIImage+animatedGIF/UIImage+animatedGIF.m b/Libraries external/UIImage+animatedGIF/UIImage+animatedGIF.m deleted file mode 100755 index 871d11e02..000000000 --- a/Libraries external/UIImage+animatedGIF/UIImage+animatedGIF.m +++ /dev/null @@ -1,119 +0,0 @@ -#import "UIImage+animatedGIF.h" -#import <ImageIO/ImageIO.h> - -#if __has_feature(objc_arc) -#define toCF (__bridge CFTypeRef) -#define fromCF (__bridge id) -#else -#define toCF (CFTypeRef) -#define fromCF (id) -#endif - -@implementation UIImage (animatedGIF) - -static int delayCentisecondsForImageAtIndex(CGImageSourceRef const source, size_t const i) { - int delayCentiseconds = 1; - CFDictionaryRef const properties = CGImageSourceCopyPropertiesAtIndex(source, i, NULL); - if (properties) { - CFDictionaryRef const gifProperties = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary); - if (gifProperties) { - NSNumber *number = fromCF CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFUnclampedDelayTime); - if (number == NULL || [number doubleValue] == 0) { - number = fromCF CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFDelayTime); - } - if ([number doubleValue] > 0) { - // Even though the GIF stores the delay as an integer number of centiseconds, ImageIO “helpfully” converts that to seconds for us. - delayCentiseconds = (int)lrint([number doubleValue] * 100); - } - } - CFRelease(properties); - } - return delayCentiseconds; -} - -static void createImagesAndDelays(CGImageSourceRef source, size_t count, CGImageRef imagesOut[count], int delayCentisecondsOut[count]) { - for (size_t i = 0; i < count; ++i) { - imagesOut[i] = CGImageSourceCreateImageAtIndex(source, i, NULL); - delayCentisecondsOut[i] = delayCentisecondsForImageAtIndex(source, i); - } -} - -static int sum(size_t const count, int const *const values) { - int theSum = 0; - for (size_t i = 0; i < count; ++i) { - theSum += values[i]; - } - return theSum; -} - -static int pairGCD(int a, int b) { - if (a < b) - return pairGCD(b, a); - while (true) { - int const r = a % b; - if (r == 0) - return b; - a = b; - b = r; - } -} - -static int vectorGCD(size_t const count, int const *const values) { - int gcd = values[0]; - for (size_t i = 1; i < count; ++i) { - // Note that after I process the first few elements of the vector, `gcd` will probably be smaller than any remaining element. By passing the smaller value as the second argument to `pairGCD`, I avoid making it swap the arguments. - gcd = pairGCD(values[i], gcd); - } - return gcd; -} - -static NSArray *frameArray(size_t const count, CGImageRef const images[count], int const delayCentiseconds[count], int const totalDurationCentiseconds) { - int const gcd = vectorGCD(count, delayCentiseconds); - size_t const frameCount = totalDurationCentiseconds / gcd; - UIImage *frames[frameCount]; - for (size_t i = 0, f = 0; i < count; ++i) { - UIImage *const frame = [UIImage imageWithCGImage:images[i]]; - for (size_t j = delayCentiseconds[i] / gcd; j > 0; --j) { - frames[f++] = frame; - } - } - return [NSArray arrayWithObjects:frames count:frameCount]; -} - -static void releaseImages(size_t const count, CGImageRef const images[count]) { - for (size_t i = 0; i < count; ++i) { - CGImageRelease(images[i]); - } -} - -static UIImage *animatedImageWithAnimatedGIFImageSource(CGImageSourceRef const source) { - size_t const count = CGImageSourceGetCount(source); - CGImageRef images[count]; - int delayCentiseconds[count]; // in centiseconds - createImagesAndDelays(source, count, images, delayCentiseconds); - int const totalDurationCentiseconds = sum(count, delayCentiseconds); - NSArray *const frames = frameArray(count, images, delayCentiseconds, totalDurationCentiseconds); - UIImage *const animation = [UIImage animatedImageWithImages:frames duration:(NSTimeInterval)totalDurationCentiseconds / 100.0]; - releaseImages(count, images); - return animation; -} - -static UIImage *animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceRef CF_RELEASES_ARGUMENT source) { - if (source) { - UIImage *const image = animatedImageWithAnimatedGIFImageSource(source); - CFRelease(source); - return image; - } else { - return nil; - } -} - -+ (UIImage *)animatedImageWithAnimatedGIFData:(NSData *)data { - return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithData(toCF data, NULL)); -} - -+ (UIImage *)animatedImageWithAnimatedGIFURL:(NSURL *)url { - return animatedImageWithAnimatedGIFReleasingImageSource(CGImageSourceCreateWithURL(toCF url, NULL)); -} - -@end |