Создание анимированного GIF в Какао - определение типа кадра
Мне удалось адаптировать некоторый код, найденный в SO, для создания анимированного GIF из "скриншотов" моего взгляда, но результаты непредсказуемы. Кадры GIF иногда представляют собой полные изображения, полные кадры (режим "заменить", как отмечает GIMP), в других случаях это просто "diff" от предыдущего слоя (режим "объединение").
Из того, что я видел, когда задействовано меньше и / или меньших кадров, CG записывает GIF в режиме "объединения", но не может получить правильные цвета. На самом деле, движущиеся части окрашены правильно, фон неправильный. Когда CG сохраняет GIF как полные кадры, цвета в порядке. Размер файла больше, но эй, очевидно, вы не можете иметь лучшее из обоих миров.:)
Есть ли способ либо:
a) force CG to create "full frames" when saving the GIF
b) fix the colors (color table?)
Что я делаю (режим ARC):
захватить видимую часть вида с
[[scrollView contentView] dataWithPDFInsideRect:[[scrollView contentView] visibleRect]];
преобразовать и изменить его размер до NSImageBitmapRep типа PNG
-(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];
}
получить массив BitmapReps и создать GIF
-(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 < [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);
Я проверил ImageBitmapReps, когда они сохраняются как PNG по отдельности, они просто отлично. Как я понял, таблицы цветов должны обрабатываться CG или я несу ответственность за создание размытых цветов? Как это сделать?
Даже при многократном выполнении одной и той же анимации создаваемые GIF-изображения могут отличаться.
Это один BitmapRep
http://andraz.eu/stuff/gif/frame.png
И это GIF с недопустимыми цветами (режим "совмещение") http://andraz.eu/stuff/gif/anim2.gif
1 ответ
Я прочитал твой код. Пожалуйста, дважды проверьте "allImages" во время создания CGImageDestinationRef и "[количество изображений]".
следующий тестовый код работает нормально:
NSDictionary *prep = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:0.2f] forKey:(NSString *) kCGImagePropertyGIFDelayTime] forKey:(NSString *) kCGImagePropertyGIFDictionary];
CGImageDestinationRef dst = CGImageDestinationCreateWithURL((__bridge CFURLRef)(fileURL), kUTTypeGIF, [filesArray count], nil);
for (int i=0;i<[filesArray count];i++)
{
//load anImage from array
...
CGImageRef imageRef=[anImage CGImageForProposedRect:nil context:nil hints:nil];
CGImageDestinationAddImage(dst, imageRef,(__bridge CFDictionaryRef)(prep));
}
bool fileSave = CGImageDestinationFinalize(dst);
CFRelease(dst);