Performant animated GIF engine for iOS

Related tags

GIF FLAnimatedImage
Overview

FLAnimatedImage is a performant animated GIF engine for iOS:

  • Plays multiple GIFs simultaneously with a playback speed comparable to desktop browsers
  • Honors variable frame delays
  • Behaves gracefully under memory pressure
  • Eliminates delays or blocking during the first playback loop
  • Interprets the frame delays of fast GIFs the same way modern browsers do

It's a well-tested component that powers all GIFs in Flipboard. To understand its behavior it comes with an interactive demo:

Flipboard playing multiple GIFs

Who is this for?

  • Apps that don't support animated GIFs yet
  • Apps that already support animated GIFs but want a higher performance solution
  • People who want to tinker with the code (the corresponding blog post is a great place to start; also see the To Do section below)

Installation & Usage

FLAnimatedImage is a well-encapsulated drop-in component. Simply replace your UIImageView instances with instances of FLAnimatedImageView to get animated GIF support. There is no central cache or state to manage.

If using CocoaPods, the quickest way to try it out is to type this on the command line:

$ pod try FLAnimatedImage

To add it to your app, copy the two classes FLAnimatedImage.h/.m and FLAnimatedImageView.h/.m into your Xcode project or add via CocoaPods by adding this to your Podfile:

pod 'FLAnimatedImage', '~> 1.0'

If using Carthage, add the following line into your Cartfile

github "Flipboard/FLAnimatedImage"

If using Swift Package Manager, add the following to your Package.swift or add via XCode:

