Partilhar via


Controles manuais de câmera no Xamarin.iOS

Os controles manuais da câmera, fornecidos pelo AVFoundation Framework no iOS 8, permitem que um aplicativo móvel assuma o controle total sobre a câmera de um dispositivo iOS. Esse nível refinado de controle pode ser usado para criar aplicativos de câmera de nível profissional e fornecer composições de artistas ajustando os parâmetros da câmera enquanto tira uma imagem estática ou vídeo.

Esses controles também podem ser úteis no desenvolvimento de aplicações científicas ou industriais, onde os resultados são menos voltados para a exatidão ou beleza da imagem e são mais voltados para destacar alguma característica ou elemento da imagem que está sendo tirada.

Objetos de captura AVFoundation

Seja gravando vídeos ou imagens estáticas usando a câmera em um dispositivo iOS, o processo usado para capturar essas imagens é basicamente o mesmo. Isso se aplica a aplicativos que usam os controles de câmera automatizados padrão ou aqueles que aproveitam os novos controles manuais de câmera:

Visão geral dos objetos de captura AVFoundation

A entrada é obtida de um AVCaptureDeviceInput para um AVCaptureSession por meio de um AVCaptureConnection. O resultado é a saída como uma imagem estática ou como um fluxo de vídeo. Todo o processo é controlado por um AVCaptureDevice.

Controles manuais fornecidos

Usando as novas APIs fornecidas pelo iOS 8, o aplicativo pode assumir o controle dos seguintes recursos da câmera:

  • Foco manual – Ao permitir que o usuário final assuma o controle do foco diretamente, um aplicativo pode fornecer mais controle sobre a imagem tirada.
  • Exposição manual – Ao fornecer controle manual sobre a exposição, um aplicativo pode fornecer mais liberdade aos usuários e permitir que eles obtenham uma aparência estilizada.
  • Balanço de branco manual – O balanço de branco é usado para ajustar a cor de uma imagem, geralmente para torná-la realista. Diferentes fontes de luz têm diferentes temperaturas de cor e as configurações da câmera usadas para capturar uma imagem são ajustadas para compensar essas diferenças. Novamente, ao permitir que o usuário controle sobre o balanço de branco, os usuários podem fazer ajustes que não podem ser feitos automaticamente.

O iOS 8 fornece extensões e aprimoramentos para APIs iOS existentes para fornecer esse controle refinado sobre o processo de captura de imagem.

Requisitos

Os itens a seguir são necessários para concluir as etapas apresentadas neste artigo:

  • Xcode 7+ e iOS 8 ou mais recente – As APIs Xcode 7 e iOS 8 ou mais recentes da Apple precisam ser instaladas e configuradas no computador do desenvolvedor.
  • Visual Studio para Mac – A versão mais recente do Visual Studio para Mac deve ser instalada e configurada no dispositivo do usuário.
  • Dispositivo iOS 8 – Um dispositivo iOS executando a versão mais recente do iOS 8. Os recursos da câmera não podem ser testados no Simulador do iOS.

Configuração geral de captura AV

Ao gravar vídeo em um dispositivo iOS, há algum código de configuração geral que é sempre necessário. Esta seção abordará a configuração mínima necessária para gravar vídeo da câmera do dispositivo iOS e exibir esse vídeo em tempo real em um UIImageViewarquivo .

Delegado de buffer de exemplo de saída

Uma das primeiras coisas necessárias será um delegado para monitorar o buffer de Saída de Exemplo e exibir uma imagem capturada do buffer para a UIImageView na interface do usuário do aplicativo.

A rotina a seguir monitorará o Buffer de Exemplo e atualizará a interface do usuário:

using System;
using Foundation;
using UIKit;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using AVFoundation;
using CoreVideo;
using CoreMedia;
using CoreGraphics;

namespace ManualCameraControls
{
    public class OutputRecorder : AVCaptureVideoDataOutputSampleBufferDelegate
    {
        #region Computed Properties
        public UIImageView DisplayView { get; set; }
        #endregion

        #region Constructors
        public OutputRecorder ()
        {

        }
        #endregion

        #region Private Methods
        private UIImage GetImageFromSampleBuffer(CMSampleBuffer sampleBuffer) {

            // Get a pixel buffer from the sample buffer
            using (var pixelBuffer = sampleBuffer.GetImageBuffer () as CVPixelBuffer) {
                // Lock the base address
                pixelBuffer.Lock (0);

                // Prepare to decode buffer
                var flags = CGBitmapFlags.PremultipliedFirst | CGBitmapFlags.ByteOrder32Little;

                // Decode buffer - Create a new colorspace
                using (var cs = CGColorSpace.CreateDeviceRGB ()) {

                    // Create new context from buffer
                    using (var context = new CGBitmapContext (pixelBuffer.BaseAddress,
                        pixelBuffer.Width,
                        pixelBuffer.Height,
                        8,
                        pixelBuffer.BytesPerRow,
                        cs,
                        (CGImageAlphaInfo)flags)) {

                        // Get the image from the context
                        using (var cgImage = context.ToImage ()) {

                            // Unlock and return image
                            pixelBuffer.Unlock (0);
                            return UIImage.FromImage (cgImage);
                        }
                    }
                }
            }
        }
        #endregion

        #region Override Methods
        public override void DidOutputSampleBuffer (AVCaptureOutput captureOutput, CMSampleBuffer sampleBuffer, AVCaptureConnection connection)
        {
            // Trap all errors
            try {
                // Grab an image from the buffer
                var image = GetImageFromSampleBuffer(sampleBuffer);

                // Display the image
                if (DisplayView !=null) {
                    DisplayView.BeginInvokeOnMainThread(() => {
                        // Set the image
                        if (DisplayView.Image != null) DisplayView.Image.Dispose();
                        DisplayView.Image = image;

                        // Rotate image to the correct display orientation
                        DisplayView.Transform = CGAffineTransform.MakeRotation((float)Math.PI/2);
                    });
                }

                // IMPORTANT: You must release the buffer because AVFoundation has a fixed number
                // of buffers and will stop delivering frames if it runs out.
                sampleBuffer.Dispose();
            }
            catch(Exception e) {
                // Report error
                Console.WriteLine ("Error sampling buffer: {0}", e.Message);
            }
        }
        #endregion
    }
}

Com essa rotina em vigor, o AppDelegate pode ser modificado para abrir uma sessão de captura AV para gravar um feed de vídeo ao vivo.

Criando uma sessão de captura AV

A sessão de captura AV é usada para controlar a gravação de vídeo ao vivo da câmera do dispositivo iOS e é necessária para colocar o vídeo em um aplicativo iOS. Como o ManualCameraControl aplicativo de exemplo está usando a sessão de captura em vários locais diferentes, ele será configurado e AppDelegate disponibilizado para todo o aplicativo.

