Мне нужно преобразовать UIImage
в NSData
, но без использования UIImagePngRepresentation
или UIImageJpegRepresentation
, для изображений из фотолиба я могу использовать метод assetlib, как указано здесь Использование ALAssetsLibrary и ALAsset извлекает изображение как NSData, но для захваченного изображения, assset url не существует, поэтому в этом случае мне нужно преобразовать UIImage
непосредственно в байты с данными exif, как я могу это сделать? пожалуйста, помогите
Преобразование UIImage в NSData без использования UIImagePngпредставления или UIImageJpegRepresentation
Ответ 1
H Bastan,
На основе вашего комментария:
... Я хочу сохранить возвращенный захваченный снимок камерой устройства через метод делегирования 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>
Другие примечания Насколько я понимаю, в этом случае мы не создаем потери поколения при сохранении изображения, как это предлагается в этом примере. Мы используем свойство UIImage CGImage и, как указано в документации:
Основные данные изображения кварца
Ответ 2
У меня была аналогичная проблема, но по соображениям безопасности я не хотел записывать данные в файловую систему по умолчанию, как было предложено Уэсом. Я также хотел иметь возможность добавлять метаданные к моему изображению. Мое решение было следующим:
- (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];
// ...
}
Ответ 3
Вы можете попробовать что-то вроде этого. Не уверен, что это лучший метод. Но стоит сделать снимок. Если доступен URL-адрес изображения, вы можете попробовать initWithContentsOfUrl
NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/test/isajf/isajf/test.jpg"];