Skip to content
This repository has been archived by the owner on May 5, 2021. It is now read-only.

Background Image is not returning back #88

Open
xyashapyx opened this issue Aug 21, 2017 · 17 comments
Open

Background Image is not returning back #88

xyashapyx opened this issue Aug 21, 2017 · 17 comments

Comments

@xyashapyx
Copy link

If you are setting BackgroundImage and draw on it, only drawn part will be returned, not BackgroundImage with drawings.

@tro-solo
Copy link

I have this problem too. It would be really helpful if you could add a boolean property 'IncludeBackgroundImage' to the ImageConstructionSettings, so it can be backwards compatible.

@Sean-LINKSOFT
Copy link

A feature to get the drawn component and the background as a single image is something that I would like to use as well. Would such a feature be considered to be added to SignaturePad?

@deckertron9000
Copy link

I'd like to see this implemented as well.

@Vandersteen
Copy link

It would be awesome indeed,

I currently 'extended' the signaturepad view as follows:

Forms View

public class MarkingView : SignaturePadView
{
    public Func<string> SaveImageWithBackground;
}

IOS Renderer

[assembly: ExportRenderer (typeof(MarkingView), typeof(MarkingViewRenderer))]
namespace B2B.iOS
{
    public class MarkingViewRenderer : ViewRenderer<MarkingView, SignaturePadView>
	{
        protected override void OnElementChanged(ElementChangedEventArgs<MarkingView> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                e.OldElement.SaveImageWithBackground = null;
            }
            if (e.NewElement != null)
            {
                e.NewElement.SaveImageWithBackground += NewElement_SaveImageWithBackground;
            }
        }

        string NewElement_SaveImageWithBackground()
        {
            UIGraphics.BeginImageContextWithOptions(Bounds.Size, false, 0f);

            using(var context = UIGraphics.GetCurrentContext())
            {
                Layer.RenderInContext(context);
                using (UIImage img = UIGraphics.GetImageFromCurrentImageContext())
                {
                    UIGraphics.EndImageContext();

                    string folder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                    string filename;
                    do
                    {
                        filename = Path.Combine(folder, "Marking-" + DateTime.Now.Ticks + ".png");
                    }
                    while (File.Exists(filename));

                    img.AsPNG().Save(filename, true);

                    return filename;
                }
            }
        }
    }
}

Android Renderer

[assembly: ExportRenderer (typeof(MarkingView), typeof(MarkingViewRenderer))]
namespace B2B.Droid
{
    public class MarkingViewRenderer : ViewRenderer<MarkingView, SignaturePadView>
	{
        protected override void OnElementChanged (ElementChangedEventArgs<MarkingView> e)
		{
			base.OnElementChanged (e);

			if (e.OldElement != null) {
                e.OldElement.SaveImageWithBackground = null;
			}
			if (e.NewElement != null) {
                e.NewElement.SaveImageWithBackground += NewElement_SaveImageWithBackground;
			}
		}

        string NewElement_SaveImageWithBackground()
        {
            using(Bitmap bm = Bitmap.CreateBitmap(Width, Height, Bitmap.Config.Argb8888))
            {
                using(Canvas canvas = new Canvas(bm))
                {
                    Drawable bgDrawable = Background;

                    if (bgDrawable != null)
                    {
                        bgDrawable.Draw(canvas);
                    }

                    Draw(canvas);

                    string folder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                    string filename;
                    do
                    {
                        filename = System.IO.Path.Combine(folder, "Marking-" + DateTime.Now.Ticks + ".png");
                    }
                    while (File.Exists(filename));

                    using (var fs = new System.IO.FileStream(filename, FileMode.CreateNew))
                    {
                        bm.Compress(Bitmap.CompressFormat.Png, 90, fs);
                        bm.Recycle();

                        return filename;
                    }
                }
            }
        }
    }
}

Feel free to use it.
It's not perfect, but it works for my needs

@mattleibow
Copy link
Contributor

This seems to be a popular request, we will put this on the list of things to do for a future release.

@mattleibow mattleibow added this to the vNext milestone Nov 10, 2017
@Sean-LINKSOFT
Copy link

Vandersteen what are the using statements from your renderer classes?
I get the following errors for the class definition line -

The type 'SignaturePad.Forms.SignaturePadView' cannot be used as type parameter 'TNativeView' in the generic type or method 'ViewRenderer<TView, TNativeView>'. There is no implicit reference conversion from 'SignaturePad.Forms.SignaturePadView' to 'UIKit.UIView'.
&
The type 'SignaturePad.Forms.SignaturePadView' cannot be used as type parameter 'TNativeView' in the generic type or method 'ViewRenderer<TView, TNativeView>'. There is no implicit reference conversion from 'SignaturePad.Forms.SignaturePadView' to 'Android.Views.View'.

@Vandersteen
Copy link

Vandersteen commented Nov 13, 2017

IOS:

using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using UIKit;
using System.IO;
using Xamarin.Controls;
//our shared app namespace
//our native app namespace

Android:

using System;
using Xamarin.Forms;
using System.IO;
using Xamarin.Forms.Platform.Android;
using Android.Graphics;
using Xamarin.Controls;
using Android.Graphics.Drawables;
//our shared app namespace
//our native app namespace

@jemmett92
Copy link

Vandersteen thats a great renderer, well done. You can make a basic image editor from that.
Do you have any idea if you can get rid extra part the signature pad adds to the background image for the signature line? I can make it transparent but its still on the image when i save it? any ideas? I was also wondering if you could add another image on top of the background image like a sticker using that renderer?

