DicomFilm.Core 1.2.0

dotnet add package DicomFilm.Core --version 1.2.0
                    
NuGet\Install-Package DicomFilm.Core -Version 1.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DicomFilm.Core" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DicomFilm.Core" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="DicomFilm.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DicomFilm.Core --version 1.2.0
                    
#r "nuget: DicomFilm.Core, 1.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DicomFilm.Core@1.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DicomFilm.Core&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=DicomFilm.Core&version=1.2.0
                    
Install as a Cake Tool

DicomFilm.Core

Türkçe · English

<a id="türkçe"></a>

Türkçe

DicomFilm.Core, DICOM dosyalarını taramak, metadata bilgilerini okumak ve görüntüleri JPG/PNG biçimine dönüştürmek için hazırlanmış çok hedefli bir .NET kütüphanesidir. .NET Core 3.1'den .NET 10'a kadar her sürüm için derleme içerir.

Windows Forms bağımlılığı yoktur. Konsol uygulaması, ASP.NET Core, Worker Service, Windows Service, masaüstü uygulaması veya Linux üzerinde çalışan bir .NET servisi içinden kullanılabilir.

Tıbbi uyarı: Üretilen JPG/PNG dosyaları tanısal kullanım, tıbbi ölçüm veya orijinal DICOM arşivinin yerine geçmek için uygun değildir. Dönüşüm sırasında bit derinliği ve klinik metadata kaybedilebilir. Orijinal DICOM dosyalarını saklayın.

İçindekiler

Özellikler

  • Bir klasörü alt klasörleriyle birlikte toplu tarar.
  • Uzantısı .dcm olmayan geçerli DICOM dosyalarını da algılar.
  • DICOM olmayan dosyaları işlemi durdurmadan raporlar.
  • Çok kareli DICOM dosyalarının her karesini ayrı görüntü olarak işler.
  • StudyInstanceUID, SeriesInstanceUID, seri ve instance numaralarını okur.
  • Dosyaları çalışma, seri, instance ve kare sırasına göre düzenler.
  • Üç farklı çıktı modu sunar:
    • Her görüntüyü ayrı JPG/PNG
    • Her DICOM serisini ayrı film
    • Bütün görüntüleri tek film
  • Orijinal, 1024 px, 2048 px ve özel uzun kenar çözünürlüğü sunar.
  • A4 dikey, A4 yatay, A3 yatay ve özel film ölçülerini destekler.
  • Otomatik veya manuel sütun hesabı yapar.
  • Siyah, mavi-siyah ve beyaz film zemini sunar.
  • PNG ve kalite ayarlı JPEG çıktısı üretir.
  • Aynı isimdeki dosyaları ezmeden _02, _03 biçiminde adlandırabilir.
  • IProgress<T> ile ilerleme ve CancellationToken ile iptal desteği sağlar.
  • Kareyi veya filmi dosyaya yazmadan bellekte Image<Rgba32> olarak döndürebilir.
  • JPEG, JPEG-LS, JPEG 2000, HT-JPEG 2000 ve RLE sıkıştırılmış DICOM aktarım sözdizimlerini destekler.

Gereksinimler

  • .NET Core 3.1, .NET 5, 6, 7, 8, 9 veya 10
  • 64 bit işlem büyük DICOM serileri için önerilir
  • .NET 8-10 üzerinde sıkıştırılmış DICOM dosyaları için hedef işletim sistemine uygun Dicom.Native kitaplığı
  • Windows üzerinde native codec kullanımı için Microsoft Visual C++ 2015-2022 Redistributable x64

Kütüphane System.Drawing kullanmaz. Görüntü işlemleri ImageSharp ile gerçekleştirilir.

Sürüm uyumluluğu

NuGet paketi aşağıdaki derlemelerin tamamını fiziksel olarak içerir:

Uygulama hedefi Paketten seçilen derleme Bağımlılık hattı Native sıkıştırılmış codec
.NET Core 3.1 netcoreapp3.1 Legacy fo-dicom/ImageSharp Dahili değil
.NET 5 net5.0 Legacy fo-dicom/ImageSharp Dahili değil
.NET 6 net6.0 Legacy fo-dicom/ImageSharp Dahili değil
.NET 7 net7.0 Legacy fo-dicom/ImageSharp Dahili değil
.NET 8 net8.0 Güncel fo-dicom/ImageSharp Dahil
.NET 9 net9.0 Güncel fo-dicom/ImageSharp Dahil
.NET 10 net10.0 Güncel fo-dicom/ImageSharp Dahil
Diğer .NET Standard 2.0 tüketicileri netstandard2.0 Legacy fo-dicom/ImageSharp Dahili değil

Bütün hedefler aynı DicomScanner, DicomFilmExporter, üç çıktı modu, çözünürlük ve film API'sini sunar. Legacy 3.1-7 derlemeleri sıkıştırılmamış DICOM görüntülerini işler. JPEG 2000, JPEG-LS, RLE ve benzeri native codec gerektiren sıkıştırılmış DICOM'larda tam dahili codec desteği .NET 8-10 derlemelerinde bulunur.

.NET Core 3.1 ile .NET 5, 6 ve 7 üreticileri tarafından yaşam döngüsü dışına çıkarılmış sürümlerdir. Kütüphane uyumluluk için bu hedefleri sağlar; internete açık veya sağlık verisi işleyen yeni sistemlerde desteklenen bir .NET LTS sürümü tercih edilmelidir.

Kurulum

Yerel NuGet paketi

Paket dosyası:

artifacts/DicomFilm.Core.1.2.0.nupkg

Paketi doğrudan projeye eklemek için:

dotnet add package DicomFilm.Core --version 1.2.0 --source "C:\Paketler"

Kalıcı bir yerel NuGet kaynağı tanımlamak için:

dotnet nuget add source "C:\Paketler" --name DicomFilmLocal
dotnet add package DicomFilm.Core --version 1.2.0

Proje dosyasından referans vermek için:

<ItemGroup>
  <PackageReference Include="DicomFilm.Core" Version="1.2.0" />
