2013-03-23 2 views
4

Я смог адаптировать некоторый код, найденный на SO, для создания анимированного GIF из «скриншотов» моего представления, но результаты непредсказуемы. Кадры GIF иногда представляют собой полные изображения, полные кадры (режим «заменить», как отмечает GIMP), в других случаях это просто «diff» из предыдущего слоя (режим «комбинировать»).Создание анимированного GIF в какао - определение типа кадра

Из того, что я видел, когда задействовано меньшее количество кадров и/или меньше, 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

single frame http://andraz.eu/stuff/gif/frame.png

И это GIF недостоверными цветов (режим "объединить") combined frames http://andraz.eu/stuff/gif/anim2.gif

ответ

2

Я прочитал ваш код. Если вы создаете CGImageDestinationRef и «[images count]», дважды проверьте «allImages».

последующий тестовый код работает отлично:

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); 
+0

Да, есть немного пропущенный код, я вижу его сейчас. allImages = [количество изображений]; и - (CGImageRef) pngRepDataToCgImageRef: (NSData *) Данные { CFDataRef imgData = (__bridge CFDataRef) данных; CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData (imgData); CGImageRef image = CGImageCreateWithPNGDataProvider (imgDataProvider, NULL, true, kCGRenderingIntentDefault); Обратное изображение; } У меня есть массив NSImageBitmapRep-s, и пока существует достаточно кадров или они достаточно большие, все работает нормально. Я рассмотрю еще кое-что. – Andraz

+0

Привет, Вы когда-нибудь получить эту работу, у меня аналогичная проблема с не все цвета, фигурирующих в выводимого Gif ... – Chris

+0

да, это работает. подтверждено. –