Viewing is open to everyone. Downloading and starring need a GitHub sign-in. Sign in with GitHub

README.md

v0.1.0-build.85 Latest Commit ede38f5

Size
7.9 KB
Lines
159
Language
markdown
SHA-256
84350ec87a52…
View on GitHub

Sign in with GitHub to download. Each download is recorded with your GitHub username.

1# CKey for .NET
2
3CKey optical codes for .NET. The package encodes payloads, renders native pixels (and exports PNG, SVG and PDF), and scans grayscale camera frames. It is a thin P/Invoke wrapper over the CKey C core and does not reimplement encoding, decoding or rendering.
4
5| Package | Target | Contents |
6|---|---|---|
7| `CKey` | `net8.0`, `netstandard2.0` | Headless core: encode, render, certify, scan, payload helpers, telemetry. No UI dependency. |
8| `CKey.Wpf` | `net8.0-windows` | Optional adapter: `WriteableBitmap` output and `BitmapSource` scanning. |
9
10Native libraries ship inside the package as `runtimes/<rid>/native/` assets for `win-x64`, `linux-x64`, `osx-x64` and `osx-arm64`. On `net8.0` the bindings use `[LibraryImport]` and are trim- and AOT-compatible. On `netstandard2.0` they use `[DllImport]`. .NET Framework apps get `ckeynative.dll` (win-x64) copied by the package's build targets.
11
12## Install
13
14```sh
15dotnet add package CKey
16dotnet add package CKey.Wpf # optional, WPF only
17```
18
19```xml
20<PackageReference Include="CKey" Version="0.1.0-build.85" />
21```
22
23The namespace is `OpenCKey`.
24
25## Encode and render
26
27```csharp
28using OpenCKey;
29
30CKeySymbol symbol = CKeySymbol.Encode("https://openckey.org/hello"); // version 0 = smallest that fits
31CKeySymbol big = CKeySymbol.Encode(bytes, version: 12, level: EccLevel.Q, layout: Layout.Print);
32
33// Native pixels: size x size RGBA8, straight alpha, no padding.
34CKeyImage image = symbol.RenderRgba(512, RasterPolicy.Coverage, transparent: false, style: CKeyStyle.Concept);
35byte[] rgba = image.Rgba;
36
37// Exports
38byte[] png = symbol.ToPng(1024);
39string svg = symbol.ToSvg(scale: 8, style: CKeyStyle.Plain);
40byte[] pdf = symbol.ToPdf(widthPt: 144); // 2 inches wide, vector
41CKeyGrayImage print = symbol.RenderPrint(1.0, 600); // 1 inch at 600 dpi, pure black/white
42```
43
44`CKeySymbol` is a managed copy of the C symbol struct. It holds no native resources, so it needs no `Dispose`.
45
46### Styles and optical safety
47
48```csharp
49var style = CKeyStyle.Concept; // or CKeyStyle.Plain, or new CKeyStyle()
50style.Modules = ModuleShape.Circle;
51style.Ink = CKeyColor.Parse("#1a1a2e");
52
53if (!symbol.CheckStyle(style, out string why)) Console.WriteLine(why);
54
55// Certification renders the style, degrades it with a camera model and decodes it.
56CKeyCertification c = symbol.Certify(style);
57// A transparent symbol needs to know what it sits on:
58c = symbol.Certify(null, transparent: true, backdropColours: new[] { CKeyColor.White });
59```
60
61Under the default `StylePolicy.Strict`, renderers refuse a style that fails the checks and throw `CKeyException`. With `StylePolicy.Adaptive`, the style is repaired instead (see `CKeyCertification.AdjustedStyle`). `StylePolicy.Override` draws the style as given.
62
63### WPF
64
65```csharp
66using OpenCKey.Wpf;
67
68imageControl.Source = symbol.ToWriteableBitmap(512, transparent: true);
69```
70
71## Scan
72
73```csharp
74// gray: one 8-bit luma plane (for example the Y plane of NV12), any stride.
75CKeyResult? result = CKeyDecoder.Decode(gray, width, height, stride);
76if (result != null)
77{
78 Console.WriteLine(result.ProfileName); // "Profile 0 · v3"
79 Console.WriteLine(result.Text ?? result.PayloadHex);
80 CKeyPayloadAction? action = result.Action; // e.g. Kind = Web, Label = "Open openckey.org"
81 // Show the payload and the action; act only when the user confirms.
82}
83```
84
85The pipeline is the iOS reader's. It finds up to six border candidates (`CKeyDecoder.FindBorders`). For each one it refines the quadrilateral to the Profile 0 field and decodes, then tries the Profile 1, 2 and 3 fields. Detection and decode are also available separately, via `FindBorders` and `DecodeCandidate`. Scanning never needs the renderer, telemetry or a network.
86
87For continuous camera scanning, use a session. It also drives the telemetry session counters:
88
89```csharp
90using var session = new CKeyScanSession(); // starts a scan session
91foreach (Frame f in camera.Frames)
92{
93 if (session.ProcessFrame(f.Gray, f.Width, f.Height, f.Stride) is { } r) { Show(r); break; }
94}
95// Dispose ends the session (failed if nothing decoded). Restart() is "scan again".
96```
97
98`CKeyPayload.Classify(text)` maps text to an action using spec/CKey-Payload-Conventions.md. Only `https`/`http`, `mailto`, `tel`, `sms`, `geo`, `address:` and vCards are recognized; anything else is plain text. `CKeyPayload.ReadableText(bytes)` applies the convention's text rule.
99
100## Safe Actions
101
102A Safe Action (`ckey-action:1:…`) is a signed code from a known site for this app. `CKeySafeActions` verifies it with the core and decides whether it runs; the app only pins keys and registers handlers.
103
104```csharp
105var actions = new CKeySafeActions("com.viadere")
106 .Trust("citeory.com", "2026-11", "<64 hex digits>", "https://citeory.com/api/ckey/requests/{request_id}")
107 .Register("open.library", new[] { "citeory.com" }, a => OpenItem(a.ParamsText))
108 .Register("signin.request", new[] { "citeory.com" }, CKeySafeActionScope.CrossDevice, null, a => ApproveSignInAsync(a));
109
110var outcome = await actions.HandleAsync(text);
111switch (outcome.Kind)
112{
113 case CKeySafeActionOutcomeKind.NotASafeAction: ShowPayload(text); break; // the ordinary payload rules
114 case CKeySafeActionOutcomeKind.Performed: break; // same-device: already ran
115 case CKeySafeActionOutcomeKind.NeedsConfirmation:
116 await OpenCKey.Wpf.CKeySafeActionPrompt.ShowAsync(window, outcome.Request!); break; // or CKeySafeActionConsolePrompt.AskAsync
117 case CKeySafeActionOutcomeKind.Rejected: ShowUnverified(outcome.Reason); break;
118}
119```
120
121Same-device actions run at once. Cross-device actions run only from an SDK prompt, which shows the verified issuer and who is asking; there is no other way to approve one. Anything that fails a check runs nothing; show that the code claims to be a Safe Action but could not be verified, with the reason. See [spec/CKey-Safe-Actions.md](../../spec/CKey-Safe-Actions.md).
122
123## Telemetry
124
125The default mode is `1`. In mode 1 the SDK counts scan sessions, frames, decodes per profile and coarse durations. Roughly once an hour it sends one anonymous aggregate batch to `https://openckey.org/api/telemetry/v1/batch`. It never sends payloads, URLs, user or device identifiers, or location. Sending happens on a thread-pool timer and never blocks or delays scanning. Only `CKeyScanSession` records anything; `CKeyDecoder` and rendering do not. See [docs/adoption-and-telemetry.md](../../docs/adoption-and-telemetry.md).
126
127To opt out:
128
129```csharp
130CKey.Telemetry = 0; // off: nothing counted, nothing sent, counters purged
131CKey.Telemetry = 2; // local only: counters via CKeyTelemetry.Snapshot(), never sent
132CKey.Telemetry = 1; // default
133```
134
135Any other value throws `ArgumentOutOfRangeException`, and the mode stays unchanged.
136
137`CKeyTelemetry.FlushAsync()` tries a send immediately, for example when your app is deactivated or moves to the background (the hourly limit still applies). `ExportState()` and `ImportState()` persist counters across restarts if you want that; persistence is off unless you store the state. A native library built with `-DCKEY_DOTNET_TELEMETRY=OFF` contains no telemetry code at all. In that case `CKeyTelemetry.IsAvailable` is false and the mode reads 0.
138
139Disclose telemetry according to your own app-store and legal requirements.
140
141## Building from source
142
143```sh
144# Native library for this machine -> sdk/dotnet/artifacts/native/<rid>/
145cmake -S sdk/dotnet/native -B build-dotnet -DCMAKE_BUILD_TYPE=Release -DCKEY_DOTNET_RID=linux-x64
146cmake --build build-dotnet --config Release
147
148# Check the C struct layouts the C# interop mirrors
149./build-dotnet/ckey_layout_probe | diff sdk/dotnet/native/tools/layout_expected.txt -
150
151dotnet test sdk/dotnet/tests/CKey.Tests -p:CKeyHostRid=linux-x64
152dotnet pack sdk/dotnet/src/CKey -c Release # add -p:CKeyRequireAllNatives=true to insist on all four RIDs
153```
154
155The package version comes from the repository's `VERSION` file.
156
157## License
158
159MIT.