Compartilhar via


Controles manuais da câmera no Xamarin.iOS

Os Controles Manuais da Câmera, fornecidos pelo iOS 8, permitem que um aplicativo móvel assuma o controle total sobre a AVFoundation Framework câmera de um dispositivo iOS. Este 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 correçã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 do AVFoundation

Seja fazendo 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 é verdade para aplicativos que usam os controles de câmera automatizados padrão ou aqueles que aproveitam os novos controles manuais da câmera:

Visão geral do AVFoundation Capture Objects

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

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 alcancem uma aparência estilizada.
  • Balanço de branco manual – O balanço de branco é usado para ajustar a cor em uma imagem, muitas vezes 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 às APIs existentes do iOS para fornecer esse controle refinado sobre o processo de captura de imagens.

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 que executa 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 da 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 amostra de saída

Uma das primeiras coisas necessárias será um delegado para monitorar o buffer de Saída de Amostra e exibir uma imagem capturada do buffer para uma 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 AV Capture é usada para controlar a gravação de vídeo ao vivo da câmera do dispositivo iOS e é necessária para obter vídeo em um aplicativo iOS. Como o aplicativo de ManualCameraControl exemplo está usando a sessão de captura em vários locais diferentes, ele será configurado no e disponibilizado para todo o AppDelegate 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 este 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 alcançar 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 assumam o controle sobre o foco no momento em que a imagem é tirada.

Como funciona o Focus

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 distante a lente está do sensor, os objetos de distância parecem mais nítidos e os mais próximos, 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 em foco mais próximos e mais distantes.
  • Macro - Este é o extremo próximo do espectro de foco e é a distância mais próxima em que a lente pode focar.
  • Infinito – Este é o extremo do espectro de foco e é a distância mais distante em que a lente pode focar.
  • Distância hiperfocal – Este é o ponto no espectro de foco onde o objeto mais distante no quadro está apenas no extremo 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, o 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 via FocusModepropriedade como:

  • AVCaptureFocusModeLocked – O foco é bloqueado em um único ponto de foco.
  • AVCaptureFocusModeAutoFocus – A câmera varre a lente através de todos os pontos focais até encontrar foco nítido e, em seguida, permanece lá.
  • AVCaptureFocusModeContinuousAutoFocus – A câmera refoca sempre que detecta uma condição fora de foco.

Os controles existentes também forneciam um ponto de interesse configurável através da propriedade, paraFocusPointOfInterest que o usuário possa tocar para se concentrar 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 escanear 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 retarda o algoritmo de foco automático e o processa em incrementos menores para evitar mover artefatos ao gravar vídeo.

Novos controles de foco no iOS 8

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

  • Controle manual total da posição da lente ao bloquear 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 receber 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 General AV Capture Setup no lugar, um UIViewController pode ser adicionado ao Storyboard do aplicativo e configurado da seguinte maneira:

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

O modo de exibiçã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 o 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:

    Ajustando manualmente a posição da lente

  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 estiver 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 brilhante para escura e mal-humorada:

Uma amostra de uma imagem que mostra a exposição de irrealisticamente brilhante a escuro e mal-humorado

Novamente, isso pode ser feito automaticamente usando controle programático para aplicações científicas ou através 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 de exposição em uma aplicação IOS 8. Vamos dar uma olhada rápida em como a exposição funciona:

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 fica aberto para deixar a luz no sensor da câmera. Quanto menor o tempo em 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 é deixada entrar e mais desfoque de movimento ocorre.
  • Mapeamento ISO – Este é um termo emprestado da fotografia de filme e refere-se à sensibilidade dos produtos químicos no filme à luz. Baixos valores de ISO no filme têm menor 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 uma característica física.
  • Abertura da lente – Este é o tamanho da abertura da lente. Em todos os dispositivos iOS, a abertura da lente é fixa, portanto, os dois únicos valores que podem ser usados para ajustar a exposição são Velocidade do obturador e ISO.

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

Antes de aprender como a exposição manual funciona, é 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 mistura ideal de ISO e velocidade do obturador para obter a cena bem iluminada. Esse ciclo é conhecido como AE Loop.

Como funciona a exposição bloqueada

Em seguida, 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, nesse modo, o bloco AE é desconectado do mecanismo de estatísticas de medição.

Controles de exposição existentes

iOS 7 e superior, forneça os seguintes controles de exposição existentes através da ExposureMode propriedade:

  • AVCaptureExposureModeLocked – Amostras da cena uma vez e usa esses valores ao longo da cena.
  • AVCaptureExposureModeContinuousAutoExposure – Amostras da cena continuamente para garantir que ela 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 acima, os seguintes recursos agora estão disponíveis para controlar a exposição no iOS 8:

  • Exposição personalizada totalmente manual.
  • Obter, definir e chave-valor observar IOS e 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 código a seguir pode ser usado para ajustar a duração da exposição e ISO:

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

Nos modos Auto e Bloqueado, o aplicativo pode ajustar o viés 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.

Exemplo de exposição manual

Com o código General AV Capture Setup no lugar, um UIViewController pode ser adicionado ao Storyboard do aplicativo e configurado da seguinte maneira:

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