Faça o seguinte para modificar o aplicativo AppDelegate e adicionar o código necessário:

  1. Clique duas vezes no AppDelegate.cs arquivo no Gerenciador de Soluções para abri-lo para edição.

  2. Adicione o seguinte usando as instruções na parte superior do arquivo :

    using System;
    using Foundation;
    using UIKit;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using AVFoundation;
    using CoreVideo;
    using CoreMedia;
    using CoreGraphics;
    using CoreFoundation;
    
  3. Adicione as seguintes variáveis privadas e propriedades computadas à AppDelegate classe:

    #region Private Variables
    private NSError Error;
    #endregion
    
    #region Computed Properties
    public override UIWindow Window {get;set;}
    public bool CameraAvailable { get; set; }
    public AVCaptureSession Session { get; set; }
    public AVCaptureDevice CaptureDevice { get; set; }
    public OutputRecorder Recorder { get; set; }
    public DispatchQueue Queue { get; set; }
    public AVCaptureDeviceInput Input { get; set; }
    #endregion
    
  4. Substitua o método concluído e altere-o para:

    public override void FinishedLaunching (UIApplication application)
    {
        // Create a new capture session
        Session = new AVCaptureSession ();
        Session.SessionPreset = AVCaptureSession.PresetMedium;
    
        // Create a device input
        CaptureDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video);
        if (CaptureDevice == null) {
            // Video capture not supported, abort
            Console.WriteLine ("Video recording not supported on this device");
            CameraAvailable = false;
            return;
        }
    
        // Prepare device for configuration
        CaptureDevice.LockForConfiguration (out Error);
        if (Error != null) {
            // There has been an issue, abort
            Console.WriteLine ("Error: {0}", Error.LocalizedDescription);
            CaptureDevice.UnlockForConfiguration ();
            return;
        }
    
        // Configure stream for 15 frames per second (fps)
        CaptureDevice.ActiveVideoMinFrameDuration = new CMTime (1, 15);
    
        // Unlock configuration
        CaptureDevice.UnlockForConfiguration ();
    
        // Get input from capture device
        Input = AVCaptureDeviceInput.FromDevice (CaptureDevice);
        if (Input == null) {
            // Error, report and abort
            Console.WriteLine ("Unable to gain input from capture device.");
            CameraAvailable = false;
            return;
        }
    
        // Attach input to session
        Session.AddInput (Input);
    
        // Create a new output
        var output = new AVCaptureVideoDataOutput ();
        var settings = new AVVideoSettingsUncompressed ();
        settings.PixelFormatType = CVPixelFormatType.CV32BGRA;
        output.WeakVideoSettings = settings.Dictionary;
    
        // Configure and attach to the output to the session
        Queue = new DispatchQueue ("ManCamQueue");
        Recorder = new OutputRecorder ();
        output.SetSampleBufferDelegate (Recorder, Queue);
        Session.AddOutput (output);
    
        // Let tabs know that a camera is available
        CameraAvailable = true;
    }
    
  5. Salve as alterações no arquivo.

Com esse código em vigor, os controles manuais da câmera podem ser facilmente implementados para experimentação e teste.

Foco manual

Ao permitir que o usuário final assuma o controle do foco diretamente, um aplicativo pode fornecer mais controle artístico sobre a imagem tirada.

Por exemplo, um fotógrafo profissional pode suavizar o foco de uma imagem para obter um efeito Bokeh. Ou crie um Efeito de Atração de Foco.

Para cientistas ou um escritor de aplicações médicas, o aplicativo pode querer mover programaticamente a lente para experimentos. De qualquer forma, a nova API permite que o usuário final ou o aplicativo assuma o controle do foco no momento em que a imagem é tirada.

Como funciona o foco

Antes de discutir os detalhes do controle de foco em um aplicativo IOS 8. Vamos dar uma olhada rápida em como o foco funciona em um dispositivo iOS:

Como o foco funciona em um dispositivo iOS

A luz entra na lente da câmera no dispositivo iOS e é focada em um sensor de imagem. A distância da lente do sensor controla onde está o ponto focal (a área onde a imagem aparecerá mais nítida), em relação ao sensor. Quanto mais longe a lente estiver do sensor, os objetos distantes parecem mais nítidos e os objetos mais próximos parecem mais nítidos.

Em um dispositivo iOS, a lente é movida para mais perto ou mais longe do sensor por ímãs e molas. Como resultado, o posicionamento exato da lente é impossível, pois varia de dispositivo para dispositivo e pode ser afetado por parâmetros como a orientação do dispositivo ou a idade do dispositivo e da mola.

Termos de foco importantes

Ao lidar com foco, existem alguns termos com os quais o desenvolvedor deve estar familiarizado:

  • Profundidade de campo – A distância entre os objetos mais próximos e mais distantes em foco.
  • Macro - Esta é a extremidade próxima do espectro de foco e é a distância mais próxima na qual a lente pode focar.
  • Infinito – Esta é a extremidade mais distante do espectro de foco e é a distância mais distante na qual a lente pode focar.
  • Distância hiperfocal – Este é o ponto no espectro de foco em que o objeto mais distante no quadro está na extremidade do foco. Em outras palavras, esta é a posição focal que maximiza a profundidade de campo.
  • Posição da lente - Isso é o que controla todos os outros termos acima. Esta é a distância da lente do sensor e, portanto, do controlador de foco.

Com esses termos e conhecimento em mente, os novos controles de foco manual podem ser implementados com sucesso em um aplicativo iOS 8.

Controles de foco existentes

O iOS 7 e versões anteriores forneciam controles de foco existentes por meio da FocusModepropriedade como:

  • AVCaptureFocusModeLocked – O foco está travado em um único ponto de foco.
  • AVCaptureFocusModeAutoFocus – A câmera varre a lente por todos os pontos focais até encontrar um foco nítido e depois permanece lá.
  • AVCaptureFocusModeContinuousAutoFocus – A câmera foca novamente sempre que detecta uma condição de desfoque.

Os controles existentes também forneceram um ponto de interesse configurável por meio daFocusPointOfInterest propriedade, para que o usuário possa tocar para focar em uma área específica. O aplicativo também pode rastrear o movimento da lente monitorando a IsAdjustingFocus propriedade.

Além disso, a restrição de AutoFocusRangeRestriction alcance foi fornecida pela propriedade como:

  • AVCaptureAutoFocusRangeRestrictionNear – Restringe o foco automático a profundidades próximas. Útil em situações como a leitura de um QR Code ou código de barras.
  • AVCaptureAutoFocusRangeRestrictionFar – Restringe o foco automático a profundidades distantes. Útil em situações em que objetos que são conhecidos por serem irrelevantes estão no campo de visão (por exemplo, uma moldura de janela).

Finalmente, há a SmoothAutoFocus propriedade que desacelera o algoritmo de foco automático e o percorre em incrementos menores para evitar artefatos móveis durante a gravação de vídeo.

Novos controles de foco no iOS 8

Além dos recursos já fornecidos pelo iOS 7 e superior, os seguintes recursos agora estão disponíveis para controlar o foco no iOS 8:

  • Controle manual total da posição da lente ao travar o foco.
  • Observação de valor-chave da posição da lente em qualquer modo de foco.

Para implementar os recursos acima, a AVCaptureDevice classe foi modificada para incluir uma propriedade somente LensPosition leitura usada para obter a posição atual da lente da câmera.

Para assumir o controle manual da posição da lente, o dispositivo de captura deve estar no modo de foco bloqueado. Exemplo:

CaptureDevice.FocusMode = AVCaptureFocusMode.Locked;

O SetFocusModeLocked método do dispositivo de captura é usado para ajustar a posição da lente da câmera. Uma rotina de retorno de chamada opcional pode ser fornecida para obter notificação quando a alteração entrar em vigor. Exemplo:

ThisApp.CaptureDevice.LockForConfiguration(out Error);
ThisApp.CaptureDevice.SetFocusModeLocked(Position.Value,null);
ThisApp.CaptureDevice.UnlockForConfiguration();

Como visto no código acima, o dispositivo de captura deve ser bloqueado para configuração antes que uma alteração na posição da lente possa ser feita. Os valores válidos de Posição da lente estão entre 0,0 e 1,0.

Exemplo de foco manual

Com o código de Configuração Geral de Captura AV em vigor, um UIViewController pode ser adicionado ao Storyboard do aplicativo e configurado da seguinte maneira:

Um UIViewController pode ser adicionado ao Storyboard dos aplicativos e configurado conforme mostrado aqui para o exemplo de foco manual.

A visualização contém os seguintes elementos principais:

  • A UIImageView que exibirá o feed de vídeo.
  • A UISegmentedControl que mudará o Modo de Foco de Automático para Bloqueado.
  • A UISlider que mostrará e atualizará a posição atual da lente.

Faça o seguinte para conectar o controlador de exibição para Controle de foco manual:

  1. Adicione as seguintes instruções using:

    using System;
    using Foundation;
    using UIKit;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using AVFoundation;
    using CoreVideo;
    using CoreMedia;
    using CoreGraphics;
    using CoreFoundation;
    using System.Timers;
    
  2. Adicione as seguintes variáveis privadas:

    #region Private Variables
    private NSError Error;
    private bool Automatic = true;
    #endregion
    
  3. Adicione as seguintes propriedades computadas:

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    public Timer SampleTimer { get; set; }
    #endregion
    
  4. Substitua o ViewDidLoad método e adicione o seguinte código:

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
    
        // Hide no camera label
        NoCamera.Hidden = ThisApp.CameraAvailable;
    
        // Attach to camera view
        ThisApp.Recorder.DisplayView = CameraView;
    
        // Create a timer to monitor and update the UI
        SampleTimer = new Timer (5000);
        SampleTimer.Elapsed += (sender, e) => {
            // Update position slider
            Position.BeginInvokeOnMainThread(() =>{
                Position.Value = ThisApp.Input.Device.LensPosition;
            });
        };
    
        // Watch for value changes
        Segments.ValueChanged += (object sender, EventArgs e) => {
    
            // Lock device for change
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
    
            // Take action based on the segment selected
            switch(Segments.SelectedSegment) {
            case 0:
                // Activate auto focus and start monitoring position
                Position.Enabled = false;
                ThisApp.CaptureDevice.FocusMode = AVCaptureFocusMode.ContinuousAutoFocus;
                SampleTimer.Start();
                Automatic = true;
                break;
            case 1:
                // Stop auto focus and allow the user to control the camera
                SampleTimer.Stop();
                ThisApp.CaptureDevice.FocusMode = AVCaptureFocusMode.Locked;
                Automatic = false;
                Position.Enabled = true;
                break;
            }
    
            // Unlock device
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    
        // Monitor position changes
        Position.ValueChanged += (object sender, EventArgs e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic) return;
    
            // Update Focus position
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
            ThisApp.CaptureDevice.SetFocusModeLocked(Position.Value,null);
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    }
    
  5. Substitua o ViewDidAppear método e adicione o seguinte para iniciar a gravação quando a exibição for carregada:

    public override void ViewDidAppear (bool animated)
    {
        base.ViewDidAppear (animated);
    
        // Start udating the display
        if (ThisApp.CameraAvailable) {
            // Remap to this camera view
            ThisApp.Recorder.DisplayView = CameraView;
    
            ThisApp.Session.StartRunning ();
            SampleTimer.Start ();
        }
    }
    
  6. Com a câmera no modo Automático, o controle deslizante se moverá automaticamente à medida que a câmera ajusta o foco:

    O controle deslizante se moverá automaticamente à medida que a câmera ajusta o foco neste aplicativo de exemplo

  7. Toque no segmento bloqueado e arraste o controle deslizante de posição para ajustar a posição da lente manualmente:

    Ajustar manualmente a posição da objetiva

  8. Pare o aplicativo.

O código acima mostrou como monitorar a posição da lente quando a câmera está no modo Automático ou usar um controle deslizante para controlar a posição da lente quando ela está no modo Bloqueado.

Exposição manual

A exposição refere-se ao brilho de uma imagem em relação ao brilho da fonte e é determinada pela quantidade de luz que atinge o sensor, por quanto tempo e pelo nível de ganho do sensor (mapeamento ISO). Ao fornecer controle manual sobre a exposição, um aplicativo pode fornecer mais liberdade ao usuário final e permitir que ele obtenha uma aparência estilizada.

Usando os controles de exposição manual, o usuário pode tirar uma imagem de irrealisticamente clara para escura e temperamental:

Uma amostra de uma imagem mostrando a exposição de irrealisticamente claro a escuro e temperamental

Novamente, isso pode ser feito automaticamente usando o controle programático para aplicações científicas ou por meio de controles manuais fornecidos pela interface do usuário dos aplicativos. De qualquer forma, as novas APIs de exposição do iOS 8 fornecem controle refinado sobre as configurações de exposição da câmera.

Como funciona a exposição

Antes de discutir os detalhes do controle da exposição em um aplicativo IOS 8. Vamos dar uma olhada rápida em como funciona a exposição:

Como funciona a exposição

