Wednesday 16 December 2020

Creating-a-Custom-Camera-View Basic Concept (Create Half Screen Camera in Xamarin forms) - Xamarin


AV Foundation, an Apple system framework that exists on macOS and iOS, along with watchOS and tvOS. The goal of this tutorial will be to help you build a fully functional iOS app that’s capable of capturing photos and videos using the device’s cameras. We’ll also be following the principles of good object oriented programming and designing a utility class that can be reused and extended in all your projects.

What is AV Foundation?

AV Foundation is the full featured framework for working with time-based audiovisual media on iOS, macOS, watchOS and tvOS. Using AV Foundation, you can easily play, create, and edit QuickTime movies and MPEG-4 files, play HLS streams, and build powerful media functionality into your apps. – Apple

So, there you have it. AV Foundation is a framework for capturing, processing, and editing audio and video on Apple devices. 


Your app should use the prebuilt camera and media control if:

  • You prioritize code sharing over customization.
  • Camera or media functionality is just a small part of your overall application.

Your app should use a custom camera control if:

  • You prioritize customization over code sharing.
  • You don’t want to navigate the user to a new view to take a photo.
  • The core experience of the app revolves around the camera.
AVFoundation is a namespace that contains classes for high-level recording and playback capabilities for audio and video on iOS. 

How You develop in Xamarin Forms ?

-------------------------------------------------------------------------------------------------------------------------------------------

Step 1 :  

You have to create  CameraPreview which inherit from View  and Bindable Property : 

public class CameraPreview : View
{
public static readonly BindableProperty CameraProperty = BindableProperty.Create (
propertyName: "Camera",
returnType: typeof(CameraOptions),
declaringType: typeof(CameraPreview),
defaultValue: CameraOptions.Rear);

public CameraOptions Camera {
get { return (CameraOptions)GetValue (CameraProperty); }
set { SetValue (CameraProperty, value); }
}
}

-------------------------------------------------------------------------------------------------------------------------------------------

CameraOptions contains Enum : 

public enum CameraOptions

{ Rear,

Front }

-------------------------------------------------------------------------------------------------------------------------------------------

Step 3: Now Using our own CamaraPreview in Xaml like below 

<Grid

            BackgroundColor="Transparent"

            HorizontalOptions="FillAndExpand"

            RowSpacing="0"

            VerticalOptions="FillAndExpand">

            <Grid.RowDefinitions>

                <RowDefinition Height="*" />

                <RowDefinition Height="250" />

            </Grid.RowDefinitions>


            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="*" />

            </Grid.ColumnDefinitions>


            <local:CameraPreview

                Grid.Row="0"

                Grid.Column="0"

                Camera="Rear"

                HeightRequest="300"

                HorizontalOptions="FillAndExpand"

                VerticalOptions="FillAndExpand"

                WidthRequest="400" />


            <Frame

                Grid.Row="0"

                Grid.Column="0"

                BackgroundColor="Transparent"

                BorderColor="White"

                HeightRequest="100"

                HorizontalOptions="Center"

                VerticalOptions="Center"

                WidthRequest="200" />


            <StackLayout

                Grid.Row="1"

                Grid.Column="0"

                BackgroundColor="Black"

                Orientation="Vertical">


                <Label

                    FontSize="Title"

                    HorizontalOptions="CenterAndExpand"

                    Text="Add Card"

                    TextColor="White" />

                <Label

                    FontSize="Large"

                    HorizontalOptions="CenterAndExpand"

                    Text="Position your card in the frame"

                    TextColor="White" />

            </StackLayout>

        </Grid> 

-------------------------------------------------------------------------------------------------------------------------------------------

Now the most important part to Create Renderer to write code in Platform part : 

IOS

CameraPreviewRenderer & UICameraPreview 

CameraPreviewRenderer.cs

using System;

using AVFoundation;

using CustomRenderer;

using CustomRenderer.iOS;

using Foundation;

using Xamarin.Forms;

using Xamarin.Forms.Platform.iOS;


[assembly: ExportRenderer(typeof(CameraPreview), typeof(CameraPreviewRenderer))]

namespace CodeXamarin.iOS

{

    public class CameraPreviewRenderer : ViewRenderer<CameraPreview, UICameraPreview>

    {

        UICameraPreview uiCameraPreview;

        private AVCaptureOutput cameraOutput;

        private AVCaptureStillImageOutput stillImageOutput;


        protected override void OnElementChanged(ElementChangedEventArgs<CameraPreview> e)

