2011-07-06 49 views
6

Tôi đang làm việc trên nhiều dự án nhỏ hơn mà sau này sẽ được đưa vào một dự án mới. Nó về cơ bản là một đơn vị thử nghiệm.Tăng tốc độ lưu hình ảnh - iOS

Điều tôi đang làm là tạo một AVCaptureSession và sau đó tạo phương thức cho OutputSampleBufferDelegate. Trong phương pháp, tôi chuyển đổi sampleBuffer thành một số UIImage và lưu UIImage. Khi tôi chạy ứng dụng trên iPhone 4 của tôi, nó chỉ có thể lưu 2-3 hình ảnh mỗi giây. Phải có một cách hiệu quả hơn để lưu hình ảnh.

Ai đó có thể giúp tôi tăng tốc độ không?

Cảm ơn!

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

Nhiệm vụ/cuộc gọi nào mất nhiều thời gian nhất khi bạn xem mã trong Insturments? – Mats

Trả lời

8

Sử dụng mã này Tôi có thể tiết kiệm thời gian để lưu hình ảnh xuống 0,1 giây.

- (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

Rất tốt. Dường như iPhone phải lưu trữ hình ảnh dưới dạng JPG trong nội bộ, và việc chuyển đổi sang png là nút cổ chai thực sự, không ghi vào đĩa? – Meekohi

+0

Tôi nhận được CGBitmapContextCreateImage: ngữ cảnh không hợp lệ 0x0. Nếu bạn muốn xem backtrace, vui lòng đặt biến môi trường CG_CONTEXT_SHOW_BACKTRACE. – loretoparisi

+0

Nếu nó không phải là một .jpg trên dòng thứ ba đến dòng cuối cùng? – shim

3

Ông có thể xin vui lòng xem có bao nhiêu hình ảnh mà bạn có thể tạo ra nếu bạn nhận xét ra dòng sau trong phương pháp đầu tiên của bạn:

[imageData writeToFile:finalPath atomically:YES]; 

Lý do tôi nói rằng là bạn đang đi dành nhiều thời gian để viết hình ảnh đó ra đĩa. Nó sẽ là thú vị để xem làm thế nào điều này thực hiện mà không cần viết các hình ảnh vào đĩa. Ít nhất theo cách đó bạn sẽ biết nếu tất cả thời gian được chi tiêu trong thực sự tạo ra hình ảnh so với lưu trữ hình ảnh. Hoặc bạn có thể làm như một poster khác được đề cập và sử dụng các công cụ cho thời gian bạn đang ở trong mỗi phương pháp.

Nếu nó chỉ ra rằng ghi hình ảnh vào đĩa mất quá nhiều thời gian, thì tôi khuyên bạn nên triển khai cơ chế lưu bộ nhớ cache sẽ lưu hình ảnh trong bộ nhớ và ghi chúng vào đĩa sau.

Nó cũng có thể giúp thử gọi writeToFile: nguyên tử: trên một chuỗi nền.

+0

cảm ơn vì đã bình luận về điều này. tôi đã xem xét và đo lường những gì đã dùng lâu nhất. nó đã chuyển đổi uiimage thành một đối tượng NSData. Tôi đã xem trực tuyến và tìm thấy một phương pháp hiệu quả hơn (sử dụng biểu diễn jpeg thay vì png) – SamB

Các vấn đề liên quan