Os três elementos básicos que se unem para controlar a exposição são:

  • Velocidade do obturador – Este é o período de tempo que o obturador está aberto para permitir que a luz entre no sensor da câmera. Quanto menor o tempo que o obturador está aberto, menos luz é deixada entrar e mais nítida é a imagem (menos desfoque de movimento). Quanto mais tempo o obturador estiver aberto, mais luz será deixada entrar e mais desfoque de movimento ocorrerá.
  • Mapeamento ISO – Este é um termo emprestado da fotografia de filme e refere-se à sensibilidade dos produtos químicos do filme à luz. Valores ISO baixos no filme têm menos granulação e reprodução de cores mais finas; valores ISO baixos em sensores digitais têm menos ruído do sensor, mas menos brilho. Quanto maior o valor ISO, mais brilhante é a imagem, mas com mais ruído do sensor. "ISO" em um sensor digital é uma medida de ganho eletrônico, não um recurso físico.
  • Abertura da lente – Este é o tamanho da abertura da lente. Em todos os dispositivos iOS, a abertura da lente é fixa, portanto, os únicos dois valores que podem ser usados para ajustar a exposição são a velocidade do obturador e o ISO.

Como funciona a exposição automática contínua

Antes de aprender como funciona a exposição manual, é uma boa ideia entender como a exposição automática contínua funciona em um dispositivo iOS.

Como funciona a exposição automática contínua em um dispositivo iOS

O primeiro é o Bloco de Exposição Automática, ele tem o trabalho de calcular a exposição ideal e está continuamente sendo alimentado com Estatísticas de Medição. Ele usa essas informações para calcular a combinação ideal de ISO e velocidade do obturador para deixar a cena bem iluminada. Este ciclo é conhecido como AE Loop.

Como funciona a exposição bloqueada

A seguir, vamos examinar como a exposição bloqueada funciona em dispositivos iOS.

Como funciona a exposição bloqueada em dispositivos iOS

Novamente, você tem o Bloco de exposição automática que está tentando calcular os valores ideais de iOS e Duração. No entanto, neste modo, o Bloco AE é desconectado do mecanismo de Estatísticas de Medição.

Controles de exposição existentes

iOS 7 e superior, fornecem os seguintes controles de exposição existentes por meio da ExposureMode propriedade:

  • AVCaptureExposureModeLocked – Amostra da cena uma vez e usa esses valores em toda a cena.
  • AVCaptureExposureModeContinuousAutoExposure – Amostras da cena continuamente para garantir que esteja bem iluminada.

O ExposurePointOfInterest pode ser usado para tocar para expor a cena selecionando um objeto de destino para expor, e o aplicativo pode monitorar a propriedade para ver quando a AdjustingExposure exposição está sendo ajustada.

Novos controles de exposição no iOS 8

Além dos recursos já fornecidos pelo iOS 7 e superior, os seguintes recursos agora estão disponíveis para controlar a exposição no iOS 8:

  • Exposição personalizada totalmente manual.
  • Obter, definir e valor-chave Observe o IOS e a velocidade do obturador (duração).

Para implementar os recursos acima, um novo AVCaptureExposureModeCustom modo foi adicionado. Quando a câmera está no modo personalizado, o seguinte código pode ser usado para ajustar a duração da exposição e o ISO:

CaptureDevice.LockForConfiguration(out Error);
CaptureDevice.LockExposure(DurationValue,ISOValue,null);
CaptureDevice.UnlockForConfiguration();

Nos modos Automático e Bloqueado, o aplicativo pode ajustar o Bias da rotina de exposição automática usando o seguinte código:

CaptureDevice.LockForConfiguration(out Error);
CaptureDevice.SetExposureTargetBias(Value,null);
CaptureDevice.UnlockForConfiguration();

Os intervalos de configuração mínimo e máximo dependem do dispositivo em que o aplicativo está sendo executado, portanto, eles nunca devem ser codificados. Em vez disso, use as seguintes propriedades para obter os intervalos de valores mínimo e máximo:

  • CaptureDevice.MinExposureTargetBias
  • CaptureDevice.MaxExposureTargetBias
  • CaptureDevice.ActiveFormat.MinISO
  • CaptureDevice.ActiveFormat.MaxISO
  • CaptureDevice.ActiveFormat.MinExposureDuration
  • CaptureDevice.ActiveFormat.MaxExposureDuration

Como visto no código acima, o dispositivo de captura deve ser bloqueado para configuração antes que uma alteração na exposição possa ser feita.

Exposição manual Example

Com o código de Configuração Geral de Captura AV em vigor, um UIViewController pode ser adicionado ao Storyboard do aplicativo e configurado da seguinte maneira:

Um UIViewController pode ser adicionado ao Storyboard dos aplicativos e configurado conforme mostrado aqui para o exemplo de exposição manual.

A visualização contém os seguintes elementos principais:

  • A UIImageView que exibirá o feed de vídeo.
  • A UISegmentedControl que mudará o Modo de Foco de Automático para Bloqueado.
  • Quatro UISlider controles que mostrarão e atualizarão o Deslocamento, Duração, ISO e Desvio.

