如何访问动画GIF的帧

时间:2013-06-18 05:56:13

标签: objective-c macos cocoa core-graphics core-image

我已成功将动画GIF加载到NSDataNSBitmapImageRep对象中。 Reference for NSBitmapImageRep

我已经想过如何使用以下命令返回数据,例如gif中的帧数:

NSNumber *frames = [bitmapRep valueForProperty:@"NSImageFrameCount"];

但是,我对如何实际访问该帧作为自己的对象感到有点困惑。

我认为这两种方法中的一种会有所帮助,但我不确定他们会如何为我提供个性化的框架。

+ representationOfImageRepsInArray:usingType:properties:
– representationUsingType:properties:

任何帮助表示赞赏。感谢

3 个答案:

答案 0 :(得分:6)

  

我已经想过如何使用以下命令返回数据,例如gif中的帧数:

NSNumber *frames = [bitmapRep valueForProperty:@"NSImageFrameCount"];
     

但是,我对如何实际访问该帧作为自己的对象感到有点困惑。

要访问特殊框架indexOfFrame0 <= indexOfFrame < [frames intValue]),您只需设置NSImageCurrentFrame即可完成。无需使用CG功能或制作帧的副本。你可以留在面向对象的Cocoa世界。一个小例子显示了所有GIF帧的持续时间:

NSNumber *frames = [bitmapRep valueForProperty:@"NSImageFrameCount"];
if( frames!=nil ){   // bitmapRep is a Gif imageRep
   for( NSUInteger i=0; i<[frames intValue]; i++ ){
      [bitmapRep setProperty:NSImageCurrentFrame
                   withValue:[NSNumber numberWithUnsignedInt:i] ];
       NSLog(@"%2d duration=%@",
                 i, [bitmapRep valueForProperty:NSImageCurrentFrameDuration] );
   }
}

另一个例子:将GIF图像的所有帧作为PNG文件写入文件系统:

NSNumber *frames = [bitmapRep valueForProperty:@"NSImageFrameCount"];
if( frames!=nil ){   // bitmapRep is a Gif imageRep
   for( NSUInteger i=0; i<[frames intValue]; i++ ){
      [bitmapRep setProperty:NSImageCurrentFrame
                   withValue:[NSNumber numberWithUnsignedInt:i] ];
       NSData *repData = [bitmapRep representationUsingType:NSPNGFileType
                                                 properties:nil];
       [repData writeToFile:
            [NSString stringWithFormat:@"/tmp/gif_%02d.png", i ] atomically:YES];
    }
}

答案 1 :(得分:2)

  

我已经想过如何使用以下命令返回数据,例如gif中的帧数:

NSNumber *frames = [bitmapRep valueForProperty:@"NSImageFrameCount"];
     

但是,我对如何实际访问该帧作为自己的对象感到有点困惑。

据我所知,你不能来自NSBitmapImageRep。

相反,从GIF数据创建CGImageSource,并使用CGImageSourceCreateImageAtIndex提取每个帧(最好是根据需要)。

或者,您可以尝试setting NSImageCurrentFrame属性。如果您需要每个帧的代表,请创建与有帧一样多的副本(减去一个,因为您有原始帧),并将每个代表的当前帧设置为不同的数字。但我没有尝试过,所以我不确定它是否真的有用。

基本上,NSBitmapImageRep的GIF支持很奇怪,所以你应该只使用CGImageSource。

  

我认为这两种方法中的一种会有所帮助,但我不确定他们会如何为我提供个性化的框架。

+ representationOfImageRepsInArray:usingType:properties:
– representationUsingType:properties:

不,这些方法用于序列化图像(或图像代表)。它们用于写入数据,而不是读取数据。(注意这些方法在type参数中期望的常量。)

答案 2 :(得分:1)

如果你想查看iOS的GIF解码器的一些工作源代码(也适用于MacOSX),那么你可以找到它AVGIF89A2MvidResourceLoader.m at github。方法是使用ImageIO框架并调用CGImageSourceCreateWithData()以及CGImageSourceCreateImageAtIndex()来访问文件中的第N个gif图像。但是,有一些棘手的细节涉及检测GIF中是否出现透明像素以及如何将结果写入文件以避免在GIF非常长而可能不明显的情况下耗尽内存。