2

あるフォーマットから別のフォーマットへの RAW 変換が可能であることを証明するプロトタイプを作成しようとしています。ニコンの .NEF 形式の RAW ファイルをキャノンの .CR2 形式に変換する必要があります。さまざまな投稿の助けを借りて、元の画像 TIFF 表現の BitmapImageRep を作成し、これを使用して .CR2 拡張子を持つ出力ファイルを書き込みます。

それは機能しますが、私にとって唯一の問題は、入力ファイルが 21.5 MB であるのに、取得している出力が 144.4 MB であることです。使用中NSTIFFCompressionPackBitsに142.1 MBが得られます。

何が起こっているのかを理解したいのですが、利用可能なさまざまな圧縮列挙型を試しましたが、成功しませんでした。

それを理解するのを手伝ってください。これはソースコードです:

@interface NSImage(RawConversion)
- (void) saveAsCR2WithName:(NSString*) fileName;
@end

@implementation NSImage(RawConversion)
- (void) saveAsCR2WithName:(NSString*) fileName
{
    // Cache the reduced image
    NSData *imageData = [self TIFFRepresentation];
    NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
//    http://www.cocoabuilder.com/archive/cocoa/151789-nsbitmapimagerep-compressed-tiff-large-files.html
    NSDictionary *imageProps = [NSDictionary dictionaryWithObjectsAndKeys:  [NSNumber numberWithInt:NSTIFFCompressionJPEG],NSImageCompressionMethod,
                                                                            [NSNumber numberWithFloat: 1.0], NSImageCompressionFactor,
                                                                            nil];
    imageData = [imageRep representationUsingType:NSTIFFFileType properties:imageProps];
    [imageData writeToFile:fileName atomically:NO];
}
@end

CR2 形式の出力ファイルを取得するにはどうすればよいでしょうか。入力ファイルのサイズとほぼ同じで、CR2 ファイルに必要なバリエーションはほとんどありません。

編集 1:メソッド を使用するという Peter の提案に基づいて変更を行いましCGImageDestinationAddImageFromSourceたが、それでも同じ結果が得られます。入力元のNEFファイルサイズは21.5MBですが、変換後の宛先ファイルサイズは144.4MBです。

コードを確認してください:

-(void)saveAsCR2WithCGImageMethodUsingName:(NSString*)inDestinationfileName withSourceFile:(NSString*)inSourceFileName
{
    CGImageSourceRef sourceFile = MyCreateCGImageSourceRefFromFile(inSourceFileName);
    CGImageDestinationRef destinationFile = createCGImageDestinationRefFromFile(inDestinationfileName);
    CGImageDestinationAddImageFromSource(destinationFile, sourceFile, 0, NULL);
//https://developer.apple.com/library/mac/#documentation/graphicsimaging/Conceptual/ImageIOGuide/ikpg_dest/ikpg_dest.html
    CGImageDestinationFinalize(destinationFile);
}

CGImageSourceRef MyCreateCGImageSourceRefFromFile (NSString* path)
{
    // Get the URL for the pathname passed to the function.
    NSURL *url = [NSURL fileURLWithPath:path];
    CGImageSourceRef  myImageSource;
    CFDictionaryRef   myOptions = NULL;
    CFStringRef       myKeys[2];
    CFTypeRef         myValues[2];

    // Set up options if you want them. The options here are for
    // caching the image in a decoded form and for using floating-point
    // values if the image format supports them.
    myKeys[0] = kCGImageSourceShouldCache;
    myValues[0] = (CFTypeRef)kCFBooleanTrue;
    myKeys[1] = kCGImageSourceShouldAllowFloat;
    myValues[1] = (CFTypeRef)kCFBooleanTrue;

    // Create the dictionary
    myOptions = CFDictionaryCreate(NULL, (const void **) myKeys,
                                   (const void **) myValues, 2,
                                   &kCFTypeDictionaryKeyCallBacks,
                                   & kCFTypeDictionaryValueCallBacks);

    // Create an image source from the URL.
    myImageSource = CGImageSourceCreateWithURL((CFURLRef)url, myOptions);
    CFRelease(myOptions);

    // Make sure the image source exists before continuing
    if (myImageSource == NULL){
        fprintf(stderr, "Image source is NULL.");
        return  NULL;
    }
    return myImageSource;
}

