How to override original image with edited image in Xamarin forms
By default, In SfImageEditor when we save image, the image will be getting saved in gallery. We can also able to override the existing image with edited image.
Step 1: Create SfImageEditor sample with all necessary assemblies.
Please refer the below link to create a simple SfImageEditor sample along with the ways to configure it.
https://help.syncfusion.com/xamarin/sfimageeditor/getting-started
Step 2: To override the existing image with edited image in all the xamarin platforms. For this, you need to implement a DependencyService which is implemented across all the platform specific projects.
For adding the DependencyService, first you need to add an interface in the PCL project as in the below code snippet:
public interface IImageEditorDependencyService { Task<Stream> UploadFromGallery(); //Choosing image from gallery for UWP void UploadFromGallery(MainPage Page); //Choosing image from gallery for Android void Save(Stream stream); //override the existing image String GetPath(); //Get the path of selected image from gallery }
Now, you have to implement and register the DependencyService in the assembly based on platform specific. This can be done as follows:
Android
[assembly: Dependency(typeof(ImagePickerImplementation)) public class ImagePickerImplementation : IImageEditorDependencyService { void IImageEditorDependencyService.Save(System.IO.Stream stream) { Save(stream); } string IImageEditorDependencyService.GetPath() { return FilePath; } private string GetPathToImage(Android.Net.Uri uri) // Get the path of selected image from gallery { string imgId = ""; using (var c1 = activity.ContentResolver.Query(uri, null, null, null, null)) { c1.MoveToFirst(); string imageId = c1.GetString(0); imgId = imageId.Substring(imageId.LastIndexOf(":") + 1); } string path = null; string selection = MediaStore.Images.Media.InterfaceConsts.Id + " =? "; using (var cursor = activity.ContentResolver.Query(MediaStore.Images.Media.ExternalContentUri, null, selection, new string[] { imgId }, null)) { if (cursor == null) return path; var columnIndex = cursor.GetColumnIndexOrThrow(MediaStore.Images.Media.InterfaceConsts.Data); cursor.MoveToFirst(); path = cursor.GetString(columnIndex); FilePath = path; } return path; } public void Save(System.IO.Stream stream) // Saving the edited image { stream.Position = 0; var fileBytes = ReadFully(stream); bytesToBitmap(fileBytes); ExportBitmapAsJPG(bytesToBitmap(fileBytes)); } void ExportBitmapAsJPG(Bitmap bitmap) // Override the existing image with edited image { var stream = new System.IO.FileStream(FilePath, System.IO.FileMode.Create); bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, stream); stream.Close(); } }
UWP
[assembly: Dependency(typeof(ImagePickerImplementation)) public class ImagePickerImplementation : IImageEditorDependencyService { public async void Save(Stream stream) // Override the existing image with edited image { IRandomAccessStream randomAccessStream = stream.AsRandomAccessStream(); var wbm = new WriteableBitmap(600, 800); await wbm.SetSourceAsync(randomAccessStream); FolderPicker folderPicker = new FolderPicker(); folderPicker.FileTypeFilter.Add(".jpg"); string PathName = Path.GetDirectoryName(FilePath); string FileName = Path.GetFileName(FilePath); StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(@"" + PathName); if (folder != null) { StorageFile file = await folder.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting); using (var storageStream = await file.OpenAsync(FileAccessMode.ReadWrite)) { var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, storageStream); var pixelStream = wbm.PixelBuffer.AsStream(); var pixels = new byte[pixelStream.Length]; await pixelStream.ReadAsync(pixels, 0, pixels.Length); encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)wbm.PixelWidth, (uint)wbm.PixelHeight, 200, 200, pixels); await encoder.FlushAsync(); } } } public string GetPath() // Get the path of selected image from gallery { return FilePath; } }
iOS
In forms iOS we get the image path as a local identifier like "570C1598-6EBC-40CC-833E-50478E70FD7C".
Due to privacy level in iOS, it is not possible to override or modify the existing images.
Step 3: Call the following DependencyService method to override the existing image with edited image.
private void Editor_ImageSaving(object sender, ImageSavingEventArgs args) { args.Cancel = true; DependencyService.Get<IImageEditorDependencyService>().Save(args.Stream); DisplayAlert("Alert", "Image has been Override" + "" + FilePath, "OK"); }
Sample link:
https://www.syncfusion.com/downloads/support/directtrac/general/ze/ImageEditor_GetttingStarted717073453.zip