AVCaptureVideoPreviewLayer: снятие моментального снимка
Я пытаюсь подражать анимации, наблюдаемой в приложении камеры по умолчанию, где моментальный снимок видоискателя камер анимируется в углу экрана приложений.
Объект AVCaptureVideoPreviewLayer, который содержит ключ к решению этой проблемы, не очень открыт для этих требований: попытка создать копию его на новом уровне с помощью
- (id)initWithLayer:(id)layer
.. возвращает пустой слой без снимка изображения, так что здесь происходит более глубокое волшебство.
Ваши подсказки/боос приветствуются.
М.
Ответы
Ответ 1
сталкивается с теми же проблемами, с немного другого угла.
Вот возможные решения, что ни одна из них не слишком велика. IMO:
-
Вы можете добавить в AVCaptureSession как AVCaptureStillImageOutput, так и AVCaptureVideoDataOutput. Когда вы устанавливаете sessionPreset на AVCaptureSessionPresetHigh, вы начнете получать фреймы с помощью API, а при переключении на AVCaptureSessionPresetPhoto вы сможете получать реальные изображения. Поэтому, прежде чем делать снимок, вы можете переключиться на видео, получить кадр, а затем вернуться к камере. Главное предостережение заключается в том, что для камеры требуется "длительное" время (пара секунд) для переключения между видеокамерой и камерой изображения.
-
Другой вариант - использовать только выход камеры (AVCaptureStillImageOutput) и использовать UIGetScreenImage для получения снимка экрана телефона. Затем вы можете обрезать элементы управления и оставить только изображение. Это становится сложным, если вы показываете элементы управления пользовательского интерфейса над изображением. Кроме того, согласно этой почте, Apple начала отклонять приложения, которые используют эту функцию (это всегда было iffy).
-
Помимо этого, я также попытался сыграть с AVCaptureVideoPreviewLayer. Там это сообщение, чтобы сохранить UIView или CALayer в UIImage. Но все это создает четкие или белые изображения. Я попытался получить доступ к слою, слою представления, суперслою, PresentationLayer, modelLayer, но безрезультатно. Я думаю, что данные в AVCaptureVideoPreviewLayer являются очень внутренними и не являются частью инфраструктуры обычного уровня.
Надеюсь, это поможет,
Одед.
Ответ 2
Я думаю, вы должны добавить AVCaptureVideoDataOutput
к текущему сеансу с помощью:
AVCaptureVideoDataOutput *videoOutput = [[AVCaptureVideoDataOutput alloc] init];
videoOutput.videoSettings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) };
[session addOutput:videoOutput];
dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL);
[videoOutput setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);
Затем реализуем метод делегата ниже, чтобы получить снимок изображения:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
UIImage *image = [self imageFromSampleBuffer:sampleBuffer];
// Add your code here that uses the image.
dispatch_async(dispatch_get_main_queue(), ^{
_imageView.image = image;
});
}
Это будет потреблять память и уменьшать производительность приложения. Чтобы улучшить, вы также можете оптимизировать свой AVCaptureVideoDataOutput
с помощью:
videoOutput.minFrameDuration = CMTimeMake(1, 15);
Вы также можете использовать alwaysDiscardsLateVideoFrames
.
Ответ 3
есть два способа захвата кадров предварительного просмотра. AVCaptureVideoDataOutput и AVCaptureStillImageOutput:)
ваш сеанс захвата настроен для захвата видеокадров, а затем создайте слой с помощью cgimage из выбранного кадра. если он настроится на неподвижные изображения, дождитесь получения неподвижного изображения и сделайте свой слой уменьшенной версией этого cgimage. если у вас еще нет вывода на вашем сеансе, вам придется добавить тот, который я думаю.
Ответ 4
Начиная с iOS 7, вы можете использовать UIView:: snapshotViewAfterScreenUpdates для моментального снимка UIView, обертывающего ваш AVCaptureVideoPreviewLayer. Это не то же самое, что UIGetScreenImage
, которое отклонит ваше приложение.
UIView *snapshot = [self.containerView snapshotViewAfterScreenUpdates:YES];
Вспомните старый способ превращения представления в изображение. По какой-то причине он работал над всем, кроме предварительного просмотра камеры:
UIGraphicsBeginImageContextWithOptions(self.containerView.bounds.size, NO, [UIScreen mainScreen].scale);
[self.containerView drawViewHierarchyInRect:self.containerView.bounds afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();