forked from parrots/SignatureToImageDotNet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSignatureToImage.cs
213 lines (197 loc) · 9.11 KB
/
SignatureToImage.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
* Author: Curtis Herbert ([email protected])
* License: BSD License
* Version: 2.0 (2012-02-11)
* Contributor: Justin Stolle ([email protected])
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Web.Script.Serialization;
namespace ConsumedByCode.SignatureToImage
{
/// <summary>
/// A supplemental class for Signature Pad (https://github.com/thomasjbradley/signature-pad)
/// that generates an image of the signature's JSON output server-side using C#. Alternately,
/// you can provide a name and generate an image that resembles a signature from a font.
/// Similar to Signature to Image PHP (https://github.com/thomasjbradley/signature-to-image)
/// </summary>
public class SignatureToImage
{
public Color BackgroundColor { get; set; }
public Color PenColor { get; set; }
public int CanvasWidth { get; set; }
public int CanvasHeight { get; set; }
public float PenWidth { get; set; }
public float FontSize { get; set; }
public string FontName { get; set; }
/// <summary>
/// Gets a new signature generator with the default options.
/// </summary>
public SignatureToImage()
{
// Default values
BackgroundColor = Color.White;
PenColor = Color.FromArgb(20, 83, 148);
CanvasWidth = 198;
CanvasHeight = 45;
PenWidth = 2;
FontSize = 24;
FontName = "Journal";
}
/// <summary>
/// Draws a signature based on the JSON provided by Signature Pad.
/// </summary>
/// <param name="json">JSON string of line drawing commands.</param>
/// <returns>Bitmap image containing the signature.</returns>
public Bitmap SigJsonToImage(string json)
{
return SigJsonToImage(json, new Size(CanvasWidth, CanvasHeight));
}
/// <summary>
/// Draws a signature based on the JSON provided by Signature Pad.
/// </summary>
/// <param name="json">JSON string of line drawing commands.</param>
/// <param name="size">System.Drawing.Size structure containing Width and Height dimensions.</param>
/// <returns>Bitmap image containing the signature.</returns>
public Bitmap SigJsonToImage(string json, Size size)
{
var signatureImage = GetBlankCanvas();
if (!string.IsNullOrWhiteSpace(json))
{
using (var signatureGraphic = Graphics.FromImage(signatureImage))
{
signatureGraphic.SmoothingMode = SmoothingMode.AntiAlias;
var pen = new Pen(PenColor, PenWidth);
var serializer = new JavaScriptSerializer();
// Next line may throw System.ArgumentException if the string
// is an invalid json primitive for the SignatureLine structure
var lines = serializer.Deserialize<List<SignatureLine>>(json);
foreach (var line in lines)
{
signatureGraphic.DrawLine(pen, line.lx, line.ly, line.mx, line.my);
}
}
}
return (Bitmap)((size.Width == CanvasWidth && size.Height == CanvasHeight) ? signatureImage : ResizeImage(signatureImage, size));
}
/// <summary>
/// Draws an approximation of a signature using a font.
/// </summary>
/// <param name="name">The string that will be drawn.</param>
/// <param name="fontPath">Full path of font file to be used if default font is not installed on the system.</param>
/// <returns>Bitmap image containing the user's signature.</returns>
public Bitmap SigNameToImage(string name, string fontPath = null)
{
return SigNameToImage(name, null, fontPath);
}
/// <summary>
/// Draws an approximation of a signature using a font.
/// </summary>
/// <param name="name">The string that will be drawn.</param>
/// <param name="size">System.Drawing.Size structure containing Width and Height dimensions.</param>
/// <param name="fontPath">Full path of font file to be used if default font is not installed on the system.</param>
/// <returns>Bitmap image containing the user's signature.</returns>
public Bitmap SigNameToImage(string name, Size size, string fontPath = null)
{
var signatureImage = GetBlankCanvas();
if (!string.IsNullOrWhiteSpace(name))
{
Font font;
// Need a reference to the font, be it the .ttf in the project or the system-installed font
if (string.IsNullOrWhiteSpace(fontPath))
{
// Path parameter not provided, try to use system-installed font
var installedFontCollection = new InstalledFontCollection();
if (installedFontCollection.Families.Any(f => f.Name == FontName))
{
font = new Font(FontName, FontSize);
}
else
{
throw new ArgumentException("The full path of the font file must be provided when the specified font is not installed on the system.", "fontPath");
}
}
else if (File.Exists(fontPath))
{
try
{
// Temporarily install font while not affecting the system-installed collection
var collection = new PrivateFontCollection();
collection.AddFontFile(fontPath);
font = new Font(collection.Families.First(), FontSize);
}
catch (FileNotFoundException)
{
// Since the existence of the file has already been tested, this exception
// means the file is invalid or not supported when trying to load
throw new Exception("The specified font file \"" + fontPath + "\" is either invalid or not supported.");
}
}
else
{
throw new FileNotFoundException("The specified font file \"" + fontPath + "\" does not exist or permission was denied.", fontPath);
}
using (var signatureGraphic = Graphics.FromImage(signatureImage))
{
signatureGraphic.TextRenderingHint = TextRenderingHint.AntiAlias;
signatureGraphic.DrawString(name, font, new SolidBrush(PenColor), 0, 0);
}
}
return (Bitmap)((size.Width == CanvasWidth && size.Height == CanvasHeight) ? signatureImage : ResizeImage(signatureImage, size));
}
/// <summary>
/// Get a blank bitmap using instance properties for dimensions and background color.
/// </summary>
/// <returns>Blank bitmap image.</returns>
private Bitmap GetBlankCanvas()
{
var blankImage = new Bitmap(CanvasWidth, CanvasHeight);
blankImage.MakeTransparent();
using (var signatureGraphic = Graphics.FromImage(blankImage))
{
signatureGraphic.Clear(BackgroundColor);
}
return blankImage;
}
/// <summary>
/// Resizes the image to fit the canvas in the event that the signature was drawn larger than it will be redisplayed.
/// </summary>
/// <param name="img">The image that will be resized.</param>
/// <param name="size">System.Drawing.Size structure containing the new Width and Height dimensions.</param>
/// <returns>Resized image.</returns>
private Image ResizeImage(Image img, Size size)
{
int srcWidth = img.Width;
int srcHeight = img.Height;
float percent = 0;
float percWidth = 0;
float percHeight = 0;
percWidth = ((float)size.Width / (float)srcWidth);
percHeight = ((float)size.Height / (float)srcHeight);
percent = (percHeight < percWidth) ? percHeight : percWidth;
int destWidth = (int)(srcWidth * percent);
int destHeight = (int)(srcHeight * percent);
Bitmap bmp = new Bitmap(destWidth, destHeight);
Graphics graphic = Graphics.FromImage((Image)bmp);
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.DrawImage(img, 0, 0, destWidth, destHeight);
graphic.Dispose();
return (Image)bmp;
}
/// <summary>
/// Line drawing commands as generated by the Signature Pad JSON export option.
/// </summary>
private class SignatureLine
{
public int lx { get; set; }
public int ly { get; set; }
public int mx { get; set; }
public int my { get; set; }
}
}
}