Note that there are some explanatory texts on larger screens.

plurals
  1. POCreating an animated GIF in Cocoa - defining frame type
    primarykey
    data
    text
    <p>I've been able to adapt some code found on SO to produce an animated GIF from the "screenshots" of my view, but the results are unpredictable. GIF frames are sometimes full images, full frames ("replace" mode, as GIMP marks it), other times are just a "diff" from previous layer ("combine" mode). </p> <p>From what I've seen, when there are fewer and/or smaller frames involved, the CG writes the GIF in "combine" mode, but failing to get the colors right. Actually, the moving parts are colored correctly, the background is wrong. When CG saves the GIF as full frames, the colors are ok. The file size is larger, but hey, obviously you cannot have the best of both worlds. :) </p> <p>Is there a way to either:</p> <pre><code> a) force CG to create "full frames" when saving the GIF b) fix the colors (color table?) </code></pre> <p>What I do is (ARC mode):</p> <p><strong>capture the visible part of the view with</strong></p> <pre><code>[[scrollView contentView] dataWithPDFInsideRect:[[scrollView contentView] visibleRect]]; </code></pre> <p><strong>convert and resize it to NSImageBitmapRep of PNG type</strong></p> <pre><code>-(NSMutableDictionary*) pngImageProps:(int)quality { NSMutableDictionary *pngImageProps; pngImageProps = [[NSMutableDictionary alloc] init]; [pngImageProps setValue:[NSNumber numberWithBool:NO] forKey:NSImageInterlaced]; double compressionF = 1; [pngImageProps setValue:[NSNumber numberWithFloat:compressionF] forKey:NSImageCompressionFactor]; return pngImageProps; } -(NSData*) resizeImageToData:(NSData*)data toDimX:(int)xdim andDimY:(int)ydim withQuality:(int)quality{ NSImage *image = [[NSImage alloc] initWithData:data]; NSRect inRect = NSZeroRect; inRect.size = [image size]; NSRect outRect = NSMakeRect(0, 0, xdim, ydim); NSImage *outImage = [[NSImage alloc] initWithSize:outRect.size]; [outImage lockFocus]; [image drawInRect:outRect fromRect:inRect operation:NSCompositeCopy fraction:1]; NSBitmapImageRep* bitmapRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:outRect]; [outImage unlockFocus]; NSMutableDictionary *imageProps = [self pngImageProps:quality]; NSData* imageData = [bitmapRep representationUsingType:NSPNGFileType properties:imageProps]; return [imageData copy]; } </code></pre> <p><strong>get the array of BitmapReps and create the GIF</strong></p> <pre><code>-(CGImageRef) pngRepDataToCgImageRef:(NSData*)data { CFDataRef imgData = (__bridge CFDataRef)data; CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData (imgData); CGImageRef image = CGImageCreateWithPNGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault); return image; } ////////// create GIF from NSArray *images; // holds all BitmapReps CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:pot], kUTTypeGIF, allImages, NULL); // set frame delay NSDictionary *frameProperties = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:0.2f] forKey:(NSString *) kCGImagePropertyGIFDelayTime] forKey:(NSString *) kCGImagePropertyGIFDictionary]; // set gif color properties NSMutableDictionary *gifPropsDict = [[NSMutableDictionary alloc] init]; [gifPropsDict setObject:(NSString *)kCGImagePropertyColorModelRGB forKey:(NSString *)kCGImagePropertyColorModel]; [gifPropsDict setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCGImagePropertyGIFHasGlobalColorMap]; // set gif loop NSDictionary *gifProperties = [NSDictionary dictionaryWithObject:gifPropsDict forKey:(NSString *) kCGImagePropertyGIFDictionary]; // loop through frames and add them to GIF for (int i=0; i &lt; [images count]; i++) { NSData *imageData = [images objectAtIndex:i]; CGImageRef imageRef = [self pngRepDataToCgImageRef:imageData]; CGImageDestinationAddImage(destination, imageRef, (__bridge CFDictionaryRef) (frameProperties)); } // save the GIF CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)(gifProperties)); CGImageDestinationFinalize(destination); CFRelease(destination); </code></pre> <p>I've checked the ImageBitmapReps, when saved as PNG individually, they are just fine. As I understood, the color tables should be handled by CG or am I responsible to produce the dithered colors? How to do that?</p> <p>Even when doing the same animation repeatedly, the GIFs produced may vary.</p> <p>This is a single BitmapRep</p> <p><a href="http://andraz.eu/stuff/gif/frame.png" rel="nofollow noreferrer">single frame http://andraz.eu/stuff/gif/frame.png</a></p> <p>And this is the GIF with the invalid colors ("combine" mode) <a href="http://andraz.eu/stuff/gif/anim2.gif" rel="nofollow noreferrer">combined frames http://andraz.eu/stuff/gif/anim2.gif</a></p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload