有了这个问题,我只想问我在没有外部库的情况下使用Xcode和iOS的可能性。我已经在探索在另一个question中使用libtiff
的可能性。
问题
我一直在筛选堆栈溢出数周,并为自己的每一个问题找到了解决方案。我有4件事需要工作:
我可以使用JPEG来获得2和4。 我可以使用相机缓冲区制作的原始数据(分别为NSData)分别为1,3和4。 我可以使用Xcode和iOS获得所有4个先决条件吗?作为最后的手段,我即将放弃并寻找你的意见。
虽然仍然在探索这个问题,但我也被困在我试过的另一条大道上,libtiff。我还在努力,但是......
以下是我尝试过的很棒的建议列表,我自己的代码只是从这些堆栈溢出源汇总而来:
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的帮助!
答案 0 :(得分:2)
由于你已经破解了1,3和4,你似乎唯一遇到的障碍是将数据和元数据保存在一起。试试这个(假设未经处理的数据位于名为CMSampleBufferRef
的{{1}}中,您已经完成了将图形数据放入名为myImageDataSampleBuffer
的{{1}}中的繁重工作:< / p>
CGImageRef
答案 1 :(得分:2)
这个帖子在解决一个非常类似的问题时非常有帮助,所以我想我会提供一个Swift 2.0实现的解决方案,以防有人来看。
stillImageOutput?.captureStillImageAsynchronouslyFromConnection(videoConnection, completionHandler: { (imageDataSampleBuffer, error) -> Void in
// get image meta data (EXIF, etc)
let metaData: CFDictionaryRef? = CMCopyDictionaryOfAttachments( kCFAllocatorDefault, imageDataSampleBuffer, kCMAttachmentMode_ShouldPropagate )
// get reference to image
guard let imageBuffer = CMSampleBufferGetImageBuffer( imageDataSampleBuffer ) else { return }
// lock the buffer
CVPixelBufferLockBaseAddress( imageBuffer, 0 )
// read image properties
let baseAddress = CVPixelBufferGetBaseAddress( imageBuffer )
let bytesPerRow = CVPixelBufferGetBytesPerRow( imageBuffer )
let width = CVPixelBufferGetWidth( imageBuffer )
let height = CVPixelBufferGetHeight( imageBuffer )
// color space
let colorSpace = CGColorSpaceCreateDeviceRGB()
// context - camera output settings kCVPixelFormatType_32BGRA
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedFirst.rawValue).union(.ByteOrder32Little)
let newContext = CGBitmapContextCreate( baseAddress, width, height, 8, bytesPerRow, colorSpace, bitmapInfo.rawValue )
//unlock buffer
CVPixelBufferUnlockBaseAddress( imageBuffer, 0 )
//Create a CGImageRef from the CVImageBufferRef
guard let newImage = CGBitmapContextCreateImage( newContext ) else {
return
}
// create tmp file and write image with metadata
let fileName = String(format: "%@_%@", NSProcessInfo.processInfo().globallyUniqueString, "cap.tiff")
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(fileName)
if let destination = CGImageDestinationCreateWithURL( fileURL, kUTTypeTIFF, 1, nil) {
CGImageDestinationAddImage( destination, newImage, metaData )
let wrote = CGImageDestinationFinalize( destination )
if !wrote || NSFileManager.defaultManager().fileExistsAtPath(fileURL.URLString) {
return
}
}
}
P.S。要使其工作,您必须像这样配置图像缓冲区:
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput?.outputSettings = [ kCVPixelBufferPixelFormatTypeKey: Int(kCVPixelFormatType_32BGRA) ]