2013-03-06 5 views
19

Мне нужно преобразовать UIImage в NSData, но без использования UIImagePngRepresentation или UIImageJpegRepresentation, для изображений с photolib я могу использовать assetlib метод, как упомянуто здесь Using ALAssetsLibrary and ALAsset take out Image as NSData, но для захваченного изображения, assset URL не существует поэтому в этом случае мне нужно преобразовать UIImage непосредственно в байты с данными exif, как я могу это сделать? пожалуйста, помогитеПреобразовать UIImage в NSData без использования UIImagePngrepresentation или UIImageJpegRepresentation

+0

Почему? Многоплатформенные причины? Это единственная причина, по которой я могу думать ...ну, если это так, попробуйте использовать LodePNG http://lodev.org/lodepng/ – borrrden

+2

Используя представление ujimage png и jpeg, размер изображения меняется, а качество изображения для jpeg уменьшается даже с качеством сжатия 1,0. Мне нужен способ прямого преобразования UIImage в байты. –

+0

Конечно, размер изображения меняется ... это характер сжатия. В противном случае все снимки будут иметь огромный размер файла (wxhx4 bytes). Кроме того, ваш размер будет зависеть от размеров файла. Я думаю, вам нужно описать вашу проблему намного лучше, чем вы сейчас. – borrrden

ответ

17

H Бастан,

Основываясь на ваш комментарий:

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

Это выглядит как ваш реальный Цель состоит в том, чтобы сохранить изображение с данными EXIF ​​в каталог документов и не получать UIImage как объект NSData с данными EXIF. В этом случае, вы можете сделать следующее в вашей реализации imagePickerController:didFinishPickingMediaWithInfo:

// Get your image. 
UIImage *capturedImage = [info objectForKey:UIImagePickerControllerOriginalImage]; 

// Get your metadata (includes the EXIF data). 
NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata]; 

// Create your file URL. 
NSFileManager *defaultManager = [NSFileManager defaultManager]; 
NSURL *docsURL = [[defaultManager URLsForDirectory:NSDocumentDirectory 
             inDomains:NSUserDomainMask] lastObject]; 
NSURL *outputURL = [docsURL URLByAppendingPathComponent:@"imageWithEXIFData.jpg"]; 

// Set your compression quuality (0.0 to 1.0). 
NSMutableDictionary *mutableMetadata = [metadata mutableCopy]; 
[mutableMetadata setObject:@(1.0) forKey:(__bridge NSString *)kCGImageDestinationLossyCompressionQuality]; 

// Create an image destination. 
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((__bridge CFURLRef)outputURL, kUTTypeJPEG , 1, NULL); 
if (imageDestination == NULL) { 

    // Handle failure. 
    NSLog(@"Error -> failed to create image destination."); 
    return; 
} 

// Add your image to the destination. 
CGImageDestinationAddImage(imageDestination, capturedImage.CGImage, (__bridge CFDictionaryRef)mutableMetadata); 

// Finalize the destination. 
if (CGImageDestinationFinalize(imageDestination) == NO) { 

    // Handle failure. 
    NSLog(@"Error -> failed to finalize the image."); 
} 

CFRelease(imageDestination); 

Из моих тестов время выполнения было примерно таким же или быстрее, чем делать:

NSData *data = UIImageJPEGRepresentation(capturedImage, 1.0); 
[data writeToURL:outputURL atomically:YES]; 

... и вы получите сохраните данные EXIF!

Вы можете также направить его в качестве фона очереди, если вы хотите, чтобы убедиться, что ваш пользовательский интерфейс остается отзывчивым:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 

    // Do the image saving here... 
}); 

Важное примечание: Вам нужно будет добавить ImageIO.framework и тому MobileCoreServices.framework для сборки вашей цели фазы и импортировать их в классе, где вы делаете сохранение изображения:

#import <ImageIO/ImageIO.h> 
#import <MobileCoreServices/MobileCoreServices.h> 

Другие ноты Насколько я понимаю, в этом случае мы не создаем потери поколений при сохранении изображения, как предлагается в этом примере. Мы используем свойство CGImage UIImage и в документации говорится:

анализируемые данные изображения Quartz

+0

Спасибо, его очень полезно. Таким образом, если я не настроил качество сжатия, он будет сохранен с оригинальным сжатием изображения qaulity n, это прекрасно со мной, также размер данных изображения также остается таким же, как и photolib, и, следовательно, это идеальный способ сделать это благодаря. –

+0

sry комментарии были для решения ниже :) did not try yours – hasan83

+0

Я был застрял в течение довольно долгого времени. но благодаря вашему решению я могу двигаться вперед. Спасибо – Asbar

0

Вы можете попробовать что-то вроде этого. Не уверен, что это лучший метод. Но стоит сделать снимок. Incase URL-адрес изображения доступен, вы можете попробовать initWithContentsOfUrl

NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/test/isajf/isajf/test.jpg"]; 
+0

привет спасибо, но я использую uiimagepicker для захватить изображение, здесь он возвращает только uiimage n, а не url для изображения, следовательно, выше метод не будет полезен –

21

У меня была аналогичная проблема, но по соображениям безопасности я не хотел писать данные в файловая система по умолчанию, предложенная Уэсом. Я также хотел иметь возможность добавлять метаданные к моему изображению. Мое решение было следующим:

- (NSData *)dataFromImage:(UIImage *)image metadata:(NSDictionary *)metadata mimetype:(NSString *)mimetype 
{ 
    NSMutableData *imageData = [NSMutableData data]; 
    CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)mimetype, NULL); 
    CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, uti, 1, NULL); 

    if (imageDestination == NULL) 
    { 
     NSLog(@"Failed to create image destination"); 
     imageData = nil; 
    } 
    else 
    { 
     CGImageDestinationAddImage(imageDestination, image.CGImage, (__bridge CFDictionaryRef)metadata); 

     if (CGImageDestinationFinalize(imageDestination) == NO) 
     { 
      NSLog(@"Failed to finalise"); 
      imageData = nil; 
     } 
     CFRelease(imageDestination); 
    } 

    CFRelease(uti); 

    return imageData; 
} 

Чтобы использовать его, вы должны сделать следующее:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{ 
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; 
    NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata]; 
    NSString *mimeType = @"image/jpeg"; // ideally this would be dynamically set. Not defaulted to a jpeg! 

    // you could add to the metadata dictionary (after converting it to a mutable copy) if you needed to. 

    // convert to NSData 
    NSData *imageData = [self dataFromImage:image metadata:metadata mimetype:mimeType]; 

    // ... 
} 
+0

Время простоя намного лучше, чем 5% от использования UIImageJpegRepresentation. но он использует примерно такую ​​же память. но, по крайней мере, он сохраняет эту память в течение очень малого времени. – hasan83

Смежные вопросы