</ItemGroup>

Kaynak projeye referans

<ItemGroup>
  <ProjectReference Include="..\DicomFilm.Core\DicomFilm.Core.csproj" />
</ItemGroup>

Temel çalışma akışı

Kullanım iki aşamadan oluşur:

  1. DicomScanner ile dosyaları bulup metadata ve kare listesini oluşturun.
  2. DicomFilmExporter ile istediğiniz çıktı modunu çalıştırın.
using DicomFilm.Core;
using DicomFilm.Core.Models;

var scanner = new DicomScanner();
var scan = await scanner.ScanFolderAsync(
    folderPath: @"C:\DICOM",
    recursive: true);

Console.WriteLine($"Dosya: {scan.FileCount}");
Console.WriteLine($"Kare:  {scan.Frames.Count}");
Console.WriteLine($"Seri:  {scan.SeriesCount}");
Console.WriteLine($"Atlanan dosya: {scan.Issues.Count}");

var exporter = new DicomFilmExporter();

var result = await exporter.ExportAsync(
    scan.Frames,
    @"C:\Cikti",
    new DicomExportOptions
    {
        Mode = DicomExportMode.EachImageSeparately,
        Frame = new FrameExportOptions
        {
            Resolution = FrameResolutionPreset.LongEdge2048,
            Format = DicomImageFormat.Png
        }
    });

Console.WriteLine($"Oluşturulan dosya: {result.OutputFiles.Count}");
Console.WriteLine($"Dönüştürülemeyen görüntü: {result.Issues.Count}");

DicomFilmRuntime.Initialize() ilk tarama veya exporter oluşturma sırasında otomatik çağrılır. Uygulama başlangıcında açıkça çağırmak da mümkündür:

DicomFilmRuntime.Initialize();

DICOM tarama

Klasör ve alt klasörleri tarama

var scanner = new DicomScanner();

DicomScanResult scan = await scanner.ScanFolderAsync(
    @"D:\Hastalar\QAX1178800267",
    recursive: true);

Klasördeki bütün dosyalar denenir. DICOM olmayan dosyalar scan.Issues listesine eklenir; geçerli DICOM dosyalarının işlenmesi devam eder.

Yalnızca üst klasörü tarama

var scan = await scanner.ScanFolderAsync(
    @"D:\DICOM",
    recursive: false);

Belirli dosyaları tarama

string[] files =
[
    @"D:\DICOM\1.dcm",
    @"D:\DICOM\2.dcm",
    @"D:\DICOM\uzantisiz_dicom"
];

var scan = await scanner.ScanFilesAsync(files);

Okunan metadata

Her DicomFrame aşağıdaki bilgileri içerir:

Alan Açıklama
FilePath Kaynak DICOM dosyasının tam yolu
FileName Kaynak dosya adı
FrameIndex Çok kareli DICOM içindeki sıfır tabanlı kare numarası
FrameCount Dosyadaki toplam kare sayısı
SeriesNumber DICOM Series Number
InstanceNumber DICOM Instance Number
PatientName Hasta adı; ^ karakterleri boşluğa çevrilir
PatientId Hasta numarası
StudyDate DICOM Study Date değeri
Modality MR, CT, CR gibi modalite
StudyDescription Çalışma açıklaması
SeriesDescription Seri açıklaması
StudyInstanceUid Çalışmanın benzersiz UID değeri
SeriesInstanceUid Serinin benzersiz UID değeri

Üç çıktı modu

1. Her görüntüyü ayrı kaydetme

Her DICOM dosyası ayrı resme dönüşür. Çok kareli DICOM dosyalarında her kare ayrı dosyadır. Film sayfası, başlık veya toplu ızgara eklenmez.

var options = new DicomExportOptions
{
    Mode = DicomExportMode.EachImageSeparately,
    Frame = new FrameExportOptions
    {
        Resolution = FrameResolutionPreset.LongEdge2048,
        Format = DicomImageFormat.Png,
        ApplyBlueFilmTint = false,
        Overwrite = false
    }
};

ExportResult result = await exporter.ExportAsync(
    scan.Frames,
    @"D:\Cikti\TekGoruntuler",
    options);

JPEG örneği:

var options = new DicomExportOptions
{
    Mode = DicomExportMode.EachImageSeparately,
    Frame = new FrameExportOptions
    {
        Resolution = FrameResolutionPreset.LongEdge1024,
        Format = DicomImageFormat.Jpeg,
        JpegQuality = 95,
        ApplyBlueFilmTint = true
    }
};

2. Her seriyi ayrı film kaydetme

Kareler SeriesInstanceUID değerine göre gruplanır. UID yoksa çalışma UID, seri numarası ve seri açıklamasından oluşan yedek anahtar kullanılır.

var options = new DicomExportOptions
{
    Mode = DicomExportMode.EachSeriesAsFilm,
    Film = new FilmExportOptions
    {
        SizePreset = FilmSizePreset.A4Portrait300Dpi,
        AutoColumns = true,
        Background = FilmBackground.BlueBlack,
        Format = DicomImageFormat.Jpeg,
        JpegQuality = 92,
        Margin = 36,
        Gap = 10,
        Overwrite = false
    }
};

ExportResult result = await exporter.ExportAsync(
    scan.Frames,
    @"D:\Cikti\SeriFilmleri",
    options);

3. Tüm görüntüleri tek film kaydetme

var options = new DicomExportOptions
{
    Mode = DicomExportMode.AllImagesAsSingleFilm,
    SingleFilmFileName = "QAX1178800267_Tum_Seriler",
    Film = new FilmExportOptions
    {
        SizePreset = FilmSizePreset.A3Landscape300Dpi,
        AutoColumns = true,
        Background = FilmBackground.ClassicBlack,
        Format = DicomImageFormat.Png
    }
};

ExportResult result = await exporter.ExportAsync(
    scan.Frames,
    @"D:\Cikti",
    options);

string filmPath = result.OutputFiles.Single();

Tek film modunda outputPath doğrudan dosya yolu da olabilir:

