objc, сохраните изображение с параметром экспозиции в альбом
Я отчаянно борюсь с этим вопросом...
Фон: у меня есть приложение, которое делает 4 снимка в одном затворе с разной экспозицией, для которого установлено значение AVCapturePhotoBracketSettings. Я преобразовал CMSampleBufferRef
в UIImage*
и сохранить их в мой фотоальбом, позвонив
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);// image is UIImage*
Но позже, когда я экспортировал изображения в мой Mac, я понял, что все параметры экспозиции проверены, щелкнув правой кнопкой мыши изображение -> Получить информацию. У меня NSArray хранит 4 экспозиции. Я хочу поместить их в UIImage по одному для каждого, поэтому после сохранения их в моем альбоме он может показывать время экспозиции в Get Info, точно так же, как показывает изображение в альбоме, если я взял его со встроенной камеры iphone.
Проблема: у меня есть 3 длины 4 NSMutableArrays. Один хранит 4 числа экспозиции в поплавке; Второй имеет 4 CMSampleBufferRef
данные изображения; Последний имеет 4 UIImage *
который конвертируется из второго для отображения на экране. Все, что мне нужно сделать, это либо сохранить UIImages с номером экспозиции в моем альбоме в формате jpeg, либо сохранить прямо из CMSampleBufferRef
с моим номером времени выдержки для моего альбома как jpeg (я не знаю, думаю, что это возможно, хотя).
Мои выводы: так, из этого поста и этого официального документа я узнал, что на самом деле UIImage не содержит метаданных.
После долгих исследований я получил два удара, которые, казалось бы, были на правильном пути.
Один использует Photo Framework, чтобы установить экспозицию в качестве актива изображения и добавить его в альбом. Это и это, и многие другие посты помогли в кодировании. Тем не менее, я не смог найти какое-либо свойство, которое я мог бы установить экспозиции. Свойства "Чтение метаданных актива" в PHAsset, кажется, все, что я мог изменить, у которого нет времени экспозиции.
Другой - это ввод-вывод изображения -> CGImageProperties -> Ключи словаря EXIF -> kCGImagePropertyExifExposureTime. Функция CGImageDestinationSetProperties может установить его. Но это для записи данных изображения в приложение вместо сохранения изображения в альбом... Итак, я наконец-то нашел свойство времени выдержки, но не могу его использовать...
Я что-то пропустил?? Поскольку это кажется очень легким делом, мой коллега по электротехнике посмотрел на меня, потому что я идиот, который провел целый день, не мог этого понять...
Обновление:
Это похоже на creationRequestForAssetFromImageAtFileURL:
Метод сможет сохранить изображение с EXIF в альбом. Этот пост ( метаданные потеряны при сохранении фотографии с использованием PHPhotoLibrary) указывает, что лучше временно сохранить данные изображения с информацией EXIF, а затем вызвать метод выше.
Я взял код из этого поста ( Сохранение фотографии с метаданными в Camera Roll с определенным именем файла) и изменил его.
создать альбом:
PHFetchResult *normalAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
NSLog(@"There are %lu albums fetched.", (unsigned long)normalAlbums.count);//output 0 I don't know why
_album = normalAlbums.firstObject;// this give me nil, but still can save image to the album, is this the cause of the problem?
Получить информацию EXIF:
//imageSampleBufferArray is the type of CMSampleBufferRef that has the image
CMSampleBufferRef sampleBuf = (CMSampleBufferRef)CFArrayGetValueAtIndex(imageSampleBufferArray, i);
NSDictionary* exifAttachments = (NSDictionary*)CMGetAttachment(sampleBuf, (CFStringRef)@"{Exif}", NULL);
Сохранить изображение:
+(void)saveImageWithMetaToCameraRoll:(UIImage*)image album:(PHAssetCollection *)album exif:(NSDictionary *)metadata{
NSMutableDictionary *meta = [metadata mutableCopy];
NSData *imageData = UIImageJPEGRepresentation(image, 1.0f);
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) imageData, NULL);
NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970] * 1000];
NSString *fileName = [NSString stringWithFormat:@"IMG_%@.jpeg", timestamp];
NSURL *tmpURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:fileName]];
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef) tmpURL, kUTTypeJPEG, 1, NULL);
CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef) meta);
CGImageDestinationFinalize(destination);
CFRelease(source);
CFRelease(destination);
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *newAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:tmpURL];
PHObjectPlaceholder *placeholderAsset = newAssetRequest.placeholderForCreatedAsset;
if (album) {
PHAssetCollectionChangeRequest *changeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:album];
[changeRequest addAssets:@[placeholderAsset]];
}
} completionHandler:^(BOOL success, NSError *error) {
//Clean up the file:
[[NSFileManager defaultManager] removeItemAtURL:tmpURL error:nil];
if (error) {
NSLog(@"%@", error);
}
}];
}
Однако, когда я смотрю на изображение в только что снятом альбоме, в нем по-прежнему нет информации EXIF, такой как время экспозиции. Все еще расследую это...