【问题标题】:Convert Gif image to NSData将 Gif 图像转换为 NSData
【发布时间】:2013-05-20 20:16:58
【问题描述】:

我的相册中有一张 gif 图像。当我使用UIImagePickerController 选择该图像时,我需要将图像转换为NSData 进行存储。

之前我用过

NSData *thumbData = UIImageJPEGRepresentation(thumbnail, 0.5);

但它不适用于 gif 图像。 thumbData 将为零。

  1. 如何从 gif 图像中获取 NSData

  2. 我怎么知道是gif图片需要特殊处理?

【问题讨论】:

  • 你是否也使用了 UIImagePNGRepresentation(thumbnail); ?
  • 看看这个link。可能对你有帮助。
  • 您的问题解决了吗?

标签: ios nsdata gif


【解决方案1】:

这里的关键是将 GIF 文件或 URL 下载直接保存到 NSData 中,而不是使其成为 UIImage。绕过 UIImage 会让 GIF 文件保留动画。

下面是一些将 GIF 文件转换为 NSData 的代码:

NSString *filePath = [[NSBundle mainBundle] pathForResource: @"gifFileName" ofType: @"gif"];

NSData *gifData = [NSData dataWithContentsOfFile: filePath];

但老实说,您真的应该考虑完全不使用 GIF。

【讨论】:

    【解决方案2】:

    斯威夫特

    Gif 必须在资产中。

    let path = Bundle.main.path(forResource: "loader", ofType: "gif")!
    let data = try! Data(contentsOf: URL(fileURLWithPath: path))
    return data
    

    【讨论】:

      【解决方案3】:

      https://github.com/mattt/AnimatedGIFImageSerialization

      UIImage *image = ...;
      NSData *data = [AnimatedGIFImageSerialization animatedGIFDataWithImage:image
                                                                    duration:1.0
                                                                   loopCount:1
                                                                       error:nil];
      

      【讨论】:

        【解决方案4】:

        转换 .GIF 文件的代码可以在 NSdata 中转换 -

        NSString *pathForFile = [[NSBundle mainBundle] pathForResource: @"myGif" ofType: @"gif"];
        
        NSData *dataOfGif = [NSData dataWithContentsOfFile: pathForFile];
        
        NSLog(@"Data: %@", dataOfGif);
        

        【讨论】:

          【解决方案5】:
          1. 那些正在寻找这个问题的快速答案的人,这里有一个 UIImage 的扩展来完成这项工作。
          import UIKit
          import MobileCoreServices
          
          extension UIImage {
              func UIImageAnimatedGIFRepresentation(gifDuration: TimeInterval = 0.0, loopCount: Int = 0) throws -> Data {
                  let images = self.images ?? [self]
                  let frameCount = images.count
                  let frameDuration: TimeInterval = gifDuration <= 0.0 ? self.duration / Double(frameCount) : gifDuration / Double(frameCount)
                  let frameDelayCentiseconds = Int(lrint(frameDuration * 100))
                  let frameProperties = [
                      kCGImagePropertyGIFDictionary: [
                          kCGImagePropertyGIFDelayTime: NSNumber(value: frameDelayCentiseconds)
                      ]
                  ]
          
                  guard let mutableData = CFDataCreateMutable(nil, 0),
                     let destination = CGImageDestinationCreateWithData(mutableData, kUTTypeGIF, frameCount, nil) else {
                      throw NSError(domain: "AnimatedGIFSerializationErrorDomain",
                                    code: -1,
                                    userInfo: [NSLocalizedDescriptionKey: "Could not create destination with data."])
                  }
                  let imageProperties = [
                      kCGImagePropertyGIFDictionary: [kCGImagePropertyGIFLoopCount: NSNumber(value: loopCount)]
                  ] as CFDictionary
                  CGImageDestinationSetProperties(destination, imageProperties)
                  for image in images {
                      if let cgimage = image.cgImage {
                          CGImageDestinationAddImage(destination, cgimage, frameProperties as CFDictionary)
                      }
                  }
          
                  let success = CGImageDestinationFinalize(destination)
                  if !success {
                      throw NSError(domain: "AnimatedGIFSerializationErrorDomain",
                                    code: -2,
                                    userInfo: [NSLocalizedDescriptionKey: "Could not finalize image destination"])
                  }
                  return mutableData as Data
              }
          }
          
          1. 虽然上述扩展可以完成这项工作,但从图像选择器处理 gif 更为简单,下面是 UIImagePickerControllerDelegate 函数中的实现。
          func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
              let info = Dictionary(uniqueKeysWithValues: info.map {key, value in (key.rawValue, value)})
              if let url = info[UIImagePickerController.InfoKey.referenceURL.rawValue] as? URL, url.pathExtension.lowercased() == "gif" {
                 picker.dismiss(animated: false, completion: nil)
                 url.getGifImageDataFromAssetUrl(completion: { imageData in
                     // Use imageData here.
                 })
                 return
              }
          }
          

          在 URL 中使用扩展功能

          import UIKit
          import Photos
          
          extension URL {
              func getGifImageDataFromAssetUrl(completion: @escaping(_ imageData: Data?) -> Void) {
                  let asset = PHAsset.fetchAssets(withALAssetURLs: [self], options: nil)
                  if let image = asset.firstObject {
                      PHImageManager.default().requestImageData(for: image, options: nil) { (imageData, _, _, _) in
                          completion(imageData)
                      }
                  }
              }
          }
          

          【讨论】:

          • 给出太慢的 gif 动画,我尝试了不同的组合但不起作用。
          • 您确定Data -&gt; UIImage 转换没有限制延迟时间吗?根据一些消息来源,任何持续时间小于 0.05 的帧都将被限制为 0.1
          • 我怎样才能确定呢?你能指导一下吗?我玩了“frameDelayCentiseconds”变量。但没什么,结果几乎一样
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-04-17
          • 2017-03-30
          • 1970-01-01
          • 2014-07-23
          • 1970-01-01
          • 2011-02-01
          • 1970-01-01
          相关资源
          最近更新 更多