dependencies: [
    .package(url: "https://github.com/Flipboard/FLAnimatedImage.git", .upToNextMajor(from: "1.0.16"))
],
targets: [
    .target(name: "TestProject", dependencies: ["FLAnimatedImage""])
]

In your code, #import "FLAnimatedImage.h", create an image from an animated GIF, and setup the image view to display it:

FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif"]]];
FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init];
imageView.animatedImage = image;
imageView.frame = CGRectMake(0.0, 0.0, 100.0, 100.0);
[self.view addSubview:imageView];

It's flexible to integrate in your custom image loading stack and backwards compatible to iOS 9.

It uses ARC and the Apple frameworks QuartzCore, ImageIO, MobileCoreServices, and CoreGraphics.

It is capable of fine-grained logging. A block can be set on FLAnimatedImage that's invoked when logging occurs with various log levels via the +setLogBlock:logLevel: method. For example:

// Set up FLAnimatedImage logging.
[FLAnimatedImage setLogBlock:^(NSString *logString, FLLogLevel logLevel) {
    // Using NSLog
    NSLog(@"%@", logString);

    // ...or CocoaLumberjackLogger only logging warnings and errors
    if (logLevel == FLLogLevelError) {
        DDLogError(@"%@", logString);
    } else if (logLevel == FLLogLevelWarn) {
        DDLogWarn(@"%@", logString);
    }
} logLevel:FLLogLevelWarn];

Since FLAnimatedImage is licensed under MIT, it's compatible with the terms of using it for any app on the App Store.

Release process

  1. Bump version in FLAnimatedImage.podspec, update CHANGES, and commit.
  2. Tag commit with > git tag -a <VERSION> -m "<VERSION>" and > git push --tags.
  3. Submit Podspec to Trunk with > pod trunk push FLAnimatedImage.podspec (ensure you're auth'ed).

To Do

  • Support other animated image formats such as APNG or WebP (WebP support implemented here)
  • Integration into network libraries and image caches
  • Investigate whether FLAnimatedImage should become a UIImage subclass
  • Smarter buffering
  • Bring demo app to iPhone

This code has successfully shipped to many people as is, but please do come with your questions, issues and pull requests!

Select apps using FLAnimatedImage

(alphabetically)

If you're using FLAnimatedImage in your app, please open a PR to add it to this list!

Comments
  • Avoiding costly CGImage creation during FLAnimatedImage initialization?

    Avoiding costly CGImage creation during FLAnimatedImage initialization?

    Hello! I'm curious about some behaviour in the initializer of FLAnimatedImage. At the moment it's line 203 of FLAnimatedImage.m, wherein a CGImage is created for each frame in the CGImageSource.

    I'm guessing the idea here was to drop frames that aren't going to display anyway, and adjusting the timings appropriately. That makes sense to me. Decoding the first (working) frame for use as a "poster image" and for buffer size calculations also makes sense to me.

    However, CGImageSourceCreateImageAtIndex is a costly operation, and it would be excellent to avoid it in the cases where the created CGImage isn't actually used. Not only does it feel wasteful (as the frames will be decoded once again during playback), it makes FLAnimatedImage initialization much slower than maybe it needs to be. If my guesses above are correct, I think we can speed things up tremendously.

    Are my guesses here correct? I'm happy to poke around and maybe open a pull request, but I want to make sure I'm not missing anything.

    enhancement 
    opened by nolanw 31
  • Support Carthage

    Support Carthage

    Before this PR is merged, add following line into your Cartfile to use with Carthage,

    github "cybertk/FLAnimatedImage" "carthage"
    
    enhancement 
    opened by cybertk 17
  • GIF not animating at the original speed

    GIF not animating at the original speed

    I'm exporting a GIF from Photoshop, and placing it into a view controller which is part of a page view controller. I'm noticing the frame rate does not match the original GIF frame rate - it's played back much slower than the original GIF, but only when run on a physical device - I tested the iPhone 6 and iPad 2. When run on the Simulator it animates at the correct speed. Has anyone else seen this, what do you think the problem is? Could our settings be incorrect when exporting the GIF to cause it to give iOS troubles playing it? Any tips and suggestions are appreciated.

    opened by hipwelljo 14
  • Failed to compile project when project uses CocoaLumberjack

    Failed to compile project when project uses CocoaLumberjack

    We use CocoaLumberjack in Medium's app and we declare ddLogLevel as: extern int ddLogLevel;

    The project now fails with the following error:

    /workspace/Pods/Headers/Public/FLAnimatedImage/FLAnimatedImage.h:115:22: redefinition of 'ddLogLevel' with a different type: 'const int' vs 'int'
    
        extern const int ddLogLevel;
    

    What do you think?

    enhancement 
    opened by vinibaggio 13
  • Reconfigure Frame Rate Divisor

    Reconfigure Frame Rate Divisor

    Closes #253

    Overview

    As discussed in the issue, when using FLAnimatedImage on iPhone 13 Pro devices running iOS 15, GIFs play at ultra speed due to some math assuming that the screen refresh rate will never change.

    Unfortunately (or fortunately?) ProMotion is now a thing, so assumptions need to be mitigated.

    Changes

    • Made use of if (@available(iOS 10.3, *)) { to use the available UIScreen.mainScreen.maximumFramesPerSecond value.
    • Previous iOS devices can continue using 60Hz, as devices running <iOS 10.3 do not know about higher refresh rates.

    Considerations

    • Explicit cast to (double) (NSTimeInterval) for accuracy.
    opened by viewDidAppear 12
  • Fix warning: MobileCoreServices has been renamed. Use CoreServices instead.

    Fix warning: MobileCoreServices has been renamed. Use CoreServices instead.

    Close #238

    If our library was installed via CocoaPods, Xcode 11.4 will issue the warning "MobileCoreServices has been renamed. Use CoreServices instead.".

    image

    How to fix: Do not explicitly link MobileCoreServices.framework in the CocoaPods generated project, by deleting MobileCoreServices from the spec.frameworks attribute in our podspec file.

    More info: https://github.com/AFNetworking/AFNetworking/pull/4532

    opened by ElfSundae 11
  • Undefined symbols for architecture x86_64

    Undefined symbols for architecture x86_64

    Hi, I'm getting the following error while building.

    Undefined symbols for architecture x86_64:
      "_OBJC_CLASS_$_DDLog", referenced from:
          objc-class-ref in FLAnimatedImage.o
          objc-class-ref in FLAnimatedImageView.o
    ld: symbol(s) not found for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    
    I'm sure that the solution is easy but, for the life of me, can't figure out the solution.
    Any help is welcome!
    Thanks!
    
    opened by mtgomes 11
  • Provide means for consuming less memory

    Provide means for consuming less memory

    This is critical if one is to use FLAnimatedImage in memory constrained environments such as application extensions.

    Things to consider:

    • Allow for customization of preload buffer (definite savings)
    • Allow for disabling of frame predrawing (questionable savings, requires spending time with instruments).

    Started at https://github.com/Flipboard/FLAnimatedImage/tree/extension-considerations.

    opened by timonus 10
  • Extension considerations

    Extension considerations

    This pull request introduces some initialization options to FLAnimatedImage that allow clients to configure it in a way that consumes less memory than the default. These settings are:

    1. Specify number of frames to keep in memory: https://github.com/Flipboard/FLAnimatedImage/commit/0b4886003f34d1b89cd1b5ec9552852c08891c15
    2. Disable frame predrawing: https://github.com/Flipboard/FLAnimatedImage/commit/4e78f71102a824d831b1b3aa348706b5640985fd

    I took some instruments in different configs

    ConfigurationMemory Used ("All Heap & Anonymous VM" in instruments)Delta from Default
    Default47.8MBN/A
    Disable frame preloading30.9MB16.9MB
    Disable frame predrawing33.9MB13.9MB
    Disable frame preloading and predrawing28.2MB19.6MB

    The reason that the memory savings in the final row isn't the sum of both disabled frame preloading and disabled frame predrawing is that predrawing only impacts loaded frames, and when there are fewer frames preloaded disabling predrawing doesn't have as large of an effect.

    I also made the designated initializer take a CGImageSource rather than NSData because of a PR recently closed on FLAnimatedImage requesting it for more flexibility.

    opened by timonus 9
  • Optimal displayLink frame interval

    Optimal displayLink frame interval

    Calculates an optimal frame interval by calculating the greatest common divisor of frame durations. This reduces the number of times displayDidRefresh: is executed when no image changes are need.

    opened by ejensen 9
  • Disable highlighting for animated image view

    Disable highlighting for animated image view

    It's broken when highlighted is set, so don't let it get set when animated. Since UICollectionViewCell helpfully (?) sets any embedded image views' highlighted property, it's particularly annoying there.

    bug 
    opened by nolanw 9
  • Crash in imageAtIndex

    Crash in imageAtIndex

    when call imageAtIndex sometimes crash like this Thread 3 Crashed: 0 libobjc.A.dylib _objc_msgSend +32 1 ImageIO ERROR_CGImageCopyImageSource_WAS_CALLED_WITH_INVALID_CGIMAGE(CGImage*) +56 2 ImageIO _CGImageGetImageSource +108 3 UIKitCore -[_UIImageCGImageContent initWithCGImage:scale:] +40 4 UIKitCore -[UIImage initWithCGImage:scale:orientation:] +76 5 UIKitCore +[UIImage imageWithCGImage:] +48

    opened by jerrydudu 0
  • Bitcode not enabled for package

    Bitcode not enabled for package

    Hi

    I have installed this package inside my XCFramework but when I try to create the framework I run into this error

    Showing All Messages Bitcode bundle could not be generated because '/Debug-iphoneos/FLAnimatedImage.o' was built without full bitcode. All object files and libraries for bitcode must be generated from Xcode Archive or Install build file '/Build/Products/Debug-iphoneos/FLAnimatedImage.o' for architecture arm64

    bug help wanted 
    opened by MalcolmnDEV 0
  • iPhone 偶尔 crash , ios14.8 or iOS 15.0,FLAnimatedImage initWithAnimatedGIFData:optimalFrameCacheSize:predrawingEnabled:]

    iPhone 偶尔 crash , ios14.8 or iOS 15.0,FLAnimatedImage initWithAnimatedGIFData:optimalFrameCacheSize:predrawingEnabled:]

    Crashed: ui 0 libdispatch.dylib 0x3b338 _dispatch_mach_send_and_wait_for_reply.cold.2 + 36 1 libdispatch.dylib 0x1e5dc _dispatch_mach_send_and_wait_for_reply + 1380 2 libdispatch.dylib 0x1e64c dispatch_mach_send_with_result_and_wait_for_reply + 56 3 libxpc.dylib 0xde30 xpc_connection_send_message_with_reply_sync + 240 4 CoreFoundation 0x1980ac __78-[CFPrefsPlistSource sendRequestNewDataMessage:toConnection:retryCount:error:]_block_invoke + 32 5 CoreFoundation 0x1468fc CFPREFERENCES_IS_WAITING_FOR_SYSTEM_CFPREFSD + 100 6 CoreFoundation 0x2a028 -[CFPrefsPlistSource sendRequestNewDataMessage:toConnection:retryCount:error:] + 420 7 CoreFoundation 0x197918 __50-[CFPrefsPlistSource alreadylocked_requestNewData]_block_invoke + 132 8 CoreFoundation 0xacf8 -[_CFXPreferences withConnectionForRole:performBlock:] + 52 9 CoreFoundation 0x294c0 -[CFPrefsPlistSource alreadylocked_requestNewData] + 328 10 CoreFoundation 0x1954d4 _copyValueForKey + 284 11 CoreFoundation 0xff2c -[CFPrefsPlistSource copyValueForKey:] + 60 12 CoreFoundation 0x187e0c __66-[_CFXPreferences copyValueForKey:identifier:user:host:container:]_block_invoke + 44 13 CoreFoundation 0xf4324 -[_CFXPreferences withSourceForIdentifier:user:byHost:container:cloud:perform:] + 844 14 CoreFoundation 0x7560 -[_CFXPreferences copyValueForKey:identifier:user:host:container:] + 212 15 CoreFoundation 0x18b85c _CFPreferencesCopyValueWithContainer + 136 16 ImageIO 0x11f48c + 196 17 ImageIO 0x16fc90 + 28 18 libdispatch.dylib 0x481c _dispatch_client_callout + 20 19 libdispatch.dylib 0x60b4 _dispatch_once_callout + 32 20 ImageIO 0x16fc58 + 112 21 ImageIO 0x172ad0 + 36 22 ImageIO 0xa48f4 + 104 23 ImageIO 0xa9bd0 CGImageSourceCreateWithData + 208 24 mmm 0x2a7fd4 -[FLAnimatedImage initWithAnimatedGIFData:optimalFrameCacheSize:predrawingEnabled:] + 204 (FLAnimatedImage.m:204) 25 mmm 0x2a91a8 +[FLAnimatedImage animatedImageWithGIFData:] + 358 (FLAnimatedImage.m:358) 26 mmm 0x14df48 -[BLProgressHUD initWithTitle:] + 41 (BLProgressHUD.m:41) 27 mmm 0x14e63c __31+[BLProgressHUD showWithTitle:]_block_invoke + 90 (BLProgressHUD.m:90) 28 libdispatch.dylib 0x2a84 _dispatch_call_block_and_release + 32 29 libdispatch.dylib 0x481c _dispatch_client_callout + 20 30 libdispatch.dylib 0x12c70 _dispatch_main_queue_callback_4CF + 884 31 CoreFoundation 0xa3a2c CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE + 16 32 CoreFoundation 0x9d904 __CFRunLoopRun + 2524 33 CoreFoundation 0x9c9f4 CFRunLoopRunSpecific + 600 34 GraphicsServices 0x3734 GSEventRunModal + 164 35 UIKitCore 0xbca75c -[UIApplication _run] + 1072 36 UIKitCore 0xbcffcc UIApplicationMain + 168 37 mmm 0x4a8278 main + 20 (main.m:20) 38 libdyld.dylib 0x1cf8 start + 4

    opened by ChangChangXin 0
  • Single-frame GIF has rendering issues on iOS 14

    Single-frame GIF has rendering issues on iOS 14

    This problem occurs when loading a single-frame GIF, the rest is unclear...

    • didMoveToWindow will be triggered when we switch viewControllers, but self.layer.contents may be nil, causing the FLAnimatedImageView to display blank. I have solved it through hook -didMoveToWindow temporarily. I hope the official can provide the correct solution as soon as possible, please...
    - (void)xxxx_didMoveToWindow
    {
        [self xxxx_didMoveToWindow];
        if (self.window && self.image && ([self.image sd_imageFormat] == SDImageFormatGIF) && self.animatedImage && self.animatedImage.frameCount == 1 && !self.layer.contents) {
            /// Single-frame GIF, which is not displayed when we switch viewControllers, needs to call setNeedsDisplay again to trigger the -displayLayer
            [self.layer setNeedsDisplay];
        }
    }
    

    single_frame_test.gif.zip Sorry for my English...

    opened by zisulu 2
