فهرست منبع

Fix decoding for single frame GIF

onevcat 10 سال پیش
والد
کامیت
3592e84255

+ 8 - 0
Kingfisher.xcodeproj/project.pbxproj

@@ -113,6 +113,9 @@
 		D13F49EA1BEDA82000CE335D /* Kingfisher.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D13F49D61BEDA67C00CE335D /* Kingfisher.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
 		D1679A461C4E78B20020FD12 /* Kingfisher-watchOS-Demo Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D1679A451C4E78B20020FD12 /* Kingfisher-watchOS-Demo Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
 		D1679A531C4E78B20020FD12 /* Kingfisher-watchOS-Demo.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = D1679A391C4E78B20020FD12 /* Kingfisher-watchOS-Demo.app */; };
+		D1D2C32A1C70A3230018F2F9 /* single-frame.gif in Resources */ = {isa = PBXBuildFile; fileRef = D1D2C3291C70A3230018F2F9 /* single-frame.gif */; };
+		D1D2C32B1C70A3230018F2F9 /* single-frame.gif in Resources */ = {isa = PBXBuildFile; fileRef = D1D2C3291C70A3230018F2F9 /* single-frame.gif */; };
+		D1D2C32C1C70A3230018F2F9 /* single-frame.gif in Resources */ = {isa = PBXBuildFile; fileRef = D1D2C3291C70A3230018F2F9 /* single-frame.gif */; };
 		D1ED2D401AD2D09F00CFC3EB /* Kingfisher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1ED2D351AD2D09F00CFC3EB /* Kingfisher.framework */; };
 		D1ED2D4C1AD2D09F00CFC3EB /* Kingfisher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1ED2D351AD2D09F00CFC3EB /* Kingfisher.framework */; };
 		D1ED2D4D1AD2D09F00CFC3EB /* Kingfisher.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D1ED2D351AD2D09F00CFC3EB /* Kingfisher.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -306,6 +309,7 @@
 		D16799EB1C4E74460020FD12 /* Kingfisher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Kingfisher.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		D1679A391C4E78B20020FD12 /* Kingfisher-watchOS-Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Kingfisher-watchOS-Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		D1679A451C4E78B20020FD12 /* Kingfisher-watchOS-Demo Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Kingfisher-watchOS-Demo Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
+		D1D2C3291C70A3230018F2F9 /* single-frame.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "single-frame.gif"; sourceTree = "<group>"; };
 		D1ED2D0B1AD2CFA600CFC3EB /* Kingfisher-Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Kingfisher-Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		D1ED2D351AD2D09F00CFC3EB /* Kingfisher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Kingfisher.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		D1ED2D3F1AD2D09F00CFC3EB /* KingfisherTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KingfisherTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -467,6 +471,7 @@
 			children = (
 				D12E0C491C47F23500AC98AD /* Info.plist */,
 				D12E0C441C47F23500AC98AD /* dancing-banana.gif */,
+				D1D2C3291C70A3230018F2F9 /* single-frame.gif */,
 				D12E0C451C47F23500AC98AD /* ImageCacheTests.swift */,
 				D12E0C461C47F23500AC98AD /* ImageDownloaderTests.swift */,
 				D12E0C471C47F23500AC98AD /* ImageExtensionTests.swift */,
@@ -975,6 +980,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				D1D2C32B1C70A3230018F2F9 /* single-frame.gif in Resources */,
 				D12E0C751C47F70600AC98AD /* dancing-banana.gif in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -983,6 +989,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				D1D2C32C1C70A3230018F2F9 /* single-frame.gif in Resources */,
 				D12E0C8A1C47F7C000AC98AD /* dancing-banana.gif in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -1048,6 +1055,7 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				D1D2C32A1C70A3230018F2F9 /* single-frame.gif in Resources */,
 				D12E0C4F1C47F23500AC98AD /* dancing-banana.gif in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

+ 14 - 12
Sources/Image.swift

@@ -214,17 +214,23 @@ extension Image {
                 return nil
             }
             
-            guard let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, i, nil),
-                gifInfo = (properties as NSDictionary)[kCGImagePropertyGIFDictionary as String] as? NSDictionary,
-                frameDuration = (gifInfo[kCGImagePropertyGIFDelayTime as String] as? NSNumber) else
-            {
-                return nil
+            if frameCount == 1 {
+                // Single frame
+                gifDuration = Double.infinity
+            } else {
+                // Animated GIF
+                guard let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, i, nil),
+                    gifInfo = (properties as NSDictionary)[kCGImagePropertyGIFDictionary as String] as? NSDictionary,
+                    frameDuration = (gifInfo[kCGImagePropertyGIFDelayTime as String] as? NSNumber) else
+                {
+                    return nil
+                }
+                gifDuration += frameDuration.doubleValue
             }
             
-            gifDuration += frameDuration.doubleValue
             images.append(Image.kf_imageWithCGImage(imageRef, scale: scale, refImage: nil))
         }
-        
+         
 #if os(OSX)
         if let image = Image(data: data) {
             image.kf_images = images
@@ -233,11 +239,7 @@ extension Image {
         }
         return nil
 #else
-        if frameCount == 1 {
-            return images.first
-        } else {
-            return Image.kf_animatedImageWithImages(images, duration: duration <= 0.0 ? gifDuration : duration)
-        }
+        return Image.kf_animatedImageWithImages(images, duration: duration <= 0.0 ? gifDuration : duration)
 #endif
     }
 }

+ 8 - 0
Tests/KingfisherTests/ImageExtensionTests.swift

@@ -74,4 +74,12 @@ class ImageExtensionTests: XCTestCase {
         XCTAssertEqual(image1.kf_duration, image.kf_duration)
         XCTAssertEqual(image1.kf_images!.count, image.kf_images!.count)
     }
+    
+    func testGenerateSingleFrameGIFImage() {
+        let image = Image.kf_animatedImageWithGIFData(gifData: testImageSingleFrameGIFData)
+        XCTAssertNotNil(image, "The image should be initiated.")
+        XCTAssertEqual(image!.kf_images!.count, 1, "There should be 8 frames.")
+        
+        XCTAssertEqual(image!.kf_duration, Double.infinity, "The image duration should be 0 since it is not animated image.")
+    }
 }

+ 2 - 2
Tests/KingfisherTests/KingfisherTestHelper.swift

@@ -37,8 +37,8 @@ let testImageData = NSData(base64EncodedString:testImageString, options: NSDataB
 
 let testImagePNGData = ImagePNGRepresentation(testImage)!
 let testImageJEPGData = ImageJPEGRepresentation(testImage, 1.0)!
-
-var testImageGIFData = NSData(contentsOfFile: NSBundle(forClass: ImageExtensionTests.self).pathForResource("dancing-banana", ofType: "gif")!)!
+let testImageGIFData = NSData(contentsOfFile: NSBundle(forClass: ImageExtensionTests.self).pathForResource("dancing-banana", ofType: "gif")!)!
+let testImageSingleFrameGIFData = NSData(contentsOfFile: NSBundle(forClass: ImageExtensionTests.self).pathForResource("single-frame", ofType: "gif")!)!
 
 let testKeys = ["http://stackoverflow.com/questions/11251340/convert-image-to-base64-string-in-ios-swift","https://onevcat.com","http://onevcat.com/content/images/2014/May/200.jpg","http://onevcat.com/content/images/2014/May/200.jpg?fads#kj1asf"]
 

BIN
Tests/KingfisherTests/single-frame.gif