O modo de exibiçã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 Offset, Duration, ISO e Bias.

Faça o seguinte para conectar o controlador de exibição para o 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 Viés para ajustar o viés 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 estiver nos modos Bloqueado ou Personalizado.

Balanço de Branco Manual

Os controles White Balance 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 alcançar efeitos artísticos.

Uma imagem de exemplo mostrando ajustes manuais do 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 amarela-alaranjada mais quente. (Confusingly, cores "frias" têm temperaturas de cor mais altas do que cores "quentes". As temperaturas de cor são uma medida física, não perceptual.)

A mente humana é muito boa em compensar as diferenças de temperatura de 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 o balanço de branco funciona:

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, como 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 de cor (em graus kelvin), com números mais altos no lado azul (mais quente) e números mais baixos no lado vermelho (mais frio). Estes são úteis para situações típicas de iluminação.

Em condições de iluminação mista, os ajustes de 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 os casts de cores aumentando o ganho de cor oposto. Por exemplo, se uma cena tem muito azul, o ganho vermelho será aumentado para compensar. Esses valores de ganho são calibrados para dispositivos específicos para que sejam dependentes do dispositivo.

Controles de balanço de branco existentes

O iOS 7 e superior forneciam os seguintes controles White Balance existentes via WhiteBalanceMode propriedade:

  • AVCapture WhiteBalance ModeLocked – Amostras da cena uma vez e usando esses valores ao longo da 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 acima, os seguintes recursos agora estão disponíveis para controlar o White Balance no iOS 8:

  • Controle totalmente manual dos ganhos RGB do dispositivo.
  • Get, Set e Key-Value Observe os ganhos RGB do dispositivo.
  • Suporte para White Balance 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 estrutura foi adicionada AVCaptureWhiteBalanceGain com os seguintes membros:

  • RedGain
  • GreenGain
  • BlueGain

O ganho máximo de balanço de branco atualmente é de quatro (4) e pode estar pronto a MaxWhiteBalanceGain partir da propriedade. Assim, 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 estrutura foi adicionada AVCaptureWhiteBalanceChromaticityValues com os seguintes membros:

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

Também foi adicionada uma AVCaptureWhiteBalanceTemperatureAndTintValues estrutura 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 a direção magenta.

Use os CaptureDevice.GetTemperatureAndTintValuesmétodos e the CaptureDevice.GetDeviceWhiteBalanceGainspara converter entre temperatura e tonalidade, cromaticidade e espaços de cor RGB ganhos.

Observação

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

Suporte a cartão cinza

A Apple usa o termo Gray World para se referir ao suporte ao Gray Card embutido no iOS 8. Ele permite que o usuário se concentre em um cartão cinza físico que cobre pelo menos 50% do centro do quadro e usa isso para ajustar o balanço de branco. O objetivo do cartão cinza é alcançar o branco que parece 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 estabeleçam.

O aplicativo bloquearia os ganhos de balanço de branco para o SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains método usando os GrayWorldDeviceWhiteBalanceGains valores da propriedade para aplicar as alterações.

O Dispositivo de Captura deve estar bloqueado para configuração antes que uma alteração no White Balance possa ser feita.

Exemplo de balanço de branco manual

Com o código General AV Capture Setup no lugar, um UIViewController pode ser adicionado ao Storyboard do aplicativo e configurado da seguinte maneira:

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

O modo de exibiçã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.
  • Um UIButton usado para obter uma amostra de 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 ao Mundo Cinza:

    Toque no botão Cartão cinza para ajustar o balanço de branco ao 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 estiver no modo Bloqueado.

Captura entre colchetes

A Captura entre colchetes é 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 explosão 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 explosão 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 de viés variada.
  • Suporte de Exposição Manual – onde todas as imagens têm uma Velocidade do Obturador (Duração) e quantidade ISO variadas.
  • Simple Burst Bracket – 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.
  • AVCaptureManualExposureBracketedStillImageSettings – Possui 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 Fazer e Não Fazer

Fazer

A seguir está 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 virão do mesmo pool compartilhado.
  • Para liberar a memória que foi alocada por uma chamada de preparação anterior, chame PrepareToCaptureStillImageBracket novamente e envie-lhe uma matriz de um objeto.

O que não fazer

A seguir está 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 de vídeo pode soltar quadros.
  • A Captura entre colchetes é suportada em 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 colchete

Com o código General AV Capture Setup no lugar, um UIViewController pode ser adicionado ao Storyboard do aplicativo e configurado da seguinte maneira:

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

O modo de exibiçã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.
  • Um UIButton usado para 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. Enquadrar uma cena e tocar no botão Capturar Colchetes:

    Enquadrar uma cena e tocar no botão Capturar Suporte

  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 de Colchete de Exposição Automática no iOS 8.

Resumo

Neste artigo, abordamos uma introdução aos novos controles manuais da câmera fornecidos pelo iOS 8 e abordamos o básico do que eles fazem e como funcionam. Demos exemplos de Foco Manual, Exposição Manual e Balanço de Branco Manual. Finalmente, demos um exemplo tomando uma Captura entre Colchetes usando os Controles Manuais de Câmera discutidos anteriormente