# C# samples — Titan-ANPR SDK

This folder contains a **.NET 8** sample solution for integrating the native **Titan-ANPR** SDK (`Titan-ANPR.dll`) from C#.

## Requirements

- **Windows x64**
- **.NET SDK 8** ([download](https://dotnet.microsoft.com/download))
- **Microsoft Visual C++ 2015-2022 Redistributable (x64)** on machines where you run the apps
- The native SDK package: a **`bin`** folder with **`Titan-ANPR.dll`** and its dependencies (ONNX Runtime, OpenVINO, etc., depending on your distribution)
- A **valid license** to run `TitanANPR_Init` / detection (return code **`-10`** often means invalid runtime license)

## Solution layout

| Project | Description |
|---------|-------------|
| **Titan.Anpr.NativeInterop** | Class library with P/Invoke: DLL load, license API (`TitanLicense_*`), unified detection API (`TitanANPR_*`). |
| **Titan.Anpr.LicenseConsole** | Console app for hardware ID, license activate/deactivate, and validation. |
| **Titan.Anpr.DetectionConsole** | Console app for one image or a folder: plate text, confidence, inference time, overlay PNG. |

Solution file: `Titan.Anpr.Samples.sln`.

## How `Titan-ANPR.dll` is resolved

The `NativeDll` class (in `Titan.Anpr.NativeInterop`) resolves the path in this **order**:

1. **`NativeDll.BinDirectoryOverride`** — set by the samples at the start of `Program.Main` (`nativeBinDirectory`). Point it at the folder that **contains** `Titan-ANPR.dll`, or set it to `null` to skip this override.
2. Environment variable **`TITAN_ANPR_NATIVE_DIR`** — same (folder containing the DLL).
3. **Repository layout search** — walk up from the executable directory looking for `bin/Titan-ANPR/Release/x64/bin` or `bin/Titan-ANPR/Debug/x64/bin`.
4. **Application directory** — if `Titan-ANPR.dll` is copied next to the `.exe`.

## Build

From this folder (`samples/csharp`):

```powershell
dotnet build Titan.Anpr.Samples.sln -c Release
```

Use platform **x64** (the `.csproj` files set `PlatformTarget` to x64).

Typical output folders:

- `src\Titan.Anpr.LicenseConsole\bin\x64\Release\net8.0\` (or `bin\Release\...` depending on solution configuration)
- `src\Titan.Anpr.DetectionConsole\bin\x64\Release\net8.0-windows\`

## Titan.Anpr.LicenseConsole

### Interactive mode

Run with no arguments: prints usage and a numeric menu (info, hwid, validate, activate, deactivate).

### Command line

| Command | Description |
|---------|-------------|
| `info` | License status, dates, customer, etc. |
| `hwid` | This machine’s hardware ID (for requesting a key). |
| `validate` | Same validation the engine uses at startup. |
| `activate <key>` | Activate with the received key. |
| `deactivate` | Clear local activation. |

Examples:

```powershell
.\Titan.Anpr.LicenseConsole.exe hwid
.\Titan.Anpr.LicenseConsole.exe activate "YOUR-KEY"
```

**Licensing:** send the **hardware ID** (from `hwid`) to **licenses@safetyroad.es** to obtain a key.

Help: `Titan.Anpr.LicenseConsole.exe --help`

## Titan.Anpr.DetectionConsole

Processes **one image** or **all images** in a directory (extensions: `.jpg`, `.jpeg`, `.png`, `.bmp`, `.tif`, `.tiff`), sorted by file name.

For each image:

- Console output: **plate** (or indication of none), **total confidence**, and **engine time** for `TitanANPR_Detect` only (ms).
- Saves a PNG `*_titan_overlay.png` (green quadrilateral, dashed orange box, text label).

**One at a time:** after each result, **close the preview window** (key, click, or Alt+F4) or press a key in the console if you use **`--no-open`**, before the next image runs. This avoids stacking many viewer windows.

```powershell
.\Titan.Anpr.DetectionConsole.exe D:\photos\one.jpg
.\Titan.Anpr.DetectionConsole.exe D:\photos\folder
.\Titan.Anpr.DetectionConsole.exe D:\photos\folder --out D:\out
.\Titan.Anpr.DetectionConsole.exe D:\photos\folder --no-open
```

| Option | Description |
|--------|-------------|
| `--out <folder>` | Write overlay PNGs to this folder (default: next to each source image). |
| `--no-open` | Do not show the WinForms preview; wait for a key in the **console** between images. |

Help: `Titan.Anpr.DetectionConsole.exe --help`

**Note:** the unified API `TitanANPR_Detect` returns **one** primary plate per image. The sample converts the bitmap to **24 bpp RGB** for the native side; if your engine expects a different pixel layout, adjust preparation in `OverlayRenderer`.

## Using NativeInterop in your own project

1. Add a project reference or reference the built **`Titan.Anpr.NativeInterop.dll`**.
2. At runtime, deploy **`Titan-ANPR.dll`** and native dependencies to an accessible folder (see resolution above).
3. Call `NativeDll.EnsureLoaded()` before any P/Invoke.
4. For detection: `TitanANPR_Init` → loop with `TitanANPR_Detect` → `TitanANPR_Dispose`.

Official C headers remain at the SDK root: `include/titan_anpr.h`, `include/titan_license.h`.

## See also

- Python ctypes samples: `../python/README.md`
