1

My gif generator function reduces the resolution and minimizes the frames from a series of photos, but I don't have anything to reduce the amount of colors or make it lossy. How would I go about doing this in Swift 4?

    func generateGif(photos: [UIImage], filename: String) -> Bool {

        let documentsDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        let path = documentsDirectoryPath.appending(filename)
        let fileProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: 0]]
        let gifProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFDelayTime as String: 0.1]] // actual speed is 0.2
        let cfURL = URL(fileURLWithPath: path) as CFURL
        if let destination = CGImageDestinationCreateWithURL(cfURL, kUTTypeGIF, photos.count, nil) {

            CGImageDestinationSetProperties(destination, fileProperties as CFDictionary?)

            var inc:Int = 0

            for _ in 0..<15 { // actual photos.count is 31

                let photo = photos[inc]

                var width:CGFloat = photo.size.width
                var height:CGFloat = photo.size.height

                let maxWidthHeight:CGFloat = 500

                if(photo.size.width > maxWidthHeight || photo.size.height > maxWidthHeight){ // gif beyond max width or height

                    if(photo.size.width > photo.size.height){

                        width = maxWidthHeight

                        let percentChange = width / photo.size.width
                        height = photo.size.height * percentChange

                    }else{

                        height = maxWidthHeight

                        let percentChange = height / photo.size.height
                        width = photo.size.width * percentChange

                    }

                    print("w:\(width) h:\(height) inc:\(inc)")

                }

                let smallerPhoto = imageWithImage(image:photo, scaledToSize:CGSize(width:width, height:height))
                CGImageDestinationAddImage(destination, smallerPhoto.cgImage!, gifProperties as CFDictionary?)

                inc+=2 // skipping ahead incrementation for less frames
            }

// here it's saving to a photo album when it's done and reporting the filesize
            CustomPhotoAlbum.sharedInstance.savePhoto(URL: URL(fileURLWithPath: path), completion: {

                var fileSize : UInt64

                do {
                    let attr = try FileManager.default.attributesOfItem(atPath: path)
                    fileSize = attr[FileAttributeKey.size] as! UInt64
                    print("gif is \(fileSize/1000000) megabytes")
                } catch {
                    print("Error: \(error)")
                }

            })

            return CGImageDestinationFinalize(destination)
        }


        return false
    }

Anything above 500 width or height returns a file that is around 11 megabytes. I imagine it could be far smaller.

Chewie The Chorkie
  • 4,896
  • 9
  • 46
  • 90
  • Usually a photo is better represented as a jpg and line art, solid colors as a gif, JPEG has differing levels of compression. - some informational here https://stackoverflow.com/questions/2336522/png-vs-gif-vs-jpeg-vs-svg-when-best-to-use That being said, IS animation required? Or is it just "transition". – Mark Schultheiss Jan 29 '18 at 20:29
  • That being said, put in "compress gif in swift 4 site:stackoverflow.com" in your favorite search engine and see a lot of similar questions, perhaps one of these will assist you? – Mark Schultheiss Jan 29 '18 at 20:44
  • Mark, I'm cycling offsets of a pixel's current color. There's really nothing much out there that I can find about compressing gifs in Swift 4. In fact, if I search "compress gif swift" in Stack Overflow, the result for this current question is the only relevant one of the three. That's why I ask here. – Chewie The Chorkie Jan 29 '18 at 21:04
  • And yes, animation is required. – Chewie The Chorkie Jan 30 '18 at 15:42
  • https://www.google.com/search?q=compress+gif+in+swift+site%3Astackoverflow.com&ie=utf-8&oe=utf-8&client=firefox-b-ab I get around 3600 results, your mileage may vary – Mark Schultheiss Jan 30 '18 at 22:41
  • My results don't really have to do with compressing gifs in Swift at all. I see stuff for animating, png compression, jpeg compression, etc. It's sad that there seems to be no common function in Swift to reduce the color indices. I guess I'll just answer this myself when I figure it out. – Chewie The Chorkie Jan 31 '18 at 16:49

1 Answers1

1

Check out giflossy based ongifsicle on github. It does exactly what you want and more. It’s in C but you can get some inspiration from there and port the relevant parts to swift.

Manuel
  • 14,274
  • 6
  • 57
  • 130