Faça o seguinte para conectar o controlador de exibição para Controle de exposição manual:

  1. Adicione as seguintes instruções using:

    using System;
    using Foundation;
    using UIKit;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using AVFoundation;
    using CoreVideo;
    using CoreMedia;
    using CoreGraphics;
    using CoreFoundation;
    using System.Timers;
    
  2. Adicione as seguintes variáveis privadas:

    #region Private Variables
    private NSError Error;
    private bool Automatic = true;
    private nfloat ExposureDurationPower = 5;
    private nfloat ExposureMinimumDuration = 1.0f/1000.0f;
    #endregion
    
  3. Adicione as seguintes propriedades computadas:

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    public Timer SampleTimer { get; set; }
    #endregion
    
  4. Substitua o ViewDidLoad método e adicione o seguinte código:

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
    
        // Hide no camera label
        NoCamera.Hidden = ThisApp.CameraAvailable;
    
        // Attach to camera view
        ThisApp.Recorder.DisplayView = CameraView;
    
        // Set min and max values
        Offset.MinValue = ThisApp.CaptureDevice.MinExposureTargetBias;
        Offset.MaxValue = ThisApp.CaptureDevice.MaxExposureTargetBias;
    
        Duration.MinValue = 0.0f;
        Duration.MaxValue = 1.0f;
    
        ISO.MinValue = ThisApp.CaptureDevice.ActiveFormat.MinISO;
        ISO.MaxValue = ThisApp.CaptureDevice.ActiveFormat.MaxISO;
    
        Bias.MinValue = ThisApp.CaptureDevice.MinExposureTargetBias;
        Bias.MaxValue = ThisApp.CaptureDevice.MaxExposureTargetBias;
    
        // Create a timer to monitor and update the UI
        SampleTimer = new Timer (5000);
        SampleTimer.Elapsed += (sender, e) => {
            // Update position slider
            Offset.BeginInvokeOnMainThread(() =>{
                Offset.Value = ThisApp.Input.Device.ExposureTargetOffset;
            });
    
            Duration.BeginInvokeOnMainThread(() =>{
                var newDurationSeconds = CMTimeGetSeconds(ThisApp.Input.Device.ExposureDuration);
                var minDurationSeconds = Math.Max(CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MinExposureDuration), ExposureMinimumDuration);
                var maxDurationSeconds = CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MaxExposureDuration);
                var p = (newDurationSeconds - minDurationSeconds) / (maxDurationSeconds - minDurationSeconds);
                Duration.Value = (float)Math.Pow(p, 1.0f/ExposureDurationPower);
            });
    
            ISO.BeginInvokeOnMainThread(() => {
                ISO.Value = ThisApp.Input.Device.ISO;
            });
    
            Bias.BeginInvokeOnMainThread(() => {
                Bias.Value = ThisApp.Input.Device.ExposureTargetBias;
            });
        };
    
        // Watch for value changes
        Segments.ValueChanged += (object sender, EventArgs e) => {
    
            // Lock device for change
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
    
            // Take action based on the segment selected
            switch(Segments.SelectedSegment) {
            case 0:
                // Activate auto exposure and start monitoring position
                Duration.Enabled = false;
                ISO.Enabled = false;
                ThisApp.CaptureDevice.ExposureMode = AVCaptureExposureMode.ContinuousAutoExposure;
                SampleTimer.Start();
                Automatic = true;
                break;
            case 1:
                // Lock exposure and allow the user to control the camera
                SampleTimer.Stop();
                ThisApp.CaptureDevice.ExposureMode = AVCaptureExposureMode.Locked;
                Automatic = false;
                Duration.Enabled = false;
                ISO.Enabled = false;
                break;
            case 2:
                // Custom exposure and allow the user to control the camera
                SampleTimer.Stop();
                ThisApp.CaptureDevice.ExposureMode = AVCaptureExposureMode.Custom;
                Automatic = false;
                Duration.Enabled = true;
                ISO.Enabled = true;
                break;
            }
    
            // Unlock device
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    
        // Monitor position changes
        Duration.ValueChanged += (object sender, EventArgs e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic) return;
    
            // Calculate value
            var p = Math.Pow(Duration.Value,ExposureDurationPower);
            var minDurationSeconds = Math.Max(CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MinExposureDuration),ExposureMinimumDuration);
            var maxDurationSeconds = CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MaxExposureDuration);
            var newDurationSeconds = p * (maxDurationSeconds - minDurationSeconds) +minDurationSeconds;
    
            // Update Focus position
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
            ThisApp.CaptureDevice.LockExposure(CMTime.FromSeconds(p,1000*1000*1000),ThisApp.CaptureDevice.ISO,null);
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    
        ISO.ValueChanged += (object sender, EventArgs e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic) return;
    
            // Update Focus position
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
            ThisApp.CaptureDevice.LockExposure(ThisApp.CaptureDevice.ExposureDuration,ISO.Value,null);
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    
        Bias.ValueChanged += (object sender, EventArgs e) => {
    
            // If we are in the automatic mode, ignore changes
            // if (Automatic) return;
    
            // Update Focus position
            ThisApp.CaptureDevice.LockForConfiguration(out Error);
            ThisApp.CaptureDevice.SetExposureTargetBias(Bias.Value,null);
            ThisApp.CaptureDevice.UnlockForConfiguration();
        };
    }
    
  5. Substitua o ViewDidAppear método e adicione o seguinte para iniciar a gravação quando a exibição for carregada:

    public override void ViewDidAppear (bool animated)
    {
        base.ViewDidAppear (animated);
    
        // Start udating the display
        if (ThisApp.CameraAvailable) {
            // Remap to this camera view
            ThisApp.Recorder.DisplayView = CameraView;
    
            ThisApp.Session.StartRunning ();
            SampleTimer.Start ();
        }
    }
    
  6. Com a câmera no modo Automático, os controles deslizantes se moverão automaticamente à medida que a câmera ajusta a exposição:

    Os controles deslizantes se moverão automaticamente à medida que a câmera ajusta a exposição

  7. Toque no segmento Bloqueado e arraste o controle deslizante Desvio para ajustar o desvio da exposição automática manualmente:

    Ajustando o viés da exposição automática manualmente

  8. Toque no segmento Personalizado e arraste os controles deslizantes Duração e ISO para controlar manualmente a exposição:

    Arraste os controles deslizantes Duração e ISO para controlar manualmente a exposição

  9. Pare o aplicativo.

O código acima mostrou como monitorar as configurações de exposição quando a câmera está no modo Automático e como usar controles deslizantes para controlar a exposição quando ela está nos modos Bloqueado ou Personalizado.

Balanço de branco manual

Os controles de balanço de branco permitem que os usuários ajustem o equilíbrio do colosr em uma imagem para torná-los mais realistas. Diferentes fontes de luz têm diferentes temperaturas de cor e as configurações da câmera usadas para capturar uma imagem devem ser ajustadas para compensar essas diferenças. Novamente, ao permitir que o usuário controle sobre o balanço de branco, ele pode fazer ajustes profissionais que as rotinas automáticas são incapazes de obter efeitos artísticos.

Uma imagem de amostra mostrando os ajustes manuais de balanço de branco

Por exemplo, a luz do dia tem um tom azulado, enquanto as luzes incandescentes de tungstênio têm uma tonalidade amarelo-laranja mais quente. (Confusamente, as cores "frias" têm temperaturas de cor mais altas do que as cores "quentes". As temperaturas de cor são uma medida física, não perceptiva.)

A mente humana é muito boa em compensar as diferenças na temperatura da cor, mas isso é algo que uma câmera não pode fazer. A câmera funciona aumentando a cor no espectro oposto para ajustar as diferenças de cor.

A nova API de exposição do iOS 8 permite que o aplicativo assuma o controle do processo e forneça controle refinado sobre as configurações de balanço de branco da câmera.

Como funciona o balanço de branco

Antes de discutir os detalhes do controle do balanço de branco em um aplicativo IOS 8. Vamos dar uma olhada rápida em como funciona o balanço de branco:

No estudo da percepção de cores, o espaço de cores CIE 1931 RGB e o espaço de cores CIE 1931 XYZ são os primeiros espaços de cores matematicamente definidos. Eles foram criados pela Comissão Internacional de Iluminação (CIE) em 1931.

O espaço de cores CIE 1931 RGB e o espaço de cores CIE 1931 XYZ

O gráfico acima nos mostra todas as cores visíveis ao olho humano, do azul profundo ao verde brilhante e ao vermelho brilhante. Qualquer ponto no diagrama pode ser plotado com um valor X e Y, conforme mostrado no gráfico acima.

Como visível no gráfico, existem valores X e Y que podem ser plotados no gráfico que estariam fora do alcance da visão humana e, como resultado, essas cores não podem ser reproduzidas por uma câmera.

A curva menor no gráfico acima é chamada de locus planckiano, que expressa a temperatura da cor (em graus kelvin), com números mais altos no lado azul (mais quente) e números mais baixos no lado vermelho (mais frio). Eles são úteis para situações típicas de iluminação.

