Introduction
This article shows how to collect and display a signature. The signature is made up of a list of line segments. Each segment contains an array of points (x and y coordinates).
There are two *.cs files MainForm.cs and SignatureControl.cs. These two files are used in C# .NET compact Framework to capture the signature and save that in a *.txt file in PocketPC. You can load the same signature from the *.txt file.
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.IO;
namespace PocketSignature
{
public class SignatureControl : Control
{
private string background = null;
public string Background
{
get
{
return background;
}
set
{
background = value;
}
}
Bitmap bmp;
Graphics graphics;
Pen pen = new Pen(Color.Black);
ArrayList pVector = new ArrayList();
Point lastPoint = new Point(0,0);
bool drawSign = false;
public event EventHandler SignatureUpdate;
public SignatureControl(){}
protected override void OnPaint(PaintEventArgs e)
{
CreateGdiObjects();
e.Graphics.DrawImage(bmp, 0, 0);
}
protected override void OnPaintBackground(PaintEventArgs e)
{
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (!drawSign)
{
drawSign = true;
lastPoint.X = e.X;
lastPoint.Y = e.Y;
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (drawSign)
{
drawSign = false;
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (drawSign)
{
graphics.DrawLine(pen, lastPoint.X, lastPoint.Y, e.X, e.Y);
pVector.Add(lastPoint.X+" "+lastPoint.Y+" "+e.X+" "+e.Y);
lastPoint.X = e.X;
lastPoint.Y = e.Y;
Invalidate();
}
}
public void Clear()
{
pVector.Clear();
InitMemoryBitmap();
Invalidate();
}
private void CreateGdiObjects()
{
if (bmp == null || bmp.Width != this.Width ||
bmp.Height != this.Height)
{
InitMemoryBitmap();
}
}
private void InitMemoryBitmap()
{
if (this.Background==null)
{
bmp = new Bitmap(this.Width,this.Height);
graphics = Graphics.FromImage(bmp);
graphics.Clear(Color.White);
}
else
{
bmp = new Bitmap(this.Background);
graphics = Graphics.FromImage(bmp);
}
}
private void RaiseSignatureUpdateEvent()
{
if (this.SignatureUpdate != null)
SignatureUpdate(this, EventArgs.Empty);
}
private void CreateFile(String fileName,String fileContent)
{
if (File.Exists(fileName))
{
Console.WriteLine("{0} already exists.", fileName);
}
StreamWriter sr = File.CreateText(fileName);
sr.WriteLine (fileContent);
sr.Close();
}
public void StoreSigData(String fileName)
{
string sigData = "";
for (int i = 0; i<pVector.Count ;i++)
{
sigData = sigData + pVector[i].ToString()+ "\n";
}
CreateFile(fileName,sigData);
}
private string PadHex(int inNum )
{
uint uiDecimal = checked((uint)System.Convert.ToUInt32(inNum));
string s = String.Format("{0:x2}", uiDecimal);
return(s);
}
}
}
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Text;
using PocketSignature;
namespace SignCaptureV2
{
public class MainForm : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel areaSignature;
private System.Windows.Forms.Button butNew;
private System.Windows.Forms.Button Save;
private System.Windows.Forms.Button Load;
SignatureControl signature = new SignatureControl();
public MainForm()
{
InitializeComponent();
signature.Location = areaSignature.Location;
signature.Size = areaSignature.Size;
signature.Background = "<a href="%22file: this.Controls.Add(signature);
}
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.areaSignature = new System.Windows.Forms.Panel();
this.butNew = new System.Windows.Forms.Button();
this.Save = new System.Windows.Forms.Button();
this.Load = new System.Windows.Forms.Button();
this.areaSignature.BackColor = System.Drawing.Color.Gainsboro;
this.areaSignature.Location = new System.Drawing.Point(8, 8);
this.areaSignature.Size = new System.Drawing.Size(224, 120);
this.areaSignature.Visible = false;
this.butNew.Font = new System.Drawing.Font("Tahoma", 8.25F,
System.Drawing.FontStyle.Regular);
this.butNew.Location = new System.Drawing.Point(0, 232);
this.butNew.Size = new System.Drawing.Size(54, 24);
this.butNew.Text = "Clear";
this.butNew.Click += new System.EventHandler(this.butNew_Click);
this.Save.Font = new System.Drawing.Font("Tahoma", 8.25F,
System.Drawing.FontStyle.Regular);
this.Save.Location = new System.Drawing.Point(64, 232);
this.Save.Size = new System.Drawing.Size(72, 24);
this.Save.Text = "Save in File";
this.Save.Click += new System.EventHandler(this.Save_Click);
this.Load.Font = new System.Drawing.Font("Tahoma", 8.25F,
System.Drawing.FontStyle.Regular);
this.Load.Location = new System.Drawing.Point(144, 232);
this.Load.Size = new System.Drawing.Size(88, 24);
this.Load.Text = "Load from file";
this.Load.Click += new System.EventHandler(this.Load_Click);
this.ClientSize = new System.Drawing.Size(258, 270);
this.Controls.Add(this.Load);
this.Controls.Add(this.Save);
this.Controls.Add(this.butNew);
this.Controls.Add(this.areaSignature);
this.Text = "PocketSignature";
}
#endregion
static void Main()
{
Application.Run(new MainForm());
}
private void butNew_Click(object sender, System.EventArgs e)
{
signature.Clear();
this.Refresh();
}
private void Save_Click(object sender, System.EventArgs e)
{
signature.StoreSigData("SignFile.txt");
}
private void Load_Click(object sender, System.EventArgs e)
{
int baseX = 10;
int baseY = 100;
string signatureFile = "SignFile.txt";
load_signature(baseX,baseY,signatureFile);
}
void load_signature(int baseX,int baseY,string signatureFile)
{
System.IO.StreamReader streamReader
= new System.IO.StreamReader("SignFile.txt");
string pointString = null;
while ((pointString = streamReader.ReadLine())!= null)
{
if(pointString.Trim().Length>0)
{
String[] points = new String[4];
points = pointString.Split(new Char[]{' '});
Pen pen = new Pen(Color.Black);
this.CreateGraphics().DrawLine(pen,
(baseX+int.Parse(points[0].ToString())),
(baseY+int.Parse(points[1].ToString())),
(baseX+int.Parse(points[2].ToString())),
(baseY+int.Parse(points[3].ToString())));
}
}
streamReader.Close();
}
}
}
On the server side, the server gets the *.txt file from the client . You can use the SaveSignature.java to convert the *.txt file to a *.jpg file.
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.util.Vector;
import java.util.Hashtable;
import java.awt.Color;
import java.awt.Graphics;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
public class SaveSignature {
static final int baseX = 25;
static final int baseY = 25;
public static void doExecute(String inputTxtFile,String outputGraphicsFile)
throws Exception {
Vector v = readFile(inputTxtFile);
Hashtable ht = getMinMax(v);
int minX = ( (Integer) ht.get("minX")).intValue();
int maxX = ( (Integer) ht.get("maxX")).intValue();
int minY = ( (Integer) ht.get("minY")).intValue();
int maxY = ( (Integer) ht.get("maxY")).intValue();
int width = maxX - minX + baseX;
int height = maxY - minY + baseY;
BufferedImage bufferedImage = new BufferedImage
(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g2d = bufferedImage.createGraphics();
g2d.setColor(Color.white);
g2d.fillRect(0, 0, width, height);
drawImage(g2d, v, minX, minY);
g2d.dispose();
File file = new File(outputGraphicsFile);
ImageIO.write(bufferedImage, "jpg", file);
}
private static void drawImage(Graphics g2d,Vector v, int minX,int minY)
throws Exception{
g2d.setColor(Color.black);
for (int j =0; j<v.size();j++){
String[] points = (String[]) v.get(j);
int x1 =0;
int y1 =0;
int x2 =0;
int y2 =0;
for (int i = 0; i < 4; i++) {
x1 = Integer.parseInt(points[0])-minX+(baseX/2);
x2 = Integer.parseInt(points[2])-minX+(baseX/2);
y1 = Integer.parseInt(points[1])-minY+(baseY/2);
y2 = Integer.parseInt(points[3])-minY+(baseY/2);
}
g2d.drawLine(x1,y1,x2,y2);
}
}
private static Hashtable getMinMax(Vector v) {
Hashtable ht = new Hashtable();
int minX =9999;
int maxX =0;
int minY =9999;
int maxY =0;
for (int j = 0; j< v.size();j++) {
String[] points = (String[]) v.get(j);
for (int i = 0; i < 4; i++) {
minX = (Integer.parseInt(points[0])<minX) ?
Integer.parseInt(points[0]):minX;
minX = (Integer.parseInt(points[2])<minX) ?
Integer.parseInt(points[2]):minX;
maxX = (Integer.parseInt(points[0])>maxX) ?
Integer.parseInt(points[0]):maxX;
maxX = (Integer.parseInt(points[2])>maxX) ?
Integer.parseInt(points[2]):maxX;
minY = (Integer.parseInt(points[1]) < minY) ?
Integer.parseInt(points[1]) : minY;
minY = (Integer.parseInt(points[3]) < minY) ?
Integer.parseInt(points[3]) : minY;
maxY = (Integer.parseInt(points[1]) > maxY) ?
Integer.parseInt(points[1]) : maxY;
maxY = (Integer.parseInt(points[3]) > maxY) ?
Integer.parseInt(points[3]) : maxY;
}
}
ht.put("minX",new Integer(minX));
ht.put("maxX", new Integer(maxX));
ht.put("minY", new Integer(minY));
ht.put("maxY", new Integer(maxY));
return ht;
}
private static Vector readFile(String fileName) throws Exception{
Vector v = new Vector();
FileReader fr = new FileReader(fileName);
BufferedReader br = new BufferedReader(fr);
String record = null;
while ( (record = br.readLine()).trim().length() > 0) {
String[] points = new String[4];
points = record.split(" ");
v.add(points);
}
return v;
}
public static void main(String[] args) {
try {
String inputTextFile = "c:\\MyFile.txt";
String outputImageFile = "c:\\Sign.jpg";
doExecute( inputTextFile,outputImageFile);
} catch (Exception e) {
System.out.println(" exception: "+ e.toString());
}
}
}
Sample Files
The generated signature text file has contents like below:
/
****Sign.txt File **/
64 152 65 152
65 152 68 151
68 151 72 149
72 149 75 147
75 147 79 143
79 143 83 139
83 139 86 136
86 136 88 133
88 133 90 131
90 131 91 128
91 128 92 126
92 126 92 124
92 124 92 123
92 123 91 122
91 122 89 121
89 121 87 121
87 121 84 121
84 121 81 121
81 121 79 122
79 122 75 124
75 124 71 128
71 128 67 132
67 132 63 136
63 136 60 141
60 141 58 145
58 145 57 148
57 148 57 150
57 150 57 152
57 152 58 152
58 152 61 152
61 152 65 151
65 151 68 149
68 149 69 147
69 147 69 145
69 145 69 144
69 144 69 142
69 142 67 140
67 140 66 138
66 138 66 136
66 136 67 132
67 132 70 127
70 127 75 123
75 123 78 120
78 120 81 117
81 117 81 119
81 119 78 135
78 135 75 151
75 151 72 157
72 157 69 161
69 161 69 162
69 162 71 157
71 157 73 152
73 152 77 146
77 146 80 140
80 140 85 135
85 135 89 132
89 132 92 130
92 130 94 129
94 129 95 129
95 129 95 130
95 130 95 136
95 136 93 141
93 141 90 146
90 146 87 148
87 148 85 149
85 149 83 150
83 150 83 149
83 149 84 147
84 147 87 146
87 146 90 146
90 146 91 146
91 146 91 149
91 149 90 152
90 152 88 155
88 155 86 156
86 156 85 156
85 156 85 155
98 151 101 149
101 149 104 146
104 146 106 143
106 143 107 140
107 140 107 139
107 139 106 139
106 139 103 142
103 142 101 145
101 145 99 148
99 148 98 151
98 151 98 153
98 153 98 154
98 154 99 155
99 155 101 155
101 155 105 153
105 153 108 150
108 150 112 145
112 145 114 139
119 106 117 111
117 111 115 125
115 125 113 139
113 139 112 153
112 153 111 158
111 158 110 160
110 160 110 159
110 159 112 155
112 155 114 152
114 152 118 147
118 147 121 144
121 144 123 143
123 143 124 142
124 142 124 143
124 143 125 146
125 146 125 150
125 150 125 154
125 154 125 156
125 156 125 157
125 157 127 156
127 156 130 154
130 154 133 151
133 151 136 148
136 148 138 144
138 144 139 141
139 141 139 140
139 140 138 140
138 140 137 141
137 141 134 144
134 144 133 147
133 147 133 151
133 151 133 154
133 154 135 156
135 156 136 157
136 157 137 157
137 157 139 156
149 139 149 141
149 141 149 144
149 144 149 146
149 146 149 149
149 149 149 151
149 151 148 154
148 154 147 155
147 155 147 154
147 154 148 149
148 149 150 143
150 143 153 137
153 137 155 133
155 133 157 130
157 130 157 129
171 139 170 139
170 139 169 141
169 141 167 145
167 145 165 149
165 149 165 151
165 151 165 153
165 153 166 153
166 153 168 153
168 153 170 149
170 149 172 146
172 146 174 143
174 143 175 142
175 142 175 141
175 141 176 143
176 143 176 145
176 145 177 146
177 146 178 147
History
- 26th February, 2004: Initial post