Releases(1.0.17)
  • 1.0.17(Jul 27, 2022)

    What's Changed

    • Fix playback speed issue on 120Hz displays by @pennig in https://github.com/Flipboard/FLAnimatedImage/pull/256

    New Contributors

    • @michafaw made their first contribution in https://github.com/Flipboard/FLAnimatedImage/pull/250
    • @pennig made their first contribution in https://github.com/Flipboard/FLAnimatedImage/pull/256

    Full Changelog: https://github.com/Flipboard/FLAnimatedImage/compare/1.0.16...1.0.17

    Source code(tar.gz)
    Source code(zip)
  • 1.0.16(Jul 27, 2022)

    What's Changed

    • Multiple code improvements (Chaoshuai [Lü] @matrush)
    • Updated Swift Package Manager support to fix unknown header issue by @benniebotha in #249

    New Contributors

    • @benniebotha made their first contribution in https://github.com/Flipboard/FLAnimatedImage/pull/249

    Full Changelog: https://github.com/Flipboard/FLAnimatedImage/compare/1.0.15...1.0.16

    Source code(tar.gz)
    Source code(zip)
  • 1.0.15(Jan 30, 2021)

  • 1.0.14(Sep 25, 2017)

  • 1.0.13(Sep 11, 2017)

  • 1.0.12(Feb 19, 2016)

    • Fix crash triggered by using certain FLAnimatedImageView initializers (Tim Johnsen @timonus)
    • Fix crash when running demo project on device (Tim Johnsen @timonus)
    Source code(tar.gz)
    Source code(zip)
  • 1.0.11(Feb 17, 2016)

    • Allow for run loop mode customization (Ignacio Romero Zurbuchen @dzenbot)
    • Add initialization flags that allow for reduced memory consumption (Tim Johnsen @timonus)
    • Crash fix (Alec Geatches @mopsled)
    Source code(tar.gz)
    Source code(zip)
  • 1.0.10(Dec 12, 2015)

    • Optimize performance by reducing CADisplayLink callbacks (Eric Jensen @ejensen)
    • Make FLAnimatedImage automatically pause when hidden (Daniel Amitay @danielamitay)
    • Decouple FLAnimatedImage from any particular logging solution (Tim Johnsen @timonus)
    Source code(tar.gz)
    Source code(zip)
  • 1.0.9(Dec 1, 2015)

    • Support Carthage (Quanlong He @cybertk, Alexander Grebenyuk @kean)
    • Add loop completion block (Kevin Delannoy @delannoyk)
    • Improve resilience against GIFs with corrupted frames (Tim Johnsen @timonus)
    • Disable image source decoded image caching (Aditya KD @caughtinflux)
    • Update sample project to support iOS 9 TLS (Alexander Grebenyuk @kean)
    • Update sample project to cache remote GIFs (Tim Johnsen @timonus)
    • Turn on -Wundef warning flag (Tim Johnsen @timonus)
    Source code(tar.gz)
    Source code(zip)
