この質問では、外部ライブラリなしで 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の助けに感謝します。