2013-03-17 5 views
2

Я пытаюсь написать прототип, чтобы доказать, что преобразование RAW из одного формата в другое возможно. Мне нужно преобразовать необработанный файл Nikon с форматом .NEF в формат .CR2 от Canon. С помощью различных сообщений я создаю исходное изображение BitmapImageRep представления TIFF изображения и использую его для записи выходного файла с расширением .CR2.NSImage + NSBitmapImageRep = Преобразование файла изображения RAW из одного формата в другой

Это действительно работает, но для меня проблема только в том, что входной файл имеет 21,5 МБ, но выход am из 144,4 МБ. При использовании NSTIFFCompressionPackBits дает мне 142.1 МБ.

Я хочу понять, что происходит, я попробовал различные сжатые копии, но без успеха.

Пожалуйста, помогите мне понять это. Это исходный код:

@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?

Edit 1: Done изменение, основанное на предложении Питера использования CGImageDestinationAddImageFromSource метода, но до сих пор я получаю тот же результат. Размер исходного файла NEF источника 21,5 МБ, но размер файла назначения после преобразования 144,4 МБ.

Пожалуйста, ознакомьтесь код:

-(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; 
} 

Edit 2: Используется второй подход, рассказанную @Peter. Это дает интересный результат. Это то же самое, что и переименование файла в finder, например, example_image.NEF, на example_image.CR2. Удивительно, что происходит при преобразовании как программно, так и в finder, исходный файл, который составляет 21,5 МБ, окажется равным 59 КБ. Это без какого-либо сжатия, установленного в коде. Пожалуйста, смотрите код и предложить:

-(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]; 
    } 
} 
+0

Почему вы отметили это как [какао-touch], если используете NSImage и NSBitmapImageRep? –

+0

Извините, спасибо за исправление. Я - разработчик iOS, и я использую его таким образом. Попробуй использовать оба этих метода. –

+1

Переименование файла в Finder меняет свой размер на 59 K? Это не так. –

ответ

1

Первое, что я хотел бы попробовать не включать NSImage или NSBitmapImageRep вообще. Вместо этого я хотел бы создать CGImageSource для исходного файла и CGImageDestination для конечного файла, а также использовать CGImageDestinationAddImageFromSource передавать все изображения от А до В.

+0

Я следил за этим подходом, но пока не смог найти успех :(Пожалуйста, просмотрите мой отредактированный вопрос с последним кодом. Теперь попробуйте свой следующий подход. –

+0

@Raj: Вы использовали тот же формат вывода, так что, конечно, вы получили тот же результат. Если вы хотите данные CR2, спросите об этом, а не TIFF. –

+0

Но как мы можем получить данные CR2 из следующих доступных? NSTIFFFileType, NSBMPFileType, NSGIFFileType, NSJPEGFileType, NSPNGFileType, NSJPEG2000FileType –

1

Вы преобразования в TIFF дважды в этом коде:

  1. Вы создаете NSImage, я предполагаю из исходного файла.
  2. Вы запрашиваете NSImage для своего TIFFRepresentation (преобразование TIFF # 1).
  3. Вы создаете NSBitmapImageRep из первых данных TIFF.
  4. Вы запрашиваете NSBitmapImageRep для генерации второго представления TIFF (преобразование TIFF # 2).

Рассмотрите возможность создания NSBitmapImageRep непосредственно из исходных данных, а не с использованием NSImage вообще. Затем вы можете перейти к шагу 4 для генерации выходных данных.

(Но я все еще хотел бы попробовать CGImageDestinationAddImageFromSource первым.)

+0

Как вы сказали, см. «Редактировать 2» в моем вопросе, что-то, что мне не хватает? Есть ли другой способ добиться того же? –

0

файлов Raw изображения имеют свое собственное (собственность) представление. Например, они могут использовать 14-битный компонент и мозаичные шаблоны, которые не поддерживаются вашим кодом. Я думаю, вы должны использовать API более низкого уровня и действительно перепроектировать формат RAW, который вы пытаетесь сохранить.

Я бы начал с DNG, что относительно просто, поскольку Adobe предоставляет SDK для его записи.