avfoundation - 如何将来自 AVFoundations captureStillImageAsynchronouslyFromConnection 的 TIFF 照片保存到 iPhone (iOS) 上带有 EXIF 元数据的文件中?

标签 avfoundation tiff exif nsdocumentdirectory

对于这个问题,我只询问在没有外部库的情况下使用 Xcode 和 iOS 的可能性。我已经在探索在另一个 question 中使用 libtiff 的可能性.

问题

数周以来,我一直在筛选堆栈溢出,并为我的每一个问题找到了可行的解决方案。我有 4 件事需要工作:

  1. 我需要来自相机的 RGBA 数据,没有任何压缩
  2. 我需要尽可能多的元数据,尤其是 EXIF
  3. 我需要以 TIFF 格式保存以与其他软件兼容和无损
  4. 我需要通过保存在文件而不是照片库中来防止随意查看

我可以使用 JPEG 得到 2 和 4。 我可以将 1、3 和 4 与从相机缓冲区制作的原始数据(分别为 NSData)一起使用。 我可以通过 Xcode 和 iOS 满足所有 4 个先决条件吗?我即将放弃并寻找您的意见作为最后的手段。

虽然仍在探索这个问题,但我也停留在我尝试过的另一条途径上,libtiff .不过我还在努力……

这是我尝试过的重要建议的列表,我自己的代码只是从这些堆栈溢出源中拼凑而成:

解决方案

captureStillImageAsynchronouslyFromConnection 的完整操作序列:

[[self myAVCaptureStillImageOutput] captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
 {
     //get all the metadata in the image
     CFDictionaryRef metadata = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, imageSampleBuffer, kCMAttachmentMode_ShouldPropagate);
     // get image reference
     CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(imageSampleBuffer);
     // >>>>>>>>>> lock buffer address
     CVPixelBufferLockBaseAddress(imageBuffer, 0);

     //Get information about the image
     uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
     size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
     size_t width = CVPixelBufferGetWidth(imageBuffer);
     size_t height = CVPixelBufferGetHeight(imageBuffer);

     // create suitable color space
     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

     //Create suitable context (suitable for camera output setting kCVPixelFormatType_32BGRA)
     CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);

     // <<<<<<<<<< unlock buffer address
     CVPixelBufferUnlockBaseAddress(imageBuffer, 0);

     // release color space
     CGColorSpaceRelease(colorSpace);

     //Create a CGImageRef from the CVImageBufferRef
     CGImageRef newImage = CGBitmapContextCreateImage(newContext);

     // release context
     CGContextRelease(newContext);

     // create destination and write image with metadata
     CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:filePath isDirectory:NO];
     CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypeTIFF, 1, NULL);
     CGImageDestinationAddImage(destination, imageRef, metadata);

     // finalize and release destination
     CGImageDestinationFinalize(destination);
     CFRelease(destination);
 }

静态图像输出相关的相机设置是:

[[self myAVCaptureSession] setSessionPreset:AVCaptureSessionPresetPhoto];

NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (id)kCVPixelBufferPixelFormatTypeKey, nil];
[myAVCaptureStillImageOutput setOutputSettings:outputSettings];

我得到了一张标称 TIFF 格式的标称未压缩图像,其中包含所有元数据。 (它在其他系统上有镜像,但现在我可以编写 EXIF 和其他元数据,我也可以对其进行微调,我确信)。

再次感谢 Wildaker感谢他的帮助!

最佳答案

由于您已经破解了 1、3 和 4,看来您缺少的唯一障碍是将数据和元数据保存在一起。试试这个(假设未处理的数据在名为 myImageDataSampleBufferCMSampleBufferRef 中,并且您已经完成了将图形数据放入 CGImageRef 的繁重工作称为 myImage):

CFDictionaryRef metadata = CMCopyDictionaryOfAttachments(kCFAllocatorDefault,
  myImageDataSampleBuffer,
  kCMAttachmentMode_ShouldPropagate);
NSFileManager* fm = [[NSFileManager alloc] init];
NSURL* pathUrl = [fm URLForDirectory:saveDir
  inDomain:NSUserDomainMask
  appropriateForURL:nil
  create:YES
  error:nil];
NSURL* saveUrl = [pathUrl URLByAppendingPathComponent:@"myfilename.tif"];
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)saveUrl,
  (CFStringRef)@"public.tiff", 1, NULL);
CGImageDestinationAddImage(destination, myImage, metadata);
CGImageDestinationFinalize(destination);
CFRelease(destination);

关于avfoundation - 如何将来自 AVFoundations captureStillImageAsynchronouslyFromConnection 的 TIFF 照片保存到 iPhone (iOS) 上带有 EXIF 元数据的文件中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17361100/

相关文章:

objective-c - 找不到 iOS 10 的相机(AVFoundation 新 API)类

ios - 无法理解我的 spritekit 游戏中的延迟?

java - TIFF 编码的 JPEG

image-manipulation - 将文本添加到 TIFF

java - 处理大型 TIFF 文件和内存分配

php - 如何在PHP中操作图像文件的各种元信息

ios - 相机弱光效果(夜间模式)

swift - 使用 Swift 录制视频 avfoundation 时我做错了什么?

iOS Swift + Alamofire 上传带exif数据的照片

iphone - 将表示图像的 NSMutableData 保存到 iPhone 照片库