2011-07-06 49 views
6

我正在研究更多的迷你项目,稍后将其纳入新项目。它基本上是一个测试单位。加快保存图像 - iOS

我正在做的是创建AVCaptureSession,然后创建一个方法OutputSampleBufferDelegate。在该方法中,我将sampleBuffer转换为UIImage并保存UIImage。当我在iPhone 4上运行应用程序时,它每秒只能保存2-3幅图像。必须有一种更有效的方式来保存图像。

有人可以帮我加快速度吗?

谢谢!

lots of the code is from here

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
    UIImage *resultUIImage = [self imageFromSampleBuffer:sampleBuffer]; 

    NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(resultUIImage)]; 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *path = [paths objectAtIndex:0]; 

    CMTime frameTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 

    NSString *filename = [NSString stringWithFormat:@"%f.png", CMTimeGetSeconds(frameTime)]; 

    NSString *finalPath = [path stringByAppendingString:filename]; 

    [imageData writeToFile:finalPath atomically:YES]; 
} 

// Create a UIImage from sample buffer data 
- (UIImage *)imageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer 
{ 
    // Get a CMSampleBuffer's Core Video image buffer for the media data 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    // Lock the base address of the pixel buffer 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    // Get the number of bytes per row for the pixel buffer 
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 

    // Get the number of bytes per row for the pixel buffer 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    // Get the pixel buffer width and height 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Create a device-dependent RGB color space 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    // Create a bitmap graphics context with the sample buffer data 
    CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    // Create a Quartz image from the pixel data in the bitmap graphics context 
    CGImageRef quartzImage = CGBitmapContextCreateImage(context); 
    // Unlock the pixel buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

    // Free up the context and color space 
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace); 

    // Create an image object from the Quartz image 
    UIImage *image = [UIImage imageWithCGImage:quartzImage]; 

    // Release the Quartz image 
    CGImageRelease(quartzImage); 

    return image; 
} 
+0

在Insturments中查看代码时,哪些任务/调用占用的时间最多? – Mats

回答

8

使用这个代码,我可以把它保存图像降低到0.1秒的时间。

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection 
{ 

    double frameTime = CFAbsoluteTimeGetCurrent(); 
    UIImage *resultUIImage = [self imageFromSampleBuffer:sampleBuffer]; 

    // takes freaking forever to do. 
    double pre = CFAbsoluteTimeGetCurrent(); 
    NSData *imageData = UIImageJPEGRepresentation(resultUIImage, 0.9); 
    NSLog(@"It took to write the file:%f",CFAbsoluteTimeGetCurrent()-pre); 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory 
                 ,NSUserDomainMask 
                 , YES); 
    NSString *path = [paths objectAtIndex:0]; 
    NSString *filename = [NSString stringWithFormat:@"%f.png", frameTime]; 
    NSString *finalPath = [path stringByAppendingString:filename]; 
    [imageData writeToFile:finalPath atomically:YES]; 
} 
+0

尼斯。看来,iPhone必须在内部存储图像的JPG格式,并且转换为PNG是真正的瓶颈,无法写入磁盘? – Meekohi

+0

我得到CGBitmapContextCreateImage:无效的上下文0x0。如果你想看到的回溯,请将CG_CONTEXT_SHOW_BACKTRACE环境变量。 – loretoparisi

+0

它应该不是第三行到最后一行的.jpg吗? – shim

3

能不能请你看,如果你在你的第一个方法注释掉以下行,您可以多少图像生成:

[imageData writeToFile:finalPath atomically:YES]; 

我之所以说这是你要去花费大量时间将该映像写入磁盘。看看如何在不将图像写入磁盘的情况下执行这一操作会很有趣。至少你会知道,如果所有的时间都花在实际创建图像和存储图像上。或者你可以像上面提到的另一张海报那样使用工具来计算你在每种方法中的时间。

如果事实证明将图像写入磁盘时间太长,那么我建议尝试实现一种缓存机制,该机制将缓存内存中的图像并稍后将其写入磁盘。

它也可能有助于尝试调用writeToFile:atomically:在后台线程上。

+0

感谢您对此发表评论。我看了一下,并测量了最长的时间。它将uiimage转换为NSData对象。我在网上看了一下,发现一个更有效的方法(使用JPEG表示,而PNG) – SamB