Em condições de iluminação mistas, os ajustes do balanço de branco precisarão se desviar do Locus Planckiano para fazer as alterações necessárias. Nessas situações, o ajuste precisará ser deslocado para o lado verde ou vermelho/magenta da escala CIE.

Os dispositivos iOS compensam as projeções de cores aumentando o ganho de cor oposta. Por exemplo, se uma cena tiver muito azul, o ganho de vermelho será aumentado para compensar. Esses valores de ganho são calibrados para dispositivos específicos, portanto, dependem do dispositivo.

Controles de balanço de branco existentes

O iOS 7 e superior forneciam os seguintes controles de Balanço de Branco existentes por meio WhiteBalanceMode da propriedade:

  • AVCapture WhiteBalance ModeLocked – Faz uma amostra da cena uma vez e usa esses valores em toda a cena.
  • AVCapture WhiteBalance ModeContinuousAutoExposure – Amostras da cena continuamente para garantir que ela esteja bem equilibrada.

E o aplicativo pode monitorar a propriedade para ver quando a AdjustingWhiteBalance exposição está sendo ajustada.

Novos controles de balanço de branco no iOS 8

Além dos recursos já fornecidos pelo iOS 7 e superior, os seguintes recursos agora estão disponíveis para controlar o Balanço de Branco no iOS 8:

  • Controle totalmente manual dos ganhos RGB do dispositivo.
  • Obter, definir e valor-chave Observe os ganhos RGB do dispositivo.
  • Suporte para balanço de branco usando um cartão cinza.
  • Rotinas de conversão de e para espaços de cores independentes do dispositivo.

Para implementar os recursos acima, a AVCaptureWhiteBalanceGain estrutura foi adicionada com os seguintes membros:

  • RedGain
  • GreenGain
  • BlueGain

O ganho máximo de balanço de branco é atualmente de quatro (4) e pode ser obtido na MaxWhiteBalanceGain propriedade. Portanto, o intervalo legal é de um (1) a MaxWhiteBalanceGain (4) atualmente.

A DeviceWhiteBalanceGains propriedade pode ser usada para observar os valores atuais. Use SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains para ajustar os ganhos de equilíbrio quando a câmera estiver no modo de balanço de branco bloqueado.

Rotinas de conversão

Rotinas de conversão foram adicionadas ao iOS 8 para ajudar na conversão de e para espaços de cores independentes do dispositivo. Para implementar as rotinas de conversão, a AVCaptureWhiteBalanceChromaticityValues estrutura foi adicionada com os seguintes membros:

  • X - é um valor de 0 a 1.
  • Y - é um valor de 0 a 1.

Uma AVCaptureWhiteBalanceTemperatureAndTintValues estrutura também foi adicionada com os seguintes membros:

  • Temperature - é um valor de ponto flutuante em graus Kelvin.
  • Tint - é um deslocamento de verde ou magenta de 0 a 150 com valores positivos para a direção verde e negativos para no magenta.

Use os CaptureDevice.GetTemperatureAndTintValuesmétodos e os CaptureDevice.GetDeviceWhiteBalanceGainsmétodos para converter entre temperatura e tonalidade, cromaticidade e espaços de cores de ganho RGB.

Observação

As rotinas de conversão são mais precisas quanto mais próximo o valor a ser convertido estiver do locus de Planck.

Suporte para cartão cinza

A Apple usa o termo Gray World para se referir ao suporte a Gray Card integrado ao iOS 8. Ele permite que o usuário se concentre em um cartão cinza físico que cubra pelo menos 50% do centro do quadro e o use para ajustar o balanço de branco. O objetivo do Cartão Cinza é obter um branco que pareça neutro.

Isso pode ser implementado em um aplicativo solicitando que o usuário coloque um cartão cinza físico na frente da câmera, monitorando a GrayWorldDeviceWhiteBalanceGains propriedade e aguardando até que os valores se estabilizem.

Em seguida, o aplicativo bloquearia os ganhos de Balanço de Branco para o SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains método usando os valores da GrayWorldDeviceWhiteBalanceGains propriedade para aplicar as alterações.

O dispositivo de captura deve ser bloqueado para configuração antes que uma alteração no balanço de branco possa ser feita.

Exemplo de balanço de branco manual

Com o código de Configuração Geral de Captura AV em vigor, um UIViewController pode ser adicionado ao Storyboard do aplicativo e configurado da seguinte maneira:

Um UIViewController pode ser adicionado ao Storyboard dos aplicativos e configurado conforme mostrado aqui para o exemplo de balanço de branco manual.

A visualização contém os seguintes elementos principais:

  • A UIImageView que exibirá o feed de vídeo.
  • A UISegmentedControl que mudará o Modo de Foco de Automático para Bloqueado.
  • Dois UISlider controles que mostrarão e atualizarão a temperatura e a tonalidade.
  • A UIButton usado para amostrar um espaço de Cartão cinza (Mundo cinza) e definir o Balanço de branco usando esses valores.