await exporter.ExportAsync(
    scan.Frames,
    @"D:\Cikti\tum-film.jpg",
    new DicomExportOptions
    {
        Mode = DicomExportMode.AllImagesAsSingleFilm,
        Film = new FilmExportOptions
        {
            Format = DicomImageFormat.Jpeg,
            JpegQuality = 90
        }
    });

Çözünürlük seçenekleri

FrameResolutionPreset, yalnızca her görüntüyü ayrı kaydetme modunda kullanılır.

Değer Sonuç
Original DICOM renderer tarafından üretilen kaynak piksel boyutu korunur
LongEdge1024 Uzun kenar 1024 piksel olur
LongEdge2048 Uzun kenar 2048 piksel olur
Custom TargetLongEdge değeri kullanılır

En-boy oranı korunur. Görüntü kare veya dikdörtgen olmaya zorlanmaz.

Orijinal çözünürlük

Frame = new FrameExportOptions
{
    Resolution = FrameResolutionPreset.Original
}

Yapay zekâ modeli için 2048 piksel

Frame = new FrameExportOptions
{
    Resolution = FrameResolutionPreset.LongEdge2048,
    Format = DicomImageFormat.Png
}

Özel çözünürlük

Frame = new FrameExportOptions
{
    Resolution = FrameResolutionPreset.Custom,
    TargetLongEdge = 1536,
    Format = DicomImageFormat.Jpeg,
    JpegQuality = 94
}

Ölçekleme Lanczos3 filtresiyle yapılır. Büyütme yeni klinik detay üretmez; yalnızca piksel boyutunu değiştirir.

Film ayarları

Hazır film ölçüleri

FilmSizePreset Piksel ölçüsü Açıklama
A4Portrait300Dpi 2480 × 3508 A4 dikey
A4Landscape300Dpi 3508 × 2480 A4 yatay
A3Landscape300Dpi 4961 × 3508 A3 yatay
Custom Width × Height Özel piksel ölçüsü

Özel film ölçüsü:

Film = new FilmExportOptions
{
    SizePreset = FilmSizePreset.Custom,
    Width = 4096,
    Height = 4096,
    AutoColumns = true
}

Otomatik sütun hesabı

Film = new FilmExportOptions
{
    AutoColumns = true
}

Kütüphane görüntü sayısı ile filmin en-boy oranına göre uygun sütun ve satır sayısını hesaplar. Bu seçenek 1.000’den fazla görüntüyü tek filme yerleştirirken özellikle önemlidir.

Manuel sütun sayısı:

Film = new FilmExportOptions
{
    AutoColumns = false,
    Columns = 5
}

Film zeminleri

FilmBackground.ClassicBlack // Saf siyah
FilmBackground.BlueBlack    // Eski mavi/karbon radyoloji filmi görünümü
FilmBackground.White        // Açık zemin

PNG ve JPEG

// Kayıpsız PNG
Film = new FilmExportOptions
{
    Format = DicomImageFormat.Png
}

// Kalite ayarlı JPEG
Film = new FilmExportOptions
{
    Format = DicomImageFormat.Jpeg,
    JpegQuality = 92
}

JpegQuality değeri 1 ile 100 arasında olmalıdır. PNG kullanıldığında bu değer dikkate alınmaz.

Boşluk ve kenar payı

Film = new FilmExportOptions
{
    Margin = 36,
    Gap = 10
}

Çok kalabalık filmlerde kütüphane hücrelerin tamamen kaybolmaması için boşluğu otomatik olarak küçültebilir.

İlerleme ve iptal

İlerleme bildirimi

var progress = new Progress<ExportProgress>(value =>
{
    Console.WriteLine(
        $"{value.Completed}/{value.Total} " +
        $"%{value.Percentage:F1} " +
        $"{value.CurrentFile}");
});

var scan = await scanner.ScanFolderAsync(
    @"D:\DICOM",
    recursive: true,
    progress: progress);

var result = await exporter.ExportAsync(
    scan.Frames,
    @"D:\Cikti",
    new DicomExportOptions
    {
        Mode = DicomExportMode.EachImageSeparately
    },
    progress);

Kullanıcı tarafından iptal

using var cancellation = new CancellationTokenSource();

Console.CancelKeyPress += (_, eventArgs) =>
{
    eventArgs.Cancel = true;
    cancellation.Cancel();
};

