Pojo's DevLog

Thursday, August 11, 2005

Saving an Animated GIF using CoreGraphics in Objective-C

I've been working on the WebKit project lately (the rendering engine behind the Safari Web Browser) and one of the tasks I was asked to complete was writing an animated gif to file using Core Graphics (CG) calls.

The documentation is kind of scarce on Apple's site, and it really doesn't explain how to set the settings so that the file will animate. It caused me so much grief that I'm going to give an example function that you can do whatever you want with.

The trick is that is an NSDictionary inside of another NSDictionary with only one key. So the data structure looks like this


[kCGImagePropertyGIFDictionary =>
[kCGImagePropertyGIFDelayTime => 2]
]
and
[kCGImagePropertyGIFDictionary =>
[kCGImagePropertyGIFLoopCount => 0]
]


Here is the example:

/**
* Takes two images and places them in an animated GIF that repeats with a 2 second delay
*/
void saveAnimatedGIFToFile(NSBitmapImageRep *firstFrame, NSBitmapImageRep *secondFrame,
NSString *animatedGIFPath)
{
// options to set the delay on each frame of 2 seconds
NSDictionary *frameProperties = [NSDictionary
dictionaryWithObject:[NSDictionary
dictionaryWithObject:[NSNumber numberWithInt:2]
forKey:(NSString *) kCGImagePropertyGIFDelayTime]
forKey:(NSString *) kCGImagePropertyGIFDictionary];

// options to turn on looping for the GIF

NSDictionary *gifProperties = [NSDictionary
dictionaryWithObject:[NSDictionary
dictionaryWithObject:[NSNumber numberWithInt:0]
forKey:(NSString *) kCGImagePropertyGIFLoopCount]
forKey:(NSString *) kCGImagePropertyGIFDictionary];

// set the place to save the GIF to
CGImageDestinationRef animatedGIF = CGImageDestinationCreateWithURL(
(CFURLRef) [NSURL fileURLWithPath:animatedGIFPath],
kUTTypeGIF,
2, // two images in this GIF
NULL
);

// get the data for the first frame
CGDataProviderRef firstFrameProvider = CGDataProviderCreateWithData(
NULL,
[firstFrame bitmapData],
[firstFrame bytesPerRow] * [firstFrame pixelsHigh],
NULL
);

// create a CGImage for the first frame
CGImageRef cgFirstFrame = CGImageCreate (
[firstFrame pixelsWide],
[firstFrame pixelsHigh],
[secondFrame bitsPerPixel] / [secondFrame samplesPerPixel],
[firstFrame bitsPerPixel],
[firstFrame bytesPerRow],
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaNone,
firstFrameProvider,
NULL,
0,
kCGRenderingIntentDefault
);

// get the data for the second frame
CGDataProviderRef secondFrameProvider = CGDataProviderCreateWithData(
NULL,
[secondFrame bitmapData],
[secondFrame bytesPerRow] * [secondFrame pixelsHigh],
NULL
);

// create a CGImage for the second frame
CGImageRef cgSecondFrame = CGImageCreate (
[secondFrame pixelsWide],
[secondFrame pixelsHigh],
[secondFrame bitsPerPixel] / [secondFrame samplesPerPixel],
[secondFrame bitsPerPixel],
[secondFrame bytesPerRow],
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaNone,
secondFrameProvider,
NULL,
0,
kCGRenderingIntentDefault
);

// place the two images into the final animated gif and set related options
CGImageDestinationAddImage(animatedGIF, cgFirstFrame, (CFDictionaryRef) frameProperties);
CGImageDestinationAddImage(animatedGIF, cgSecondFrame, (CFDictionaryRef) frameProperties);
CGImageDestinationSetProperties(animatedGIF, (CFDictionaryRef) gifProperties);

// save the gif to a file
CGImageDestinationFinalize(animatedGIF);

// release the memory used
CGDataProviderRelease(firstFrameProvider);
CGDataProviderRelease(secondFrameProvider);
CGImageRelease(cgFirstFrame);
CGImageRelease(cgSecondFrame);
CFRelease(animatedGIF);
}

4 Comments:

At 2:09 AM, Blogger eddbrooks8889 said...

I read over your blog, and i found it inquisitive, you may find My Blog interesting. My blog is just about my day to day life, as a park ranger. So please Click Here To Read My Blog

 
At 4:49 AM, Blogger kevinwilliams45077699 said...

I read over your blog, and i found it inquisitive, you may find My Blog interesting. So please Click Here To Read My Blog

http://pennystockinvestment.blogspot.com

 
At 11:26 PM, Blogger cpwq8uulk52 said...

Get any Desired College Degree, In less then 2 weeks.

Call this number now 24 hours a day 7 days a week (413) 208-3069

Get these Degrees NOW!!!

"BA", "BSc", "MA", "MSc", "MBA", "PHD",

Get everything within 2 weeks.
100% verifiable, this is a real deal

Act now you owe it to your future.

(413) 208-3069 call now 24 hours a day, 7 days a week.

 
At 8:21 AM, Blogger Matt Long said...

I realize this post is really old now, but wanted to say thanks for posting it. It was exactly what I was looking for.

-Matt

 

Post a Comment

<< Home