Камера iPhone быстро снимает фотографии, но не может их сохранить

Я пытаюсь быстро делать и сохранять фотографии с помощью камеры, так быстро, как это может делать iPhone. Проблема в том, что они не сохраняются до конца, а затем это занимает вечность, или от 1/2 до 3/4 не сохраняются вообще (ошибка Write busy или -[NSKeyedUnarchiver initForReadingWithData:]: data is NULL).

Готов поспорить, я просто перегружаю память телефона, но не могу придумать, как с этим справиться эффективно. Стандартное приложение камеры iPhone прекрасно справляется с этим - снимает почти со скоростью 1 фото в секунду и сохраняет без проблем.

Есть идеи, как лучше управлять процессом / памятью, чтобы можно было сохранять в процессе работы, но при этом быстро снимать?

Вот немного моего кода. takePicture вызывается всякий раз, когда self.readyToTake = YES.

- (void)takePicture {
    self.delegate = self;
    [super takePicture];
    self.readyToTake = NO;
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    self.readyToTake = YES;
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}

- (void)image:(UIImage*)image didFinishSavingWithError:(NSError *)error contextInfo:(NSDictionary*)info {
    if (error)
    {
        NSLog([NSString stringWithFormat:@"** ERROR SAVING PHOTO: %@", [error localizedDescription]]);
    }
}

Спасибо за помощь!


ИЗМЕНИТЬ

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


person James Skidmore    schedule 07.07.2011    source источник


Ответы (3)


вы можете сделать это. т.е. разрешить делать следующую фотографию только после сохранения предыдущей. Также представьте пул автозапуска для управления памятью.

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    [pool drain];
}


- (void)image:(UIImage*)image didFinishSavingWithError:(NSError *)error contextInfo:(NSDictionary*)info {
    if (error)
    {
        NSLog([NSString stringWithFormat:@"** ERROR SAVING PHOTO: %@", [error localizedDescription]]);
    }
    self.readyToTake = YES;
}
person Ilanchezhian    schedule 07.07.2011
comment
Проблема с включением следующей фотографии после сохранения предыдущей заключается в том, что камера больше не снимает быстро. Для сохранения большинства фотографий требуется около 3-5 секунд. - person James Skidmore; 07.07.2011
comment
Мы можем выполнить функцию сохранения в каком-то фоновом потоке ... но все же, если это займет 3-5 секунд, это может привести к ненужному процессу ... Все зависит от оборудования, я думаю ... - person Ilanchezhian; 08.07.2011

Первое, что я попробую, - это асинхронно выгрузить эти вызовы в очередь отправки:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    self.readyToTake = YES;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
        UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    });
}

Если у вас все еще есть проблемы, я посмотрю на AVCaptureSession и друзей. Это дает вам гораздо больше контроля и в целом лучшую производительность. На портале разработчика есть отличный пример проекта, использующего этот метод: SquareCam

ИЗМЕНИТЬ

Вы также можете попробовать использовать AssetsLibrary вместо UIImageWriteToSavedPhotosAlbum (это то, что мы используем во всех наших приложениях) Что-то вроде:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    self.readyToTake = YES;
    // you probably want to create this once and keep it around as a property
    // on your controller
    ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
    [library writeImageToSavedPhotosAlbum:image.CGImageRef orientation:(ALAssetOrientation)image.orientation completionBlock:^(NSURL *assetURL, NSError *error) {
         // do whatever you need to do when the image is saved
     }];
}
person Art Gillespie    schedule 19.04.2012
comment
Спасибо, Art. Использование очереди отправки экономит примерно в 2 раза больше, чем раньше, но по-прежнему экономит около 1/3, а остальные либо приходят с Write busy, либо -[NSKeyedUnarchiver initForReadingWithData:]: data is NULL. Есть предположения? - person James Skidmore; 19.04.2012
comment
Использование AVCaptureSession действительно позволяет делать фотографии в быстром темпе, но фотографии сохраняются (с примерами, которые я видел) с использованием того же UIImageWriteToSavedPhotosAlbum. Причина, по которой они могут намного быстрее сохранять с AVCaptureSession, заключается в том, что изображения имеют размер только 480x640. Я могу сохранить так же быстро, используя текущий метод, если я уменьшу их размер до такого маленького, но мне нужны фотографии нормального размера. Я ценю вашу помощь и любые другие идеи! - person James Skidmore; 19.04.2012
comment
Фактически, вы можете получить полноразмерные фотографии с сенсора, используя AVCaptureSession с AVCaptureSessionPresetPhoto Что вы делаете в image:didFinishSavingWithError: - person Art Gillespie; 19.04.2012
comment
Еще можно попробовать использовать AssetsLibrary ... См. Мою правку. - person Art Gillespie; 19.04.2012

на сайте developer.apple.com есть один лучший пример приложения, в котором показано решение вашей проблемы. Они автоматически сохраняют фотографии с интервалом в 1 секунду, когда пользователь нажимает кнопку «по времени» вот его код, он, безусловно, поможет вам, так как я могу хранить 5 фотографий со скоростью 1 / сек.

См. Страницу MyViewController.m, и после получения изображений в массиве вы можете сохранить их в фотоальбом с помощью какой-либо функции в другой очереди.

person The iOSDev    schedule 25.04.2012