Stream to ByteArray - Convert Signature pad to Ima

2019-09-17 10:47发布

问题:

I am using a Signature pad for Xamarin forms and I am trying to set the signature to an image source.

I am trying to convert stream to ByteArray but the converted bytearray is always empty.

In the function ReadFully I have tried two approaches but both returned 0 bytes

Could you please suggest where i am going wrong.

I looked up on the internet found these links

https://forums.xamarin.com/discussion/19853/load-image-form-byte-array

XAML

    <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Radical.Views.DocketSignaturePad"
             xmlns:acr="clr-namespace:Acr.XamForms.SignaturePad;assembly=Acr.XamForms.SignaturePad"
             Title="DocketSignaturePad">
  <ScrollView>
    <StackLayout Padding="10">
            <acr:SignaturePadView
                x:Name="padView"
                HeightRequest="320"
                WidthRequest="240"

                BackgroundColor="White"
                CaptionText="Caption This"
                CaptionTextColor="Black"
                ClearText="Clear Me!"
                ClearTextColor="Red"
                PromptText="Prompt Here"
                PromptTextColor="Red"
                SignatureLineColor="Aqua"
                StrokeColor="Black"
                StrokeWidth="2"
            />

            <Button Clicked="OnChangeTheme" Text="Change Theme" />
            <Button Clicked="SaveSignature" Text="Save signature"/>
            <Image x:Name="signatureImage" WidthRequest="300" HeightRequest="100" BackgroundColor="Blue"/>
        </StackLayout>
  </ScrollView>
</ContentPage>

Xaml.cs

    async void SaveSignature(object sender, EventArgs e)
        {

            List<DrawPoint> signaturePoints = padView.GetDrawPoints().ToList();

            if (signaturePoints.Count > 0)
            {
                Stream imageAsBytes = new MemoryStream(ReadFully(padView.GetImage(ImageFormatType.Jpg)));
                signatureImage.Source = ImageSource.FromStream(() => new MemoryStream(ReadFully(padView.GetImage(ImageFormatType.Jpg))));
}
}

public static byte[] ReadFully(Stream input)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                input.CopyTo(ms);
                return ms.ToArray();
            }


            //byte[] buffer = new byte[16 * 1024];
            //using (MemoryStream ms = new MemoryStream())
            //{
            //    int read;
            //    while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
            //    {
            //        ms.Write(buffer, 0, read);
            //    }
            //    return ms.ToArray();
            //}


        }

回答1:

You can use this code, it worked for me:

Stream image = await sign.GetImageStreamAsync(SignatureImageFormat.Png);                   
img_signature.Source = ImageSource.FromStream(() => image);


回答2:

I probably could fix your code using conversions but for my taste there are too many conversions you don't need. The problem is that after you get a stream it points to the end of it. Here is more optimal way of doing what you need:

void SaveSignature(object sender, EventArgs e)
{
            List<DrawPoint> signaturePoints = padView.GetDrawPoints().ToList();
            if (signaturePoints.Count > 0)
            {
                Stream s = padView.GetImage(ImageFormatType.Png);
                //s.Position = 0; or
                s.Seek(0,SeekOrigin.Begin);
                signatureImage.Source = ImageSource.FromStream(() => { return s; });
            }
}

Note, it doesn't work using JPG well because you cannot make it transparent background so it shows just black rectangle. It works with PNG. You might take a look on scaling an image if pad is not the same size as your image

One more thing: I would try to avoid putting stacklayout into scrollview. On small devices instead of writing the signature it tries to move the screen.

And I would look at more modern control from Xamarin