@Vandersteen
Copy link

I did not test it but I think you could do the following:

  1. Find the specific views that you want to render (Background, Lines)
  2. Render those in the context instead of the whole view
    //Replace
    Layer.RenderInContext(context);
    
    //With
    Control.BackgroundImageView.Layer.RenderInContext(context);
    Control.SignatureLine.Layer.RenderInContext(context);

Same thing for android:

//Replace
Draw(canvas);

//With
Control.BackgroundImageView.Draw(canvas);
Control.SignatureLine.Draw(canvas);
  1. You could do the same if you want to add an extra image on top:

var watermark = new UIImageView(); ...
watermark.Layer.RenderInContext(context);

Again, not tested, but that's where I would start

@PizzaBoatJim
Copy link

Vandersteen NICE GOING! What you have developed is exactly what I need now. I have tried to implement it, but getting errors. Would it be possible for you to post a sample code of your render implementation?

@Vandersteen
Copy link

I posted the renderers above.

For the view usage you will just need to do the following:

var markingView = new MarkingView();
...
var pathToImage = markingView. SaveImageWithBackground();

@PizzaBoatJim
Copy link

PizzaBoatJim commented May 10, 2018

Vandersteen - thank you for the post. I implemented your code, but many problems arise and I cannot compile. I must be doing something wrong. Here is my code:

`using System;
using Xamarin.Forms;
using System.IO;
using Xamarin.Forms.Platform.Android;
using Android.Graphics;
using Xamarin.Controls;
using Android.Graphics.Drawables;
using ES;
using ES.Droid;
//our native app namespace
[assembly: ExportRenderer(typeof(MarkingView), typeof(MarkingViewRenderer))]
namespace ES.Droid
{
public class MarkingView : SignaturePadView
{
public Func SaveImageWithBackground;
}

public class MarkingViewRenderer : ViewRenderer<MarkingView, SignaturePadView>
{
    protected override void OnElementChanged(ElementChangedEventArgs<MarkingView> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement != null)
        {
            e.OldElement.SaveImageWithBackground = null;
        }
        if (e.NewElement != null)
        {
            e.NewElement.SaveImageWithBackground += NewElement_SaveImageWithBackground;
        }
    }

    private string NewElement_SaveImageWithBackground()
    {
        using (Bitmap bm = Bitmap.CreateBitmap(Width, Height, Bitmap.Config.Argb8888))
        {
            using (Canvas canvas = new Canvas(bm))
            {
                Drawable bgDrawable = Background;

                if (bgDrawable != null)
                {
                    bgDrawable.Draw(canvas);
                }

                Draw(canvas);

                string folder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                string filename;
                do
                {
                    filename = System.IO.Path.Combine(folder, "Marking-" + DateTime.Now.Ticks + ".png");
                }
                while (File.Exists(filename));

                using (var fs = new FileStream(filename, FileMode.CreateNew))
                {
                    bm.Compress(Bitmap.CompressFormat.Png, 90, fs);
                    bm.Recycle();

                    return filename;
                }
            }
        }
    }
}

}`

Here are the errors:
Severity Code Description Project File Line Suppression State Error CS0311 The type 'ES.Droid.MarkingView' cannot be used as type parameter 'TView' in the generic type or method 'ViewRenderer<TView, TNativeView>'. There is no implicit reference conversion from 'ES.Droid.MarkingView' to 'Xamarin.Forms.View'. EnSpect.Android C:\J\Software\ES\ES\ES.Android\MarkingView.cs 20 Active

Severity Code Description Project File Line Suppression State Error CS0311 The type 'ES.Droid.MarkingView' cannot be used as type parameter 'TElement' in the generic type or method 'ElementChangedEventArgs<TElement>'. There is no implicit reference conversion from 'ES.Droid.MarkingView' to 'Xamarin.Forms.Element'. ES.Android C:\J\Software\ES\ES\ES.Android\MarkingView.cs 22 Active

Severity Code Description Project File Line Suppression State Error CS1729 'SignaturePadView' does not contain a constructor that takes 0 arguments ES.Android C:\J\Software\ES\ES\ES.Android\MarkingView.cs 14 Active

Any suggestions how to fix?

@mattleibow mattleibow removed this from the 3.0-preview milestone May 18, 2018
@mattleibow
Copy link
Contributor

This needs a bit more thought - same with other "chrome" features, similar to #127

@PaulVrugt
Copy link

I actually used the example of @Vandersteen to implement the signaturepad to allow us to annotate images. I know this component is meant for recording signatures, but we use it to let people annotate images they just selected or pictures they just took to clarify a photo of a situation. This works perfectly. Support built into the package would be great, because it would mean less code to maintain on our end.

@chrislowcher
Copy link

I would love to see this implemented as well. It would be really helpful. Thanks

@tsafadi
Copy link

tsafadi commented May 10, 2020

@Vandersteen very nice solution! However, I would want to pass an argument to the function such that I can save it to a specific directory. Could you help me extend the function for an additional parameter that I can pass into the SaveImageWithBackground function.
Something like:
signPad.SaveImageWithBackground(“something”);

@tsafadi
Copy link

tsafadi commented May 14, 2020

I extended @Vandersteen's example by taking one more argument, such that I can pass in the directory where to save the files to. In my case, I want to save them in a specific directory for each signature:

public class CustomSignaturePadView : SignaturePadView
{
    public Func<string, string> SaveImageWithBackground;
}

And then you only need to extend the NewElement_SaveImageWithBackground functions by one parameter, like so string NewElement_SaveImageWithBackground(string path).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests