matthewpalmer / Regift

Easily convert a video to a GIF on iOS.
MIT License
526 stars 80 forks source link

How to add properties to change compression quality, image dimensions, etc? #20

Closed JessicaYeh closed 9 years ago

JessicaYeh commented 9 years ago

How do I modify

let fileProperties = [kCGImagePropertyGIFDictionary as String:
    [
        kCGImagePropertyGIFLoopCount as String: loopCount
    ]]

let frameProperties = [kCGImagePropertyGIFDictionary as String:
    [
        kCGImagePropertyGIFDelayTime as String: delayTime
    ]]

in the createGif() function in the library to change the compression quality, image dimensions, and other things? I'm trying to make the GIF a smaller file size without sacrificing frames per second (I'm able to change the number of frames that gets put into the GIF to make the file smaller but then it looks really bad).

I looked in the documentation and there are several properties that can be applied: https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGImageDestination/#//apple_ref/doc/constant_group/Destination_Properties

https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGImageProperties_Reference/index.html#//apple_ref/doc/uid/TP40005103

But I tried applying some of them by doing the following:

let frameProperties = [
    kCGImageDestinationLossyCompressionQuality as String: 0.5,
    kCGImagePropertyGIFDictionary as String:
    [
        kCGImagePropertyGIFDelayTime as String: delayTime
    ]]

And it appears to have no effect. I compare the file size without that property and with that property, and they are the same.

Am I not applying the property correctly?

Related StackOverflow question that I posted: http://stackoverflow.com/questions/33050909/how-to-use-kcgimagedestinationlossycompressionquality-in-saving-gif-from-video

matthewpalmer commented 9 years ago

Answered the question on stackoverflow (thanks for posting it up there—much preferred!). Another thing that I don't think will work but is worth a shot is moving the kCGImageDestinationLossyCompressionQuality as String: 0.5 inside the kCGImagePropertyGIFDictionary.

JessicaYeh commented 9 years ago

Thanks for the quick response! That's very unfortunate. Just tried putting it inside the gif dictionary and it didn't work either. Going to try other methods of resizing (either resize the video or resize each frame that gets added to the GIF) and see if it works.

JessicaYeh commented 9 years ago

Success! I Googled for a function to resize a CGImage (http://fingertwister.tumblr.com/post/9074775714/code-to-create-a-resized-cgimage-from-a-cgimage) and then converted it to swift:

func resizeCGImage(image: CGImageRef, width: Int, height: Int) -> CGImageRef! {

    // create context, keeping original image properties
    let context = CGBitmapContextCreate(nil, width, height, CGImageGetBitsPerComponent(image), CGImageGetBytesPerRow(image), CGImageGetColorSpace(image), CGImageGetAlphaInfo(image).rawValue)
    if (context == nil) {
        return nil
    }

    // draw image to context (resizing it)
    CGContextDrawImage(context, CGRectMake(0.0, 0.0, CGFloat(width), CGFloat(height)), image)

    // extract resulting image from context
    return CGBitmapContextCreateImage(context)
}

and then tried it out by modifying the part in the code that uses CGImageDestinationAddImage and hardcoded a scale factor of half, so now the code says:

let imageRef = try generator.copyCGImageAtTime(time, actualTime: nil)
let width = CGImageGetWidth(imageRef)
let height = CGImageGetHeight(imageRef)
let resizedImageRef = resizeCGImage(imageRef, width: width/2, height: height/2)
CGImageDestinationAddImage(destination, resizedImageRef, frameProperties as CFDictionaryRef)

And the result was just as expected, the GIF dimensions were halved and the file size dropped from 8MB to 2.5MB. The performance also doesn't appear to be adversely affected.

I think the ability to configure the output GIF's dimensions would be a pretty good addition to this library. Very nice job with this library by the way, I find it very useful.

matthewpalmer commented 9 years ago

Awesome!

Yeah that'd be a sweet addition. Feel free to open a PR if you like :). As long as it has test coverage I'd be happy to merge it into master.

Will close this issue, but feel free to reopen at any stage 👍

z-br commented 6 years ago

Did anything like this get merged? Would to be able to control output sizing. For now, I think I'm going to work on resizing the input video.