Windows Phone – Signature capturing with InkPresenter and save to PNG file

Today I received a small package by post for my neighbor and I must sign on a small device to confirm that I received the package. Therefore the deliver can be sure that I will give it to my neighbor. I thought it was very interesting to write a small application on Windows Phone which should work like the device of postman. This application allows people signing on the screen and it will store this signature into IsolatedStorageFile and show it again in image control below to confirm that the program works correctly.

As you can see in the demo image of application, I have 4 buttons: Undo, Redo, Clear and Save. The “Undo”, “Redo” buttons allow me to remove the strokes or redraw them. The strokes will be drawn on InkPresenter control and then saved into a PNG file. To draw the stroke on InkPresenter, I must handle the MouseLeftButtonDown to capture the mouse movement and draw stroke from point to point.

private StylusPoint GetStylusPoint(Point p)
{
	return new StylusPoint(p.X, p.Y);
}
private void inkSignature_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
	inkSignature.CaptureMouse();
	m_strokeCurrent = new Stroke();
	m_strokeCurrent.StylusPoints.Add(GetStylusPoint(e.GetPosition(inkSignature)));
	m_strokeCurrent.DrawingAttributes.Color = Colors.Blue;
	inkSignature.Strokes.Add(m_strokeCurrent);
}
private void inkSignature_MouseMove(object sender, MouseEventArgs e)
{
	if (m_strokeCurrent != null)
		m_strokeCurrent.StylusPoints.Add(GetStylusPoint(e.GetPosition(inkSignature)));
}

To implement “Undo” and “Redo” feature, I use a stack of strokes to push/pop a stroke in history and then remove/add it on InkPresenter.

private void btnUndo_Click(object sender, RoutedEventArgs e)
{
	if (inkSignature.Strokes != null && inkSignature.Strokes.Count > 0)
	{
		m_stackRemovedStrokes.Push(inkSignature.Strokes.Last());
		inkSignature.Strokes.RemoveAt(inkSignature.Strokes.Count - 1);
	}
}

private void btnRedo_Click(object sender, RoutedEventArgs e)
{
	if (m_stackRemovedStrokes != null && m_stackRemovedStrokes.Count > 0)
	{
		inkSignature.Strokes.Add(m_stackRemovedStrokes.Pop());
	}
}

At last, I use WriteableBitmap to take a snapshot of InkPresenter and encode it to a PNG format file. In current version of Visual Studio for Windows Phone CTP there is still not a PngBitmapEncoder. Therefore I use a custom one from this blog http://geekswithblogs.net/braulio/archive/2009/07/12/export-canvas-to-png-and-save-it-in-your-local.aspx . You can find the source code of PNG Encoder in the archive at the end of this post, too.

private void btnSave_Click(object sender, RoutedEventArgs e)
{
	WriteableBitmap wbBitmap = new WriteableBitmap(inkSignature, new TranslateTransform());
	EditableImage eiImage = new EditableImage(wbBitmap.PixelWidth, wbBitmap.PixelHeight);

	try
	{
		for (int y = 0; y < wbBitmap.PixelHeight; ++y)
		{
			for (int x = 0; x < wbBitmap.PixelWidth; ++x)
			{
				int pixel = wbBitmap.Pixels[wbBitmap.PixelWidth * y + x];
				eiImage.SetPixel(x, y,
				(byte)((pixel >> 16) & 0xFF),
				(byte)((pixel >>  8 ) & 0xFF ) ,
				(byte)(pixel & 0xFF), (byte)((pixel >> 24) & 0xFF)
				);
			}
		}
	}
	catch (System.Security.SecurityException)
	{
		throw new Exception("Cannot print images from other domains");
	}

	// Save it to disk
	Stream streamPNG = eiImage.GetStream();
	StreamReader srPNG = new StreamReader(streamPNG);
	byte[] baBinaryData = new Byte[streamPNG.Length];
	long bytesRead = streamPNG.Read(baBinaryData, 0, (int)streamPNG.Length);

	IsolatedStorageFileStream isfStream = new IsolatedStorageFileStream("temp.png", FileMode.Create, IsolatedStorageFile.GetUserStoreForApplication());
	isfStream.Write(baBinaryData, 0, baBinaryData.Length);
	isfStream.Close();

	//Show to image
	isfStream = new IsolatedStorageFileStream("temp.png", FileMode.Open, IsolatedStorageFile.GetUserStoreForApplication());
	BitmapImage biImage = new BitmapImage();
	biImage.SetSource(isfStream);
	isfStream.Close();
	imgResult.Source = biImage;
}

You can download complete source code here “Windows Phone Sig Capture
Reference: http://www.nickharris.net/2010/03/silverlight-for-mobile-on-windows-phone-7-inkpresenter-fun/