locked
Loading a Signature Captured into an ASP.Net Web Page... RRS feed

  • Question

  • User-1975938688 posted

    I have a mobile device that i developed software to capture a signature from customers when an item is delivered.  The signature is captured as a bitmap and saved to the database as raw bytes.  The problem I am having is when loading the signature into an ASP.net web page for viewing.  I can't seem to figure out how to translate it back into a viewable image.  Instead it just gives me a blank picture box.  I used the DevBuzz tutorial on making a vb.net signature capture control, which works very well for my devices.  Can anyone help me with getting a viewable image onto the webpage?

    I am trying to display the signature image in a gridview as a list of confirmations.  I am using a Handler.ashx to handle the population of the images in the gridview.  I can post the signature capture code if anyone thinks it will help in figuring out how to load it into the webpage.

    Wednesday, February 9, 2011 10:30 AM

All replies

  • User-1975938688 posted

    Also as additional information I have tried also navigating to the handler and passing the query string and I get binary output at the top of the screen.  I would think that I would get an image...or atleast since I am getting some binary at the top of the page I figure I would get a viewable image when sent to the image control....

    For example when navigating to the Handler page passing a query string for an image in the database I get: signatureÝzH<�+7.*A

    Could the problem be that it is passing also the column name?  If so how can I drop that from the response?

    Wednesday, February 9, 2011 3:32 PM
  • User-1975938688 posted

    Ok so below is the code i use on the device to upload the signature image.  I have tried the BinaryWrite function from both the Handler and from a basic webpage passing a query string for the ID of the signature image but i am not getting any results.  All i get from the database is the raw binary string representing the signature image.  How can i turn it back into an image and display it in my asp.net webpage...  This is getting very frustrating... :|



    using Microsoft.VisualBasic;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Text;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.IO;
    
    namespace Groves_Driver_Pad
    {
        public class SignatureControl : Control
        {
            // gdi objects
            private Bitmap _bmp;
            private Graphics _graphics;
    
            private Pen _pen = new Pen(Color.Brown);
            // list of line segments
    
            private ArrayList _lines = new ArrayList();
            // the current line segment
            private ArrayList _points = new ArrayList();
    
            private Point _lastPoint = new Point(0, 0);
            // if drawing signature or not
    
            private bool _collectPoints = false;
            // notify parent that line segment was updated
            public event EventHandler SignatureUpdate;
    
            // List of signature line segments.
            public ArrayList Lines
            {
                get { return _lines; }
            }
    
            public Bitmap Bmp
            {
                get { return _bmp; }
            }
    
            // Return the signature flattened to a stream of bytes.
            public byte[] SignatureBits
            {
                get { return SignatureData.GetBytes(this.Width, this.Height, _lines); }
            }
    
            public SignatureControl()
            {
            }
    
            protected override void OnPaint(PaintEventArgs e)
            {
                // blit the memory bitmap to the screen
                // we draw on the memory bitmap on mousemove so there
                // is nothing else to draw at this time (the memory 
                // bitmap already contains all of the lines)
                //MyBase.OnPaint(e)
                CreateGdiObjects();
                e.Graphics.DrawImage(_bmp, 0, 0);
            }
    
            protected override void OnPaintBackground(PaintEventArgs e)
            {
                // don't pass to base since we paint everything, avoid flashing
                //MyBase.OnPaintBackground(e)
            }
    
            protected override void OnMouseDown(MouseEventArgs e)
            {
                base.OnMouseDown(e);
    
                // process if currently drawing signature
                if (!_collectPoints)
                {
                    // start collecting points
                    _collectPoints = true;
    
                    // use current mouse click as the first point
                    _lastPoint.X = e.X;
                    _lastPoint.Y = e.Y;
    
                    // this is the first point in the list
                    _points.Clear();
                    _points.Add(_lastPoint);
                }
            }
    
            protected override void OnMouseUp(MouseEventArgs e)
            {
                base.OnMouseUp(e);
    
                // process if drawing signature
                if (_collectPoints)
                {
                    // stop collecting points
                    _collectPoints = false;
    
                    // add current line to list of segments
                    Point[] points = new Point[_points.Count];
                    int i = 0;
                    for (i = 0; i <= _points.Count - 1; i++)
                    {
                        Point pt = (Point)_points[i];
                        points[i].X = pt.X;
                        points[i].Y = pt.Y;
                    }
    
                    _lines.Add(points);
    
                    // start over with a new line
                    _points.Clear();
    
                    // notify container a new segment was added
                    RaiseSignatureUpdateEvent();
                }
            }
    
            protected override void OnMouseMove(MouseEventArgs e)
            {
                base.OnMouseMove(e);
    
                // process if drawing signature
                if (_collectPoints)
                {
                    // add point to current line segment
                    _points.Add(new Point(e.X, e.Y));
    
                    // draw the new segment on the memory bitmap
                    _graphics.DrawLine(_pen, _lastPoint.X, _lastPoint.Y, e.X, e.Y);
    
                    // update the current position
                    _lastPoint.X = e.X;
                    _lastPoint.Y = e.Y;
    
                    // display the updated bitmap
                    Invalidate();
                }
            }
    
            // Clear the signature.
            public void Clear()
            {
                _lines.Clear();
                InitMemoryBitmap();
                Invalidate();
            }
    
            // Create any GDI objects required to draw signature.
            private void CreateGdiObjects()
            {
                // only create if don't have one or the size changed
                if (_bmp == null)
                {
                    InitMemoryBitmap();
                }
                else if (_bmp.Width != this.Bmp.Width | _bmp.Height != this.Bmp.Height)
                {
                    InitMemoryBitmap();
                }
            }
    
            // Create a memory bitmap that is used to draw the signature.
    
            private void InitMemoryBitmap()
            {
                // load the background image
                _bmp = new Bitmap(Properties.Resources.sign_here);
    
                // get graphics object now to make drawing during mousemove faster
                _graphics = Graphics.FromImage(_bmp);
            }
    
            // Notify container that a line segment has been added.
            private void RaiseSignatureUpdateEvent()
            {
                if (SignatureUpdate != null)
                {
                    SignatureUpdate(this, EventArgs.Empty);
                }
            }
    
        }
    
        public class SignatureData
        {
            // this identifies this class, used when sent over socket
            // so receiving application can validate the data stream
    
            public const string SignatureId = "signature";
            // width of signature canvas
            private int _width;
            // height of signature canvas
            private int _height;
            // list of line segments
            private ArrayList _lines;
    
            //
            // Properties
            //
    
            public ArrayList Lines
            {
                get { return _lines; }
            }
    
            public int Width
            {
                get { return _width; }
            }
    
            public int Height
            {
                get { return _height; }
            }
    
            // construct an object from stream of bytes
            public SignatureData(byte[] bits)
            {
                // index into data stream
                int bitsIndex = 0;
    
                // get signature id
                if (!IsValidStream(bits, ref bitsIndex))
                {
                    // this is not what we are expecting
                    throw new Exception("Invalid data stream.");
                }
    
                // width and height
                _width = Network.GetInt32(bits, ref bitsIndex);
                _height = Network.GetInt32(bits, ref bitsIndex);
    
                // number of line segments
                Int32 linesCount = Network.GetInt32(bits, ref bitsIndex);
                _lines = new ArrayList(linesCount);
    
                // loop through each line segment and get points
                int line = 0;
                for (line = 0; line <= linesCount - 1; line++)
                {
                    // number of points in this segment
                    Int32 pointsCount = Network.GetInt32(bits, ref bitsIndex);
                    Point[] points = new Point[pointsCount];
    
                    // get all points in this segment
                    int point = 0;
                    for (point = 0; point <= pointsCount - 1; point++)
                    {
                        points[point].X = Network.GetInt32(bits, ref bitsIndex);
                        points[point].Y = Network.GetInt32(bits, ref bitsIndex);
                    }
    
                    // add line segment to list
                    _lines.Add(points);
                }
            }
    
    
            // Flatten object to a stream of bytes.
            public static byte[] GetBytes(int width, int height, ArrayList lines)
            {
                // hold byte stream
                MemoryStream stream = new MemoryStream();
    
                // signature id
                Network.WriteString(stream, SignatureData.SignatureId);
    
                // width and height
                Network.WriteInt32(stream, width);
                Network.WriteInt32(stream, height);
    
                // number of segments
                Network.WriteInt32(stream, lines.Count);
    
                // each segment
                //Point[] points = null;
                foreach (Point[] points in lines)
                {
                    // points in the segment
                    Network.WriteInt32(stream, points.Length);
                    //Point pt = default(Point);
                    foreach (Point pt in points)
                    {
                        Network.WriteInt32(stream, pt.X);
                        Network.WriteInt32(stream, pt.Y);
                    }
                }
    
                return stream.ToArray();
            }
    
    
            // Return true if byte array is a valid SignatureData class,
            // otherwise return false.
            private bool IsValidStream(byte[] bits, ref int bitsIndex)
            {
                bool valid = false;
    
                // see if first value is length of signature id
                Int32 idLength = Network.GetInt32(bits, ref bitsIndex);
                if (idLength == SignatureData.SignatureId.Length)
                {
                    // get the signature id mark
                    byte[] id = Network.GetBytes(bits, ref bitsIndex, idLength);
    
                    // see if this is the stream we expect
                    if (ASCIIEncoding.ASCII.GetString(id, 0, idLength) == SignatureData.SignatureId)
                    {
                        valid = true;
                    }
                }
    
                return valid;
            }
    
        }
    
        // Network helper functions.
        public class Network
        {
    
            // all static methods
            private Network()
            {
            }
    
            // Write int bytes to byte stream.
            public static void WriteInt32(MemoryStream stream, Int32 data)
            {
                stream.Write(BitConverter.GetBytes(data), 0, Marshal.SizeOf(data));
            }
    
            // Write string to byte stream. First write length, followed
            // by string content.
            public static void WriteString(MemoryStream stream, string data)
            {
                // write length of string followed by the string bytes
                WriteInt32(stream, data.Length);
                stream.Write(ASCIIEncoding.ASCII.GetBytes(data), 0, data.Length);
            }
    
            // Return int from byte stream.
            public static Int32 GetInt32(byte[] bits, ref int bitsIndex)
            {
                Int32 data = BitConverter.ToInt32(bits, bitsIndex);
                bitsIndex += Marshal.SizeOf(data);
                return data;
            }
    
            // Return specified bytes from byte stream.
            public static byte[] GetBytes(byte[] bits, ref int bitsIndex, int length)
            {
                byte[] data = new byte[length + 1];
                Buffer.BlockCopy(bits, bitsIndex, data, 0, length);
                bitsIndex += length;
                return data;
            }
    
        }
    
    }
    




    Thursday, February 10, 2011 10:26 AM
  • User-1975938688 posted

    I am getting closer to solving my problem.  Now I have added the above code as a class to my website, and on a sample page i have added code to load the signature image:


    Imports System.Data.SqlClient
    Imports Groves_Driver_Pad
    Imports System.Drawing
    
    Partial Class SignatureTest
        Inherits System.Web.UI.Page
        Private WithEvents _signature As SignatureControl = New SignatureControl
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Try
                Dim strSQL As String = "SELECT Signature, SignName FROM DrivingDirections WHERE ID = @ID"
                Dim myConn As New SqlConnection(ConfigurationManager.ConnectionStrings("TicketTrackerConnectionString").ConnectionString)
    
                Dim myCommand As New SqlCommand(strSQL, myConn)
                Dim param As SqlParameter = Nothing
    
                param = New SqlParameter("@ID", Data.SqlDbType.Int)
                param.Value = Request.QueryString("ID").ToString()
                myCommand.Parameters.Add(param)
    
                myConn.Open()
                Dim myReader As SqlDataReader = myCommand.ExecuteReader()
    
                If myReader.Read() Then
    
                    If Not myReader("Signature") Is DBNull.Value Then
    
                        Dim stream As System.IO.MemoryStream = New System.IO.MemoryStream(CType(myReader("Signature"), Byte()))
    
                        Dim _sigData As New SignatureData(stream.ToArray)
    
                        Response.Write(myReader("SignName").ToString())
    
                        redrawSig(_sigData)
    
    
                    End If ' If Not myReader("Signature") Is DBNull.Value Then
    
                    myReader.Close()
    
                End If ' If myReader.Read Then
                myConn.Close()
            Catch ex As Exception
    
                Response.Write("Error: " & ex.Message)
            End Try
        End Sub
    
        Private Sub redrawSig(ByVal thisSigData As SignatureData)
    
            Dim _graphics As Graphics
    
            _graphics = Graphics.FromImage(_signature.Bmp)
    
            DrawSignature(_graphics, thisSigData)
    
            _signature.Invalidate()
    
        End Sub
    
        Private Sub DrawSignature(ByVal g As Graphics, ByVal thisSigData As SignatureData)
    
            ' background
            'g.Clear(Color.Cornsilk)
    
            'Dim borderPen As New Pen(Color.Brown)
            Dim sigPen As New Pen(Color.Firebrick)
    
            ' border
            'g.DrawRectangle(borderPen, 0, 0, 220 - 1, 120 - 1)
    
            ' return if don't have a signature
            If thisSigData Is Nothing Then
    
                Return
    
            End If
    
            If thisSigData.Width = 0 Or thisSigData.Height = 0 Then
    
                Return
    
            End If
    
            ' draw each line segment
            Dim line As Point()
            For Each line In thisSigData.Lines
    
                If Not line Is Nothing Then
    
                    If line.Length > 0 Then
    
                        ' draw lines or curves
                        g.DrawLines(sigPen, line)
    
                    End If
    
                End If
    
            Next line
    
        End Sub
    
    End Class
    


    However now I am getting this error: Error: Value cannot be null. Parameter name: image

    I am not sure how the image can be null since there is binary data at the location of the ID that I am passing to the page...Does anyone have any ideas?

    Update: I know there is binary data at the id location because I can do Response.BinaryWrite and see the binary characters at the top of the page instead of an error...

    Thursday, February 10, 2011 11:48 AM
  • User-1975938688 posted

    No suggestions, ideas or recommendations?  I am really stumped here.  I can get the signature to reload on the mobile device but not the web page.  I am not sure why it works on the device but not the webpage.  I wonder if I need to convert the control into a web control?  Any Ideas?

    Friday, February 11, 2011 9:31 AM
  • User-179775383 posted

    Hi,

    I am wondering if you have got any solution to this problem? becuase i am having a same problem.

    Friday, November 25, 2011 11:44 AM
  • User-1975938688 posted
    Yes I did solve it. You have to specify the file format when trying to display it. In my case it was jpg.
    Friday, November 25, 2011 12:01 PM
  • User-179775383 posted

    Hi,

    Could you pls copy your code here?

    Friday, November 25, 2011 12:52 PM