title: Creating Gif Image Color Maps in iOS 11
body: <p>I recently was having an issue when creating a Gif where if it got too big colors went missing. However thanks to help from SO someone was able to help me find a work around and create my own color map.</p>
  
  <p>Previous Question here...<a href="https://stackoverflow.com/questions/44960714/ios-colors-incorrect-when-saving-animated-gif">iOS Colors Incorrect When Saving Animated Gif</a></p>
  
  <p>This worked great up until iOS 11. I can't find anything in the docs that changed and would make this no longer work. What I have found is if I remove <code>kCGImagePropertyGIFImageColorMap</code> A gif is generated but it has the original issue where colors go missing if the gif gets to large like my previous question. This makes sense as this was added to fix that issue.</p>
  
  <p>Suspected Issue...</p>
  
  <pre><code>func createGifFromImage(_ image: UIImage) -&gt; URL{
  
      let fileProperties: [CFString: CFDictionary] = [kCGImagePropertyGIFDictionary: [
          kCGImagePropertyGIFHasGlobalColorMap: false as NSNumber] as CFDictionary]
  
      let documentsDirectoryPath = "file://\(NSTemporaryDirectory())"
  
      if let documentsDirectoryURL = URL(string: documentsDirectoryPath){
  
          let fileURL = documentsDirectoryURL.appendingPathComponent("test.gif")
          let destination = CGImageDestinationCreateWithURL(fileURL as CFURL, kUTTypeGIF, 1, nil)!
  
          CGImageDestinationSetProperties(destination, fileProperties as CFDictionary);
  
          let colorMap = image.getColorMap()
          print("ColorMap \(colorMap.exported as NSData)")
  
          let frameProperties: [String: AnyObject] = [
              String(kCGImagePropertyGIFImageColorMap): colorMap.exported as NSData
          ]
  
          let properties: [String: AnyObject] = [
              String(kCGImagePropertyGIFDictionary): frameProperties as AnyObject
          ]
  
          CGImageDestinationAddImage(destination, image.cgImage!, properties as CFDictionary);
  
          if (!CGImageDestinationFinalize(destination)) {
              print("failed to finalize image destination")
          }
  
          return fileURL
      }
  
      //shouldn't get here
      return URL(string: "")!
  }
  </code></pre>
  
  <p>Here is a link to download a test project. Note if you run it on a 10.3 simulator it works great but if you run it on iOS 11 it is a white image.</p>
  
  <p><a href="https://www.dropbox.com/s/hdmkwyz47ondd52/gifTest2.zip?dl=0" rel="noreferrer">https://www.dropbox.com/s/hdmkwyz47ondd52/gifTest2.zip?dl=0</a></p>
  
  <p>Other code that is referenced...</p>
  
  <pre><code>extension UIImage{
      //MARK: - Pixel
      func getColorMap() -&gt; ColorMap {
  
          var colorMap = ColorMap()
  
          let pixelData = self.cgImage!.dataProvider!.data
          let data: UnsafePointer&lt;UInt8&gt; = CFDataGetBytePtr(pixelData)
  
          var byteIndex = 0
  
          for _ in 0 ..&lt; Int(size.height){
              for _ in 0 ..&lt; Int(size.width){
  
                  let color = Color(red: data[byteIndex], green: data[byteIndex + 1], blue: data[byteIndex + 2])
                  colorMap.colors.insert(color)
                  byteIndex += 4
              }
          }
  
          return colorMap
      }
  }
  </code></pre>
  
  <p>ColorMap</p>
  
  <pre><code>struct Color : Hashable {
      let red: UInt8
      let green: UInt8
      let blue: UInt8
  
      var hashValue: Int {
          return Int(red) + Int(green) + Int(blue)
      }
  
      public static func == (lhs: Color, rhs: Color) -&gt; Bool {
          return [lhs.red, lhs.green, lhs.blue] == [rhs.red, rhs.green, rhs.blue]
      }
  }
  
  
  struct ColorMap {
      var colors = Set&lt;Color&gt;()
  
      var exported: Data {
          let data = Array(colors)
              .map { [$0.red, $0.green, $0.blue] }
              .joined()
  
          return Data(bytes: Array(data))
      }
  }
  </code></pre>