Using the TX Text Control Document Viewer, electronic signatures can be requested from users to sign a pre-defined signature field. This signature field is then replaced with the acquired signature image and digitally signed using a digital certificate.
Instead of signing pre-defined fields, the latest version of the Document Viewer is able to acquire a signature image from users in order to insert the signature image as an annotation object to the document. Those annotation objects are stored independently from the document and can be retrieved using the annotations.export ╰ TX Text Control .NET Server for ASP.NET
╰ JavaScript API - Document Viewer Viewer
╰ Annotations Object
╰ export Method
Exports all annotations as a JSON string. JavaScript method.
Signature Annotations
Signature annotations can be added using a new button in the annotation toolbar:
Using the signature soft pad, multiple signatures can be drawn or uploaded. Those signatures are stored locally and can be used across sessions:
After placing a signature onto a document, they are part of the annotation collection.
Exporting Annotations
When exporting the annotations as JSON using the annotations.export method, the placed signature is added as an SVG image. In this sample application, this JSON object is being sent to the HttpPost Controller method MergeAnnotations:
function storeAnnotations() { | |
var annotations = TXDocumentViewer.annotations.export(); | |
var obj = JSON.parse(annotations); | |
var serviceURL = '@Url.Action("MergeAnnotations", "Home")'; | |
$.ajax({ | |
type: 'POST', | |
url: serviceURL, | |
contentType: 'application/json', | |
dataType: 'json', | |
data: JSON.stringify(obj), | |
success: successFunc, | |
error: errorFunc | |
}); | |
function successFunc(data, status) { | |
TXDocumentViewer.loadDocument(data.data, 'results.tx'); | |
} | |
function errorFunc() { | |
alert('error'); | |
} | |
} |
Inserting Annotations as Images
Server-side, the array of Annotation arrays is received as Annotation objects defined through the following model:
public class Location { | |
public double x { get; set; } | |
public double y { get; set; } | |
} | |
public class Pen { | |
public string type { get; set; } | |
public double objectWidth { get; set; } | |
public double objectHeight { get; set; } | |
} | |
public class Annotation { | |
public Pen pen { get; set; } | |
public string user { get; set; } | |
public Location location { get; set; } | |
public long time { get; set; } | |
public List<Comment> comments { get; set; } | |
public string id { get; set; } | |
public string image { get; set; } | |
} | |
public class Comment { | |
public string comment { get; set; } | |
public List<string> user { get; set; } | |
public long date { get; set; } | |
public string id { get; set; } | |
public string status { get; set; } | |
} |
In the controller method, the SVG signature image representation of each annotation is used to create a new Image ╰ TX Text Control .NET Server for ASP.NET
╰ TXTextControl Namespace
╰ Image Class
An instance of the Image class represents an image in a Text Control document. object from a MemoryStream. Finally, the image is added to the document at the given location and page number.
[HttpPost] | |
public string MergeAnnotations() { | |
Stream inputStream = Request.InputStream; | |
inputStream.Position = 0; | |
StreamReader str = new StreamReader(inputStream); | |
string sBuf = str.ReadToEndAsync().Result; | |
List<List<TXTextControl.SignatureAnnotation.Annotation>> annotations = | |
JsonConvert.DeserializeObject<List<List<TXTextControl.SignatureAnnotation.Annotation>>>(sBuf); | |
byte[] bTx; | |
int iPageNumber = 0; | |
string prePng = "data:image/png;base64,"; | |
string preSvg = "data:image/svg+xml;utf8,"; | |
// calculate the current resolution | |
var dpi = 1440 / DocumentController.DpiX; | |
// create temporary ServerTextControl | |
using (ServerTextControl tx = new ServerTextControl()) { | |
tx.Create(); | |
// load the document | |
tx.Load(Server.MapPath("~/App_Data/Documents/template_sign.tx"), StreamType.InternalUnicodeFormat); | |
// loop through the array of annotations | |
foreach (List<TXTextControl.SignatureAnnotation.Annotation> pages in annotations) { | |
iPageNumber++; | |
foreach (TXTextControl.SignatureAnnotation.Annotation annotation in pages) { | |
// handle only signatures | |
if (annotation.pen.type != "signature") | |
continue; | |
byte[] bytes; | |
// get SVG or PNG as bytes and remove the prefix | |
if (annotation.image.StartsWith(prePng)) | |
bytes = Convert.FromBase64String(annotation.image.Remove(0, prePng.Length)); | |
else | |
bytes = Encoding.UTF8.GetBytes(annotation.image.Remove(0, preSvg.Length)); | |
// create a memory stream from SVG | |
using (MemoryStream ms = new MemoryStream( | |
bytes, 0, bytes.Length, writable: false, publiclyVisible: true)) { | |
// TX image from memory stream | |
TXTextControl.Image img = new TXTextControl.Image(ms); | |
// add the image as a fixed object on the current page (array) | |
tx.Images.Add( | |
img, | |
iPageNumber, | |
new System.Drawing.Point(0, (int)(annotation.location.y * dpi)), | |
TXTextControl.ImageInsertionMode.BelowTheText | TXTextControl.ImageInsertionMode.FixedOnPage); | |
// set the location | |
img.Location = new System.Drawing.Point( | |
(int)(annotation.location.x * dpi), | |
img.Location.Y); | |
} | |
} | |
} | |
// save the document as PDF | |
tx.Save(out bTx, TXTextControl.BinaryStreamType.InternalUnicodeFormat); | |
} | |
// return as base64 encoded string | |
return Convert.ToBase64String(bTx); | |
} |
After all images have been added, the document is saved and returned to the client. This way, those signature annotations can be also embedded into PDF documents.