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.

Free Developer key for development and testing; yearly Pro / Enterprise plans for production. A license key is required since 1.0.0: get the free key in a minute.

Packages

PackageWhat it is
DicomKitCore: 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.ImagingDecode and render pixel data: RLE, JPEG, JPEG-LS, JPEG 2000, LUTs and windowing, PNG / JPEG export, thumbnails.
DicomKit.WebDICOMweb: DICOM JSON and XML models, streaming multipart, QIDO-RS / WADO-RS / STOW-RS client.
DicomKit.Web.AspNetCoreDICOMweb 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-frame LazyDicomPixelData).
  • Networking on System.IO.Pipelines. DicomServer is 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. DicomClient is the matching SCU, with streamed C-FIND results and C-CANCEL. It also does SCP/SCU role selection and stores received objects bit-exact. DicomQuery builds identifiers and DicomQueryMatcher implements PS3.4 matching for your own SCP.
  • Conversion. DicomConverter turns 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

GuideCovers
Get startedInstall, open a file, query a PACS, many large files at once, anonymization
NetworkingC-ECHO, C-STORE, C-FIND, Modality Worklist, C-MOVE, C-GET (SCU and SCP)
Large filesMemory model, lazy pixel data, limits, measurements
ImagingDecoding, codecs, display pipeline, export
DICOMwebDICOM JSON / XML, the client, the ASP.NET Core endpoints and stores
ConversionPDF, JPEG, PNG and BMP to DICOM: attributes written and limitations
Licensing & activationLicense keys, the activation tool, offline activation, moving machines
ExamplesRunnable console samples: DumpFile, EchoScu, StoreScp, StoreScu, Anonymize, ConvertToDicom and LargeFile
Release notesWhat 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.

WhoLicenseCost
Developers evaluating, developing or testing (not in production)Developer key, one machineFree
Production use, including shipping inside your applicationsPro or Enterprise, yearlyPricing

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.

Not a medical device. DicomKit is a developer library. It is provided without warranty and is not certified for diagnostic or clinical use. If you build a product for such use, validating, certifying and obtaining regulatory approval for that product is your responsibility.