try
{
    await exporter.ExportAsync(
        scan.Frames,
        @"D:\Cikti",
        new DicomExportOptions
        {
            Mode = DicomExportMode.EachImageSeparately
        },
        cancellationToken: cancellation.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("İşlem kullanıcı tarafından iptal edildi.");
}

Hata yönetimi

Tarama ve çoklu dışa aktarma sırasında tek bir bozuk dosya bütün işlemi durdurmaz.

DicomScanResult scan = await scanner.ScanFolderAsync(@"D:\DICOM");

foreach (DicomReadIssue issue in scan.Issues)
{
    Console.WriteLine($"Okunamadı: {issue.FilePath}");
    Console.WriteLine(issue.Message);
}

ExportResult export = await exporter.ExportFramesAsync(
    scan.Frames,
    @"D:\Cikti");

foreach (ExportIssue issue in export.Issues)
{
    Console.WriteLine($"Dönüştürülemedi: {issue.FilePath}");
    Console.WriteLine(issue.Message);
}

ExportFilmAsync tek çıktı oluşturduğu için kritik bir kare/codec hatasında exception fırlatabilir. Çağrıyı try/catch ile çevreleyin.

Düşük seviyeli API

Üst seviye ExportAsync yerine doğrudan özel metotlar kullanılabilir.

Kareleri ayrı kaydetme

ExportResult result = await exporter.ExportFramesAsync(
    scan.Frames,
    @"D:\Cikti",
    new FrameExportOptions
    {
        Resolution = FrameResolutionPreset.LongEdge2048,
        Format = DicomImageFormat.Png
    });

Serileri ayrı film kaydetme

ExportResult result = await exporter.ExportSeriesAsync(
    scan.Frames,
    @"D:\Seriler",
    new FilmExportOptions
    {
        SizePreset = FilmSizePreset.A4Portrait300Dpi,
        AutoColumns = true
    });

Tek film dosyası kaydetme

string output = await exporter.ExportFilmAsync(
    scan.Frames,
    @"D:\Cikti\film.png",
    new FilmExportOptions
    {
        Format = DicomImageFormat.Png
    });

Tek kareyi bellekte işleme

RenderFrame, dışa aktarmadan önce özel model ön işlemesi yapmak için kullanılabilir.

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;

DicomFrame firstFrame = scan.Frames[0];

using Image<Rgba32> image = exporter.RenderFrame(
    firstFrame,
    targetLongEdge: 2048,
    applyBlueFilmTint: false);

// Burada kendi yapay zekâ ön işleminizi uygulayabilirsiniz.
await image.SaveAsPngAsync(@"D:\Cikti\model-input.png");

Dönen Image<Rgba32> nesnesi mutlaka Dispose edilmelidir; bu nedenle using kullanın.

Film görüntüsünü bellekte işleme

using Image<Rgba32> film = exporter.ComposeFilm(
    scan.Frames,
    new FilmExportOptions
    {
        SizePreset = FilmSizePreset.A3Landscape300Dpi,
        AutoColumns = true
    });

// Kaydetmeden önce başka bir işlem uygulanabilir.
await film.SaveAsPngAsync(@"D:\Cikti\film.png");

ASP.NET Core örneği

Servisleri DI container’a kaydedin:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<DicomScanner>();
builder.Services.AddSingleton<DicomFilmExporter>();

var app = builder.Build();

Minimal API endpoint örneği:

app.MapPost("/dicom/export", async (
    DicomScanner scanner,
    DicomFilmExporter exporter,
    CancellationToken cancellationToken) =>
{
    const string inputFolder = @"D:\DICOM\Gelen";
    const string outputFolder = @"D:\DICOM\Cikti";

    var scan = await scanner.ScanFolderAsync(
        inputFolder,
        recursive: true,
        cancellationToken: cancellationToken);

    var result = await exporter.ExportAsync(
        scan.Frames,
        outputFolder,
        new DicomExportOptions
        {
            Mode = DicomExportMode.EachImageSeparately,
            Frame = new FrameExportOptions
            {
                Resolution = FrameResolutionPreset.LongEdge2048,
                Format = DicomImageFormat.Png
            }
        },
        cancellationToken: cancellationToken);

    return Results.Ok(new
    {
        scan.FileCount,
        FrameCount = scan.Frames.Count,
        scan.SeriesCount,
        Outputs = result.OutputFiles.Count,
        ScanErrors = scan.Issues.Count,
        ExportErrors = result.Issues.Count
    });
});

Gerçek bir web uygulamasında kullanıcıdan gelen klasör veya dosya yollarını doğrudan kullanmayın. Yetkili bir çalışma dizinine normalize edin, erişim denetimi uygulayın ve hasta verilerini loglara yazmayın.

Dosya adlandırma

Ayrı kareler

{PatientId}_Seri_{SeriesNumber}_Goruntu_{InstanceNumber}.png

Çok kareli DICOM:

{PatientId}_Seri_030_Goruntu_0001_Kare_001.png

Seri filmleri

{PatientId}_Seri_{SeriesNumber}_{SeriesDescription}.jpg

Geçersiz dosya adı karakterleri _ ile değiştirilir. Overwrite=false olduğunda mevcut veya tekrar eden isimler _02, _03 biçiminde numaralandırılır.

Performans ve dağıtım

Büyük çalışmalar

  • Kareler dışa aktarılırken görüntüler sırayla işlenir ve dispose edilir.
  • A4 2480×3508 RGB görüntü bellekte yaklaşık 25 MB ham piksel alanı kullanır; işlem sırasında geçici kopyalar nedeniyle daha fazlası gerekebilir.
  • A3 ve binlerce kare içeren çalışmalar için 64 bit process kullanın.
  • Yapay zekâ girdisi için çoğu durumda ayrı 1024/2048 px kareler, tek dev filmden daha kullanışlıdır.
  • Aynı exporter nesnesi kullanılabilir; ancak çok sayıda paralel native codec çağrısı yüksek bellek tüketebilir.

Sıkıştırılmış DICOM codec’leri

.NET 8-10 derlemeleri fo-dicom.Codecs paketini ve native transcoder yöneticisini otomatik kaydeder. Desteklenen başlıca biçimler:

  • RLE Lossless
  • JPEG Baseline / Extended / Lossless
  • JPEG-LS Lossless / Near-Lossless
  • JPEG 2000 Lossless / Lossy
  • HT-JPEG 2000

Native codec yüklenemiyorsa uygulama çıktı klasöründe hedef işletim sistemi ve mimariye uygun Dicom.Native dosyasının bulunduğunu kontrol edin.

.NET Core 3.1 ile .NET 5-7 derlemelerinde eski runtime uyumluluğunu korumak için native codec paketi otomatik eklenmez. Bu hedeflerde sıkıştırılmamış Explicit/Implicit VR Little Endian DICOM görüntüleri kullanılmalıdır veya uygulama kendi sürümüyle uyumlu bir codec yöneticisini ayrıca yapılandırmalıdır.

Hasta verilerinin korunması

  • Dosya adlarında varsayılan olarak PatientId bulunur.
  • Çıktılar paylaşılacaksa dosya adlarını anonimleştirin veya çıktıları kontrollü dizinde tutun.
  • PatientName, PatientId ve UID değerlerini uygulama loglarına yazmadan önce gizlilik politikanızı değerlendirin.
  • Bu kütüphane otomatik DICOM anonimleştirme yapmaz.

API referansı

DicomScanner

Metot Açıklama
ScanFolderAsync(folderPath, recursive, progress, cancellationToken) Bir klasörü tarar
ScanFilesAsync(filePaths, progress, cancellationToken) Verilen dosya listesini tarar

DicomFilmExporter

Metot Açıklama
ExportAsync(...) Üç moddan birini tek API üzerinden çalıştırır
ExportFramesAsync(...) Her kareyi ayrı dosyaya kaydeder
ExportSeriesAsync(...) Her seriyi ayrı film dosyasına kaydeder
ExportFilmAsync(...) Bütün kareleri tek film dosyasına kaydeder
RenderFrame(...) Tek kareyi bellekte Image<Rgba32> olarak döndürür
ComposeFilm(...) Film sayfasını bellekte Image<Rgba32> olarak döndürür

DicomExportOptions

Özellik Varsayılan Açıklama
Mode EachImageSeparately Üç çıktı modundan biri
Frame new FrameExportOptions() Ayrı kare ayarları
Film new FilmExportOptions() Film ayarları
SingleFilmFileName DICOM_Film Tek film modunda klasöre yazılacak dosya adı

FrameExportOptions

Özellik Varsayılan Açıklama
Format Png PNG veya JPEG
JpegQuality 92 JPEG kalite değeri, 1-100
Resolution LongEdge2048 Hazır çözünürlük seçimi
TargetLongEdge 0 Custom çözünürlükte uzun kenar
ApplyBlueFilmTint false Mavi film renk tonu uygular
Overwrite false Mevcut dosyanın üzerine yazmaya izin verir

FilmExportOptions

Özellik Varsayılan Açıklama
SizePreset A4Portrait300Dpi Hazır film ölçüsü
Width 2480 Custom genişlik
Height 3508 Custom yükseklik
Columns 4 Manuel sütun sayısı
AutoColumns true Otomatik ızgara hesabı
Gap 10 Hücreler arası piksel boşluğu
Margin 36 Film kenar payı
Background BlueBlack Film zemini
Format Png PNG veya JPEG
JpegQuality 92 JPEG kalite değeri
Overwrite false Seri dosyalarının üzerine yazma davranışı

Sonuç nesneleri

Tip Açıklama
DicomScanResult.Frames Okunan bütün kareler
DicomScanResult.Issues Okunamayan dosyalar
ExportResult.OutputFiles Oluşturulan dosya yolları
ExportResult.Issues Dönüştürülemeyen kare veya seriler
ExportProgress Tamamlanan/toplam işlem ve geçerli dosya

Test ve paket oluşturma

Uçtan uca smoke test:

dotnet run --project tests\DicomFilm.Core.Smoke\DicomFilm.Core.Smoke.csproj -c Release

NuGet paketi üretme:

dotnet pack src\DicomFilm.Core\DicomFilm.Core.csproj -c Release -o artifacts

Çalıştırılabilir örnek proje:

dotnet run --project samples\DicomFilm.Core.Example -- "D:\DICOM" "D:\Cikti" frames
dotnet run --project samples\DicomFilm.Core.Example -- "D:\DICOM" "D:\Cikti" series
dotnet run --project samples\DicomFilm.Core.Example -- "D:\DICOM" "D:\Cikti" film

<a id="english"></a>

English

DicomFilm.Core is a multi-target .NET library for scanning DICOM files, reading metadata, grouping series, and exporting images to JPG or PNG. The NuGet package contains dedicated builds from .NET Core 3.1 through .NET 10.

It has no Windows Forms or System.Drawing dependency. It can be used from console applications, ASP.NET Core APIs, Worker Services, Windows Services, desktop applications, and Linux-hosted .NET services.

Medical disclaimer: Exported JPG/PNG files are not intended for diagnostic use, medical measurements, or replacement of the original DICOM archive. Conversion may discard bit depth and clinical metadata. Always retain the original DICOM files.

Contents

<a id="features-en"></a>

Features

  • Recursively scans an entire directory.
  • Detects valid DICOM files even when they do not use the .dcm extension.
  • Reports non-DICOM or unreadable files without stopping the whole scan.
  • Treats every frame in a multi-frame DICOM as a separate image.
  • Reads patient, study, series, modality, instance, and UID metadata.
  • Orders frames by study, series, instance, file name, and frame index.
  • Provides three export modes:
    • Each image as a separate JPG/PNG file
    • Each DICOM series as a separate film sheet
    • All images combined into one film sheet
  • Supports original, 1024 px, 2048 px, and custom long-edge resolutions.
  • Supports A4 portrait, A4 landscape, A3 landscape, and custom film dimensions.
  • Provides automatic or manual grid column selection.
  • Provides classic black, blue-black radiology film, and white backgrounds.
  • Exports lossless PNG or quality-controlled JPEG.
  • Avoids overwriting duplicate file names by adding _02, _03, and similar suffixes.
  • Supports progress reporting through IProgress<T> and cancellation through CancellationToken.
  • Can return an in-memory Image<Rgba32> without writing a file.
  • Modern targets support JPEG, JPEG-LS, JPEG 2000, HT-JPEG 2000, and RLE compressed DICOM transfer syntaxes.

<a id="compatibility-en"></a>

Compatibility

The NuGet package physically contains all of the following builds:

Application target Package asset Dependency line Bundled native compressed codecs
.NET Core 3.1 netcoreapp3.1 Legacy fo-dicom/ImageSharp No
.NET 5 net5.0 Legacy fo-dicom/ImageSharp No
.NET 6 net6.0 Legacy fo-dicom/ImageSharp No
.NET 7 net7.0 Legacy fo-dicom/ImageSharp No
.NET 8 net8.0 Current fo-dicom/ImageSharp Yes
.NET 9 net9.0 Current fo-dicom/ImageSharp Yes
.NET 10 net10.0 Current fo-dicom/ImageSharp Yes
Other .NET Standard 2.0 consumers netstandard2.0 Legacy fo-dicom/ImageSharp No

Every target exposes the same scanning, grouping, export-mode, resolution, and film-layout API. The legacy .NET Core 3.1–.NET 7 line supports uncompressed DICOM rendering. Full built-in native codec support for JPEG 2000, JPEG-LS, RLE, and related compressed transfer syntaxes is provided by the .NET 8–10 builds.

.NET Core 3.1 and .NET 5, 6, and 7 are out of support from their vendor. These targets are included for compatibility. Use a supported .NET LTS release for new systems, especially systems exposed to the internet or processing medical data.

<a id="installation-en"></a>

Installation

The local package file is:

artifacts/DicomFilm.Core.1.2.0.nupkg

Install directly from a directory:

dotnet add package DicomFilm.Core --version 1.2.0 --source "C:\Packages"

Or add a permanent local feed:

dotnet nuget add source "C:\Packages" --name DicomFilmLocal
dotnet add package DicomFilm.Core --version 1.2.0

Package reference:

<ItemGroup>
  <PackageReference Include="DicomFilm.Core" Version="1.2.0" />
</ItemGroup>

Project reference during local development:

<ItemGroup>
  <ProjectReference Include="..\DicomFilm.Core\DicomFilm.Core.csproj" />
</ItemGroup>

<a id="quick-start-en"></a>

Quick start

The typical flow has two stages:

  1. Scan a folder with DicomScanner to create a metadata and frame list.
  2. Pass the frames to DicomFilmExporter using one of the three export modes.
using DicomFilm.Core;
using DicomFilm.Core.Models;

var scanner = new DicomScanner();
var scan = await scanner.ScanFolderAsync(
    folderPath: @"C:\DICOM",
    recursive: true);

Console.WriteLine($"Files:  {scan.FileCount}");
Console.WriteLine($"Frames: {scan.Frames.Count}");
Console.WriteLine($"Series: {scan.SeriesCount}");
Console.WriteLine($"Skipped files: {scan.Issues.Count}");

var exporter = new DicomFilmExporter();
var result = await exporter.ExportAsync(
    scan.Frames,
    @"C:\Output",
    new DicomExportOptions
    {
        Mode = DicomExportMode.EachImageSeparately,
        Frame = new FrameExportOptions
        {
            Resolution = FrameResolutionPreset.LongEdge2048,
            Format = DicomImageFormat.Png
        }
    });

Console.WriteLine($"Created: {result.OutputFiles.Count}");
Console.WriteLine($"Failed:  {result.Issues.Count}");

DicomFilmRuntime.Initialize() is called automatically during the first scan or exporter construction. It may also be invoked explicitly during application startup:

DicomFilmRuntime.Initialize();

<a id="scanning-en"></a>

Scanning DICOM files

Scan a folder recursively:

DicomScanResult scan = await scanner.ScanFolderAsync(
    @"D:\Patients\QAX1178800267",
    recursive: true);

Scan only the top-level directory:

var scan = await scanner.ScanFolderAsync(
    @"D:\DICOM",
    recursive: false);

Scan a specific file list, including files without an extension:

string[] files =
[
    @"D:\DICOM\1.dcm",
    @"D:\DICOM\2.dcm",
    @"D:\DICOM\dicom_without_extension"
];

var scan = await scanner.ScanFilesAsync(files);

Each DicomFrame provides:

Property Description
FilePath / FileName Source DICOM path and file name
FrameIndex / FrameCount Multi-frame position and total frame count
SeriesNumber DICOM Series Number
InstanceNumber DICOM Instance Number
PatientName / PatientId Patient metadata
StudyDate Raw DICOM Study Date value
Modality MR, CT, CR, and similar modality
StudyDescription Study description
SeriesDescription Series description
StudyInstanceUid Unique study UID
SeriesInstanceUid Unique series UID

<a id="export-modes-en"></a>

Three export modes

1. Export every image separately

Every DICOM frame becomes an independent image. No film sheet, header, or contact-sheet grid is added.

var result = await exporter.ExportAsync(
    scan.Frames,
    @"D:\Output\IndividualImages",
    new DicomExportOptions
    {
        Mode = DicomExportMode.EachImageSeparately,
        Frame = new FrameExportOptions
        {
            Resolution = FrameResolutionPreset.LongEdge2048,
            Format = DicomImageFormat.Png,
            ApplyBlueFilmTint = false,
            Overwrite = false
        }
    });

JPEG with a blue film tint:

Frame = new FrameExportOptions
{
    Resolution = FrameResolutionPreset.LongEdge1024,
    Format = DicomImageFormat.Jpeg,
    JpegQuality = 95,
    ApplyBlueFilmTint = true
}
2. Export every series as a separate film

Frames are grouped by SeriesInstanceUID. When the UID is unavailable, a fallback key based on study UID, series number, and series description is used.

var result = await exporter.ExportAsync(
    scan.Frames,
    @"D:\Output\SeriesFilms",
    new DicomExportOptions
    {
        Mode = DicomExportMode.EachSeriesAsFilm,
        Film = new FilmExportOptions
        {
            SizePreset = FilmSizePreset.A4Portrait300Dpi,
            AutoColumns = true,
            Background = FilmBackground.BlueBlack,
            Format = DicomImageFormat.Jpeg,
            JpegQuality = 92,
            Margin = 36,
            Gap = 10,
            Overwrite = false
        }
    });
3. Export all images as one film
var result = await exporter.ExportAsync(
    scan.Frames,
    @"D:\Output",
    new DicomExportOptions
    {
        Mode = DicomExportMode.AllImagesAsSingleFilm,
        SingleFilmFileName = "QAX1178800267_All_Series",
        Film = new FilmExportOptions
        {
            SizePreset = FilmSizePreset.A3Landscape300Dpi,
            AutoColumns = true,
            Background = FilmBackground.ClassicBlack,
            Format = DicomImageFormat.Png
        }
    });

A full file path may also be supplied in single-film mode:

await exporter.ExportAsync(
    scan.Frames,
    @"D:\Output\all-images.jpg",
    new DicomExportOptions
    {
        Mode = DicomExportMode.AllImagesAsSingleFilm,
        Film = new FilmExportOptions
        {
            Format = DicomImageFormat.Jpeg,
            JpegQuality = 90
        }
    });

<a id="resolution-en"></a>

Resolution options

FrameResolutionPreset is used by the separate-image mode:

Value Result
Original Keeps the size produced by the DICOM renderer
LongEdge1024 Resizes the long edge to 1024 pixels
LongEdge2048 Resizes the long edge to 2048 pixels
Custom Uses the TargetLongEdge value

Aspect ratio is preserved. Images are not forced into a square.

// Original size
Frame = new FrameExportOptions
{
    Resolution = FrameResolutionPreset.Original
};

// 2048 px AI-model input
Frame = new FrameExportOptions
{
    Resolution = FrameResolutionPreset.LongEdge2048,
    Format = DicomImageFormat.Png
};

// Custom 1536 px long edge
Frame = new FrameExportOptions
{
    Resolution = FrameResolutionPreset.Custom,
    TargetLongEdge = 1536,
    Format = DicomImageFormat.Jpeg,
    JpegQuality = 94
};

Resizing uses a Lanczos3 resampler. Upscaling changes pixel dimensions but does not create new clinical detail.

<a id="film-options-en"></a>

Film options

Film sizes
Preset Pixel dimensions Description
A4Portrait300Dpi 2480 × 3508 A4 portrait
A4Landscape300Dpi 3508 × 2480 A4 landscape
A3Landscape300Dpi 4961 × 3508 A3 landscape
Custom Width × Height Custom pixel dimensions
Film = new FilmExportOptions
{
    SizePreset = FilmSizePreset.Custom,
    Width = 4096,
    Height = 4096,
    AutoColumns = true
};
Automatic or manual grid
// Automatically chooses rows and columns from image count and film ratio.
Film = new FilmExportOptions { AutoColumns = true };

// Forces a five-column grid.
Film = new FilmExportOptions
{
    AutoColumns = false,
    Columns = 5
};

Automatic grid selection is particularly useful for studies containing hundreds or thousands of frames.

Backgrounds
FilmBackground.ClassicBlack // Pure black
FilmBackground.BlueBlack    // Blue-black/carbon radiology film
FilmBackground.White        // Light background
PNG and JPEG
Film = new FilmExportOptions
{
    Format = DicomImageFormat.Png
};

Film = new FilmExportOptions
{
    Format = DicomImageFormat.Jpeg,
    JpegQuality = 92
};

JpegQuality must be between 1 and 100. It is ignored for PNG output.

Margins and cell gaps
Film = new FilmExportOptions
{
    Margin = 36,
    Gap = 10
};

For extremely dense sheets, the library may automatically reduce the gap so that image cells do not disappear.

<a id="progress-en"></a>

Progress and cancellation

var progress = new Progress<ExportProgress>(value =>
{
    Console.WriteLine(
        $"{value.Completed}/{value.Total} " +
        $"{value.Percentage:F1}% " +
        $"{value.CurrentFile}");
});

var scan = await scanner.ScanFolderAsync(
    @"D:\DICOM",
    recursive: true,
    progress: progress);

var result = await exporter.ExportAsync(
    scan.Frames,
    @"D:\Output",
    new DicomExportOptions
    {
        Mode = DicomExportMode.EachImageSeparately
    },
    progress);

Cancellation example:

using var cancellation = new CancellationTokenSource();

Console.CancelKeyPress += (_, eventArgs) =>
{
    eventArgs.Cancel = true;
    cancellation.Cancel();
};

try
{
    await exporter.ExportAsync(
        scan.Frames,
        @"D:\Output",
        new DicomExportOptions
        {
            Mode = DicomExportMode.EachImageSeparately
        },
        cancellationToken: cancellation.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Operation cancelled.");
}

<a id="errors-en"></a>

Error handling

A single unreadable file does not stop a folder scan or multi-file export.

foreach (DicomReadIssue issue in scan.Issues)
{
    Console.WriteLine($"Could not read: {issue.FilePath}");
    Console.WriteLine(issue.Message);
}

foreach (ExportIssue issue in result.Issues)
{
    Console.WriteLine($"Could not export: {issue.FilePath}");
    Console.WriteLine(issue.Message);
}

ExportFilmAsync produces one output and may throw when a critical frame or codec error occurs. Wrap direct single-film calls in try/catch.

<a id="low-level-en"></a>

Low-level API

The dedicated methods may be used instead of the unified ExportAsync entry point:

// Separate image files
ExportResult frames = await exporter.ExportFramesAsync(
    scan.Frames,
    @"D:\Output",
    new FrameExportOptions
    {
        Resolution = FrameResolutionPreset.LongEdge2048,
        Format = DicomImageFormat.Png
    });

// One film per series
ExportResult series = await exporter.ExportSeriesAsync(
    scan.Frames,
    @"D:\Series",
    new FilmExportOptions
    {
        SizePreset = FilmSizePreset.A4Portrait300Dpi,
        AutoColumns = true
    });

// One film containing all frames
string filmPath = await exporter.ExportFilmAsync(
    scan.Frames,
    @"D:\Output\film.png",
    new FilmExportOptions
    {
        Format = DicomImageFormat.Png
    });

Render a frame in memory for custom AI preprocessing:

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;

using Image<Rgba32> image = exporter.RenderFrame(
    scan.Frames[0],
    targetLongEdge: 2048,
    applyBlueFilmTint: false);

await image.SaveAsPngAsync(@"D:\Output\model-input.png");

Compose a film in memory:

using Image<Rgba32> film = exporter.ComposeFilm(
    scan.Frames,
    new FilmExportOptions
    {
        SizePreset = FilmSizePreset.A3Landscape300Dpi,
        AutoColumns = true
    });

await film.SaveAsPngAsync(@"D:\Output\film.png");

Always dispose the returned Image<Rgba32> object, preferably with using.

<a id="aspnet-en"></a>

ASP.NET Core example

Register the services:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<DicomScanner>();
builder.Services.AddSingleton<DicomFilmExporter>();

var app = builder.Build();

Minimal API endpoint:

app.MapPost("/dicom/export", async (
    DicomScanner scanner,
    DicomFilmExporter exporter,
    CancellationToken cancellationToken) =>
{
    const string inputFolder = @"D:\DICOM\Incoming";
    const string outputFolder = @"D:\DICOM\Output";

    var scan = await scanner.ScanFolderAsync(
        inputFolder,
        recursive: true,
        cancellationToken: cancellationToken);

    var result = await exporter.ExportAsync(
        scan.Frames,
        outputFolder,
        new DicomExportOptions
        {
            Mode = DicomExportMode.EachImageSeparately,
            Frame = new FrameExportOptions
            {
                Resolution = FrameResolutionPreset.LongEdge2048,
                Format = DicomImageFormat.Png
            }
        },
        cancellationToken: cancellationToken);

    return Results.Ok(new
    {
        scan.FileCount,
        FrameCount = scan.Frames.Count,
        scan.SeriesCount,
        Outputs = result.OutputFiles.Count,
        ScanErrors = scan.Issues.Count,
        ExportErrors = result.Issues.Count
    });
});

Do not pass untrusted user-supplied paths directly to the scanner in production. Normalize paths into an authorized working directory, enforce access controls, and avoid writing patient data to logs.

<a id="naming-en"></a>

File naming

Separate frames:

{PatientId}_Seri_{SeriesNumber}_Goruntu_{InstanceNumber}.png

Multi-frame DICOM:

{PatientId}_Seri_030_Goruntu_0001_Kare_001.png

Series films:

{PatientId}_Seri_{SeriesNumber}_{SeriesDescription}.jpg

Invalid file-name characters are replaced with _. When Overwrite=false, existing or duplicate names receive _02, _03, and similar suffixes.

<a id="deployment-en"></a>

Performance, codecs, and privacy

Large studies
  • Images are processed sequentially and disposed after export.
  • An A4 2480×3508 RGB image uses roughly 25 MB of raw pixel memory; temporary processing copies may require more.
  • Use a 64-bit process for A3 sheets and studies with thousands of frames.
  • Separate 1024/2048 px images are usually more useful to a vision model than one extremely dense film sheet.
  • Avoid launching many native codec operations in parallel unless memory usage has been measured.
Compressed DICOM codecs

The .NET 8–10 builds automatically register fo-dicom.Codecs and its native transcoder. They support RLE, JPEG Baseline/Extended/Lossless, JPEG-LS, JPEG 2000, and HT-JPEG 2000.

If a native codec cannot be loaded, verify that the correct Dicom.Native binary for the operating system and CPU architecture is present in the application output.

The .NET Core 3.1–.NET 7 builds do not automatically include native codecs in order to preserve legacy runtime compatibility. Use uncompressed Explicit/Implicit VR Little Endian DICOM files on these targets, or configure a codec manager compatible with the host runtime.

Patient privacy
  • Generated file names include PatientId by default.
  • Anonymize names before sharing outputs or store them in a controlled directory.
  • Review your privacy policy before logging PatientName, PatientId, or UID values.
  • The library does not automatically anonymize the source DICOM dataset.

<a id="api-en"></a>

API reference

DicomScanner
Method Description
ScanFolderAsync(...) Scans a directory, optionally recursively
ScanFilesAsync(...) Scans an explicit file collection
DicomFilmExporter
Method Description
ExportAsync(...) Runs any of the three export modes
ExportFramesAsync(...) Writes every frame as a separate file
ExportSeriesAsync(...) Writes every series as a separate film
ExportFilmAsync(...) Writes all supplied frames as one film
RenderFrame(...) Returns one in-memory Image<Rgba32>
ComposeFilm(...) Returns an in-memory film Image<Rgba32>
DicomExportOptions
Property Default Description
Mode EachImageSeparately Selects one of the three export modes
Frame New defaults Separate-image settings
Film New defaults Film-sheet settings
SingleFilmFileName DICOM_Film File name used when a directory is passed to single-film mode
FrameExportOptions
Property Default Description
Format Png PNG or JPEG
JpegQuality 92 JPEG quality from 1 to 100
Resolution LongEdge2048 Resolution preset
TargetLongEdge 0 Long-edge size for Custom
ApplyBlueFilmTint false Applies a blue radiology-film tint
Overwrite false Allows replacing an existing output name
FilmExportOptions
Property Default Description
SizePreset A4Portrait300Dpi Film dimensions preset
Width / Height 2480 / 3508 Custom dimensions
Columns 4 Manual column count
AutoColumns true Enables automatic grid calculation
Gap 10 Pixel gap between cells
Margin 36 Outer film margin
Background BlueBlack Film background style
Format Png PNG or JPEG
JpegQuality 92 JPEG quality
Overwrite false Controls replacement of series files
Result objects
Type/property Description
DicomScanResult.Frames All successfully read frames
DicomScanResult.Issues Unreadable or non-DICOM files
ExportResult.OutputFiles Created output paths
ExportResult.Issues Frames or series that could not be exported
ExportProgress Completed/total count and current file

Build and test

Run the end-to-end smoke tests:

dotnet run --project tests\DicomFilm.Core.Smoke\DicomFilm.Core.Smoke.csproj -c Release -f net6.0
dotnet run --project tests\DicomFilm.Core.Smoke\DicomFilm.Core.Smoke.csproj -c Release -f net8.0

Build every compatibility target:

dotnet build tests\DicomFilm.Core.Compatibility\DicomFilm.Core.Compatibility.csproj -c Release

Create the NuGet package:

dotnet pack src\DicomFilm.Core\DicomFilm.Core.csproj -c Release -o artifacts

Run the complete console example:

dotnet run --project samples\DicomFilm.Core.Example -- "D:\DICOM" "D:\Output" frames
dotnet run --project samples\DicomFilm.Core.Example -- "D:\DICOM" "D:\Output" series
dotnet run --project samples\DicomFilm.Core.Example -- "D:\DICOM" "D:\Output" film
Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 is compatible. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.0 32 8/2/2026

TR: .NET Core 3.1 ve .NET 5-10 hedefleri, üç çıktı modu, seri gruplama, çözünürlük seçenekleri ve JPG/PNG çıktısı. EN: Targets .NET Core 3.1 and .NET 5-10 with three export modes, series grouping, resolution presets and JPG/PNG output.