diff --git a/knowledge-base/extracting-point-data-from-signature-signaturepad-dotnet-maui.md b/knowledge-base/extracting-point-data-from-signature-signaturepad-dotnet-maui.md new file mode 100644 index 00000000..9f6c880c --- /dev/null +++ b/knowledge-base/extracting-point-data-from-signature-signaturepad-dotnet-maui.md @@ -0,0 +1,197 @@ +--- +title: Extracting Point Data from Signature in SignaturePad for UI for .NET MAUI +description: Learn how to extract point and line data from a signature in the SignaturePad component for UI for .NET MAUI. +type: how-to +page_title: How to Extract Point Data from SignaturePad in UI for .NET MAUI +meta_title: How to Extract Point Data from SignaturePad in UI for .NET MAUI +slug: extracting-point-data-from-signature-signaturepad-dotnet-maui +tags: signaturepad, ui-for-dotnet-maui, point-data, signature, vector-data +res_type: kb +ticketid: 1600847 +--- + +## Environment + + + + + + + + + + + + +
ProductUI for .NET MAUI SignaturePad
VersionCurrent
+ +## Description + +I want to extract point and line data from the signature created using the [SignaturePad](https://docs.telerik.com/devtools/maui/controls/signaturepad/overview) component of UI for .NET MAUI. The goal is to format the signature data as a string that represents the x, y coordinates of the strokes in the signature. Different formats for the output data are required, such as a custom format or an SVG-like format. + +This knowledge base article also answers the following questions: +- How to save signature data as points and strokes from SignaturePad UI for .NET MAUI? +- How to format SignaturePad data into custom or SVG-like string formats? +- How to process and scan SignaturePad image to extract point coordinates? + +## Solution + +To achieve this, process the signature image generated by the SignaturePad component and extract vector data representing the point coordinates. Follow these steps: + +### 1. Save the Signature as an Image + +Save the signature as a PNG image using the `SaveImageAsync` method: + +```csharp +using var stream = new MemoryStream(); + +await SigPad1.SaveImageAsync(stream, new SaveImageSettings +{ + ImageFormat = Telerik.Maui.Controls.SignaturePad.ImageFormat.Png, + BackgroundColor = Colors.AliceBlue, + StrokeColor = Colors.DarkBlue, + StrokeThickness = 2 +}); + +var imageBytes = stream.ToArray(); +GetVectorFromSignatureImage(imageBytes); +``` + +### 2. Process the Image to Extract Vector Data + +Create a method to process the image and extract vector data. This involves three stages: + +**Stage 1: Prepare Bitmaps** +- Decode the image bytes into `SKBitmap`. +- Create a grayscale bitmap for better contrast. +- Convert the grayscale bitmap into a binary bitmap (black and white) using a threshold. + +**Stage 2: Scan Bitmap and Create Point Groups** +- Scan the binary bitmap for black pixels. +- Group neighboring black pixels into strokes using an algorithm. +- Store grouped strokes as `List>`. + +**Stage 3: Format the Data** +- Serialize the grouped strokes into a desired format. +- Supported formats: + - Custom: `"1,2;3,4;5,6/7,8;9,10;11,12"` + - SVG-like: `"M x y L x y L x y ..."` + +Below is the complete implementation: + +```csharp +public static string GetVectorFromSignatureImage(byte[] imageBytes, string formatType = "custom") +{ + using var bitmap = SKBitmap.Decode(imageBytes); + var grayscaleBitmap = new SKBitmap(bitmap.Width, bitmap.Height); + var binaryBitmap = new SKBitmap(bitmap.Width, bitmap.Height); + + // Convert to grayscale + for (var y = 0; y < bitmap.Height; y++) + { + for (var x = 0; x < bitmap.Width; x++) + { + var color = bitmap.GetPixel(x, y); + var gray = (byte)(0.3 * color.Red + 0.59 * color.Green + 0.11 * color.Blue); + grayscaleBitmap.SetPixel(x, y, new SKColor(gray, gray, gray)); + } + } + + // Convert to binary (black/white) + for (var y = 0; y < grayscaleBitmap.Height; y++) + { + for (var x = 0; x < grayscaleBitmap.Width; x++) + { + var color = grayscaleBitmap.GetPixel(x, y); + var value = color.Red < 128 ? SKColors.Black : SKColors.White; + binaryBitmap.SetPixel(x, y, value); + } + } + + var pxScanned = new bool[binaryBitmap.Width, binaryBitmap.Height]; + var groupedStrokes = new List>(); + + int[] dx = { -1, 0, 1, 0, -1, -1, 1, 1 }; + int[] dy = { 0, -1, 0, 1, -1, 1, -1, 1 }; + + for (var y = 0; y < binaryBitmap.Height; y++) + { + for (var x = 0; x < binaryBitmap.Width; x++) + { + if (pxScanned[x, y] || binaryBitmap.GetPixel(x, y) != SKColors.Black) + continue; + + pxScanned[x, y] = true; + + var queue = new Queue(); + queue.Enqueue(new SKPoint(x, y)); + + var stroke = new List(); + + while (queue.Count > 0) + { + var point = queue.Dequeue(); + stroke.Add(point); + + for (var i = 0; i < dx.Length; i++) + { + var nx = (int)point.X + dx[i]; + var ny = (int)point.Y + dy[i]; + + if (nx >= 0 && ny >= 0 && nx < binaryBitmap.Width && ny < binaryBitmap.Height && + !pxScanned[nx, ny] && binaryBitmap.GetPixel(nx, ny) == SKColors.Black) + { + pxScanned[nx, ny] = true; + queue.Enqueue(new SKPoint(nx, ny)); + } + } + } + + if (stroke.Count > 0) + groupedStrokes.Add(stroke); + } + } + + var sb = new System.Text.StringBuilder(); + var ic = System.Globalization.CultureInfo.InvariantCulture; + var fm = "N1"; + + switch (formatType.ToLower()) + { + case "custom": + for (var i = 0; i < groupedStrokes.Count; i++) + { + for (var j = 0; j < groupedStrokes[i].Count; j++) + { + sb.Append(groupedStrokes[i][j].X.ToString(fm, ic)); + sb.Append(","); + sb.Append(groupedStrokes[i][j].Y.ToString(fm, ic)); + if (j < groupedStrokes[i].Count - 1) sb.Append(";"); + } + if (i < groupedStrokes.Count - 1) sb.Append("/"); + } + break; + + case "svg": + for (var gs = 0; gs < groupedStrokes.Count; gs++) + { + sb.Append(gs == 0 ? "M " : " L "); + for (var p = 0; p < groupedStrokes[gs].Count; p++) + { + sb.Append(groupedStrokes[gs][p].X.ToString(fm, ic)); + sb.Append(" "); + sb.Append(groupedStrokes[gs][p].Y.ToString(fm, ic)); + } + } + break; + } + + return sb.ToString(); +} +``` + +## See Also + +- [SignaturePad Overview](https://docs.telerik.com/devtools/maui/controls/signaturepad/overview) +- [SaveImageSettings Documentation](https://docs.telerik.com/devtools/maui/api/telerik.maui.controls.signaturepad.saveimagesettings) +- [SKBitmap Documentation](https://docs.microsoft.com/en-us/dotnet/api/skiasharp.skbitmap?view=skiasharp-2.80)