Owner
Flipboard
Flipboard
An animated gif & apng engine for iOS in Swift. Have a great performance on memory and cpu usage.

Features Small but complete, only200lines of code. Allow to control display quality, memory usage, loop time and display progress. Have a great perfor

Jiawei Wang 1k Nov 9, 2022
Async GIF image decoder and Image viewer supporting play GIF images. It just use very less memory.

YLGIFImage Asynchronized GIF image class and Image viewer supporting play/stop GIF images. It just use very less memory. Following GIF usually will co

Yong Li 1.8k Aug 15, 2022
SwiftyGif - High performance & easy to use Gif engine

SwiftyGif High performance & easy to use Gif engine Features UIImage and UIImageView extension based Remote GIFs with customizable loader Great CPU/Me

Alexis Creuzot 1.7k Jan 3, 2023
High-performance animated GIF support for iOS in Swift

Gifu adds protocol-based, performance-aware animated GIF support to UIKit. (It's also a prefecture in Japan). Install Swift Package Manager Add the fo

Reda Lemeden 2.8k Jan 4, 2023
Complete Animated GIF Support for iOS, with Functions, NSJSONSerialization-style Class, and (Optional) UIImage Swizzling

AnimatedGIFImageSerialization This library is no longer maintained. In iOS 13+ and macOS 10.15+, use CGAnimateImageAtURLWithBlock instead. AnimatedGIF

Mattt 1.1k Sep 29, 2022
Image framework for iOS to display/encode/decode animated WebP, APNG, GIF, and more.

YYImage Image framework for iOS to display/encode/decode animated WebP, APNG, GIF, and more. (It's a component of YYKit) Features Display/encode/decod

null 1.7k Dec 9, 2022
🌠 A small UIImage extension with gif support

?? A small UIImage extension with gif support

SwiftGif 1.3k Dec 20, 2022
Convert live photos and videos into animated GIFs in iOS, or extract frames from them.

Create a GIF from the provided video file url, Or extract images from videos. This repository has been separated from original repo along with some no

gitmerge 83 May 18, 2022
High performance and delightful way to play with APNG format in iOS.

APNGKit is a high performance framework for loading and displaying APNG images in iOS and macOS. It's built with high-level abstractions and brings a

Wei Wang 2.1k Jan 2, 2023
Test2 - A curated list of Open Source example iOS apps developed in Swift

Example iOS Apps A curated list of Open Source example iOS apps developed in Swi

null 0 Jan 4, 2022
Captcha implementation in ios App

CaptchaDemo_ios A Swift project to showcase implementation of Google ReCaptcha in iOS Application. Features A light weight basic wrapper to handle com

Tanvi jain 1 Feb 7, 2022
iOS implementation of the Catrobat language

Catty Catty, also known as Pocket Code for iOS, is an on-device visual programming system for iPhones. Catrobat is a visual programming language and s

null 74 Dec 25, 2022
Performant animated GIF engine for iOS

FLAnimatedImage is a performant animated GIF engine for iOS: Plays multiple GIFs simultaneously with a playback speed comparable to desktop browsers H

Flipboard 7.8k Dec 29, 2022
XAnimatedImage is a performant animated GIF engine for iOS written in Swift based on FLAnimatedImage

XAnimatedImage is a performant animated GIF engine for iOS written in Swift based on FLAnimatedImage. An illustration is shown below: Features Plays m

Khaled Taha 561 Sep 9, 2022
An animated gif & apng engine for iOS in Swift. Have a great performance on memory and cpu usage.

Features Small but complete, only200lines of code. Allow to control display quality, memory usage, loop time and display progress. Have a great perfor

Jiawei Wang 1k Nov 9, 2022
Async GIF image decoder and Image viewer supporting play GIF images. It just use very less memory.

YLGIFImage Asynchronized GIF image class and Image viewer supporting play/stop GIF images. It just use very less memory. Following GIF usually will co

Yong Li 1.8k Aug 15, 2022
High performance GIF engine

SwiftyGif High performance & easy to use Gif engine Features UIImage and UIImageView extension based Remote GIFs with customizable loader Great CPU/Me

Alexis Creuzot 1.7k Jan 3, 2023
SwiftyGif - High performance & easy to use Gif engine

SwiftyGif High performance & easy to use Gif engine Features UIImage and UIImageView extension based Remote GIFs with customizable loader Great CPU/Me

Alexis Creuzot 1.7k Jan 3, 2023
High-performance animated GIF support for iOS in Swift

Gifu adds protocol-based, performance-aware animated GIF support to UIKit. (It's also a prefecture in Japan). Install Swift Package Manager Add the fo

Reda Lemeden 2.6k Jun 21, 2021
High-performance animated GIF support for iOS in Swift

Gifu adds protocol-based, performance-aware animated GIF support to UIKit. (It's also a prefecture in Japan). Install Swift Package Manager Add the fo

Reda Lemeden 2.8k Jan 4, 2023