        {

            base.OnElementChanged(e);

            if (e.OldElement != null)

            {

                // Unsubscribe

                uiCameraPreview.Tapped -= OnCameraPreviewTapped;

            }

            if (e.NewElement != null)

            {

                if (Control == null)

                {

                    uiCameraPreview = new UICameraPreview(e.NewElement.Camera);

                    SetNativeControl(uiCameraPreview);

                }

                // Subscribe

                uiCameraPreview.Tapped += OnCameraPreviewTapped;

            }

        }

        async void OnCameraPreviewTapped(object sender, EventArgs e)

        {

            if (uiCameraPreview.IsPreviewing)

            {

                var videoConnection = uiCameraPreview.stillImageOutput.ConnectionFromMediaType(AVMediaType.Video);

                var sampleBuffer = await uiCameraPreview.stillImageOutput.CaptureStillImageTaskAsync(videoConnection);

                var jpegImageAsNsData = AVCaptureStillImageOutput.JpegStillToNSData(sampleBuffer);

                var jpegAsByteArray = jpegImageAsNsData.ToArray(); // you will get output of image here.

                uiCameraPreview.CaptureSession.StopRunning();

                uiCameraPreview.IsPreviewing = false;

            }

            else

            {

                uiCameraPreview.CaptureSession.StartRunning();

                uiCameraPreview.IsPreviewing = true;

            }

        }

        protected override void Dispose(bool disposing)

        {

            if (disposing)

            {

                Control.CaptureSession.Dispose();

                Control.Dispose();

            }

            base.Dispose(disposing);

        }

    }

}

-------------------------------------------------------------------------------------------------------------------------------------------

UICameraPreview.cs

using System;

using System.Linq;

using AVFoundation;

using CoreGraphics;

using Foundation;

using UIKit;


namespace CustomRenderer.iOS

{

    public class UICameraPreview : UIView

    {

        AVCaptureVideoPreviewLayer previewLayer;

        CameraOptions cameraOptions;

        public AVCaptureStillImageOutput stillImageOutput;

        public event EventHandler<EventArgs> Tapped;

        public AVCaptureSession CaptureSession { get; private set; }

        public bool IsPreviewing { get; set; }

        public UICameraPreview(CameraOptions options)

        {

            cameraOptions = options;

            IsPreviewing = false;

            Initialize();

        }

        public override void LayoutSubviews()

        {

            base.LayoutSubviews();

            if (previewLayer != null)

                previewLayer.Frame = Bounds;

        }

        public override void TouchesBegan(NSSet touches, UIEvent evt)

        {

            base.TouchesBegan(touches, evt);

            OnTapped();

        }

        protected virtual void OnTapped()

        {

            var eventHandler = Tapped;

            if (eventHandler != null)

            {

                eventHandler(this, new EventArgs());

            }

        }

        void Initialize()

        {

            CaptureSession = new AVCaptureSession();

            previewLayer = new AVCaptureVideoPreviewLayer(CaptureSession)

            {

                Frame = Bounds,

                VideoGravity = AVLayerVideoGravity.ResizeAspectFill

            };

            var videoDevices = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video);

            var cameraPosition = (cameraOptions == CameraOptions.Front) ? AVCaptureDevicePosition.Front : AVCaptureDevicePosition.Back;

            var device = videoDevices.FirstOrDefault(d => d.Position == cameraPosition);

            if (device == null)

            {                return;            }

            var dictionary = new NSMutableDictionary();

            dictionary[AVVideo.CodecKey] = new NSNumber((int)AVVideoCodec.JPEG);

            stillImageOutput = new AVCaptureStillImageOutput()

            { OutputSettings = new NSDictionary()   };

            CaptureSession.AddOutput(stillImageOutput);

            NSError error;

            var input = new AVCaptureDeviceInput(device, out error);

            CaptureSession.AddInput(input);

            Layer.AddSublayer(previewLayer);

            CaptureSession.StartRunning();

            IsPreviewing = true;

        }

    }

}

I am not writing here for Android Platform Code , You can download the code and check it out, CameraPreviewRenderer Android file is there. You can get more idea on that.

Full SourceCode Link 


Please comment if you found it is useful for you, or ask any query i will try to provide you more details on your query.

Thank you

Reference  : 


1 comment:

  1. Thank you for your post. This is excellent information. It is amazing and wonderful to visit your site. For more info:- Xamarin App Development

    ReplyDelete

All About .NET MAUI

  What’s .NET MAUI? .NET MAUI (.NET Multi-platform App UI) is a framework for building modern, multi-platform, natively compiled iOS, Androi...

Ads2