1

I am exporting an animated gif using swift targeting Mac OS, which works but the properties I've set aren't being applied. I have set up my properties and when I log them they show up like so:

{
HasGlobalColorMap = 1;
LoopCount = 0;
}

In a loop I add each frame to the destination:

CGImageDestinationAddImage(destination, cgGif, gifProperties as CFDictionaryRef)

Then after the loop I attempt to set the properties one more time and finalise the destination:

CGImageDestinationSetProperties(destination, gifProperties as CFDictionaryRef)
            if (!CGImageDestinationFinalize(destination)) {
            NSLog("failed to finalize image destination")
        }

However the resulting image is not set to loop. Why would that be?

Jay
  • 902
  • 2
  • 12
  • 27

1 Answers1

5

Actually, I've made some progress...

I was setting the options like this:

        var imageProperties:NSMutableDictionary = NSMutableDictionary()
    imageProperties.setObject(NSNumber(float: 0.1), forKey: kCGImagePropertyGIFDelayTime as NSString)
    imageProperties.setObject(NSNumber(bool: false), forKey: kCGImagePropertyHasAlpha as NSString)
    imageProperties.setObject(NSString(string: "kUTTypeGIF"), forKey: kCGImageSourceTypeIdentifierHint as NSString)
    imageProperties.setObject(NSNumber(bool: false), forKey: kCGImagePropertyGIFImageColorMap as NSString)
    imageProperties.setObject(NSNumber(bool: true), forKey: kCGImageSourceShouldCache as NSString)
    let nestedImageProperties:NSDictionary = [imageProperties: kCGImagePropertyGIFDictionary]
    println("nestedImageProperties: \(nestedImageProperties)")

Which was giving me this structure:

nestedImageProperties: {
    {
    DelayTime = "0.1";
    HasAlpha = 0;
    ImageColorMap = 0;
    kCGImageSourceShouldCache = 1;
    kCGImageSourceTypeIdentifierHint = kUTTypeGIF;
} = "{GIF}";
}

I found an implementation that defined the properties like this:

let fileProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: 0]]
let frameProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFDelayTime as String: 1.0]]

giving this structure:

Frame Properties: [{GIF}: [DelayTime: 1.0]]
File Properties: [{GIF}: [LoopCount: 0]]

I then applied the fileProperties to the destination:

CGImageDestinationSetProperties(destination, fileProperties as CFDictionaryRef)

and the frameProperties to each images as it was added:

CGImageDestinationAddImage(destination, imageRef, frameProperties as CFDictionaryRef)

and, finally, it's working, they're being applied.

Haven't tried multiple properties yet but should be ok.

theSiberman
  • 441
  • 4
  • 14
  • I didn't realise I had to set different properties for frame and image, TY! If you want to make your multiple properties work, you just need to change the nestedImageProperties declaration to this: let nestedImageProperties = [kCGImagePropertyGIFDictionary as String: imageProperties] that way you get {"{GIF}" = {props} } instead of the other way round, as in the structure you posted. – Jay Mar 25 '15 at 17:07
  • No worries, yes, that is the right way to declare a key:value in a dictionary ;) Sometime i miss the blazingly obvious, cheers. – theSiberman Mar 25 '15 at 21:19