DicomKit
A high-throughput, low-allocation, fuzz-resistant DICOM toolkit for .NET 8, .NET 9 and .NET 10, by PrologicSign Technology. Parsing, networking (DIMSE), imaging and DICOMweb, in pure managed code on Windows, Linux and macOS.
Packages
| Package | What it is |
|---|---|
DicomKit | Core: Part 10 parser and writer, large files, C-ECHO / C-STORE / C-FIND / Modality Worklist / C-MOVE / C-GET SCU and SCP, anonymization, batch processing, mapping, PDF and image to DICOM conversion, logging. |
DicomKit.Imaging | Decode and render pixel data: RLE, JPEG, JPEG-LS, JPEG 2000, LUTs and windowing, PNG / JPEG export, thumbnails. |
DicomKit.Web | DICOMweb: DICOM JSON and XML models, streaming multipart, QIDO-RS / WADO-RS / STOW-RS client. |
DicomKit.Web.AspNetCore | DICOMweb server: app.MapDicomWeb() endpoints over a pluggable store. |
Install
dotnet add package DicomKit
dotnet add package DicomKit.Imaging
dotnet add package DicomKit.Web
dotnet add package DicomKit.Web.AspNetCore
The packages are versioned together. All of them target net8.0, net9.0 and net10.0 and ship XML documentation.
Quick start
Open a file and dump it
using DicomKit;
using DicomKit.IO;
using var file = await DicomFile.OpenAsync("image.dcm"); // metadata parsed, pixel data left on disk
Console.WriteLine($"{file.TransferSyntax}: {file.Dataset.GetString(DicomTag.PatientName)}");
foreach (var item in file.Dataset)
Console.WriteLine($"{item.Tag} {item.VR.Code()} {DicomDictionary.KeywordOf(item.Tag)}");
foreach (var issue in file.Issues)
Console.WriteLine(issue); // problems are reported, never thrown
C-STORE SCP with dependency injection
using Microsoft.Extensions.Hosting;
using DicomKit;
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddDicomKit(o => o.Logging.Directory = @"D:\logs\dicom");
builder.Services.AddDicomKitServer(@"D:\incoming", s => // {root}/{CallingAE}/{SOPInstanceUID}.dcm
{
s.Port = 11112;
s.AeTitle = "DICOMKIT_SCP";
});
await builder.Build().RunAsync();
For your own storage, implement IDicomStoreHandler and register it with AddDicomKitServer<THandler>().
C-FIND query
using DicomKit;
using DicomKit.Network;
using DicomKit.Query;
await using var client = await DicomClient.ConnectAsync("pacs.example.org", 104, new DicomClientOptions
{
CallingAE = "WORKSTATION",
CalledAE = "PACS",
QueryRetrieveSopClasses = [DicomUids.StudyRootQueryRetrieveFind],
});
var query = DicomQuery.Studies(patientName: "DOE*", studyDate: "20260101-20260131");
await foreach (var study in client.FindAsync(DicomUids.StudyRootQueryRetrieveFind, query))
Console.WriteLine($"{study.GetString(DicomTag.StudyInstanceUID)} {study.GetString(DicomTag.StudyDescription)}");
await client.ReleaseAsync();
Render to PNG
using DicomKit.Imaging;
using var image = await DicomImage.OpenAsync("ct.dcm");
image.WindowCenter = 40; // soft-tissue window, in HU
image.WindowWidth = 400;
await using var png = File.Create("ct.png");
await image.RenderToPngAsync(png);
Convert a PDF to DICOM
using DicomKit.Conversion;
using DicomKit.IO;
using var study = await DicomFile.OpenAsync("IM0001.dcm");
using var pdf = await DicomConverter.FromPdfAsync("requisition.pdf",
new DicomConversionOptions { CopyFrom = study.Dataset, SeriesDescription = "Scanned documents" });
await pdf.SaveAsync("requisition.dcm"); // Encapsulated PDF Storage, in the same study
DICOMweb QIDO-RS
using DicomKit;
using DicomKit.Web;
using DicomKit.Web.Client;
var client = new DicomWebClient(new HttpClient { BaseAddress = new Uri("https://pacs.example.org/dicom-web/") });
var query = new QidoQuery { Limit = 50 }
.Match(DicomTag.PatientID, "12345")
.Include(DicomTag.StudyDescription);
await foreach (var study in client.SearchStudiesAsync(query))
Console.WriteLine(study.GetString(DicomTag.StudyInstanceUID));
Seven complete console programs (dump, echo, send, receive, anonymize, convert, large files) are on the examples page, with a download of all of them.
Features
Core (DicomKit)
- Parser that never throws on bad data. Truncation, wrong lengths, unknown VRs, mislabelled transfer syntaxes, missing delimiters and absurd nesting become
DicomParseIssues with placeholder nodes. Explicit / Implicit VR Little Endian, Explicit Big Endian, Deflate and encapsulated pixel data. - Large files. Bulk values are recorded as offsets and read only on demand. Multi-gigabyte files parse with memory bounded by the metadata, with nothing allocated on the LOH (
DicomStreamParser, per-frameLazyDicomPixelData). - Networking on
System.IO.Pipelines.DicomServeris an SCP for C-ECHO, C-STORE, C-FIND (Patient and Study Root), Modality Worklist, C-MOVE and C-GET, with per-association back-pressure.DicomClientis the matching SCU, with streamed C-FIND results and C-CANCEL. It also does SCP/SCU role selection and stores received objects bit-exact.DicomQuerybuilds identifiers andDicomQueryMatcherimplements PS3.4 matching for your own SCP. - Conversion.
DicomConverterturns PDF into Encapsulated PDF and JPEG, PNG or BMP into Secondary Capture. JPEG is stored without re-compression. The original bytes can be extracted again. - Anonymization with a PS3.15-style profile and salted, deterministic UID remapping. Batch processing runs over all cores with per-file fault isolation and skips non-DICOM inputs. Mapping (
dataset.MapTo<T>()) and channel-routed audit logging are included too. - Dependency injection:
AddDicomKit,AddDicomKitServer.
Imaging (DicomKit.Imaging): native 1 to 32-bit pixel data, MONOCHROME1/2, RGB, YBR and PALETTE COLOR, multi-frame. Codecs: RLE, JPEG baseline / extended / lossless, JPEG-LS and JPEG 2000. Modality LUT, VOI LUT and window presets. PNG and JPEG writers.
DICOMweb (DicomKit.Web, DicomKit.Web.AspNetCore): DICOM JSON and Native DICOM Model XML. A streaming multipart/related reader and writer with size limits. A DicomWebClient that streams studies as IAsyncEnumerable. ASP.NET Core QIDO-RS / WADO-RS / STOW-RS endpoints over IDicomWebStore, with in-memory and file-system stores.
Documentation
| Guide | Covers |
|---|---|
| Get started | Install, open a file, query a PACS, many large files at once, anonymization |
| Networking | C-ECHO, C-STORE, C-FIND, Modality Worklist, C-MOVE, C-GET (SCU and SCP) |
| Large files | Memory model, lazy pixel data, limits, measurements |
| Imaging | Decoding, codecs, display pipeline, export |
| DICOMweb | DICOM JSON / XML, the client, the ASP.NET Core endpoints and stores |
| Conversion | PDF, JPEG, PNG and BMP to DICOM: attributes written and limitations |
| Licensing & activation | License keys, the activation tool, offline activation, moving machines |
| Examples | Runnable console samples: DumpFile, EchoScu, StoreScp, StoreScu, Anonymize, ConvertToDicom and LargeFile |
| Release notes | What changed in each version |
License and disclaimer
Copyright (c) 2026 PrologicSign Technology. All rights reserved. Licensed under the DicomKit License Agreement included in each package.
| Who | License | Cost |
|---|---|---|
| Developers evaluating, developing or testing (not in production) | Developer key, one machine | Free |
| Production use, including shipping inside your applications | Pro or Enterprise, yearly | Pricing |
Since 1.0.0 a license key is required; get a free Developer key. No runtime or per-deployment fees. A lapsed or expired paid license never stops running work: it falls back to the Community feature level. A free Developer license stops when it expires; renew it for free from the portal. The 1.0.0-preview packages were free and did not require a key; they are deprecated in favour of 1.0.0.
Setting a license in one line
DicomKit.Licensing.DicomKitLicense.SetFromFile("license.lic"); // signed license file: offline, no network
await DicomKit.Licensing.DicomKitLicense.SetAsync("PLGIC-COM-XXXXX-XXXXX-XXXXX-XXXXX"); // short key: activated online once
Perpetual and term licenses never phone home after activation. Air-gapped sites use the offline flow: DicomKitLicense.CreateOfflineActivationRequest() → portal → license file → DicomKitLicense.SetFromFile. The full activation guide, including the activation tool, is in Licensing & activation.
Third-party codecs in DicomKit.Imaging: CoreJ2K and CharLS.Managed, both BSD-3-Clause.
On this page
Resources
Questions? Contact support, we reply within 24 hours, every day.