├── background.png ├── Classes ├── .DS_Store ├── AnimatedGifExampleViewController.h ├── AnimatedGifExampleAppDelegate.h ├── AnimatedGifExampleAppDelegate.m ├── AnimatedGifExampleViewController.m ├── AnimatedGif.h └── AnimatedGif.m ├── apple_logo_animated.gif ├── AnimatedGifExample_Prefix.pch ├── main.m ├── AnimatedGifExample-Info.plist ├── MainWindow.xib ├── AnimatedGifExample.xcodeproj └── project.pbxproj └── AnimatedGifExampleViewController.xib /background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kasatani/AnimatedGifExample/HEAD/background.png -------------------------------------------------------------------------------- /Classes/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kasatani/AnimatedGifExample/HEAD/Classes/.DS_Store -------------------------------------------------------------------------------- /apple_logo_animated.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kasatani/AnimatedGifExample/HEAD/apple_logo_animated.gif -------------------------------------------------------------------------------- /AnimatedGifExample_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'AnimatedGifExample' target in the 'AnimatedGifExample' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AnimatedGifExample 4 | // 5 | // Created by Stijn Spijker on 05-07-09. 6 | // Copyright __MyCompanyName__ 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) { 12 | 13 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | [pool release]; 16 | return retVal; 17 | } 18 | -------------------------------------------------------------------------------- /Classes/AnimatedGifExampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AnimatedGifExampleViewController.h 3 | // AnimatedGifExample 4 | // 5 | // Created by Stijn Spijker on 05-07-09. 6 | // Copyright __MyCompanyName__ 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AnimatedGif.h" 11 | 12 | @interface AnimatedGifExampleViewController : UIViewController { 13 | UIImageView *remoteAnimationView; 14 | IBOutlet UIImageView *theFirstAnimatedGif, *theSecondAnimatedGif; 15 | 16 | } 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /Classes/AnimatedGifExampleAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AnimatedGifExampleAppDelegate.h 3 | // AnimatedGifExample 4 | // 5 | // Created by Stijn Spijker on 05-07-09. 6 | // Copyright __MyCompanyName__ 2009. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class AnimatedGifExampleViewController; 12 | 13 | @interface AnimatedGifExampleAppDelegate : NSObject { 14 | UIWindow *window; 15 | AnimatedGifExampleViewController *viewController; 16 | } 17 | 18 | @property (nonatomic, retain) IBOutlet UIWindow *window; 19 | @property (nonatomic, retain) IBOutlet AnimatedGifExampleViewController *viewController; 20 | 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /Classes/AnimatedGifExampleAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AnimatedGifExampleAppDelegate.m 3 | // AnimatedGifExample 4 | // 5 | // Created by Stijn Spijker on 05-07-09. 6 | // Copyright __MyCompanyName__ 2009. All rights reserved. 7 | // 8 | 9 | #import "AnimatedGifExampleAppDelegate.h" 10 | #import "AnimatedGifExampleViewController.h" 11 | 12 | @implementation AnimatedGifExampleAppDelegate 13 | 14 | @synthesize window; 15 | @synthesize viewController; 16 | 17 | 18 | - (void)applicationDidFinishLaunching:(UIApplication *)application { 19 | 20 | // Override point for customization after app launch 21 | [window addSubview:viewController.view]; 22 | [window makeKeyAndVisible]; 23 | } 24 | 25 | 26 | - (void)dealloc { 27 | [viewController release]; 28 | [window release]; 29 | [super dealloc]; 30 | } 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /AnimatedGifExample-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSMainNibFile 28 | MainWindow 29 | 30 | 31 | -------------------------------------------------------------------------------- /Classes/AnimatedGifExampleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AnimatedGifExampleViewController.m 3 | // AnimatedGifExample 4 | // 5 | // Created by Stijn Spijker on 05-07-09. 6 | // Copyright __MyCompanyName__ 2009. All rights reserved. 7 | // 8 | 9 | #import "AnimatedGifExampleViewController.h" 10 | 11 | @implementation AnimatedGifExampleViewController 12 | 13 | // 14 | // viewDidLoad 15 | // 16 | // Get's the animated gif, and places it on the view. 17 | // 18 | - (void)viewDidLoad 19 | { 20 | [super viewDidLoad]; 21 | 22 | // First example, a local file 23 | NSURL * firstUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"apple_logo_animated" ofType:@"gif"]]; 24 | UIImageView * firstAnimation = [AnimatedGif getAnimationForGifAtUrl: firstUrl]; 25 | 26 | // Second example, through HTTP 27 | NSURL * secondUrl = [NSURL URLWithString:@"http://www.gifs.net/Animation11/Food_and_Drinks/Fruits/Apple_jumps.gif"]; 28 | UIImageView * secondAnimation = [AnimatedGif getAnimationForGifAtUrl: secondUrl]; 29 | 30 | remoteAnimationView = [secondAnimation retain]; 31 | 32 | // Add them to the view. 33 | [theFirstAnimatedGif addSubview:firstAnimation]; 34 | [theSecondAnimatedGif addSubview:secondAnimation]; 35 | } 36 | 37 | - (void)didReceiveMemoryWarning { 38 | // Releases the view if it doesn't have a superview. 39 | 40 | [super didReceiveMemoryWarning]; 41 | } 42 | 43 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 44 | NSURL *url = [NSURL URLWithString:textField.text]; 45 | if (url) { 46 | [remoteAnimationView removeFromSuperview]; 47 | [remoteAnimationView release]; 48 | remoteAnimationView = [[AnimatedGif getAnimationForGifAtUrl:url] retain]; 49 | [theSecondAnimatedGif addSubview:remoteAnimationView]; 50 | } 51 | 52 | [textField resignFirstResponder]; 53 | return YES; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Classes/AnimatedGif.h: -------------------------------------------------------------------------------- 1 | // 2 | // AnimatedGif.m 3 | // 4 | // Created by Stijn Spijker (http://www.stijnspijker.nl/) on 2009-07-03. 5 | // Based on gifdecode written april 2009 by Martin van Spanje, P-Edge media. 6 | // 7 | // Changes on gifdecode: 8 | // - Small optimizations (mainly arrays) 9 | // - Object Orientated Approach (Class Methods as well as Object Methods) 10 | // - Added the Graphic Control Extension Frame for transparancy 11 | // - Changed header to GIF89a 12 | // - Added methods for ease-of-use 13 | // - Added animations with transparancy 14 | // - No need to save frames to the filesystem anymore 15 | // 16 | // Changelog: 17 | // 18 | // 2010-03-16: Added queing mechanism for static class use 19 | // 2010-01-24: Rework of the entire module, adding static methods, better memory management and URL asynchronous loading 20 | // 2009-10-08: Added dealloc method, and removed leaks, by Pedro Silva 21 | // 2009-08-10: Fixed double release for array, by Christian Garbers 22 | // 2009-06-05: Initial Version 23 | // 24 | // Permission is given to use this source code file, free of charge, in any 25 | // project, commercial or otherwise, entirely at your risk, with the condition 26 | // that any redistribution (in part or whole) of source code must retain 27 | // this copyright and permission notice. Attribution in compiled projects is 28 | // appreciated but not required. 29 | // 30 | 31 | #ifdef TARGET_OS_IPHONE 32 | #import 33 | #else 34 | #import 35 | #endif TARGET_OS_IPHONE 36 | 37 | @interface AnimatedGifFrame : NSObject 38 | { 39 | NSData *data; 40 | NSData *header; 41 | double delay; 42 | int disposalMethod; 43 | CGRect area; 44 | } 45 | 46 | @property (nonatomic, copy) NSData *header; 47 | @property (nonatomic, copy) NSData *data; 48 | @property (nonatomic) double delay; 49 | @property (nonatomic) int disposalMethod; 50 | @property (nonatomic) CGRect area; 51 | 52 | @end 53 | 54 | @interface AnimatedGifQueueObject : NSObject 55 | { 56 | UIImageView *uiv; 57 | NSURL *url; 58 | } 59 | 60 | @property (nonatomic, retain) UIImageView *uiv; 61 | @property (nonatomic, retain) NSURL *url; 62 | 63 | @end 64 | 65 | 66 | @interface AnimatedGif : NSObject 67 | { 68 | NSData *GIF_pointer; 69 | NSMutableData *GIF_buffer; 70 | NSMutableData *GIF_screen; 71 | NSMutableData *GIF_global; 72 | NSMutableArray *GIF_frames; 73 | 74 | NSMutableArray *imageQueue; 75 | bool busyDecoding; 76 | 77 | int GIF_sorted; 78 | int GIF_colorS; 79 | int GIF_colorC; 80 | int GIF_colorF; 81 | int animatedGifDelay; 82 | 83 | int dataPointer; 84 | 85 | UIImageView *imageView; 86 | } 87 | 88 | @property (nonatomic, retain) UIImageView* imageView; 89 | @property bool busyDecoding; 90 | 91 | - (void) addToQueue: (AnimatedGifQueueObject *) agqo; 92 | + (UIImageView*) getAnimationForGifAtUrl: (NSURL *) animationUrl; 93 | - (void) decodeGIF:(NSData *)GIF_Data; 94 | - (void) GIFReadExtensions; 95 | - (void) GIFReadDescriptor; 96 | - (bool) GIFGetBytes:(int)length; 97 | - (bool) GIFSkipBytes: (int) length; 98 | - (NSData*) getFrameAsDataAtIndex:(int)index; 99 | - (UIImage*) getFrameAsImageAtIndex:(int)index; 100 | - (UIImageView*) getAnimation; 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /MainWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 768 5 | 10A288 6 | 715 7 | 1010 8 | 411.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 46 12 | 13 | 14 | YES 15 | 16 | 17 | 18 | YES 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | YES 23 | 24 | YES 25 | 26 | 27 | YES 28 | 29 | 30 | 31 | YES 32 | 33 | IBFilesOwner 34 | 35 | 36 | IBFirstResponder 37 | 38 | 39 | 40 | AnimatedGifExampleViewController 41 | 42 | 43 | 44 | 45 | 292 46 | {320, 480} 47 | 48 | 1 49 | MSAxIDEAA 50 | 51 | NO 52 | NO 53 | 54 | 55 | 56 | 57 | 58 | YES 59 | 60 | 61 | delegate 62 | 63 | 64 | 65 | 4 66 | 67 | 68 | 69 | viewController 70 | 71 | 72 | 73 | 11 74 | 75 | 76 | 77 | window 78 | 79 | 80 | 81 | 14 82 | 83 | 84 | 85 | 86 | YES 87 | 88 | 0 89 | 90 | 91 | 92 | 93 | 94 | -1 95 | 96 | 97 | File's Owner 98 | 99 | 100 | 3 101 | 102 | 103 | AnimatedGifExample App Delegate 104 | 105 | 106 | -2 107 | 108 | 109 | 110 | 111 | 10 112 | 113 | 114 | 115 | 116 | 12 117 | 118 | 119 | 120 | 121 | 122 | 123 | YES 124 | 125 | YES 126 | -1.CustomClassName 127 | -2.CustomClassName 128 | 10.CustomClassName 129 | 10.IBEditorWindowLastContentRect 130 | 10.IBPluginDependency 131 | 12.IBEditorWindowLastContentRect 132 | 12.IBPluginDependency 133 | 3.CustomClassName 134 | 3.IBPluginDependency 135 | 136 | 137 | YES 138 | UIApplication 139 | UIResponder 140 | AnimatedGifExampleViewController 141 | {{512, 351}, {320, 480}} 142 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 143 | {{525, 346}, {320, 480}} 144 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 145 | AnimatedGifExampleAppDelegate 146 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 147 | 148 | 149 | 150 | YES 151 | 152 | 153 | YES 154 | 155 | 156 | 157 | 158 | YES 159 | 160 | 161 | YES 162 | 163 | 164 | 165 | 14 166 | 167 | 168 | 169 | YES 170 | 171 | AnimatedGifExampleAppDelegate 172 | NSObject 173 | 174 | YES 175 | 176 | YES 177 | viewController 178 | window 179 | 180 | 181 | YES 182 | AnimatedGifExampleViewController 183 | UIWindow 184 | 185 | 186 | 187 | IBProjectSource 188 | Classes/AnimatedGifExampleAppDelegate.h 189 | 190 | 191 | 192 | AnimatedGifExampleAppDelegate 193 | NSObject 194 | 195 | IBUserSource 196 | 197 | 198 | 199 | 200 | AnimatedGifExampleViewController 201 | UIViewController 202 | 203 | IBProjectSource 204 | Classes/AnimatedGifExampleViewController.h 205 | 206 | 207 | 208 | 209 | 0 210 | 211 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 212 | 213 | 214 | YES 215 | AnimatedGifExample.xcodeproj 216 | 3 217 | 218 | 219 | -------------------------------------------------------------------------------- /AnimatedGifExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 45; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1D3623260D0F684500981E51 /* AnimatedGifExampleAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* AnimatedGifExampleAppDelegate.m */; }; 11 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 12 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 13 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 14 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; 15 | 2899E5220DE3E06400AC0155 /* AnimatedGifExampleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2899E5210DE3E06400AC0155 /* AnimatedGifExampleViewController.xib */; }; 16 | 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; 17 | 28D7ACF80DDB3853001CB0EB /* AnimatedGifExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* AnimatedGifExampleViewController.m */; }; 18 | BCFF93E11000E1E800162DEF /* AnimatedGif.m in Sources */ = {isa = PBXBuildFile; fileRef = BCFF93E01000E1E800162DEF /* AnimatedGif.m */; }; 19 | BCFF93E91000E28900162DEF /* apple_logo_animated.gif in Resources */ = {isa = PBXBuildFile; fileRef = BCFF93E81000E28900162DEF /* apple_logo_animated.gif */; }; 20 | BCFF94911000EC2800162DEF /* background.png in Resources */ = {isa = PBXBuildFile; fileRef = BCFF94901000EC2800162DEF /* background.png */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 25 | 1D3623240D0F684500981E51 /* AnimatedGifExampleAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimatedGifExampleAppDelegate.h; sourceTree = ""; }; 26 | 1D3623250D0F684500981E51 /* AnimatedGifExampleAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AnimatedGifExampleAppDelegate.m; sourceTree = ""; }; 27 | 1D6058910D05DD3D006BFB54 /* AnimatedGifExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AnimatedGifExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 29 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 30 | 2899E5210DE3E06400AC0155 /* AnimatedGifExampleViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AnimatedGifExampleViewController.xib; sourceTree = ""; }; 31 | 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 32 | 28D7ACF60DDB3853001CB0EB /* AnimatedGifExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimatedGifExampleViewController.h; sourceTree = ""; }; 33 | 28D7ACF70DDB3853001CB0EB /* AnimatedGifExampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AnimatedGifExampleViewController.m; sourceTree = ""; }; 34 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 35 | 32CA4F630368D1EE00C91783 /* AnimatedGifExample_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimatedGifExample_Prefix.pch; sourceTree = ""; }; 36 | 8D1107310486CEB800E47090 /* AnimatedGifExample-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "AnimatedGifExample-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; 37 | BCFF93DF1000E1E800162DEF /* AnimatedGif.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimatedGif.h; sourceTree = ""; }; 38 | BCFF93E01000E1E800162DEF /* AnimatedGif.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AnimatedGif.m; sourceTree = ""; }; 39 | BCFF93E81000E28900162DEF /* apple_logo_animated.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = apple_logo_animated.gif; sourceTree = ""; }; 40 | BCFF94901000EC2800162DEF /* background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = background.png; sourceTree = ""; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 49 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 50 | 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXFrameworksBuildPhase section */ 55 | 56 | /* Begin PBXGroup section */ 57 | 080E96DDFE201D6D7F000001 /* Classes */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | BCFF93DF1000E1E800162DEF /* AnimatedGif.h */, 61 | BCFF93E01000E1E800162DEF /* AnimatedGif.m */, 62 | 1D3623240D0F684500981E51 /* AnimatedGifExampleAppDelegate.h */, 63 | 1D3623250D0F684500981E51 /* AnimatedGifExampleAppDelegate.m */, 64 | 28D7ACF60DDB3853001CB0EB /* AnimatedGifExampleViewController.h */, 65 | 28D7ACF70DDB3853001CB0EB /* AnimatedGifExampleViewController.m */, 66 | ); 67 | path = Classes; 68 | sourceTree = ""; 69 | }; 70 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 1D6058910D05DD3D006BFB54 /* AnimatedGifExample.app */, 74 | ); 75 | name = Products; 76 | sourceTree = ""; 77 | }; 78 | 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 080E96DDFE201D6D7F000001 /* Classes */, 82 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 83 | 29B97317FDCFA39411CA2CEA /* Resources */, 84 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 85 | 19C28FACFE9D520D11CA2CBB /* Products */, 86 | ); 87 | name = CustomTemplate; 88 | sourceTree = ""; 89 | }; 90 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 32CA4F630368D1EE00C91783 /* AnimatedGifExample_Prefix.pch */, 94 | 29B97316FDCFA39411CA2CEA /* main.m */, 95 | ); 96 | name = "Other Sources"; 97 | sourceTree = ""; 98 | }; 99 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | BCFF94901000EC2800162DEF /* background.png */, 103 | BCFF93E81000E28900162DEF /* apple_logo_animated.gif */, 104 | 2899E5210DE3E06400AC0155 /* AnimatedGifExampleViewController.xib */, 105 | 28AD733E0D9D9553002E5188 /* MainWindow.xib */, 106 | 8D1107310486CEB800E47090 /* AnimatedGifExample-Info.plist */, 107 | ); 108 | name = Resources; 109 | sourceTree = ""; 110 | }; 111 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 115 | 1D30AB110D05D00D00671497 /* Foundation.framework */, 116 | 288765A40DF7441C002DB57D /* CoreGraphics.framework */, 117 | ); 118 | name = Frameworks; 119 | sourceTree = ""; 120 | }; 121 | /* End PBXGroup section */ 122 | 123 | /* Begin PBXNativeTarget section */ 124 | 1D6058900D05DD3D006BFB54 /* AnimatedGifExample */ = { 125 | isa = PBXNativeTarget; 126 | buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "AnimatedGifExample" */; 127 | buildPhases = ( 128 | 1D60588D0D05DD3D006BFB54 /* Resources */, 129 | 1D60588E0D05DD3D006BFB54 /* Sources */, 130 | 1D60588F0D05DD3D006BFB54 /* Frameworks */, 131 | ); 132 | buildRules = ( 133 | ); 134 | dependencies = ( 135 | ); 136 | name = AnimatedGifExample; 137 | productName = AnimatedGifExample; 138 | productReference = 1D6058910D05DD3D006BFB54 /* AnimatedGifExample.app */; 139 | productType = "com.apple.product-type.application"; 140 | }; 141 | /* End PBXNativeTarget section */ 142 | 143 | /* Begin PBXProject section */ 144 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 145 | isa = PBXProject; 146 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "AnimatedGifExample" */; 147 | compatibilityVersion = "Xcode 3.1"; 148 | hasScannedForEncodings = 1; 149 | mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; 150 | projectDirPath = ""; 151 | projectRoot = ""; 152 | targets = ( 153 | 1D6058900D05DD3D006BFB54 /* AnimatedGifExample */, 154 | ); 155 | }; 156 | /* End PBXProject section */ 157 | 158 | /* Begin PBXResourcesBuildPhase section */ 159 | 1D60588D0D05DD3D006BFB54 /* Resources */ = { 160 | isa = PBXResourcesBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, 164 | 2899E5220DE3E06400AC0155 /* AnimatedGifExampleViewController.xib in Resources */, 165 | BCFF93E91000E28900162DEF /* apple_logo_animated.gif in Resources */, 166 | BCFF94911000EC2800162DEF /* background.png in Resources */, 167 | ); 168 | runOnlyForDeploymentPostprocessing = 0; 169 | }; 170 | /* End PBXResourcesBuildPhase section */ 171 | 172 | /* Begin PBXSourcesBuildPhase section */ 173 | 1D60588E0D05DD3D006BFB54 /* Sources */ = { 174 | isa = PBXSourcesBuildPhase; 175 | buildActionMask = 2147483647; 176 | files = ( 177 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 178 | 1D3623260D0F684500981E51 /* AnimatedGifExampleAppDelegate.m in Sources */, 179 | 28D7ACF80DDB3853001CB0EB /* AnimatedGifExampleViewController.m in Sources */, 180 | BCFF93E11000E1E800162DEF /* AnimatedGif.m in Sources */, 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | }; 184 | /* End PBXSourcesBuildPhase section */ 185 | 186 | /* Begin XCBuildConfiguration section */ 187 | 1D6058940D05DD3E006BFB54 /* Debug */ = { 188 | isa = XCBuildConfiguration; 189 | buildSettings = { 190 | ALWAYS_SEARCH_USER_PATHS = NO; 191 | COPY_PHASE_STRIP = NO; 192 | GCC_DYNAMIC_NO_PIC = NO; 193 | GCC_OPTIMIZATION_LEVEL = 0; 194 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 195 | GCC_PREFIX_HEADER = AnimatedGifExample_Prefix.pch; 196 | INFOPLIST_FILE = "AnimatedGifExample-Info.plist"; 197 | PRODUCT_NAME = AnimatedGifExample; 198 | }; 199 | name = Debug; 200 | }; 201 | 1D6058950D05DD3E006BFB54 /* Release */ = { 202 | isa = XCBuildConfiguration; 203 | buildSettings = { 204 | ALWAYS_SEARCH_USER_PATHS = NO; 205 | COPY_PHASE_STRIP = YES; 206 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 207 | GCC_PREFIX_HEADER = AnimatedGifExample_Prefix.pch; 208 | INFOPLIST_FILE = "AnimatedGifExample-Info.plist"; 209 | PRODUCT_NAME = AnimatedGifExample; 210 | }; 211 | name = Release; 212 | }; 213 | C01FCF4F08A954540054247B /* Debug */ = { 214 | isa = XCBuildConfiguration; 215 | buildSettings = { 216 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 217 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 218 | GCC_C_LANGUAGE_STANDARD = c99; 219 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 220 | GCC_WARN_UNUSED_VARIABLE = YES; 221 | PREBINDING = NO; 222 | SDKROOT = iphoneos3.0; 223 | }; 224 | name = Debug; 225 | }; 226 | C01FCF5008A954540054247B /* Release */ = { 227 | isa = XCBuildConfiguration; 228 | buildSettings = { 229 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 230 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 231 | GCC_C_LANGUAGE_STANDARD = c99; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 233 | GCC_WARN_UNUSED_VARIABLE = YES; 234 | PREBINDING = NO; 235 | SDKROOT = iphoneos3.0; 236 | }; 237 | name = Release; 238 | }; 239 | /* End XCBuildConfiguration section */ 240 | 241 | /* Begin XCConfigurationList section */ 242 | 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "AnimatedGifExample" */ = { 243 | isa = XCConfigurationList; 244 | buildConfigurations = ( 245 | 1D6058940D05DD3E006BFB54 /* Debug */, 246 | 1D6058950D05DD3E006BFB54 /* Release */, 247 | ); 248 | defaultConfigurationIsVisible = 0; 249 | defaultConfigurationName = Release; 250 | }; 251 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "AnimatedGifExample" */ = { 252 | isa = XCConfigurationList; 253 | buildConfigurations = ( 254 | C01FCF4F08A954540054247B /* Debug */, 255 | C01FCF5008A954540054247B /* Release */, 256 | ); 257 | defaultConfigurationIsVisible = 0; 258 | defaultConfigurationName = Release; 259 | }; 260 | /* End XCConfigurationList section */ 261 | }; 262 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 263 | } 264 | -------------------------------------------------------------------------------- /Classes/AnimatedGif.m: -------------------------------------------------------------------------------- 1 | // 2 | // AnimatedGif.m 3 | // 4 | // Created by Stijn Spijker (http://www.stijnspijker.nl/) on 2009-07-03. 5 | // Based on gifdecode written april 2009 by Martin van Spanje, P-Edge media. 6 | // 7 | // Changes on gifdecode: 8 | // - Small optimizations (mainly arrays) 9 | // - Object Orientated Approach (Class Methods as well as Object Methods) 10 | // - Added the Graphic Control Extension Frame for transparancy 11 | // - Changed header to GIF89a 12 | // - Added methods for ease-of-use 13 | // - Added animations with transparancy 14 | // - No need to save frames to the filesystem anymore 15 | // 16 | // Changelog: 17 | // 18 | // 2010-03-16: Added queing mechanism for static class use 19 | // 2010-01-24: Rework of the entire module, adding static methods, better memory management and URL asynchronous loading 20 | // 2009-10-08: Added dealloc method, and removed leaks, by Pedro Silva 21 | // 2009-08-10: Fixed double release for array, by Christian Garbers 22 | // 2009-06-05: Initial Version 23 | // 24 | // Permission is given to use this source code file, free of charge, in any 25 | // project, commercial or otherwise, entirely at your risk, with the condition 26 | // that any redistribution (in part or whole) of source code must retain 27 | // this copyright and permission notice. Attribution in compiled projects is 28 | // appreciated but not required. 29 | // 30 | 31 | #import "AnimatedGif.h" 32 | 33 | @implementation AnimatedGifFrame 34 | 35 | @synthesize data, delay, disposalMethod, area, header; 36 | 37 | - (void) dealloc 38 | { 39 | [data release]; 40 | [header release]; 41 | [super dealloc]; 42 | } 43 | 44 | 45 | @end 46 | 47 | @implementation AnimatedGifQueueObject 48 | 49 | @synthesize uiv; 50 | @synthesize url; 51 | 52 | @end 53 | 54 | 55 | @implementation AnimatedGif 56 | 57 | static AnimatedGif * instance; 58 | 59 | @synthesize imageView; 60 | @synthesize busyDecoding; 61 | 62 | + (AnimatedGif *) sharedInstance 63 | { 64 | if (instance == nil) 65 | { 66 | instance = [[AnimatedGif alloc] init]; 67 | } 68 | 69 | return instance; 70 | } 71 | 72 | + (UIImageView *) getAnimationForGifAtUrl:(NSURL *)animationUrl 73 | { 74 | 75 | AnimatedGifQueueObject *agqo = [[AnimatedGifQueueObject alloc] init]; 76 | [agqo setUiv: [[UIImageView alloc] init]]; // 2x retain, alloc and the property. 77 | [[agqo uiv] autorelease]; // We expect the user to retain the return object. 78 | [agqo setUrl: animationUrl]; // this object is only retained by the queueobject, which will be released when loading finishes 79 | [[AnimatedGif sharedInstance] addToQueue: agqo]; 80 | [agqo release]; 81 | 82 | if ([[AnimatedGif sharedInstance] busyDecoding] != YES) 83 | { 84 | [[AnimatedGif sharedInstance] setBusyDecoding: YES]; 85 | 86 | // Asynchronous loading for URL's, else the GUI won't appear until image is loaded. 87 | [[AnimatedGif sharedInstance] performSelector:@selector(asynchronousLoading) withObject:nil afterDelay:0.0]; 88 | } 89 | 90 | return [agqo uiv]; 91 | } 92 | 93 | - (void) asynchronousLoading 94 | { 95 | // While we have something in queue. 96 | while ([imageQueue count] > 0) 97 | { 98 | NSData *data = [NSData dataWithContentsOfURL: [(AnimatedGifQueueObject *) [imageQueue objectAtIndex: 0] url]]; 99 | imageView = [[imageQueue objectAtIndex: 0] uiv]; 100 | [self decodeGIF: data]; 101 | UIImageView *tempImageView = [self getAnimation]; 102 | [imageView setImage: [tempImageView image]]; 103 | [imageView sizeToFit]; 104 | [imageView setAnimationImages: [tempImageView animationImages]]; 105 | [imageView startAnimating]; 106 | 107 | [imageQueue removeObjectAtIndex:0]; 108 | } 109 | 110 | busyDecoding = NO; 111 | } 112 | 113 | - (void) addToQueue: (AnimatedGifQueueObject *) agqo 114 | { 115 | [imageQueue addObject: agqo]; 116 | } 117 | 118 | - (id) init 119 | { 120 | if (self = [super init]) 121 | { 122 | imageQueue = [[NSMutableArray alloc] init]; 123 | } 124 | return self; 125 | } 126 | 127 | // the decoder 128 | // decodes GIF image data into separate frames 129 | // based on the Wikipedia Documentation at: 130 | // 131 | // http://en.wikipedia.org/wiki/Graphics_Interchange_Format#Example_.gif_file 132 | // http://en.wikipedia.org/wiki/Graphics_Interchange_Format#Animated_.gif 133 | // 134 | - (void)decodeGIF:(NSData *)GIFData 135 | { 136 | GIF_pointer = GIFData; 137 | 138 | if (GIF_buffer != nil) 139 | { 140 | [GIF_buffer release]; 141 | } 142 | 143 | if (GIF_global != nil) 144 | { 145 | [GIF_global release]; 146 | } 147 | 148 | if (GIF_screen != nil) 149 | { 150 | [GIF_screen release]; 151 | } 152 | 153 | [GIF_frames release]; 154 | 155 | GIF_buffer = [[NSMutableData alloc] init]; 156 | GIF_global = [[NSMutableData alloc] init]; 157 | GIF_screen = [[NSMutableData alloc] init]; 158 | GIF_frames = [[NSMutableArray alloc] init]; 159 | 160 | // Reset file counters to 0 161 | dataPointer = 0; 162 | 163 | [self GIFSkipBytes: 6]; // GIF89a, throw away 164 | [self GIFGetBytes: 7]; // Logical Screen Descriptor 165 | 166 | // Deep copy 167 | [GIF_screen setData: GIF_buffer]; 168 | 169 | // Copy the read bytes into a local buffer on the stack 170 | // For easy byte access in the following lines. 171 | int length = [GIF_buffer length]; 172 | unsigned char aBuffer[length]; 173 | [GIF_buffer getBytes:aBuffer length:length]; 174 | 175 | if (aBuffer[4] & 0x80) GIF_colorF = 1; else GIF_colorF = 0; 176 | if (aBuffer[4] & 0x08) GIF_sorted = 1; else GIF_sorted = 0; 177 | GIF_colorC = (aBuffer[4] & 0x07); 178 | GIF_colorS = 2 << GIF_colorC; 179 | 180 | if (GIF_colorF == 1) 181 | { 182 | [self GIFGetBytes: (3 * GIF_colorS)]; 183 | 184 | // Deep copy 185 | [GIF_global setData:GIF_buffer]; 186 | } 187 | 188 | unsigned char bBuffer[1]; 189 | while ([self GIFGetBytes:1] == YES) 190 | { 191 | [GIF_buffer getBytes:bBuffer length:1]; 192 | 193 | if (bBuffer[0] == 0x3B) 194 | { // This is the end 195 | break; 196 | } 197 | 198 | switch (bBuffer[0]) 199 | { 200 | case 0x21: 201 | // Graphic Control Extension (#n of n) 202 | [self GIFReadExtensions]; 203 | break; 204 | case 0x2C: 205 | // Image Descriptor (#n of n) 206 | [self GIFReadDescriptor]; 207 | break; 208 | } 209 | } 210 | 211 | // clean up stuff 212 | [GIF_buffer release]; 213 | GIF_buffer = nil; 214 | 215 | [GIF_screen release]; 216 | GIF_screen = nil; 217 | 218 | [GIF_global release]; 219 | GIF_global = nil; 220 | } 221 | 222 | // 223 | // Returns a subframe as NSMutableData. 224 | // Returns nil when frame does not exist. 225 | // 226 | // Use this to write a subframe to the filesystems (cache etc); 227 | - (NSData*) getFrameAsDataAtIndex:(int)index 228 | { 229 | if (index < [GIF_frames count]) 230 | { 231 | return ((AnimatedGifFrame *)[GIF_frames objectAtIndex:index]).data; 232 | } 233 | else 234 | { 235 | return nil; 236 | } 237 | } 238 | 239 | // 240 | // Returns a subframe as an autorelease UIImage. 241 | // Returns nil when frame does not exist. 242 | // 243 | // Use this to put a subframe on your GUI. 244 | - (UIImage*) getFrameAsImageAtIndex:(int)index 245 | { 246 | NSData *frameData = [self getFrameAsDataAtIndex: index]; 247 | UIImage *image = nil; 248 | 249 | if (frameData != nil) 250 | { 251 | image = [UIImage imageWithData:frameData]; 252 | } 253 | 254 | return image; 255 | } 256 | 257 | // 258 | // This method converts the arrays of GIF data to an animation, counting 259 | // up all the seperate frame delays, and setting that to the total duration 260 | // since the iPhone Cocoa framework does not allow you to set per frame 261 | // delays. 262 | // 263 | // Returns nil when there are no frames present in the GIF, or 264 | // an autorelease UIImageView* with the animation. 265 | - (UIImageView*) getAnimation 266 | { 267 | if ([GIF_frames count] > 0) 268 | { 269 | if (imageView != nil) 270 | { 271 | // This sets up the frame etc for the UIImageView by using the first frame. 272 | [imageView setImage:[self getFrameAsImageAtIndex:0]]; 273 | [imageView sizeToFit]; 274 | } 275 | else 276 | { 277 | imageView = [[UIImageView alloc] initWithImage:[self getFrameAsImageAtIndex:0]]; 278 | } 279 | 280 | 281 | // Add all subframes to the animation 282 | NSMutableArray *array = [[NSMutableArray alloc] init]; 283 | for (int i = 0; i < [GIF_frames count]; i++) 284 | { 285 | [array addObject: [self getFrameAsImageAtIndex:i]]; 286 | } 287 | 288 | NSMutableArray *overlayArray = [[NSMutableArray alloc] init]; 289 | UIImage *firstImage = [array objectAtIndex:0]; 290 | CGSize size = firstImage.size; 291 | CGRect rect = CGRectZero; 292 | rect.size = size; 293 | 294 | UIGraphicsBeginImageContext(size); 295 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 296 | 297 | int i = 0; 298 | AnimatedGifFrame *lastFrame = nil; 299 | for (UIImage *image in array) { 300 | AnimatedGifFrame *frame = [GIF_frames objectAtIndex:i]; 301 | if (lastFrame) { 302 | switch (lastFrame.disposalMethod) { 303 | case 1: 304 | // Do not dispose 305 | break; 306 | case 2: 307 | // Restore to background color 308 | CGContextClearRect(ctx, lastFrame.area); 309 | break; 310 | case 3: 311 | // TODO Restore to previous 312 | break; 313 | } 314 | } 315 | CGContextSaveGState(ctx); 316 | CGContextScaleCTM(ctx, 1.0, -1.0); 317 | CGContextTranslateCTM(ctx, 0.0, -size.height); 318 | CGContextDrawImage(ctx, rect, image.CGImage); 319 | CGContextRestoreGState(ctx); 320 | [overlayArray addObject:UIGraphicsGetImageFromCurrentImageContext()]; 321 | lastFrame = frame; 322 | i++; 323 | } 324 | UIGraphicsEndImageContext(); 325 | 326 | [imageView setAnimationImages:overlayArray]; 327 | 328 | [overlayArray release]; 329 | [array release]; 330 | 331 | // Count up the total delay, since Cocoa doesn't do per frame delays. 332 | double total = 0; 333 | for (AnimatedGifFrame *frame in GIF_frames) { 334 | total += frame.delay; 335 | } 336 | 337 | // GIFs store the delays as 1/100th of a second, 338 | // UIImageViews want it in seconds. 339 | [imageView setAnimationDuration:total/100]; 340 | 341 | // Repeat infinite 342 | [imageView setAnimationRepeatCount:0]; 343 | 344 | [imageView startAnimating]; 345 | [[imageView retain] autorelease]; 346 | 347 | return imageView; 348 | } 349 | else 350 | { 351 | return nil; 352 | } 353 | } 354 | 355 | - (void)GIFReadExtensions 356 | { 357 | // 21! But we still could have an Application Extension, 358 | // so we want to check for the full signature. 359 | unsigned char cur[1], prev[1]; 360 | [self GIFGetBytes:1]; 361 | [GIF_buffer getBytes:cur length:1]; 362 | 363 | while (cur[0] != 0x00) 364 | { 365 | 366 | // TODO: Known bug, the sequence F9 04 could occur in the Application Extension, we 367 | // should check whether this combo follows directly after the 21. 368 | if (cur[0] == 0x04 && prev[0] == 0xF9) 369 | { 370 | [self GIFGetBytes:5]; 371 | 372 | AnimatedGifFrame *frame = [[AnimatedGifFrame alloc] init]; 373 | 374 | unsigned char buffer[5]; 375 | [GIF_buffer getBytes:buffer length:5]; 376 | frame.disposalMethod = (buffer[0] & 0x1c) >> 2; 377 | //NSLog(@"flags=%x, dm=%x", (int)(buffer[0]), frame.disposalMethod); 378 | 379 | // We save the delays for easy access. 380 | frame.delay = (buffer[1] | buffer[2] << 8); 381 | 382 | unsigned char board[8]; 383 | board[0] = 0x21; 384 | board[1] = 0xF9; 385 | board[2] = 0x04; 386 | 387 | for(int i = 3, a = 0; a < 5; i++, a++) 388 | { 389 | board[i] = buffer[a]; 390 | } 391 | 392 | frame.header = [NSData dataWithBytes:board length:8]; 393 | 394 | [GIF_frames addObject:frame]; 395 | [frame release]; 396 | break; 397 | } 398 | 399 | prev[0] = cur[0]; 400 | [self GIFGetBytes:1]; 401 | [GIF_buffer getBytes:cur length:1]; 402 | } 403 | } 404 | 405 | - (void) GIFReadDescriptor 406 | { 407 | [self GIFGetBytes:9]; 408 | 409 | // Deep copy 410 | NSMutableData *GIF_screenTmp = [NSMutableData dataWithData:GIF_buffer]; 411 | 412 | unsigned char aBuffer[9]; 413 | [GIF_buffer getBytes:aBuffer length:9]; 414 | 415 | CGRect rect; 416 | rect.origin.x = ((int)aBuffer[1] << 8) | aBuffer[0]; 417 | rect.origin.y = ((int)aBuffer[3] << 8) | aBuffer[2]; 418 | rect.size.width = ((int)aBuffer[5] << 8) | aBuffer[4]; 419 | rect.size.height = ((int)aBuffer[7] << 8) | aBuffer[6]; 420 | 421 | AnimatedGifFrame *frame = [GIF_frames lastObject]; 422 | frame.area = rect; 423 | 424 | if (aBuffer[8] & 0x80) GIF_colorF = 1; else GIF_colorF = 0; 425 | 426 | unsigned char GIF_code = GIF_colorC, GIF_sort = GIF_sorted; 427 | 428 | if (GIF_colorF == 1) 429 | { 430 | GIF_code = (aBuffer[8] & 0x07); 431 | 432 | if (aBuffer[8] & 0x20) 433 | { 434 | GIF_sort = 1; 435 | } 436 | else 437 | { 438 | GIF_sort = 0; 439 | } 440 | } 441 | 442 | int GIF_size = (2 << GIF_code); 443 | 444 | size_t blength = [GIF_screen length]; 445 | unsigned char bBuffer[blength]; 446 | [GIF_screen getBytes:bBuffer length:blength]; 447 | 448 | bBuffer[4] = (bBuffer[4] & 0x70); 449 | bBuffer[4] = (bBuffer[4] | 0x80); 450 | bBuffer[4] = (bBuffer[4] | GIF_code); 451 | 452 | if (GIF_sort) 453 | { 454 | bBuffer[4] |= 0x08; 455 | } 456 | 457 | NSMutableData *GIF_string = [NSMutableData dataWithData:[[NSString stringWithString:@"GIF89a"] dataUsingEncoding: NSUTF8StringEncoding]]; 458 | [GIF_screen setData:[NSData dataWithBytes:bBuffer length:blength]]; 459 | [GIF_string appendData: GIF_screen]; 460 | 461 | if (GIF_colorF == 1) 462 | { 463 | [self GIFGetBytes:(3 * GIF_size)]; 464 | [GIF_string appendData:GIF_buffer]; 465 | } 466 | else 467 | { 468 | [GIF_string appendData:GIF_global]; 469 | } 470 | 471 | // Add Graphic Control Extension Frame (for transparancy) 472 | [GIF_string appendData:frame.header]; 473 | 474 | char endC = 0x2c; 475 | [GIF_string appendBytes:&endC length:sizeof(endC)]; 476 | 477 | size_t clength = [GIF_screenTmp length]; 478 | unsigned char cBuffer[clength]; 479 | [GIF_screenTmp getBytes:cBuffer length:clength]; 480 | 481 | cBuffer[8] &= 0x40; 482 | 483 | [GIF_screenTmp setData:[NSData dataWithBytes:cBuffer length:clength]]; 484 | 485 | [GIF_string appendData: GIF_screenTmp]; 486 | [self GIFGetBytes:1]; 487 | [GIF_string appendData: GIF_buffer]; 488 | 489 | while (true) 490 | { 491 | [self GIFGetBytes:1]; 492 | [GIF_string appendData: GIF_buffer]; 493 | 494 | unsigned char dBuffer[1]; 495 | [GIF_buffer getBytes:dBuffer length:1]; 496 | 497 | long u = (long) dBuffer[0]; 498 | 499 | if (u != 0x00) 500 | { 501 | [self GIFGetBytes:u]; 502 | [GIF_string appendData: GIF_buffer]; 503 | } 504 | else 505 | { 506 | break; 507 | } 508 | 509 | } 510 | 511 | endC = 0x3b; 512 | [GIF_string appendBytes:&endC length:sizeof(endC)]; 513 | 514 | // save the frame into the array of frames 515 | frame.data = GIF_string; 516 | } 517 | 518 | /* Puts (int) length into the GIF_buffer from file, returns whether read was succesfull */ 519 | - (bool) GIFGetBytes: (int) length 520 | { 521 | if (GIF_buffer != nil) 522 | { 523 | [GIF_buffer release]; // Release old buffer 524 | GIF_buffer = nil; 525 | } 526 | 527 | if ([GIF_pointer length] >= dataPointer + length) // Don't read across the edge of the file.. 528 | { 529 | GIF_buffer = [[GIF_pointer subdataWithRange:NSMakeRange(dataPointer, length)] retain]; 530 | dataPointer += length; 531 | return YES; 532 | } 533 | else 534 | { 535 | return NO; 536 | } 537 | } 538 | 539 | /* Skips (int) length bytes in the GIF, faster than reading them and throwing them away.. */ 540 | - (bool) GIFSkipBytes: (int) length 541 | { 542 | if ([GIF_pointer length] >= dataPointer + length) 543 | { 544 | dataPointer += length; 545 | return YES; 546 | } 547 | else 548 | { 549 | return NO; 550 | } 551 | 552 | } 553 | 554 | - (void) dealloc 555 | { 556 | if (GIF_buffer != nil) 557 | { 558 | [GIF_buffer release]; 559 | } 560 | 561 | if (GIF_screen != nil) 562 | { 563 | [GIF_screen release]; 564 | } 565 | 566 | if (GIF_global != nil) 567 | { 568 | [GIF_global release]; 569 | } 570 | 571 | [GIF_frames release]; 572 | 573 | [imageView release]; 574 | 575 | [super dealloc]; 576 | } 577 | @end 578 | -------------------------------------------------------------------------------- /AnimatedGifExampleViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 768 5 | 10D573 6 | 762 7 | 1038.29 8 | 460.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 87 12 | 13 | 14 | YES 15 | 16 | 17 | 18 | YES 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | YES 23 | 24 | YES 25 | 26 | 27 | YES 28 | 29 | 30 | 31 | YES 32 | 33 | IBFilesOwner 34 | IBCocoaTouchFramework 35 | 36 | 37 | IBFirstResponder 38 | IBCocoaTouchFramework 39 | 40 | 41 | 42 | 274 43 | 44 | YES 45 | 46 | 47 | 314 48 | {{0, 145}, {320, 180}} 49 | 50 | NO 51 | YES 52 | 4 53 | NO 54 | IBCocoaTouchFramework 55 | 56 | NSImage 57 | background.png 58 | 59 | 60 | 61 | 62 | 301 63 | {{0, 167}, {160, 158}} 64 | 65 | NO 66 | NO 67 | 4 68 | NO 69 | IBCocoaTouchFramework 70 | 71 | 72 | 73 | 301 74 | {{159, 167}, {160, 158}} 75 | 76 | NO 77 | NO 78 | 4 79 | NO 80 | IBCocoaTouchFramework 81 | 82 | 83 | 84 | 292 85 | {{80, 20}, {160, 45}} 86 | 87 | NO 88 | YES 89 | NO 90 | IBCocoaTouchFramework 91 | Animated Gif 92 | 93 | Helvetica 94 | 24 95 | 16 96 | 97 | 98 | 1 99 | MC45ODkxMzA0NCAwLjk4OTEzMDQ0IDAuOTg5MTMwNDQAA 100 | 101 | 102 | 1 103 | 10 104 | 1 105 | 106 | 107 | 108 | 292 109 | {{111, 52}, {98, 21}} 110 | 111 | NO 112 | YES 113 | NO 114 | IBCocoaTouchFramework 115 | with transparancy 116 | 117 | Helvetica 118 | 12 119 | 16 120 | 121 | 122 | 123 | 1 124 | 10 125 | 1 126 | 127 | 128 | 129 | 292 130 | {{139, 73}, {42, 21}} 131 | 132 | NO 133 | YES 134 | NO 135 | IBCocoaTouchFramework 136 | by 137 | 138 | Helvetica 139 | 9 140 | 16 141 | 142 | 143 | 144 | 1 145 | 9 146 | 1 147 | 148 | 149 | 150 | 292 151 | {{89, 102}, {141, 35}} 152 | 153 | NO 154 | YES 155 | NO 156 | IBCocoaTouchFramework 157 | Stijn Spijker 158 | 159 | 160 | 161 | 1 162 | 10 163 | 1 164 | 165 | 166 | 167 | 292 168 | {{130, 371}, {187, 21}} 169 | 170 | NO 171 | YES 172 | NO 173 | IBCocoaTouchFramework 174 | http://www.stijnspijker.nl/ 175 | 176 | 177 | 1 178 | 10 179 | 2 180 | 181 | 182 | 183 | 292 184 | {{157, 400}, {160, 21}} 185 | 186 | NO 187 | YES 188 | NO 189 | IBCocoaTouchFramework 190 | stijn@stijnspijker.nl 191 | 192 | 193 | 1 194 | 10 195 | 2 196 | 197 | 198 | 199 | 292 200 | {{179, 419}, {138, 21}} 201 | 202 | NO 203 | YES 204 | NO 205 | IBCocoaTouchFramework 206 | no spam please :) 207 | 208 | Helvetica 209 | 10 210 | 16 211 | 212 | 213 | 214 | 1 215 | 10 216 | 2 217 | 218 | 219 | 220 | 292 221 | {{0, 146}, {320, 19}} 222 | 223 | 224 | 1 225 | MSAxIDEgMC41NQA 226 | 227 | NO 228 | NO 229 | IBCocoaTouchFramework 230 | 0 231 | 232 | Type URL Here 233 | 234 | 3 235 | MAA 236 | 237 | 2 238 | 239 | 240 | YES 241 | YES 242 | 17 243 | 244 | 1 245 | 3 246 | 1 247 | IBCocoaTouchFramework 248 | 249 | 250 | 251 | {320, 460} 252 | 253 | 254 | 1 255 | MC4xMzU4Njk1NiAwLjEzNTg2OTU2IDAuMTM1ODY5NTYAA 256 | 257 | NO 258 | IBCocoaTouchFramework 259 | 260 | 261 | 262 | 263 | YES 264 | 265 | 266 | view 267 | 268 | 269 | 270 | 7 271 | 272 | 273 | 274 | theFirstAnimatedGif 275 | 276 | 277 | 278 | 20 279 | 280 | 281 | 282 | theSecondAnimatedGif 283 | 284 | 285 | 286 | 21 287 | 288 | 289 | 290 | delegate 291 | 292 | 293 | 294 | 23 295 | 296 | 297 | 298 | 299 | YES 300 | 301 | 0 302 | 303 | 304 | 305 | 306 | 307 | -1 308 | 309 | 310 | File's Owner 311 | 312 | 313 | -2 314 | 315 | 316 | 317 | 318 | 6 319 | 320 | 321 | YES 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 8 338 | 339 | 340 | 341 | 342 | 10 343 | 344 | 345 | 346 | 347 | 11 348 | 349 | 350 | 351 | 352 | 12 353 | 354 | 355 | 356 | 357 | 13 358 | 359 | 360 | 361 | 362 | 14 363 | 364 | 365 | 366 | 367 | 15 368 | 369 | 370 | 371 | 372 | 16 373 | 374 | 375 | 376 | 377 | 18 378 | 379 | 380 | 381 | 382 | 19 383 | 384 | 385 | 386 | 387 | 22 388 | 389 | 390 | 391 | 392 | 393 | 394 | YES 395 | 396 | YES 397 | -1.CustomClassName 398 | -2.CustomClassName 399 | 10.IBPluginDependency 400 | 11.IBPluginDependency 401 | 12.IBPluginDependency 402 | 13.IBPluginDependency 403 | 14.IBPluginDependency 404 | 15.IBPluginDependency 405 | 16.IBPluginDependency 406 | 19.IBPluginDependency 407 | 22.IBPluginDependency 408 | 6.IBEditorWindowLastContentRect 409 | 6.IBPluginDependency 410 | 8.IBPluginDependency 411 | 412 | 413 | YES 414 | AnimatedGifExampleViewController 415 | UIResponder 416 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 417 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 418 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 419 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 420 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 421 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 422 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 423 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 424 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 425 | {{448, 314}, {320, 460}} 426 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 427 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 428 | 429 | 430 | 431 | YES 432 | 433 | 434 | YES 435 | 436 | 437 | 438 | 439 | YES 440 | 441 | 442 | YES 443 | 444 | 445 | 446 | 23 447 | 448 | 449 | 450 | YES 451 | 452 | AnimatedGifExampleViewController 453 | UIViewController 454 | 455 | YES 456 | 457 | YES 458 | theFirstAnimatedGif 459 | theSecondAnimatedGif 460 | 461 | 462 | YES 463 | UIImageView 464 | UIImageView 465 | 466 | 467 | 468 | IBProjectSource 469 | Classes/AnimatedGifExampleViewController.h 470 | 471 | 472 | 473 | 474 | YES 475 | 476 | NSObject 477 | 478 | IBFrameworkSource 479 | Foundation.framework/Headers/NSError.h 480 | 481 | 482 | 483 | NSObject 484 | 485 | IBFrameworkSource 486 | Foundation.framework/Headers/NSFileManager.h 487 | 488 | 489 | 490 | NSObject 491 | 492 | IBFrameworkSource 493 | Foundation.framework/Headers/NSKeyValueCoding.h 494 | 495 | 496 | 497 | NSObject 498 | 499 | IBFrameworkSource 500 | Foundation.framework/Headers/NSKeyValueObserving.h 501 | 502 | 503 | 504 | NSObject 505 | 506 | IBFrameworkSource 507 | Foundation.framework/Headers/NSKeyedArchiver.h 508 | 509 | 510 | 511 | NSObject 512 | 513 | IBFrameworkSource 514 | Foundation.framework/Headers/NSNetServices.h 515 | 516 | 517 | 518 | NSObject 519 | 520 | IBFrameworkSource 521 | Foundation.framework/Headers/NSObject.h 522 | 523 | 524 | 525 | NSObject 526 | 527 | IBFrameworkSource 528 | Foundation.framework/Headers/NSPort.h 529 | 530 | 531 | 532 | NSObject 533 | 534 | IBFrameworkSource 535 | Foundation.framework/Headers/NSRunLoop.h 536 | 537 | 538 | 539 | NSObject 540 | 541 | IBFrameworkSource 542 | Foundation.framework/Headers/NSStream.h 543 | 544 | 545 | 546 | NSObject 547 | 548 | IBFrameworkSource 549 | Foundation.framework/Headers/NSThread.h 550 | 551 | 552 | 553 | NSObject 554 | 555 | IBFrameworkSource 556 | Foundation.framework/Headers/NSURL.h 557 | 558 | 559 | 560 | NSObject 561 | 562 | IBFrameworkSource 563 | Foundation.framework/Headers/NSURLConnection.h 564 | 565 | 566 | 567 | NSObject 568 | 569 | IBFrameworkSource 570 | Foundation.framework/Headers/NSXMLParser.h 571 | 572 | 573 | 574 | NSObject 575 | 576 | IBFrameworkSource 577 | UIKit.framework/Headers/UIAccessibility.h 578 | 579 | 580 | 581 | NSObject 582 | 583 | IBFrameworkSource 584 | UIKit.framework/Headers/UINibLoading.h 585 | 586 | 587 | 588 | NSObject 589 | 590 | IBFrameworkSource 591 | UIKit.framework/Headers/UIResponder.h 592 | 593 | 594 | 595 | UIControl 596 | UIView 597 | 598 | IBFrameworkSource 599 | UIKit.framework/Headers/UIControl.h 600 | 601 | 602 | 603 | UIImageView 604 | UIView 605 | 606 | IBFrameworkSource 607 | UIKit.framework/Headers/UIImageView.h 608 | 609 | 610 | 611 | UILabel 612 | UIView 613 | 614 | IBFrameworkSource 615 | UIKit.framework/Headers/UILabel.h 616 | 617 | 618 | 619 | UIResponder 620 | NSObject 621 | 622 | 623 | 624 | UISearchBar 625 | UIView 626 | 627 | IBFrameworkSource 628 | UIKit.framework/Headers/UISearchBar.h 629 | 630 | 631 | 632 | UISearchDisplayController 633 | NSObject 634 | 635 | IBFrameworkSource 636 | UIKit.framework/Headers/UISearchDisplayController.h 637 | 638 | 639 | 640 | UITextField 641 | UIControl 642 | 643 | IBFrameworkSource 644 | UIKit.framework/Headers/UITextField.h 645 | 646 | 647 | 648 | UIView 649 | 650 | 651 | 652 | UIView 653 | UIResponder 654 | 655 | IBFrameworkSource 656 | UIKit.framework/Headers/UIView.h 657 | 658 | 659 | 660 | UIViewController 661 | 662 | IBFrameworkSource 663 | UIKit.framework/Headers/UINavigationController.h 664 | 665 | 666 | 667 | UIViewController 668 | 669 | IBFrameworkSource 670 | UIKit.framework/Headers/UITabBarController.h 671 | 672 | 673 | 674 | UIViewController 675 | UIResponder 676 | 677 | IBFrameworkSource 678 | UIKit.framework/Headers/UIViewController.h 679 | 680 | 681 | 682 | 683 | 0 684 | IBCocoaTouchFramework 685 | 686 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 687 | 688 | 689 | 690 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 691 | 692 | 693 | 694 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 695 | 696 | 697 | YES 698 | AnimatedGifExample.xcodeproj 699 | 3 700 | 701 | background.png 702 | {320, 180} 703 | 704 | 87 705 | 706 | 707 | --------------------------------------------------------------------------------