Forum Xamarin.Forms

How to take a photo in Xamarin.Forms using Camera Preview control?

MikilllMikilll Member ✭✭✭

The Xamarin docs describe how to create a Camera Preview control.
https://docs.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/customrenderers-view/

But how to enhance this control and add the ability to take a photo in Xamarin.Forms?

I say in advance that I don't want to use James Montemagno Media Plugin plugin (https://github.com/jamesmontemagno/MediaPlugin) because this plugin does not allow to have camera view inside your XAML. It always opens a new page with a camera.

Answers

  • jezhjezh Member, Xamarin Team Xamurai

    You can try to put the Preview in the layout of your page, and compress and show the image after taking picture.
    For xamarin android , you can check:
    https://forums.xamarin.com/discussion/17625/custom-camera-takepicture
    https://stackoverflow.com/questions/44562282/capture-image-from-camera-and-display-in-same-activity-xamarin

    The main steps is:
    1. Create a Preview class for Camera Preview:
    public class Preview : SurfaceView, ISurfaceHolderCallback
    {
    private Android.Hardware.Camera mCamera;

        public Preview(Context context, Android.Hardware.Camera camera):base(context)
        {
            mCamera = camera;
            Holder.AddCallback(this);
            // deprecated setting, but required on Android versions prior to 3.0
            Holder.SetType(SurfaceType.PushBuffers);
        }
        public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height)
        {
            // If your preview can change or rotate, take care of those events here.
            // Make sure to stop the preview before resizing or reformatting it.
    
            if (Holder.Surface == null)
            {
                // preview surface does not exist
                return;
            }
    
            // stop preview before making changes
            try
            {
                mCamera.StopPreview();
            }
            catch (Exception e)
            {
                // ignore: tried to stop a non-existent preview
            }
    
            // set preview size and make any resize, rotate or
            // reformatting changes here
    
            // start preview with new settings
            try
            {
                mCamera.SetPreviewDisplay(Holder);
                mCamera.StartPreview();
    
            }
            catch (Exception e)
            {
                //Deal with exception
            }
        }
    
        public void SurfaceCreated(ISurfaceHolder holder)
        {
           // The Surface has been created, now tell the camera where to draw the preview.
            try
            {
                mCamera.SetPreviewDisplay(Holder);
                mCamera.StartPreview();
            }
            catch (IOException e)
            {
                e.PrintStackTrace();
            }
        }
    
        public void SurfaceDestroyed(ISurfaceHolder holder)
        {
            // empty. Take care of releasing the Camera preview in your activity.
        }
    
    }
    

    2. Prepare the Layout to hold the Camera Preview and your Image

         <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
          <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="250dp">
            <FrameLayout
            android:id="@+id/camera_preview"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            />
          </LinearLayout>
          <ImageView
            android:id="@+id/imgResult"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
          />
          <Button
            android:id="@+id/btnClick"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Click Me"/>
        </LinearLayout>
    

    3.Create Camera and Preview in Page and register for taking picture's callback

           public class MainActivity : Activity,IPictureCallback
           {
            bool isCameraOpened;
            Preview mPreview;
            Android.Hardware.Camera mCamera;
            Button btnClick;
            FrameLayout camera_preview;
            protected override void OnCreate(Bundle bundle)
            {
                base.OnCreate(bundle);
    
                // Set our view from the "main" layout resource
                SetContentView (Resource.Layout.Main);
                btnClick = FindViewById<Button>(Resource.Id.btnClick);
                camera_preview = FindViewById<FrameLayout>(Resource.Id.camera_preview);
                mCamera = GetCameraInstance();
                mCamera.SetDisplayOrientation(90);
                mPreview = new Preview(this, mCamera);
                camera_preview.AddView(mPreview);
                btnClick.Click += BtnClick_Click;
            }
    
            private bool CheckCameraHardware()
            {
                if (this.PackageManager.HasSystemFeature(Android.Content.PM.PackageManager.FeatureCamera))
                {
                    return true;
                } else
                {
                    return false;
                }
    
            }    
          private void BtnClick_Click(object sender, System.EventArgs e)
          {
            mCamera.TakePicture(null, null, this);
          }    
            private Android.Hardware.Camera GetCameraInstance()
            {
                Android.Hardware.Camera c=null;
                try
                {
                    c = Android.Hardware.Camera.Open();
                }
                catch (Java.Lang.Exception e)
                {
    
                }
    
                return c;
            }
    
            public void OnPictureTaken(byte[] data, Android.Hardware.Camera camera)
            {
                Bitmap bitmap=BitmapFactory.DecodeByteArray(data, 0, data.Length);
                Bitmap resizedBitmap=Bitmap.CreateScaledBitmap(bitmap, 100, 100, true);
                FindViewById<ImageView>(Resource.Id.imgResult).SetImageBitmap(resizedBitmap);
                //restart the preview
                if (mCamera != null)
                {
                    mCamera.StartPreview();
                }
             }
             }
    
Sign In or Register to comment.