Skip to content

Commit

Permalink
Added DTAnimatedGIF implementation and Demo
Browse files Browse the repository at this point in the history
  • Loading branch information
odrobnik committed Jul 2, 2014
1 parent 1e35c4c commit fa75e3e
Show file tree
Hide file tree
Showing 14 changed files with 780 additions and 0 deletions.
18 changes: 18 additions & 0 deletions Core/Source/iOS/DTAnimatedGIF/DTAnimatedGIF.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// DTAnimatedGIF.h
// DTFoundation
//
// Created by Oliver Drobnik on 7/2/14.
// Copyright (c) 2014 Cocoanetics. All rights reserved.
//


/**
Loads an animated GIF from file, compatible with UIImageView
*/
UIImage *DTAnimatedGIFFromFile(NSString *path);

/**
Loads an animated GIF from data, compatible with UIImageView
*/
UIImage *DTAnimatedGIFFromData(NSData *data);
128 changes: 128 additions & 0 deletions Core/Source/iOS/DTAnimatedGIF/DTAnimatedGIF.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//
// DTAnimatedGIF.m
// DTFoundation
//
// Created by Oliver Drobnik on 7/2/14.
// Copyright (c) 2014 Cocoanetics. All rights reserved.
//

#import "DTAnimatedGIF.h"
#import <ImageIO/ImageIO.h>

// returns the frame duration for a given image in 1/100th seconds
// source: http://stackoverflow.com/questions/16964366/delaytime-or-unclampeddelaytime-for-gifs
static NSUInteger DTAnimatedGIFFrameDurationForImageAtIndex(CGImageSourceRef source, NSUInteger index)
{
NSUInteger frameDuration = 10;

NSDictionary *frameProperties = CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(source,index,nil));
NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];

NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];

if(delayTimeUnclampedProp)
{
frameDuration = [delayTimeUnclampedProp floatValue]*100;
}
else
{
NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];

if(delayTimeProp)
{
frameDuration = [delayTimeProp floatValue]*100;
}
}

// Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
// We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
// a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
// for more information.

if (frameDuration < 1)
{
frameDuration = 10;
}

return frameDuration;
}

// returns the great common factor of two numbers
static NSUInteger DTAnimatedGIFGreatestCommonFactor(NSUInteger num1, NSUInteger num2)
{
NSUInteger t, remainder;

if (num1 < num2)
{
t = num1;
num1 = num2;
num2 = t;
}

remainder = num1 % num2;

if (!remainder)
{
return num2;
}
else
{
return DTAnimatedGIFGreatestCommonFactor(num2, remainder);
}
}

static UIImage *DTAnimatedGIFFromImageSource(CGImageSourceRef source)
{
size_t const numImages = CGImageSourceGetCount(source);

NSMutableArray *frames = [NSMutableArray arrayWithCapacity:numImages];

// determine gretest common factor of all image durations
NSUInteger greatestCommonFactor = DTAnimatedGIFFrameDurationForImageAtIndex(source, 0);

for (NSUInteger i=1; i<numImages; i++)
{
NSUInteger centiSecs = DTAnimatedGIFFrameDurationForImageAtIndex(source, i);
greatestCommonFactor = DTAnimatedGIFGreatestCommonFactor(greatestCommonFactor, centiSecs);
}

// build array of images, duplicating as necessary
for (NSUInteger i=0; i<numImages; i++)
{
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, i, NULL);
UIImage *frame = [UIImage imageWithCGImage:cgImage];

NSUInteger centiSecs = DTAnimatedGIFFrameDurationForImageAtIndex(source, i);
NSUInteger repeat = centiSecs/greatestCommonFactor;

for (NSUInteger j=0; j<repeat; j++)
{
[frames addObject:frame];
}

CGImageRelease(cgImage);
}

// create animated image from the array
NSTimeInterval totalDuration = [frames count] * greatestCommonFactor / 100.0;
return [UIImage animatedImageWithImages:frames duration:totalDuration];
}

UIImage *DTAnimatedGIFFromFile(NSString *path)
{
NSURL *URL = [NSURL fileURLWithPath:path];
CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)(URL), NULL);
UIImage *image = DTAnimatedGIFFromImageSource(source);
CFRelease(source);

return image;
}

UIImage *DTAnimatedGIFFromData(NSData *data)
{
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)(data), NULL);
UIImage *image = DTAnimatedGIFFromImageSource(source);
CFRelease(source);

return image;
}
Loading

0 comments on commit fa75e3e

Please sign in to comment.