3

I have been capturing user signatures using signature pad (https://github.com/szimek/signature_pad/). I need to be able to convert these signatures into a jpeg that retains the image of the signature. I can't get it to work with out the images just being a big black box. I think it has something to do with how the images are rendered.

I used this tutorial to create the signatures (https://www.thewebflash.com/using-signature-pad-with-asp-net-mvc/). I need the signature in a picture format so I can put it on my form. I'm guessing something is going wrong because javascript is needed to render the byte[] correctly, so I'm not converting the raw byte[] to a jpeg correctly in the controller (last part).

Here is my code:

Class:

public class Signature
{
        public int ID { get; set; }
        [UIHint("SignaturePad")]
        public byte[] MySignature { get; set; }

}

public class SignatureDbContext : DbContext
{
    public DbSet<Signature> SignatureDatabase { get; set; }
}

UIHint attribute in order to specify that the following SignaturePad.cshtml templates should be used to display the model property in a view.

Views\Shared\DisplayTemplates\SignaturePad.cshtml :

@model byte[]

<div class="signature-pad">
<canvas class="panel panel-default"></canvas>
<button type="button" class="btn btn-default btn-sm btn-clear-     canvas">Clear</button>
@Html.HiddenFor(model => model, new { @disabled = "disabled" })

and Views\Shared\EditorTemplates\SignaturePad.cshtml :

@model byte[]

<div class="signature-pad">
<canvas class="panel panel-default"></canvas>
<button type="button" class="btn btn-default btn-sm btn-clear-canvas">Clear</button>
@Html.HiddenFor(model => model, ViewData["htmlAttributes"])

In my css Content\Site.css I have this :

.signature-pad > canvas {
display: block;
width: 300px;
height: 150px;
margin-bottom: 5px;
}

In the scripts folder I have a javascript script to help render the image on the view.

SignaturePadInit.js :

var signaturePadWrappers = document.querySelectorAll('.signature-pad');

[].forEach.call(signaturePadWrappers, function (wrapper) {
var canvas = wrapper.querySelector('canvas');
var clearButton = wrapper.querySelector('.btn-clear-canvas');
var hiddenInput = wrapper.querySelector('input[type="hidden"]');

var signaturePad = new SignaturePad(canvas);

// Read base64 string from hidden input
var base64str = hiddenInput.value;

if (base64str) {
    // Draws signature image from data URL
    signaturePad.fromDataURL('data:image/png;base64,' + base64str);
}

if (hiddenInput.disabled) {
    signaturePad.off();
    clearButton.classList.add('hidden');
} else {
    signaturePad.onEnd = function () {
        // Returns signature image as data URL and set it to hidden input
        base64str = signaturePad.toDataURL().split(',')[1];
        hiddenInput.value = base64str;
    };

    clearButton.addEventListener('click', function () {
        // Clear the canvas and hidden input
        signaturePad.clear();
        hiddenInput.value = '';
    });
}
});

When I want to see the signature in a view I include this at the buttom or else the signature appears as an empty white box:

@section Scripts {
<script src="~/Scripts/signature_pad.min.js"></script>
<script src="~/Scripts/SignaturePadInit.js"></script>
}

The signature_pad.min.js comes default with the signaturepad library through nuget. I didn't touch it and I don't think it needs to be discussed. I haven't included it because it is extremely long.

Here is my code for converting the byte[] to a jpeg. It converts the byte[] to a jpeg and adds it to a pdf but I have excluded everything but the part that converts to a jpeg. even saving the image locally yeilds a file that is a black block with no signature :

    public ActionResult GeneratePDFforSignature(int? id)
    {

        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Signature signature = db.SignatureDatabase.Find(id);

        Image x = (Bitmap)((new ImageConverter()).ConvertFrom(signature.MySignature));
        System.Drawing.Image img = x;
        img.Save(Server.MapPath("~/Content/test.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);

        //return View();
        return RedirectToAction("Index");
    }

I really dont know what to do next to fix this and get the signatures as a jpeg with an actual image in it. I guess I'll keep messing with the SignaturePadInit.js for now. If anyone needs me to post more information to fix this please let me know in the comments.

Tyler S. Loeper
  • 816
  • 11
  • 22

1 Answers1

3

Just a stab here, but have you tried to see if rendering to 24bit png will work allowing for areas that have no image/ signature be transparent?

I only think this because I had similar issues where there were encoded pixels for transparency that I wasn't thinking about and it had the same issue. (Would have commented but the system won't let me )

Marcus
  • 453
  • 3
  • 10
  • 1
    Thanks for the tip. I'll give it a shot. I know signature pad defaults blank pixels to black transparent. I'll try and see if the signature is hidden somewhere in the image. I'll give an update if it works. – Tyler S. Loeper Mar 03 '17 at 01:48
  • Yea I'd try that first. I had similar issue with other package and it plagued me forever. So even if it's not the issue with you I felt I had to share maybe give a direction to take. – Marcus Mar 03 '17 at 01:54
  • 2
    You're right. I saved the signature as a png and filtered out the transparent pixels and sure enough there is the signature hidden in the image. It was buried under all the black pixels. Thank you for the help. I have marked your answer as correct. – Tyler S. Loeper Mar 03 '17 at 02:10
  • @TylerSigi May i know how you fixed it ? – Aswin Arshad Jan 19 '18 at 11:41