Ускорьте сохранение изображения - iOS - PullRequest
6 голосов
/ 06 июля 2011

Я работаю над мини-проектом, который позже будет включен в новый проект. Это в основном тестовая единица.

Я создаю AVCaptureSession, а затем создаю метод для OutputSampleBufferDelegate. В этом методе я конвертирую sampleBuffer в UIImage и сохраняю UIImage. Когда я запускаю приложение на своем iPhone 4, оно может сохранять только 2-3 изображения в секунду. Должен быть более эффективный способ сохранить изображение.

Может кто-нибудь помочь мне ускорить его?

Спасибо!

много кода отсюда

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

Ответы [ 2 ]

7 голосов
/ 01 октября 2011

Используя этот код, я могу сэкономить время до 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];
}
4 голосов
/ 24 сентября 2011

Не могли бы вы посмотреть, сколько изображений вы можете сгенерировать, если вы закомментируете следующую строку в вашем первом методе:

[imageData writeToFile:finalPath atomically:YES];

Причина, по которой я говорю, что вы собираетесь потратить много времени на запись этого образа на диск. Было бы интересно посмотреть, как это работает без записи изображений на диск. По крайней мере, таким образом вы будете знать, все ли время потрачено на создание образа, а не на его сохранение. Или вы можете сделать так, как упомянул другой плакат, и использовать инструменты, чтобы определить, как долго вы находитесь в каждом методе.

Если окажется, что запись изображений на диск занимает слишком много времени, тогда я предлагаю попробовать реализовать механизм кэширования, который будет кэшировать изображения в памяти и записывать их на диск позже.

Может также помочь попытаться вызвать writeToFile: atomically: в фоновом потоке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...