Reputation: 515
I am trying to limit the number of colors of an animated GIF (created from an array of CGImageRef
).
However, I am have difficulty actually setting the custom color table. Does anyone know how to do this with Core Graphics?
I know of kCGImagePropertyGIFImageColorMap
. Below is some test code (borrowing heavily from this github gist -- since it's the only instance of kCGImagePropertyGIFImageColorMap
Google could find).
NSString *path = [@"~/Desktop/test.png" stringByExpandingTildeInPath];
CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData((CFDataRef)[NSData dataWithContentsOfFile:path]);
CGImageRef image = CGImageCreateWithPNGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault);
const uint8_t colorTable[ 8 ] = { 0, 0, 0, 0, 255, 255, 255 , 255};
NSData* colorTableData = [ NSData dataWithBytes: colorTable length: 8 ];
NSMutableDictionary *gifProps = [NSMutableDictionary dictionary];
[gifProps setObject:colorTableData forKey:(NSString *)kCGImagePropertyGIFImageColorMap];
[gifProps setObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCGImagePropertyGIFHasGlobalColorMap];
NSDictionary* imgProps = [ NSDictionary dictionaryWithObject: gifProps
forKey: (NSString*) kCGImagePropertyGIFDictionary ];
NSURL* destUrl = [NSURL fileURLWithPath:[@"~/Desktop/test.gif" stringByExpandingTildeInPath]];
CGImageDestinationRef dst = CGImageDestinationCreateWithURL( (CFURLRef) destUrl, kUTTypeGIF, 1, NULL );
CGImageDestinationAddImage( dst, image, imgProps );
CGImageDestinationSetProperties(dst, (CFDictionaryRef) imgProps);
CGImageDestinationFinalize( dst );
CFRelease( dst );
This, however, does not produce a black & white image.
Furthermore, I've tried opening a GIF to find the color table information, but that's providing little help.
CGImageSourceRef imageSourceRef = CGImageSourceCreateWithURL((CFURLRef) destUrl, NULL);
NSDictionary *dict = (NSDictionary *)CGImageSourceCopyPropertiesAtIndex(imageSourceRef,0, NULL);
CGImageRef img = CGImageSourceCreateImageAtIndex(imageSourceRef, 0, NULL);
printf("Color space model: %d, indexed=%d, rgb = %d\n", CGColorSpaceGetModel(CGImageGetColorSpace(img)), kCGColorSpaceModelIndexed,kCGColorSpaceModelRGB);
NSLog(@"%@", dict);
It says the color space is RGB for GIFs. Yet, if I try that code with an indexed PNG, it says the color space is indexed.
Furthermore, all the GIFs I've tried have a image dictionary that looks roughly like the following:
{
ColorModel = RGB;
Depth = 8;
HasAlpha = 1;
PixelHeight = 176;
PixelWidth = 314;
"{GIF}" = {
DelayTime = "0.1";
UnclampedDelayTime = "0.04";
};
}
(If I use CGImageSourceCopyProperties(...)
, it mentions a global color map, but again no color table is provided.)
Upvotes: 7
Views: 2469
Reputation: 41
I didn't run your code, but from reading it I saw one mistake: The color space in gif is rgb
, so your color map should have numcolors*3
items (in stead of *4
). IOS doesn't deal gracefully with color maps whose size is not a multiple of 3...
In other words:
const uint8_t colorTable[ 6 ] = { 0, 0, 0, 255, 255 , 255};
NSData* colorTableData = [ NSData dataWithBytes: colorTable length:6];
should do the job.
Upvotes: 2