CGImageDestinationRef createCGImageDestinationRefFromFile (NSString *path)
{
    NSURL *url = [NSURL fileURLWithPath:path];
    CGImageDestinationRef myImageDestination;

//https://developer.apple.com/library/mac/#documentation/graphicsimaging/Conceptual/ImageIOGuide/ikpg_dest/ikpg_dest.html
    float compression = 1.0; // Lossless compression if available.
    int orientation = 4; // Origin is at bottom, left.
    CFStringRef myKeys[3];
    CFTypeRef   myValues[3];
    CFDictionaryRef myOptions = NULL;
    myKeys[0] = kCGImagePropertyOrientation;
    myValues[0] = CFNumberCreate(NULL, kCFNumberIntType, &orientation);
    myKeys[1] = kCGImagePropertyHasAlpha;
    myValues[1] = kCFBooleanTrue;
    myKeys[2] = kCGImageDestinationLossyCompressionQuality;
    myValues[2] = CFNumberCreate(NULL, kCFNumberFloatType, &compression);
    myOptions = CFDictionaryCreate( NULL, (const void **)myKeys, (const void **)myValues, 3,
                                   &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

//https://developer.apple.com/library/mac/#documentation/graphicsimaging/Conceptual/ImageIOGuide/imageio_basics/ikpg_basics.html#//apple_ref/doc/uid/TP40005462-CH216-SW3
    CFStringRef destFileType = CFSTR("public.tiff");
//    CFStringRef destFileType = kUTTypeJPEG;
    CFArrayRef types = CGImageDestinationCopyTypeIdentifiers(); CFShow(types);

    myImageDestination = CGImageDestinationCreateWithURL((CFURLRef)url, destFileType, 1, myOptions);
    return myImageDestination;
}

編集 2: @Peter が語った 2 番目のアプローチを使用しました。これにより、興味深い結果が得られます。その効果は、ファインダー内のファイルの名前を「example_image.NEF」から「example_image.CR2」に変更するのと同じです。驚くべきことに、プログラムとファインダーの両方で変換すると、21.5 MB のソース ファイルが 59 KB になることがわかります。これは、コードに圧縮セットがありません。コードを見て提案してください:

-(void)convertNEFWithTiffIntermediate:(NSString*)inNEFFile toCR2:(NSString*)inCR2File
{
    NSData *fileData = [[NSData alloc] initWithContentsOfFile:inNEFFile];
    if (fileData)
    {
        NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:fileData];
//        [imageRep setCompression:NSTIFFCompressionNone
//                          factor:1.0];
        NSDictionary *imageProps = nil;
        NSData *destinationImageData = [imageRep representationUsingType:NSTIFFFileType properties:imageProps];
        [destinationImageData writeToFile:inCR2File atomically:NO];
    }
}
4

3 に答える 3

1

私が最初に試みることは、NSImage または NSBitmapImageRep をまったく含まないことです。代わりに、ソース ファイルの CGImageSource と宛先ファイルの CGImageDestination を作成し、CGImageDestinationAddImageFromSourceA から B にすべての画像を転送するために使用します。

于 2013-03-17T09:10:15.740 に答える
1

このコードでは、TIFF に 2 回変換しています。

  1. ソースファイルから NSImage を作成します。
  2. TIFFRepresentationNSImage にその(TIFF 変換 #1)を要求します。
  3. 最初の TIFF データから NSBitmapImageRep を作成します。
  4. NSBitmapImageRep に 2 番目の TIFF 表現 (TIFF 変換 #2) を生成するように依頼します。

ソース データから直接 NSBitmapImageRep を作成し、NSImage をまったく使用しないことを検討してください。その後、ステップ 4 に直接スキップして、出力データを生成します。

(しかし、私はまだCGImageDestinationAddImageFromSource最初に試します。)

于 2013-03-17T09:13:43.503 に答える