Download Code

Xamarin Camera SurfaceView Android

In this tutorial you will learn how to preview camera on surface view within Xamarin Camera SurfaceView android application using surface-view. How to apply color effects on camera preview.First of all i’ll give you explanation everything concerning about this tutorial.

These are the concerning things in this Xamarin Camera SurfaceView android tutorial.

  • Camera
  • Surface View
  • ISurfaceHolder
  • ISurfaceHolderCallback

First let’s talk about Camera.

Xamarin Camera

Camera is used to capture image and video.Some Android devices have front camera or some are not having that camera facility.Basic use of Camera.There are alot of Camera feature like you can detect face,apply color effects etc.So let’s talk about Effect on camera.Here is the list of color effects method on camera hardware some might be supported on your device some might be not.

  • Camera.Parameters.EFFECT_AQUA
  • Camera.Parameters.EFFECT_NEGATIVE
  • Camera.Parameters.EFFECT_NONE
  • Camera.Parameters.EFFECT_MONO
  • Camera.Parameters.EFFECT_BLACKBOARD
  • Camera.Parameters.EFFECT_SEPIA
  • Camera.Parameters.EFFECT_WHITEBOARD
  • Camera.Parameters.EFFECT_POSTERIZE
  • Camera.Parameters.EFFECT_SOLARIZE

Surface View

Surface View class provides dedicated surface within view hierarchy.Surface View is basically extends from View class.Surface View can be used to place overlays buttons or any other like camera preview.

ISurfaceHolder

Abstract interface to someone holding a display surface. Allows you to control the surface size and format, edit the pixels in the surface, and monitor changes to the surface. This interface is typically available through the SurfaceView class.

ISurfaceHolderCallback

A client may implement this interface to receive information about changes to the surface.

Second Description might clear good enough.
You use an interface of which receiver object will call one or more methods connected to that object.

We are not concerning with any layout.

Steps in this tutorial are.

  • Detect Number of Cameras
  • Switch Camera’s
  • Apply Effect on Camera Preview
  • Resize Camera Preview
  • You should have menu with one item

Now create new Xamarin Camera SurfaceView android application project and go to your MainActivity.cs class.

MainActivity.cs

using System;
using System.Collections.Generic;

using Android.App;
using Android.Content;
using Android.Hardware;
using Android.OS;
using Android.Views;
using System.Drawing;
using Android.Util;

namespace surfaceview
{
	[Activity (Label = "surfaceview", MainLauncher = true, Icon = "@mipmap/icon")]
	public class MainActivity : Activity
	{
		Preview mPreview;   // preview class object/variable
		Camera mCamera;     // camera class variable
		int numberOfCameras;   // number of cam's
		int cameraCurrentlyLocked;    // camera status

		// The first rear facing camera
		int defaultCameraId;

