2X faster development
The ultimate Xamarin UI toolkit to boost your development speed.
This article explains how to load an image from camera / gallery in Syncfusion Xamarin Image Editor (SfImageEditor) with the following procedure.
To take a picture in Xamarin.Forms, you need to use the native platform’s API’s to access the camera. Here, it has been done with help of DependencyService which is implemented across all the platform specific projects.
Here implements CameraInterface interface.
public interface CameraInterface { void LaunchCamera(FileFormatEnum imageType, string imageId = null); void LaunchGallery(FileFormatEnum imageType, string imageId = null); }
Using it, register the DependencyService based on platform specific as per in below Android:public void LaunchCamera(FileFormatEnum fileType, string imageId) { var intent = new Intent(MediaStore.ActionImageCapture); Intent takePictureIntent = new Intent(MediaStore.ActionImageCapture); if (takePictureIntent.ResolveActivity(MainActivity.ActivityContext.PackageManager) != null) { try { var documentsDirectry = MainActivity.ActivityContext.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures); cameraFile = new Java.IO.File(documentsDirectry, imageId + "." + fileType.ToString()); if (cameraFile != null) { using (var mediaStorageDir = new Java.IO.File(documentsDirectry, string.Empty)) { if (!mediaStorageDir.Exists()) { if (!mediaStorageDir.Mkdirs()) throw new IOException("Couldn't create directory, have you added the WRITE_EXTERNAL_STORAGE permission?"); } } } } catch (IOException ex) { Console.WriteLine(ex); } //Ensure the authority matches what you put in the AndroidManifest.xml file Android.Net.Uri photoURI = FileProvider.GetUriForFile(((Activity)MainActivity.ActivityContext), "com.yourcompany.IECameraAndGallery.fileprovider", cameraFile); takePictureIntent.PutExtra(MediaStore.ExtraOutput, photoURI); ((Activity)MainActivity.ActivityContext).StartActivityForResult(takePictureIntent, 0); } } public void LaunchGallery(FileFormatEnum fileType, string imageId) { var imageIntent = new Intent(); imageIntent.SetType("image/*"); if (imageId != null) { imageIntent.PutExtra("fileName", imageId + "." + fileType.ToString()); } imageIntent.SetAction(Intent.ActionGetContent); ((Activity)MainActivity.ActivityContext).StartActivityForResult(Intent.CreateChooser(imageIntent, "Select photo"), 1); }
Note: Set the requestLegacyExternalStorage value as true in your app’s manifest file, if the target version is 10.
iOS:public async void LaunchCamera(FileFormatEnum imageType, string imageId = null) { //Check if we have permission to use the camera var authorizationStatus = AVCaptureDevice.GetAuthorizationStatus(AVMediaType.Video); if (authorizationStatus != AVAuthorizationStatus.Authorized) { var access = await AVCaptureDevice.RequestAccessForMediaTypeAsync(AVMediaType.Video); if (access) { if (imageId == null) GotAccessToCamera(imageType); else { var fileName = imageId + "." + imageType.ToString(); GotAccessToCamera(imageType, fileName); } } } else { if (imageId == null) GotAccessToCamera(imageType); else { var fileName = imageId + "." + imageType.ToString(); GotAccessToCamera(imageType, fileName); } } } public void LaunchGallery(FileFormatEnum imageType, string imageId = null) { try { var imagePicker = new UIImagePickerController { SourceType = UIImagePickerControllerSourceType.PhotoLibrary, MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.PhotoLibrary) }; imagePicker.AllowsEditing = true; var window = UIApplication.SharedApplication.KeyWindow; var vc = window.RootViewController; while (vc.PresentedViewController != null) { vc = vc.PresentedViewController; } vc.PresentViewController(imagePicker, true, null); imagePicker.FinishedPickingMedia += (sender, e) => { UIImage originalImage = e.Info[UIImagePickerController.EditedImage] as UIImage; if (originalImage != null) { NSData pngImage = null; if (imageType == FileFormatEnum.JPEG) pngImage = originalImage.AsJPEG(); else pngImage = originalImage.AsPNG(); byte[] myByteArray = new byte[pngImage.Length]; System.Runtime.InteropServices.Marshal.Copy(pngImage.Bytes, myByteArray, 0, Convert.ToInt32(pngImage.Length)); MessagingCenter.Send<byte[]>(myByteArray, "ImageSelected"); } Device.BeginInvokeOnMainThread(() => { vc.DismissViewController(true, null); }); }; imagePicker.Canceled += (sender, e) => vc.DismissViewController(true, null); } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e); } } … private void GotAccessToCamera(FileFormatEnum imageType, string imageId = null) { var imagePicker = new UIImagePickerController { SourceType = UIImagePickerControllerSourceType.Camera }; var window = UIApplication.SharedApplication.KeyWindow; var vc = window.RootViewController; while (vc.PresentedViewController != null) { vc = vc.PresentedViewController; } vc.PresentViewController(imagePicker, true, null); imagePicker.FinishedPickingMedia += (sender, e) => { UIImage image = (UIImage)e.Info.ObjectForKey(new NSString("UIImagePickerControllerOriginalImage")); UIImage rotateImage = RotateImage(image, image.Orientation); rotateImage = rotateImage.Scale(new CGSize(rotateImage.Size.Width, rotateImage.Size.Height), 0.5f); NSData imgData = null; if (imageType == FileFormatEnum.PNG) imgData = rotateImage.AsPNG(); else imgData = rotateImage.AsJPEG(); byte[] myByteArray = new byte[imgData.Length]; System.Runtime.InteropServices.Marshal.Copy(imgData.Bytes, myByteArray, 0, Convert.ToInt32(imgData.Length)); if (imageId != null) SavePhoto(rotateImage, imageId, imageType); MessagingCenter.Send<byte[]>(myByteArray, "ImageSelected"); Device.BeginInvokeOnMainThread(() => { vc.DismissViewController(true, null); }); }; imagePicker.Canceled += (sender, e) => vc.DismissViewController(true, null); } … UWP:public async void LaunchCamera(FileFormatEnum imageType, string imageId = null) { CameraCaptureUI captureUI = new CameraCaptureUI(); captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg; captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.JpegXR; captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Png; StorageFile photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo); if (photo != null) { var stream = await photo.OpenAsync(FileAccessMode.Read); var reader = new DataReader(stream.GetInputStreamAt(0)); var bytes = new byte[stream.Size]; await reader.LoadAsync((uint)stream.Size); reader.ReadBytes(bytes); MessagingCenter.Send<byte[]>(bytes, "ImageSelected"); } } public async void LaunchGallery(FileFormatEnum imageType, string imageId = null) { FileOpenPicker openPicker = new FileOpenPicker(); openPicker.FileTypeFilter.Add(".jpg"); openPicker.FileTypeFilter.Add(".png"); openPicker.FileTypeFilter.Add(".jpeg"); StorageFile file = await openPicker.PickSingleFileAsync(); if (file != null) { var stream = await file.OpenAsync(FileAccessMode.Read); var reader = new DataReader(stream.GetInputStreamAt(0)); var bytes = new byte[stream.Size]; await reader.LoadAsync((uint)stream.Size); reader.ReadBytes(bytes); MessagingCenter.Send<byte[]>(bytes, "ImageSelected"); } }
Finally use the below code snippet to display the loaded image from galley or camera into SfImageEditor.
void OpenImageEditor(ImageSource imageSource) { editor.Source = imageSource; }
Output:
See also:
How do I add a shape to an image?
How do I add a text to an image?
How can I customize the default toolbar?
|
2X faster development
The ultimate Xamarin UI toolkit to boost your development speed.
This page will automatically be redirected to the sign-in page in 10 seconds.
System.NullReferenceException: 'Object reference not set to an instance of an object.'
Hi John,
We have ensured this sample in all the platforms and its working properly. Can you share the replication steps, platform, and device info? It will be helpful for us to investigate further.
Hi I am trying this code but it looks out dated. Do you have newer code
Thank you
Good afternoon,
I am running the above code on a Nokia 1 Model TA-1047, Android version 8.1.0 and when tappin on 'Take a photo' I get the following error at MainActivity.cs:81
Thanks for looking into this. Bernard
--- error --> {Android.OS.FileUriExposedException: file:///storage/emulated/0/Pictures/ImageEditor/ImageEditor_Photo_20200323173056867.jpg exposed beyond app through ClipData.Item.getUri() at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue args) [0x0008e] in <26521a5118b44c858c385715922b9d5d>:0 at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue parameters) [0x0005d] in <26521a5118b44c858c385715922b9d5d>:0 at Android.App.Activity.StartActivityForResult (Android.Content.Intent intent, System.Int32 requestCode) [0x00044] in <4ccdb3137d974856b786e1aeebbfbab6>:0 at IECameraandGallery.Droid.ImageEditorService.UploadFromCamera (IECameraandGallery.MainPage editor) [0x000d7] in C:\Git\Syncfusion\load-image-from-Camera-Gallery\IECameraandGallery\IECameraandGallery.Android\MainActivity.cs:81 at IECameraandGallery.MainPage.TakeAPhotoTapped (System.Object sender, System.EventArgs e) [0x0006f] in C:\Git\Syncfusion\load-image-from-Camera-Gallery\IECameraandGallery\IECameraandGallery\MainPage.xaml.cs:82 at Xamarin.Forms.TapGestureRecognizer.SendTapped (Xamarin.Forms.View sender) [0x0002e] in d:\agent\1\s\Xamarin.Forms.Core\TapGestureRecognizer.cs:48 at Xamarin.Forms.Platform.Android.TapGestureHandler.OnTap (System.Int32 count, Xamarin.Forms.Point point) [0x000a2] in d:\agent\1\s\Xamarin.Forms.Platform.Android\TapGestureHandler.cs:52 at Xamarin.Forms.Platform.Android.InnerGestureListener.Android.Views.GestureDetector.IOnGestureListener.OnSingleTapUp (Android.Views.MotionEvent e) [0x00014] in d:\agent\1\s\Xamarin.Forms.Platform.Android\InnerGestureListener.cs:151 at Android.Views.GestureDetector+IOnGestureListenerInvoker.n_OnSingleTapUp_Landroid_viewMotionEvent (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_e) [0x00011] in <4ccdb3137d974856b786e1aeebbfbab6>:0 at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.43(intptr,intptr,intptr) --- End of managed Android.OS.FileUriExposedException stack trace --- android.os.FileUriExposedException: file:///storage/emulated/0/Pictures/ImageEditor/ImageEditor_Photo_20200323173056867.jpg exposed beyond app through ClipData.Item.getUri() at android.os.StrictMode.onFileUriExposed(StrictMode.java:1960) at android.net.Uri.checkFileUriExposed(Uri.java:2356) at android.content.ClipData.prepareToLeaveProcess(ClipData.java:942) at android.content.Intent.prepareToLeaveProcess(Intent.java:9850) at android.content.Intent.prepareToLeaveProcess(Intent.java:9835) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1610) at android.app.Activity.startActivityForResult(Activity.java:4501) at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:767) at android.app.Activity.startActivityForResult(Activity.java:4459) at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:754) at crc643f46942d9dd1fff9.InnerGestureListener.n_onSingleTapUp(Native Method) at crc643f46942d9dd1fff9.InnerGestureListener.onSingleTapUp(InnerGestureListener.java:79) at android.view.GestureDetector.onTouchEvent(GestureDetector.java:640) at crc64ee486da937c010f4.ImageRenderer.n_onTouchEvent(Native Method) at crc64ee486da937c010f4.ImageRenderer.onTouchEvent(ImageRenderer.java:62) at android.view.View.dispatchTouchEvent(View.java:11808) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at crc643f46942d9dd1fff9.Platform_DefaultRenderer.n_dispatchTouchEvent(Native Method) at crc643f46942d9dd1fff9.Platform_DefaultRenderer.dispatchTouchEvent(Platform_DefaultRenderer.java:55) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at crc643f46942d9dd1fff9.Platform_DefaultRenderer.n_dispatchTouchEvent(Native Method) at crc643f46942d9dd1fff9.Platform_DefaultRenderer.dispatchTouchEvent(Platform_DefaultRenderer.java:55) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at crc643f46942d9dd1fff9.Platform_DefaultRenderer.n_dispatchTouchEvent(Native Method) at crc643f46942d9dd1fff9.Platform_DefaultRenderer.dispatchTouchEvent(Platform_DefaultRenderer.java:55) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at crc643f46942d9dd1fff9.VisualElementRenderer_1.n_dispatchTouchEvent(Native Method) at crc643f46942d9dd1fff9.VisualElementRenderer_1.dispatchTouchEvent(VisualElementRenderer_1.java:65) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at crc643f46942d9dd1fff9.PlatformRenderer.n_dispatchTouchEvent(Native Method) at crc643f46942d9dd1fff9.PlatformRenderer.dispatchTouchEvent(PlatformRenderer.java:55) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3022) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2680) at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:449) at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1839) at android.app.Activity.dispatchTouchEvent(Activity.java:3321) at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69) at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69) at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:411) at android.view.View.dispatchPointerEvent(View.java:12052) at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4976) at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4786) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4318) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4371) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4337) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4464) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4345) at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4521) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4318) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4371) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4337) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4345) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4318) at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6912) at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6886) at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6843) at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7030) at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:186) at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method) at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:177) at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:6997) at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:7053) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:916) at android.view.Choreographer.doCallbacks(Choreographer.java:728) at android.view.Choreographer.doFrame(Choreographer.java:654) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:902) at android.os.Handler.handleCallback(Handler.java:790) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6523) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857) }
Tested on a Huawei BG2-W09 tablet (Android 6.0 - API 23) and works well on that. Seems only the little Nokia phone has a problem with the camera (Gallery is fine).
This code is very different from the linked github example, and it is incomplete! In the android example there are two uninitialized variables.
Could you please provide better documentation for this? I'm sure we're all able to extract the necessary information from the example somehow, but this incomplete / wrong example is bad :(
Hi Christoph,
We modified and refreshed this document code as seen in the GitHub example.