How to save a SkiaSharp drawing?

Will.ItraxWill.Itrax CAMember ✭✭✭

I must be missing something. I started with the FingerPainting part of the TouchTrackingEffectDemos. After drawing something, I want to save it so I added a Save Button (just like there is a Clear Button). The Save button is supposed to save the drawing to my device but all I get is a blank white jpg. I am using Snapshot to capture the image. I suspect that it is not working the way I expect.
Here is my code for the Save. Any insight into how to save the drawing to a file is much appreciated!

`
void OnSaveButtonClicked(object sender, EventArgs args)
{
int width = (int)canvasView.CanvasSize.Width;
int height = (int)canvasView.CanvasSize.Height;
var info = new SKImageInfo(width, height);

        var item = (FingerPaintPage)((Button)sender).BindingContext;

        using (var surface = SKSurface.Create(width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul))
        {
            SKData skData = surface.Snapshot().Encode();

            IFolder folder = FileSystem.Current.LocalStorage;
            string path = folder.Path;
            string fileout = path + "/outfile.jpg";
            string fileout2 = path + "/outfile2.jpg";

            // Plan A)
            using (Stream stream2 = File.OpenWrite(fileout))
            {
                skData.SaveTo(stream2);
            }        

            // Plan B)
            SKBitmap bitmap = new SKBitmap(width, height);
            // create an image and then get the PNG (or any other) encoded data
            using (var image = SKImage.FromBitmap(bitmap))
            using (var data = image.Encode(SKEncodedImageFormat.Jpeg, 100))
            {
                // save the data to a stream
                using (var stream = File.OpenWrite(fileout2))
                {
                    data.SaveTo(stream);
                }
            }
        }
    }`

Best Answer

Answers

  • DJNovaDJNova USMember ✭✭

    You will need to do the actual file saving in platform specific dependencies. Or use one of the Xamarin Plugins that provide file access interfaces.

  • Will.ItraxWill.Itrax CAMember ✭✭✭

    @seanyda Ok - I did not expect to have to totally redraw everything on a new canvas - but you are right. Thanks!

  • mhdziyyadmhdziyyad Member ✭✭

    @Will.Itrax I am in need of the fingerpaint with save which i have been trying for longer time, since i am new to this platform can you help me with this. Thank You

  • Will.ItraxWill.Itrax CAMember ✭✭✭

    @mhdziyyad What have you tried so far?

  • mhdziyyadmhdziyyad Member ✭✭
    edited February 13

    @Will.Itrax I have tried integrating the code from fingerpaint save from skiasharp demos and from the discussion "forums.xamarin.com/discussion/102674/how-to-save-finger-painting-from-skcanvasview-into-file"

  • Will.ItraxWill.Itrax CAMember ✭✭✭

    @mhdziyyad So, what parts have you got working? What is not working and what is it doing? Please show the code that is not working.

  • mhdziyyadmhdziyyad Member ✭✭
    edited February 14

    async void OnSaveButtonClicked(object sender, EventArgs args)
    {
    using (SKImage image = SKImage.FromBitmap(saveBitmap))
    {
    try
    {
    SKData data = image.Encode();
    DateTime dt = DateTime.Now;
    string filename = String.Format("FingerPaint-{0:D4}{1:D2}{2:D2}-{3:D2}{4:D2}{5:D2}{6:D3}.png",
    dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Millisecond);

                    IPhotoLibrary photoLibrary = DependencyService.Get<IPhotoLibrary>();
                    if (photoLibrary == null)
                    {
                        return;
                    }
    
                    bool result = await photoLibrary.SavePhotoAsync(data.ToArray(), "FingerPaint", filename);
    
                    if (!result)        // The image is not saving on result and it displays the alert
                    {
                        await DisplayAlert("FingerPaint", "Artwork could not be saved. Sorry!", "OK");
                    }
                }
                catch(Exception ex)
                {
                   string err = ex.InnerException.ToString();
                }
    
            }
        }
    

    //PhotoLibrary.cs

    public async Task SavePhotoAsync(byte[] data, string folder, string filename)
    {
    try
    {
    File picturesDirectory = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryPictures);
    File folderDirectory = picturesDirectory;

                if (!string.IsNullOrEmpty(folder))
                {
                    folderDirectory = new File(picturesDirectory, folder);
                    folderDirectory.Mkdirs();
                }
    
                using (File bitmapFile = new File(folderDirectory, filename))
                {
                    bitmapFile.CreateNewFile();
    
                    using (FileOutputStream outputStream = new FileOutputStream(bitmapFile))
                    {
                        await outputStream.WriteAsync(data);
                    }
    
                    // Make sure it shows up in the Photos gallery promptly.
                  /*  MediaScannerConnection.ScanFile(MainActivity.Instance,
                                                    new string[] { bitmapFile.Path },
                                                    new string[] { "image/png", "image/jpeg" }, null);*/
                }
            }
            catch
            {
                return false;
            }
    
            return true;
        }
    

    False is sent by:

    MediaScannerConnection.ScanFile(MainActivity.Instance,
    new string[] { bitmapFile.Path },
    new string[] { "image/png", "image/jpeg" }, null);

  • mhdziyyadmhdziyyad Member ✭✭

    @Will.Itrax I have resolved my issue, still thank you for your time :) :)

  • Will.ItraxWill.Itrax CAMember ✭✭✭

    @mhdziyyad Thanks for the code sample. That is very helpful.
    I see that you solved it. Would you mind sharing what you had to do - in case a later reader of this thread has the same problem?
    Thanks!

  • mhdziyyadmhdziyyad Member ✭✭

    @Will.Itrax

    protected override void OnCreate(Bundle bundle)
    {
    TabLayoutResource = Resource.Layout.Tabbar;
    ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);
            Instance = this;                                                      // I missed this line on MainActivity.cs
            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App());
        }
    
  • Will.ItraxWill.Itrax CAMember ✭✭✭

    @mhdziyyad Thanks for sharing!

  • mhdziyyadmhdziyyad Member ✭✭

    @Will.Itrax said:
    @mhdziyyad Thanks for sharing!

    It's my pleasure :) :)

Sign In or Register to comment.