Faça o seguinte para conectar o controlador de exibição para o controle manual de balanço de branco:

  1. Adicione as seguintes instruções using:

    using System;
    using Foundation;
    using UIKit;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using AVFoundation;
    using CoreVideo;
    using CoreMedia;
    using CoreGraphics;
    using CoreFoundation;
    using System.Timers;
    
  2. Adicione as seguintes variáveis privadas:

    #region Private Variables
    private NSError Error;
    private bool Automatic = true;
    #endregion
    
  3. Adicione as seguintes propriedades computadas:

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    public Timer SampleTimer { get; set; }
    #endregion
    
  4. Adicione o seguinte método privado para definir o novo balanço de branco Temperatura e Tonalidade:

    #region Private Methods
    void SetTemperatureAndTint() {
        // Grab current temp and tint
        var TempAndTint = new AVCaptureWhiteBalanceTemperatureAndTintValues (Temperature.Value, Tint.Value);
    
        // Convert Color space
        var gains = ThisApp.CaptureDevice.GetDeviceWhiteBalanceGains (TempAndTint);
    
        // Set the new values
        if (ThisApp.CaptureDevice.LockForConfiguration (out Error)) {
            gains = NomralizeGains (gains);
            ThisApp.CaptureDevice.SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains (gains, null);
            ThisApp.CaptureDevice.UnlockForConfiguration ();
        }
    }
    
    AVCaptureWhiteBalanceGains NomralizeGains (AVCaptureWhiteBalanceGains gains)
    {
        gains.RedGain = Math.Max (1, gains.RedGain);
        gains.BlueGain = Math.Max (1, gains.BlueGain);
        gains.GreenGain = Math.Max (1, gains.GreenGain);
    
        float maxGain = ThisApp.CaptureDevice.MaxWhiteBalanceGain;
        gains.RedGain = Math.Min (maxGain, gains.RedGain);
        gains.BlueGain = Math.Min (maxGain, gains.BlueGain);
        gains.GreenGain = Math.Min (maxGain, gains.GreenGain);
    
        return gains;
    }
    #endregion
    
  5. Substitua o ViewDidLoad método e adicione o seguinte código:

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
    
        // Hide no camera label
        NoCamera.Hidden = ThisApp.CameraAvailable;
    
        // Attach to camera view
        ThisApp.Recorder.DisplayView = CameraView;
    
        // Set min and max values
        Temperature.MinValue = 1000f;
        Temperature.MaxValue = 10000f;
    
        Tint.MinValue = -150f;
        Tint.MaxValue = 150f;
    
        // Create a timer to monitor and update the UI
        SampleTimer = new Timer (5000);
        SampleTimer.Elapsed += (sender, e) => {
            // Convert color space
            var TempAndTint = ThisApp.CaptureDevice.GetTemperatureAndTintValues (ThisApp.CaptureDevice.DeviceWhiteBalanceGains);
    
            // Update slider positions
            Temperature.BeginInvokeOnMainThread (() => {
                Temperature.Value = TempAndTint.Temperature;
            });
    
            Tint.BeginInvokeOnMainThread (() => {
                Tint.Value = TempAndTint.Tint;
            });
        };
    
        // Watch for value changes
        Segments.ValueChanged += (sender, e) => {
            // Lock device for change
            if (ThisApp.CaptureDevice.LockForConfiguration (out Error)) {
    
                // Take action based on the segment selected
                switch (Segments.SelectedSegment) {
                case 0:
                // Activate auto focus and start monitoring position
                    Temperature.Enabled = false;
                    Tint.Enabled = false;
                    ThisApp.CaptureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.ContinuousAutoWhiteBalance;
                    SampleTimer.Start ();
                    Automatic = true;
                    break;
                case 1:
                // Stop auto focus and allow the user to control the camera
                    SampleTimer.Stop ();
                    ThisApp.CaptureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.Locked;
                    Automatic = false;
                    Temperature.Enabled = true;
                    Tint.Enabled = true;
                    break;
                }
    
                // Unlock device
                ThisApp.CaptureDevice.UnlockForConfiguration ();
            }
        };
    
        // Monitor position changes
        Temperature.TouchUpInside += (sender, e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic)
                return;
    
            // Update white balance
            SetTemperatureAndTint ();
        };
    
        Tint.TouchUpInside += (sender, e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic)
                return;
    
            // Update white balance
            SetTemperatureAndTint ();
        };
    
        GrayCardButton.TouchUpInside += (sender, e) => {
    
            // If we are in the automatic mode, ignore changes
            if (Automatic)
                return;
    
            // Get gray card values
            var gains = ThisApp.CaptureDevice.GrayWorldDeviceWhiteBalanceGains;
    
            // Set the new values
            if (ThisApp.CaptureDevice.LockForConfiguration (out Error)) {
                ThisApp.CaptureDevice.SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains (gains, null);
                ThisApp.CaptureDevice.UnlockForConfiguration ();
            }
        };
    }
    
  6. Substitua o ViewDidAppear método e adicione o seguinte para iniciar a gravação quando a exibição for carregada:

    public override void ViewDidAppear (bool animated)
    {
        base.ViewDidAppear (animated);
    
        // Start udating the display
        if (ThisApp.CameraAvailable) {
            // Remap to this camera view
            ThisApp.Recorder.DisplayView = CameraView;
    
            ThisApp.Session.StartRunning ();
            SampleTimer.Start ();
        }
    }
    
  7. Salve as alterações no código e execute o aplicativo.

  8. Com a câmera no modo Automático, os controles deslizantes se moverão automaticamente à medida que a câmera ajusta o balanço de branco:

    Os controles deslizantes se moverão automaticamente à medida que a câmera ajusta o balanço de branco

  9. Toque no segmento Bloqueado e arraste os controles deslizantes Temp e Tint para ajustar o balanço de branco manualmente:

    Arraste os controles deslizantes Temp e Tint para ajustar o balanço de branco manualmente

  10. Com o segmento Bloqueado ainda selecionado, coloque um cartão cinza físico na frente da câmera e toque no botão Cartão cinza para ajustar o balanço de branco para o Mundo Cinza:

    Toque no botão Cartão Cinza para ajustar o balanço de branco para o Mundo Cinza

  11. Pare o aplicativo.

O código acima mostrou como monitorar as configurações de balanço de branco quando a câmera está no modo Automático ou usar controles deslizantes para controlar o balanço de branco quando está no modo Bloqueado.

Captura entre colchetes

A Captura Agrupada é baseada nas configurações dos Controles Manuais da Câmera apresentados acima e permite que o aplicativo capture um momento no tempo, de várias maneiras diferentes.

Simplificando, a captura entre colchetes é uma sequência de imagens estáticas tiradas com uma variedade de configurações de imagem para imagem.

Como funciona a Captura entre colchetes

Usando a Captura entre colchetes no iOS 8, um aplicativo pode predefinir uma série de controles manuais da câmera, emitir um único comando e fazer com que a cena atual retorne uma série de imagens para cada uma das predefinições manuais.

Noções básicas de captura entre colchetes

Novamente, a captura entre colchetes é uma sequência de imagens estáticas tiradas com configurações variadas de imagem para imagem. Os tipos de Captura entre colchetes disponíveis são:

  • Suporte de exposição automática – onde todas as imagens têm uma quantidade variada de polarização.
  • Suporte de exposição manual – onde todas as imagens têm uma velocidade do obturador (duração) e quantidade ISO variadas.
  • Suporte de rajada simples – Uma série de imagens estáticas tiradas em rápida sucessão.

Novos controles de captura entre colchetes no iOS 8

Todos os comandos de Captura entre colchetes são implementados na AVCaptureStillImageOutput classe. Use o CaptureStillImageBracketmétodo para obter uma série de imagens com a matriz de configurações fornecida.

Duas novas classes foram implementadas para lidar com as configurações:

  • AVCaptureAutoExposureBracketedStillImageSettings – Tem uma propriedade, ExposureTargetBias, usada para definir o viés para um suporte de exposição automática.
  • AVCaptureManual ExposureBracketedStillImageSettings – Tem duas propriedades, ExposureDuration e ISO, usado para definir a velocidade do obturador e ISO para um suporte de exposição manual.

Controles de captura entre colchetes O que fazer e o que não fazer

Fazer

Veja a seguir uma lista de coisas que devem ser feitas ao usar os controles de captura entre colchetes no iOS 8:

  • Prepare o aplicativo para a pior situação de captura chamando o PrepareToCaptureStillImageBracket método.
  • Suponha que os buffers de exemplo venham do mesmo pool compartilhado.
  • Para liberar a memória que foi alocada por uma chamada de preparação anterior, chame PrepareToCaptureStillImageBracket novamente e envie uma matriz de um objeto.

