4

SO で見つかったいくつかのコードを適応させて、ビューの「スクリーンショット」からアニメーション GIF を生成することができましたが、結果は予測できません。GIF フレームは、完全な画像、完全なフレーム (GIMP がマークする「置換」モード) である場合もあれば、前のレイヤーからの単なる「差分」(「結合」モード) である場合もあります。

私が見たところ、含まれるフレームが少ない、または小さい場合、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]];

PNGタイプのNSImageBitmapRepに変換してサイズ変更します

-(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 です

単一フレーム
(出典: andraz.eu )

そして、これは無効な色を含む GIF (「結合」モード) (出典: andraz.eu )結合されたフレーム

4

1 に答える 1

2

私はあなたのコードを読みました。CGImageDestinationRef の作成中に「allImages」と「[images count]」を再確認してください。

次のテスト コードは正常に動作します。

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);
于 2013-04-10T23:12:10.083 に答える