带着这个问题,我只询问我在没有外部库的情况下使用 Xcode 和 iOS 的可能性。我已经在探索libtiff
在另一个问题中使用的可能性。
问题
几周以来,我一直在筛选堆栈溢出,并为自己的每一个问题找到了可行的解决方案。我有 4 件事需要做:
- 我需要来自相机的 RGBA 数据,没有任何压缩
- 我需要尽可能多的元数据,尤其是 EXIF
- 我需要保存为 TIFF 格式,以便与其他软件兼容和无损
- 我需要通过保存在文件而不是照片库中来防止随意查看
我可以使用 JPEG 获得 2 和 4。我可以使用从相机缓冲区制作的原始数据(分别为 NSData)获得 1、3 和 4。我可以使用 Xcode 和 iOS 满足所有 4 个先决条件吗?我即将放弃并寻找您的意见作为最后的手段。
在仍在探索这一点的同时,我也被困在了我尝试过的另一条途径libtiff上。我还在努力,虽然...
这是我尝试过的好建议列表,我自己的代码只是从堆栈溢出源中组合而成,如下所示:
- 如何将 exif 元数据写入图像(不是相机胶卷,只是 UIImage 或 JPEG)(让我希望我可以使用 JPEG 格式,在做 Apple 喜欢的事情时非常轻松)
- 来自“645 PRO”等相机的原始图像数据</a>(这将是使用例如libtiff的重点)
- 将 CGImageRef 保存为 png 文件?(
kUTTypeTIFF
也适用于 ,但没有元数据)
解决方案
完整的动作序列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的帮助!