		protected override void OnCreate (Bundle savedInstanceState)
		{
			base.OnCreate (savedInstanceState);

		

			// Create our Preview view and set it as the content of our activity.
			mPreview = new Preview (this);
			SetContentView (mPreview);

			// Find the total number of cameras available
			numberOfCameras = Camera.NumberOfCameras;

			// Find the ID of the default camera
			Camera.CameraInfo cameraInfo = new Camera.CameraInfo ();
			for (int i = 0; i < numberOfCameras; i++) { Camera.GetCameraInfo (i, cameraInfo); if (cameraInfo.Facing == CameraFacing.Back) { defaultCameraId = i; } } } protected override void OnResume () { base.OnResume (); // Open the default i.e. the first rear facing camera. mCamera = Camera.Open (); cameraCurrentlyLocked = defaultCameraId; mPreview.PreviewCamera = mCamera; } protected override void OnPause () { base.OnPause (); // Because the Camera object is a shared resource, it's very // important to release it when the activity is paused. if (mCamera != null) { mPreview.PreviewCamera = null; mCamera.Release (); mCamera = null; } } public override bool OnCreateOptionsMenu (IMenu menu) { // Inflate our menu which can gather user input for switching camera MenuInflater.Inflate (Resource.Menu.camera_menu, menu); return true; } public override bool OnOptionsItemSelected (IMenuItem item) { // Handle item selection switch (item.ItemId) { case Resource.Id.switch_cam: // check for availability of multiple cameras if (numberOfCameras == 1) { AlertDialog.Builder builder = new AlertDialog.Builder (this); builder.SetMessage ("Alert") .SetNeutralButton ("Close", (Android.Content.IDialogInterfaceOnClickListener)null); AlertDialog alert = builder.Create (); alert.Show (); return true; } // OK, we have multiple cameras. // Release this camera -> cameraCurrentlyLocked
				if (mCamera != null) {
					mCamera.StopPreview ();
					mPreview.PreviewCamera = null;
					mCamera.Release ();
					mCamera = null;
				}

				// Acquire the next camera and request Preview to reconfigure
				// parameters.
				mCamera = Camera.Open ((cameraCurrentlyLocked + 1) % numberOfCameras);
				cameraCurrentlyLocked = (cameraCurrentlyLocked + 1) % numberOfCameras;
				mPreview.SwitchCamera (mCamera);

				// Start the preview
				mCamera.StartPreview ();
				return true;

			default:
				return base.OnOptionsItemSelected (item);
			}
		}
			
	}

	class Preview : ViewGroup,  ISurfaceHolderCallback
	{
		string TAG = "Preview";

		SurfaceView mSurfaceView;
		ISurfaceHolder mHolder;
		Camera.Size mPreviewSize;
		IList mSupportedPreviewSizes;
		Camera _camera;

		public Camera PreviewCamera {
			get { return _camera; } 
			set {
				_camera = value;
				if (_camera != null) {
					mSupportedPreviewSizes = PreviewCamera.GetParameters().SupportedPreviewSizes;
					RequestLayout ();
				}
			}
		}

		public Preview (Context context) : base (context)
		{
			mSurfaceView = new SurfaceView (context);
			AddView (mSurfaceView);

			// Install a SurfaceHolder.Callback so we get notified when the
			// underlying surface is created and destroyed.
			mHolder = mSurfaceView.Holder;
			mHolder.AddCallback (this);
			mHolder.SetType (SurfaceType.PushBuffers);
		}

		public void SwitchCamera (Camera camera)
		{
			PreviewCamera = camera;

			try {
				camera.SetPreviewDisplay (mHolder);
			} catch (Java.IO.IOException exception) {
				Log.Error (TAG, "IOException caused by setPreviewDisplay()", exception);
			}

			Camera.Parameters parameters = camera.GetParameters ();
			parameters.SetPreviewSize (mPreviewSize.Width, mPreviewSize.Height);
			RequestLayout ();

			camera.SetParameters (parameters);
		}

		protected override void OnMeasure (int widthMeasureSpec, int heightMeasureSpec)
		{
			// We purposely disregard child measurements because act as a
			// wrapper to a SurfaceView that centers the camera preview instead
			// of stretching it.
			int width = ResolveSize (SuggestedMinimumWidth, widthMeasureSpec);
			int height = ResolveSize (SuggestedMinimumHeight, heightMeasureSpec);
			SetMeasuredDimension (width, height);

			if (mSupportedPreviewSizes != null) {
				mPreviewSize = GetOptimalPreviewSize (mSupportedPreviewSizes, width, height);
			}
		}

		protected override void OnLayout (bool changed, int l, int t, int r, int b)
		{
			if (changed && ChildCount > 0) {
				View child = GetChildAt (0);

				int width = r - l;
				int height = b - t;

				int previewWidth = width;
				int previewHeight = height;
				if (mPreviewSize != null) {
					previewWidth = mPreviewSize.Width;
					previewHeight = mPreviewSize.Height;
				}

				// Center the child SurfaceView within the parent.
				if (width * previewHeight > height * previewWidth) {
					int scaledChildWidth = previewWidth * height / previewHeight;
					child.Layout ((width - scaledChildWidth) / 2, 0,
						(width + scaledChildWidth) / 2, height);
				} else {
					int scaledChildHeight = previewHeight * width / previewWidth;
					child.Layout (0, (height - scaledChildHeight) / 2,
						width, (height + scaledChildHeight) / 2);
				}
			}
		}

		public void SurfaceCreated (ISurfaceHolder holder)
		{
			// The Surface has been created, acquire the camera and tell it where
			// to draw.
			try {
				if (PreviewCamera != null) {
					PreviewCamera.SetPreviewDisplay (holder);
					PreviewCamera.SetDisplayOrientation(90);
				}
			} catch (Java.IO.IOException exception) {
				Log.Error (TAG, "IOException caused by setPreviewDisplay()", exception);
			}
		}

		public void SurfaceDestroyed (ISurfaceHolder holder)
		{
			// Surface will be destroyed when we return, so stop the preview.
			if (PreviewCamera != null) {
				PreviewCamera.StopPreview ();
			}
		}

		private Camera.Size GetOptimalPreviewSize (IList sizes, int w, int h)
		{
			const double ASPECT_TOLERANCE = 0.1;
			double targetRatio = (double)w / h;

			if (sizes == null)
				return null;

			Camera.Size optimalSize = null;
			double minDiff = Double.MaxValue;

			int targetHeight = h;

			// Try to find an size match aspect ratio and size
			foreach (Camera.Size size in sizes) {
				double ratio = (double)size.Width / size.Height;

				if (Math.Abs (ratio - targetRatio) > ASPECT_TOLERANCE)
					continue;

				if (Math.Abs (size.Height - targetHeight) < minDiff) {
					optimalSize = size;
					minDiff = Math.Abs (size.Height - targetHeight);
				}
			}

			// Cannot find the one match the aspect ratio, ignore the requirement
			if (optimalSize == null) {
				minDiff = Double.MaxValue;
				foreach (Camera.Size size in sizes) {
					if (Math.Abs (size.Height - targetHeight) < minDiff) {
						optimalSize = size;
						minDiff = Math.Abs (size.Height - targetHeight);
					}
				}
			}

			return optimalSize;
		}

		public void SurfaceChanged (ISurfaceHolder holder, Android.Graphics.Format format, int w, int h)
		{
			// Now that the size is known, set up the camera parameters and begin
			// the preview.
			Camera.Parameters parameters = PreviewCamera.GetParameters ();

			parameters.ColorEffect = Camera.Parameters.EffectSepia;
			parameters.SetPreviewSize (mPreviewSize.Width, mPreviewSize.Height);
			RequestLayout ();

			PreviewCamera.SetParameters (parameters);


			PreviewCamera.StartPreview ();
		}
	}
}

Now at last add camera permission in your AndroidManifest.xml file.

Run your Xamarin Camera SurfaceView android application project.Output should be like.

surfaceview,Surface View,camera color effects,Xamarin Camera,Xamarin Camera SurfaceView,Xamarin Camera SurfaceView android,Camera SurfaceView android

That’s it for Xamarin Camera SurfaceView android tutorial.

Thanks.