O que não fazer

Veja a seguir uma lista de coisas que não devem ser feitas ao usar os controles de captura entre colchetes no iOS 8:

  • Não misture os tipos de configurações de Captura entre colchetes em uma única captura.
  • Não solicite mais do que MaxBracketedCaptureStillImageCount imagens em uma única captura.

Detalhes da captura entre colchetes

Os seguintes detalhes devem ser levados em consideração ao trabalhar com a Captura entre colchetes no iOS 8:

  • As configurações entre colchetes substituem temporariamente as AVCaptureDevice configurações.
  • As configurações de estabilização de flash e imagem estática são ignoradas.
  • Todas as imagens devem usar o mesmo formato de saída (jpeg, png, etc.)
  • A visualização do vídeo pode perder quadros.
  • A Captura entre colchetes é compatível com todos os dispositivos compatíveis com o iOS 8.

Com essas informações em mente, vamos dar uma olhada em um exemplo de uso da Captura entre colchetes no iOS 8.

Exemplo de captura de colchetes

Com o código de Configuração Geral de Captura AV em vigor, um UIViewController pode ser adicionado ao Storyboard do aplicativo e configurado da seguinte maneira:

Um UIViewController pode ser adicionado ao Storyboard dos aplicativos e configurado conforme mostrado aqui exemplo de captura de colchetes.

A visualização contém os seguintes elementos principais:

  • A UIImageView que exibirá o feed de vídeo.
  • Três UIImageViews que exibirão os resultados da captura.
  • A UIScrollView para abrigar o feed de vídeo e as visualizações dos resultados.
  • Costumava UIButton fazer uma captura entre colchetes com algumas configurações predefinidas.

Faça o seguinte para conectar o controlador de exibição para Captura entre colchetes:

  1. Adicione as seguintes instruções using:

    using System;
    using System.Drawing;
    using Foundation;
    using UIKit;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Linq;
    using AVFoundation;
    using CoreVideo;
    using CoreMedia;
    using CoreGraphics;
    using CoreFoundation;
    using CoreImage;
    
  2. Adicione as seguintes variáveis privadas:

    #region Private Variables
    private NSError Error;
    private List<UIImageView> Output = new List<UIImageView>();
    private nint OutputIndex = 0;
    #endregion
    
  3. Adicione as seguintes propriedades computadas:

    #region Computed Properties
    public AppDelegate ThisApp {
        get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
    }
    #endregion
    
  4. Adicione o seguinte método privado para criar as exibições de imagem de saída necessárias:

    #region Private Methods
    private UIImageView BuildOutputView(nint n) {
    
        // Create a new image view controller
        var imageView = new UIImageView (new CGRect (CameraView.Frame.Width * n, 0, CameraView.Frame.Width, CameraView.Frame.Height));
    
        // Load a temp image
        imageView.Image = UIImage.FromFile ("Default-568h@2x.png");
    
        // Add a label
        UILabel label = new UILabel (new CGRect (0, 20, CameraView.Frame.Width, 24));
        label.TextColor = UIColor.White;
        label.Text = string.Format ("Bracketed Image {0}", n);
        imageView.AddSubview (label);
    
        // Add to scrolling view
        ScrollView.AddSubview (imageView);
    
        // Return new image view
        return imageView;
    }
    #endregion
    
  5. Substitua o ViewDidLoad método e adicione o seguinte código:

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
    
        // Hide no camera label
        NoCamera.Hidden = ThisApp.CameraAvailable;
    
        // Attach to camera view
        ThisApp.Recorder.DisplayView = CameraView;
    
        // Setup scrolling area
        ScrollView.ContentSize = new SizeF (CameraView.Frame.Width * 4, CameraView.Frame.Height);
    
        // Add output views
        Output.Add (BuildOutputView (1));
        Output.Add (BuildOutputView (2));
        Output.Add (BuildOutputView (3));
    
        // Create preset settings
        var Settings = new AVCaptureBracketedStillImageSettings[] {
            AVCaptureAutoExposureBracketedStillImageSettings.Create(-2.0f),
            AVCaptureAutoExposureBracketedStillImageSettings.Create(0.0f),
            AVCaptureAutoExposureBracketedStillImageSettings.Create(2.0f)
        };
    
        // Wireup capture button
        CaptureButton.TouchUpInside += (sender, e) => {
            // Reset output index
            OutputIndex = 0;
    
            // Tell the camera that we are getting ready to do a bracketed capture
            ThisApp.StillImageOutput.PrepareToCaptureStillImageBracket(ThisApp.StillImageOutput.Connections[0],Settings,async (bool ready, NSError err) => {
                // Was there an error, if so report it
                if (err!=null) {
                    Console.WriteLine("Error: {0}",err.LocalizedDescription);
                }
            });
    
            // Ask the camera to snap a bracketed capture
            ThisApp.StillImageOutput.CaptureStillImageBracket(ThisApp.StillImageOutput.Connections[0],Settings, (sampleBuffer, settings, err) =>{
                // Convert raw image stream into a Core Image Image
                var imageData = AVCaptureStillImageOutput.JpegStillToNSData(sampleBuffer);
                var image = CIImage.FromData(imageData);
    
                // Display the resulting image
                Output[OutputIndex++].Image = UIImage.FromImage(image);
    
                // IMPORTANT: You must release the buffer because AVFoundation has a fixed number
                // of buffers and will stop delivering frames if it runs out.
                sampleBuffer.Dispose();
            });
        };
    }
    
  6. Substitua o ViewDidAppear método e adicione o seguinte código:

    public override void ViewDidAppear (bool animated)
    {
        base.ViewDidAppear (animated);
    
        // Start udating the display
        if (ThisApp.CameraAvailable) {
            // Remap to this camera view
            ThisApp.Recorder.DisplayView = CameraView;
    
            ThisApp.Session.StartRunning ();
        }
    }
    
    
  7. Salve as alterações no código e execute o aplicativo.

  8. Enquadre uma cena e toque no botão Capturar colchete:

    Enquadre uma cena e toque no botão

  9. Deslize da direita para a esquerda para ver as três imagens tiradas pela Captura entre colchetes:

    Deslize da direita para a esquerda para ver as três imagens tiradas pela captura entre colchetes

  10. Pare o aplicativo.

O código acima mostrou como configurar e fazer uma captura com suporte de exposição automática no iOS 8.

Resumo

Neste artigo, abordamos uma introdução aos novos controles manuais de câmera fornecidos pelo iOS 8 e abordamos os fundamentos do que eles fazem e como funcionam. Demos exemplos de Foco Manual, Exposição Manual e Balanço de Branco Manual. Por fim, demos um exemplo de captura entre colchetes usando os controles manuais de câmera discutidos anteriormente