Skip to content

Commit 65eb52b

Browse files
authored
Merge pull request #27 from Azure-Samples/xinyzhou/update_wpf_sample
update wpf sample for code style and readme
2 parents a7eff1f + 2b2f42e commit 65eb52b

16 files changed

+127
-158
lines changed

dotnet/InkRecognition/wpf-app/README.md

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,28 @@ languages:
55
products:
66
- WPF
77
- azure
8-
- windows
98
---
109

11-
# Ink Intelligence Cognitive Service C# WPF Sample
10+
# Ink Recognizer Cognitive Service C# WPF Sample
1211

1312
![Build passing](https://img.shields.io/badge/build-passing-brightgreen.svg) ![License](https://img.shields.io/badge/license-MIT-green.svg)
1413

15-
Ink Recognizer Cognitive Service provides recognition of digital ink. It takes the digital ink stroke data as input and provides a document tree with individual recognition units as output. This project has sample code to demonstrate a few ways developers can take advantage of the service.
14+
Ink Recognizer Cognitive Service provides recognition of digital ink. It takes the digital ink stroke data as input and provides a document tree with individual recognition units as output. This project has sample code to demonstrate a few ways developers can take advantage of the service. This sample also shows use case for [Xaml Island](https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/xaml-host-controls) on InkCanvas, which import UWP controls into desktop applications.
1615

1716
## Features
1817

19-
This project framework provides the following features:
18+
This sample provides the following features:
2019

21-
* Capturing very basic inking input.
22-
23-
* Creating the JSON payload using the JSON schema used by Ink Recognizer.
24-
25-
* Calling the Ink Recognizer REST APIs with the JSON payload
26-
27-
* Parsing the JSON response from the service, build the document tree and parse it.
20+
* Collect ink strokes from Xaml Island InkCanvas
21+
* Create JSON request following InkRecognizer service's schema.
22+
* Call the InkRecognizer REST API
23+
* Parse the JSON reponse to build the document tree
2824

2925
## Contents
3026

3127
| File/folder | Description |
3228
|-------------|-------------|
3329
| `src` | Sample source code. |
34-
| `.gitignore` | Define what to ignore at commit time. |
35-
| `CHANGELOG.md` | List of changes to the sample. |
36-
| `CONTRIBUTING.md` | Guidelines for contributing to the sample. |
3730
| `README.md` | This README file. |
3831
| `LICENSE` | The license for the sample. |
3932

@@ -42,17 +35,36 @@ This project framework provides the following features:
4235
### Prerequisites
4336

4437
* [Visual Studio](https://docs.microsoft.com/en-us/visualstudio/install/install-visual-studio)
45-
* Windows SDK Version >= 10.0.18362. You can install it from Visual Studio Installer under **Indivial components** tab, or download from [Windows Insider Preview SDK](https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewSDK)
46-
* If you install the Windows SDK into a customized path, please edit **src\NoteTaker.csproj** to change the HintPath of **Windows.winmd** to the correct path
47-
* Requires subscription key from [Azure Cognitive Services](https://docs.microsoft.com/en-us/azure/cognitive-services/authentication)
48-
49-
## Build the Sample
50-
51-
1. Clone or download this sample repository `git clone https://github.com/Azure-Samples/cognitive-services-csharp-wpf-ink-recognition.git`
52-
2. Start Visual Studio and select **File > Open > Project/Solution** and open "NoteTaker.sln"
53-
3. Replace "[YOUR SUBSCRIPTION KEY]" in MainWindows.xaml.cs with valid subscription key
54-
4. Press Ctrl+Shift+B, or select **Build > Build Solution**
55-
56-
## Run the sample
57-
58-
To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or select Debug > Start Without Debugging.
38+
* [.Net Framework >= 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework)
39+
* Windows SDK Version >= 10.0.18362. You can install it from Visual Studio Installer under **Indivial components** tab, or download from [Windows 10 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)
40+
* If you install the Windows SDK into a customized path, please edit **src\NoteTaker.csproj** to change the HintPath of **Windows.winmd** to the correct path
41+
* Nuget Packages
42+
* [Newtonsoft.JSON](https://www.newtonsoft.com/json)
43+
* [Microsoft.Net.Http](https://www.nuget.org/packages/Microsoft.Net.Http/)
44+
* [Xaml Island for WPF](https://www.nuget.org/packages/Microsoft.Toolkit.Wpf.UI.Controls)
45+
* Subscription key from [Azure Cognitive Services](https://docs.microsoft.com/en-us/azure/cognitive-services/authentication)
46+
* Windows Build 1903 or higher is required for Xaml island features
47+
48+
### Build the Sample
49+
50+
1. Clone or download this sample repository `git clone https://github.com/Azure-Samples/cognitive-services-csharp-wpf-ink-recognition.git`
51+
2. Start Visual Studio and select **File > Open > Project/Solution** and open **src\NoteTaker.sln**
52+
3. Replace "[YOUR SUBSCRIPTION KEY]" in **src\MainWindows.xaml.cs** with valid subscription key
53+
4. Select **Build > Build Solution**
54+
55+
### Run the sample
56+
57+
* To debug the sample and then run it, select **Debug > Start Debugging**. To run the sample without debugging, select **Debug > Start Without Debugging**.
58+
* Write down something on the upper region of the app
59+
* After one second of inactivity, the ink will be recognized and the result will be visible in the lower region of the app
60+
61+
## Resources
62+
63+
Additional resources related the project are located below
64+
65+
* [Learn more about Ink Recognizer](http://go.microsoft.com/fwlink/?LinkID=2084782)
66+
* [Ink Recognizer API Reference](http://go.microsoft.com/fwlink/?LinkID=2085147)
67+
* [Ink Recognizer JavaScript sample](https://github.com/Azure-Samples/cognitive-services-REST-api-samples/tree/master/javascript/InkRecognition/javascript-app)
68+
* [Ink Recognizer UWP sample](https://github.com/Azure-Samples/cognitive-services-REST-api-samples/tree/master/dotnet/InkRecognition/uwp-app)
69+
* [Ink Recognizer Java sample](https://github.com/Azure-Samples/cognitive-services-REST-api-samples/tree/master/java/InkRecognition/android-sample-app)
70+
* [Ink Recognizer Swift sample](https://github.com/Azure-Samples/cognitive-services-REST-api-samples/tree/master/swift/InkRecognition)

dotnet/InkRecognition/wpf-app/src/HTTP/HttpManager.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using Contoso.NoteTaker.JSON;
2-
using Contoso.NoteTaker.JSON.Format;
32
using System;
43
using System.Net;
54
using System.Net.Http;
@@ -23,23 +22,24 @@ public HttpManager(string appKey, string baseAddress, string destinationUrl)
2322

2423
public async Task<HttpResponseMessage> PutAsync(string jsonRequest)
2524
{
26-
var httpContent = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
27-
var httpResponse = await httpClient.PutAsync(destinationUrl, httpContent);
28-
29-
// Throw exception for malformed/unauthorized http requests
30-
if (httpResponse.StatusCode == HttpStatusCode.BadRequest || httpResponse.StatusCode == HttpStatusCode.NotFound || httpResponse.StatusCode == HttpStatusCode.Unauthorized)
25+
try
3126
{
32-
var errorJson = await httpResponse.Content.ReadAsStringAsync();
27+
var httpContent = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
28+
var httpResponse = await httpClient.PutAsync(destinationUrl, httpContent);
3329

34-
var errDetail = JSONProcessor.ParseInkRecognitionError(errorJson);
35-
ThrowExceptionForHttpError(errDetail);
30+
// Throw exception for malformed/unauthorized http requests
31+
if (httpResponse.StatusCode == HttpStatusCode.BadRequest || httpResponse.StatusCode == HttpStatusCode.Unauthorized)
32+
{
33+
var errorJson = await httpResponse.Content.ReadAsStringAsync();
34+
var errDetail = JSONProcessor.ParseInkRecognitionError(errorJson);
35+
throw new HttpRequestException(errDetail.ToString());
36+
}
37+
return httpResponse;
38+
}
39+
catch(Exception e)
40+
{
41+
throw e;
3642
}
37-
return httpResponse;
38-
}
39-
40-
private void ThrowExceptionForHttpError(HttpErrorDetails httpError)
41-
{
42-
throw new HttpRequestException(httpError.ToString());
4343
}
4444
}
4545
}

dotnet/InkRecognition/wpf-app/src/Helpers/InkPointHelper.cs

Lines changed: 0 additions & 49 deletions
This file was deleted.

dotnet/InkRecognition/wpf-app/src/JSON/Converter/InkPointsToStringConverter.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
using Newtonsoft.Json;
2-
using Contoso.NoteTaker.Helpers;
32
using System;
43
using System.Collections.Generic;
54
using Windows.UI.Input.Inking;
5+
using System.Linq;
6+
using System.Reflection;
67

78
namespace Contoso.NoteTaker.JSON.Converter
89
{
910
public class InkPointsToStringConverter : JsonConverter
1011
{
1112
public override bool CanConvert(Type objectType)
1213
{
13-
throw new NotImplementedException();
14+
return typeof(IReadOnlyList<InkPoint>).IsAssignableFrom(objectType);
1415
}
1516

1617
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
1718
{
19+
// Since CanRead flag is false, this function will not be called
1820
throw new NotImplementedException();
1921
}
2022

@@ -23,7 +25,10 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
2325
var points = value as IReadOnlyList<InkPoint>;
2426
if (points != null)
2527
{
26-
var pointsStr = InkPointHelper.InkPointsToString(points);
28+
var pointsStr = string.Join(",",
29+
points.Select(p => Convert.ToSingle(p.Position.X) + "," +
30+
Convert.ToSingle(p.Position.Y))
31+
);
2732
serializer.Serialize(writer, pointsStr);
2833
}
2934
else

dotnet/InkRecognition/wpf-app/src/JSON/Converter/InkRecognitionResponseConverter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public override bool CanConvert(Type objectType)
1515

1616
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
1717
{
18+
// Since CanWrite flag is false, this function will not be called
1819
throw new NotImplementedException();
1920
}
2021

dotnet/InkRecognition/wpf-app/src/JSON/Format/HttpErrorDetails.cs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,9 @@ public class HttpErrorDetails
1919
public override string ToString()
2020
{
2121
string msg = "";
22-
if (ErrorCode != null)
23-
{
24-
msg += "Http Error code: " + ErrorCode;
25-
}
26-
27-
if (Target != null)
28-
{
29-
msg += " Target: " + Target;
30-
}
31-
32-
if (Message != null)
33-
{
34-
msg += " Message : " + Message;
35-
}
22+
msg += (ErrorCode != null) ? " Http Error code : " + ErrorCode : "";
23+
msg += (Target != null) ? " Target : " + Target : "";
24+
msg += (Message != null) ? " Message : " + Message : "";
3625

3726
if (Details != null)
3827
{

dotnet/InkRecognition/wpf-app/src/JSON/Format/InkRecognitionUnit.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using Newtonsoft.Json;
2-
using Contoso.NoteTaker.JSON.Converter;
2+
using System;
33
using System.Collections.Generic;
44
using System.Runtime.Serialization;
5-
using Windows.Foundation;
6-
using System;
75

86
namespace Contoso.NoteTaker.JSON.Format
97
{

dotnet/InkRecognition/wpf-app/src/JSON/Format/InkRecognizerStroke.cs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
1-

2-
using Contoso.NoteTaker.Helpers;
3-
using Contoso.NoteTaker.JSON.Converter;
1+
using Contoso.NoteTaker.JSON.Converter;
42
using Newtonsoft.Json;
53
using System;
64
using System.Collections.Generic;
75
using System.Runtime.Serialization;
6+
using Windows.Foundation;
87
using Windows.UI.Input.Inking;
98

109
namespace Contoso.NoteTaker.JSON.Format
1110
{
1211
public class InkRecognizerStroke
1312
{
1413
[JsonIgnore]
15-
private InkStroke InkStroke { get; set; }
14+
private InkStroke inkStrokeInternal { get; set; }
1615

1716
[JsonProperty(PropertyName = "id")]
18-
public UInt64 Id { get { return InkStroke.Id; } }
17+
public UInt64 Id { get { return inkStrokeInternal.Id; } }
1918

2019
[JsonProperty(PropertyName = "language", NullValueHandling = NullValueHandling.Ignore)]
2120
public string Language { get; set; } = null;
@@ -26,20 +25,31 @@ public class InkRecognizerStroke
2625
[JsonProperty(PropertyName = "points"), JsonConverter(typeof(InkPointsToStringConverter))]
2726
public IReadOnlyList<InkPoint> Points { get; protected set; }
2827

29-
[JsonProperty(PropertyName = "drawingAttributes")]
30-
public InkDrawingAttributes DrawingAttributes { get { return InkStroke.DrawingAttributes; } }
31-
3228
public InkRecognizerStroke(InkStroke stroke, float DpiX, float DpiY)
3329
{
34-
InkStroke = stroke;
30+
inkStrokeInternal = stroke;
3531

36-
var pointsInPixels = GetInkPoints();
37-
Points = InkPointHelper.ConvertPixelsToMillimeters(pointsInPixels, DpiX, DpiY).AsReadOnly();
32+
var pointsInPixels = inkStrokeInternal.GetInkPoints();
33+
Points = ConvertPixelsToMillimeters(pointsInPixels, DpiX, DpiY).AsReadOnly();
3834
}
3935

40-
public IReadOnlyList<InkPoint> GetInkPoints()
36+
private List<InkPoint> ConvertPixelsToMillimeters(IReadOnlyList<InkPoint> pointsInPixels, float DpiX, float DpiY)
4137
{
42-
return InkStroke.GetInkPoints();
38+
var transformedInkPoints = new List<InkPoint>();
39+
const float inchToMillimeterFactor = 25.4f;
40+
41+
42+
foreach (var point in pointsInPixels)
43+
{
44+
var transformedX = (point.Position.X / DpiX) * inchToMillimeterFactor;
45+
var transformedY = (point.Position.Y / DpiY) * inchToMillimeterFactor;
46+
var transformedPoint = new Point(transformedX, transformedY);
47+
var transformedInkPoint = new InkPoint(transformedPoint, point.Pressure);
48+
49+
transformedInkPoints.Add(transformedInkPoint);
50+
}
51+
52+
return transformedInkPoints;
4353
}
4454
}
4555

dotnet/InkRecognition/wpf-app/src/JSON/Format/RecognitionUnitKind.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ namespace Contoso.NoteTaker.JSON.Format
55
public enum RecognitionUnitKind
66
{
77
[EnumMember(Value = "writingRegion")]
8-
InkWritingRegion,
8+
WritingRegion,
99

1010
[EnumMember(Value = "paragraph")]
11-
InkParagraph,
11+
Paragraph,
1212

1313
[EnumMember(Value = "line")]
14-
InkLine,
14+
Line,
1515

1616
[EnumMember(Value = "inkWord")]
1717
InkWord,
@@ -20,7 +20,7 @@ public enum RecognitionUnitKind
2020
InkDrawing,
2121

2222
[EnumMember(Value = "listItem")]
23-
InkListItem,
23+
ListItem,
2424

2525
[EnumMember(Value = "inkBullet")]
2626
InkBullet,

dotnet/InkRecognition/wpf-app/src/JSON/Format/Rectangle.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ namespace Contoso.NoteTaker.JSON.Format
55
public class Rectangle
66
{
77
[JsonProperty(PropertyName = "topX")]
8-
public float topX { get; set; }
8+
public float TopX { get; set; }
99

1010
[JsonProperty(PropertyName = "topY")]
11-
public float topY { get; set; }
11+
public float TopY { get; set; }
1212

1313
[JsonProperty(PropertyName = "width")]
14-
public float width { get; set; }
14+
public float Width { get; set; }
1515

1616
[JsonProperty(PropertyName = "height")]
17-
public float height { get; set; }
17+
public float Height { get; set; }
1818
}
1919
}

0 commit comments

Comments
 (0)