Giter Site home page Giter Site logo

fo-dicom / fo-dicom Goto Github PK

View Code? Open in Web Editor NEW
1.0K 98.0 629.0 168.31 MB

Fellow Oak DICOM for .NET, .NET Core, Universal Windows, Android, iOS, Mono and Unity

Home Page: https://fo-dicom.github.io/stable/v5/index.html

License: Other

C# 99.99% Batchfile 0.01%
dicom netcore medical medical-imaging dot-net c-sharp nuget jpeg fo-dicom netstandard

fo-dicom's Introduction

fo-dicom logo

Fellow Oak DICOM

NuGet build development codecov

License

This library is licensed under the Microsoft Public License (MS-PL). See License.txt for more information.

Features

  • Targets .NET Standard 2.0
  • DICOM dictionary version 2023b
  • High-performance, fully asynchronous async/await API
  • JPEG (including lossless), JPEG-LS, JPEG2000, HTJPEG2000, and RLE image compression (via additional package)
  • Supports very large datasets with content loading on demand
  • Image rendering to System.Drawing.Bitmap or SixLabors.ImageSharp
  • JSON and XML export/import
  • Anonymization
  • DICOM services
  • Customize components via DI container

Supported Runtimes

Fellow Oak DICOM officially supports the following runtimes:

  • .NET Core 7.0
  • .NET Core 6.0
  • .NET Framework 4.6.2

Other runtimes that implement .NET Standard 2.0 may work, but be aware that our CI pipeline only tests these platforms (and only on Windows)

Installation

Easiest is to obtain fo-dicom binaries from NuGet. This package reference the core fo-dicom assemblies for all Microsoft and Xamarin platforms.

NuGet Packages

Valid for version 5.0.0 and later

Package Description
fo-dicom Core package containing parser, services and tools.
fo-dicom.Imaging.Desktop Library with referencte to System.Drawing, required for rendering into Bitmaps
fo-dicom.Imaging.ImageSharp Library with reference to ImageSharp, can be used for platform independent rendering
fo-dicom.Codecs Cross-platform Dicom codecs for fo-dicom, developed by Efferent Health (https://github.com/Efferent-Health/fo-dicom.Codecs)

Documentation

Documentation, including API documentation, is available via GitHub pages:

Usage Notes

Image rendering configuration

Out-of-the-box, fo-dicom defaults to an internal class FellowOakDicom.Imaging.IImage-style image rendering. To switch to Desktop-style or ImageSharp-style image rendering, you first have to add the nuget package you desire and then call:

new DicomSetupBuilder()
    .RegisterServices(s => s.AddFellowOakDicom().AddImageManager<WinFormsImageManager>())
.Build();

or

new DicomSetupBuilder()
    .RegisterServices(s => s.AddFellowOakDicom().AddImageManager<ImageSharpImageManager>())
.Build();

Then when rendering you can cast the IImage to the type by

var image = new DicomImage("filename.dcm");
var bitmap = image.RenderImage().As<Bitmap>();

or

var image = new DicomImage("filename.dcm");
var sharpimage = image.RenderImage().AsSharpImage();

Logging configuration

Fellow Oak DICOM uses Microsoft.Extensions.Logging, so if you are already using that, Fellow Oak DICOM logging will show up automatically.

In the past, Fellow Oak DICOM had a custom abstraction for logging: ILogger and ILogManager. For backwards compatibility purposes, this is still supported but not recommended for new applications.

services.AddLogManager<MyLogManager>();

where MyLogManager looks like this:

using FellowOakDicom.Log;

public class MyLogManager: ILogManager {
    public ILogger GetLogger(string name) {
        ...
    }
}

Sample applications

There are a number of simple sample applications that use fo-dicom available in separate repository here. These also include the samples that were previously included in the Examples sub-folder of the VS solutions.

Examples

File Operations

var file = DicomFile.Open(@"test.dcm");             // Alt 1
var file = await DicomFile.OpenAsync(@"test.dcm");  // Alt 2

var patientid = file.Dataset.GetString(DicomTag.PatientID);

file.Dataset.AddOrUpdate(DicomTag.PatientName, "DOE^JOHN");

// creates a new instance of DicomFile
var newFile = file.Clone(DicomTransferSyntax.JPEGProcess14SV1);

file.Save(@"output.dcm");             // Alt 1
await file.SaveAsync(@"output.dcm");  // Alt 2

Render Image to JPEG

var image = new DicomImage(@"test.dcm");
image.RenderImage().AsBitmap().Save(@"test.jpg");                     // Windows Forms

C-Store SCU

var client = DicomClientFactory.Create("127.0.0.1", 12345, false, "SCU", "ANY-SCP");
await client.AddRequestAsync(new DicomCStoreRequest(@"test.dcm"));
await client.SendAsync();

C-Echo SCU/SCP

var server = new DicomServer<DicomCEchoProvider>(12345);

var client = DicomClientFactory.Create("127.0.0.1", 12345, false, "SCU", "ANY-SCP");
client.NegotiateAsyncOps();
// Optionally negotiate user identity
client.NegotiateUserIdentity(new DicomUserIdentityNegotiation
{
    UserIdentityType = DicomUserIdentityType.Jwt,
    PositiveResponseRequested = true,
    PrimaryField = "JWT_TOKEN"
});
for (int i = 0; i < 10; i++)
    await client.AddRequestAsync(new DicomCEchoRequest());
await client.SendAsync();

C-Find SCU

var cfind = DicomCFindRequest.CreateStudyQuery(patientId: "12345");
cfind.OnResponseReceived = (DicomCFindRequest rq, DicomCFindResponse rp) => {
	Console.WriteLine("Study UID: {0}", rp.Dataset.GetString(DicomTag.StudyInstanceUID));
};

var client = DicomClientFactory.Create("127.0.0.1", 11112, false, "SCU-AE", "SCP-AE");
await client.AddRequestAsync(cfind);
await client.SendAsync();

C-Move SCU

var cmove = new DicomCMoveRequest("DEST-AE", studyInstanceUid);

var client = DicomClientFactory.Create("127.0.0.1", 11112, false, "SCU-AE", "SCP-AE");
await client.AddRequestAsync(cmove);
await client.SendAsync(); 

N-Action SCU

// It is better to increase 'associationLingerTimeoutInMs' default is 50 ms, which may not be
// be sufficient
var dicomClient = DicomClientFactory.Create("127.0.0.1", 12345, false, "SCU-AE", "SCP-AE",
DicomClientDefaults.DefaultAssociationRequestTimeoutInMs, DicomClientDefaults.DefaultAssociationReleaseTimeoutInMs,5000);
var txnUid = DicomUIDGenerator.GenerateDerivedFromUUID().UID;
var nActionDicomDataSet = new DicomDataset
{
    { DicomTag.TransactionUID,  txnUid }
};
var dicomRefSopSequence = new DicomSequence(DicomTag.ReferencedSOPSequence);
var seqItem = new DicomDataset()
{
    { DicomTag.ReferencedSOPClassUID, "1.2.840.10008.5.1.4.1.1.1" },
    { DicomTag.ReferencedSOPInstanceUID, "1.3.46.670589.30.2273540226.4.54" }
};
dicomRefSopSequence.Items.Add(seqItem);
nActionDicomDataSet.Add(dicomRefSopSequence);
var nActionRequest = new DicomNActionRequest(DicomUID.StorageCommitmentPushModelSOPClass,
                DicomUID.StorageCommitmentPushModelSOPInstance, 1)
{
    Dataset = nActionDicomDataSet,
    OnResponseReceived = (DicomNActionRequest request, DicomNActionResponse response) => 
    {
        Console.WriteLine("NActionResponseHandler, response status:{0}", response.Status);
    },
};
await dicomClient.AddRequestAsync(nActionRequest);
dicomClient.OnNEventReportRequest = OnNEventReportRequest;
await dicomClient.SendAsync();

private static Task<DicomNEventReportResponse> OnNEventReportRequest(DicomNEventReportRequest request)
{
    var refSopSequence = request.Dataset.GetSequence(DicomTag.ReferencedSOPSequence);
    foreach(var item in refSopSequence.Items)
    {
        Console.WriteLine("SOP Class UID: {0}", item.GetString(DicomTag.ReferencedSOPClassUID));
        Console.WriteLine("SOP Instance UID: {0}", item.GetString(DicomTag.ReferencedSOPInstanceUID));
    }
    return Task.FromResult(new DicomNEventReportResponse(request, DicomStatus.Success));
}

C-ECHO with advanced DICOM client connection: manual control over TCP connection and DICOM association

var cancellationToken = CancellationToken.None;
// Alternatively, inject IDicomServerFactory via dependency injection instead of using this static method
using var server = DicomServerFactory.Create<DicomCEchoProvider>(12345); 

var connectionRequest = new AdvancedDicomClientConnectionRequest
{
    NetworkStreamCreationOptions = new NetworkStreamCreationOptions
    {
        Host = "127.0.0.1",
        Port = server.Port,
    }
};

// Alternatively, inject IAdvancedDicomClientConnectionFactory via dependency injection instead of using this static method
using var connection = await AdvancedDicomClientConnectionFactory.OpenConnectionAsync(connectionRequest, cancellationToken);

var associationRequest = new AdvancedDicomClientAssociationRequest
{
    CallingAE = "EchoSCU",
    CalledAE = "EchoSCP",
    // Optionally negotiate user identity
    UserIdentityNegotiation = new DicomUserIdentityNegotiation
    {
        UserIdentityType = DicomUserIdentityType.UsernameAndPasscode,
        PositiveResponseRequested = true,
        PrimaryField = "USERNAME",
        SecondaryField = "PASSCODE",
    }
};

var cEchoRequest = new DicomCEchoRequest();

using var association = await connection.OpenAssociationAsync(associationRequest, cancellationToken);
try
{
    DicomCEchoResponse cEchoResponse = await association.SendCEchoRequestAsync(cEchoRequest, cancellationToken).ConfigureAwait(false);
    
    Console.WriteLine(cEchoResponse.Status);
}
finally
{
    await association.ReleaseAsync(cancellationToken);
}

New to DICOM?

If you are new to DICOM, then take a look at the DICOM tutorial of Saravanan Subramanian: https://saravanansubramanian.com/dicomtutorials/ The author is also using fo-dicom in some code samples.

fo-dicom's People

Contributors

abdullah248 avatar amoerie avatar anders9ustafsson avatar bjorn-malmo avatar bobster3000 avatar davste83 avatar dependabot[bot] avatar gofal avatar hdesouky avatar ianyates avatar idubnori avatar jaime-olivares avatar javier-alvarez avatar justsomehack avatar lste avatar maherjendoubi avatar mdubey82 avatar mia-san avatar michaelm223 avatar mocsharp avatar mrbean-bremen avatar pengchen0692 avatar pvrobays avatar rcd avatar rickardraysearch avatar shivakumar-ms avatar smithago avatar sudheeshps avatar viktoriasalociova avatar zaid-safadi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fo-dicom's Issues

Split fo-dicom into portable core and platform specific assemblies

It would be a welcome addition if (parts of) fo-dicom could be available for platforms other than .NET., for example Windows Universal (Windows 10), Xamarin.iOS and Xamarin.Android.

My vision is that we have a core Portable Class Library (PCL), DICOM.Core. This library contains the abstract manager classes and imaging, I/O, networking interfaces. Then, for each target platform, we have a library that reference the core library and contains the implementations of the managers and interfaces. These platform specific libraries can also contain dependencies to the platform specific codec implementations. To begin with, we would have DICOM.Desktop for the .NET platform, but then we could expand with DICOM.Windows for the Universal Windows Platform, DICOM.Mono for the Mono platform, and so on.

Move file name based I/O to extension methods for facilitated adaptation to PCL

NOTE! The proposal in this comment is obsolete! See this comment for updated proposal.

The .NET file I/O operations in the System.IO namespace are generally not applicable to other platforms.

PCLStorage provides a platform agnostic abstraction layer for common file I/O operations.

To facilitate porting fo-dicom to other platforms such as Windows 8/Windows Phone 8.1/Universal Windows 10 as well as Xamarin iOS and Xamarin Android, I suggest that the internal calls to System.IO.File, System.IO.Directory etc. should be refactored to use PCLStorage constructs instead.

Please share your thoughts on this issue.

DicomDataset.Add(DicomTag, ...) method does not support multi-valued LO, PN, SH and UI tags

The DICOM standard supports multi-valued elements for value representations LO, PN, SH and UI, but the DicomDataset<T>(DicomTag, params T[]) methods fails to recognize all arguments but the first for the listed value representations.

On the same note, the DicomPersonName constructor overloads interfere with each other when one or more string arguments are passed. To unequivocally support multi-valued DicomPersonName elements, the DicomPersonName(params string[]) constructor should be re-signatured into DicomPersonName(string[]).

Reduce usage of geometry types from System.Drawing namespace

To facilitate the adaptation to portable class libraries, usage of geometric types from the System.Drawing namespace (e.g. Point, SizeF, Rectangle) should be kept at a minimum. Usage should be avoided completely in the public API. Ideally, the System.Drawing geometry types should only be used when required by the signature of a called method and there is no available alternative. Cases where this might occur is when calling e.g. Graphics.DrawImage and similar methods.

There is already a suitable replacement for System.Drawing.Point in the Dicom.Imaging.Mathematics namespace, namely Point2. Types analogous to Point2 may be implemented to cover up for other System.Drawing geometry types to maximize the portability of the library.

Applying Color Palette LUT on 16- and 32-bit images

Originally posted in Google Groups by Mukul Lanke on September 2, 2015:

I am trying to apply Color Palette using LUT (Lookup Tables) in my software. I also have a sample Lookup-Table file (packed inside the zip file I have attached with this mail). This file applies the "GreenFireBlue" type of ColorPalette to the DicomImage currently being viewed. This lookup-table file has been generated by another viewer. Now, when I apply it to my DicomViewer program, it does generate an image; but when compared with the image generated from the another viewer, it shows difference. Mainly, the Blue color does not get applied at all in my program.

Below is the code which I have written to achieve the same functionality:

string strDICOMFile =  @"D:\DicomImage.dcm";
string strLUTFile = @"D:\GreenFireBlue.lut";

DicomImage di = new DicomImage(strDICOMFile);
Color32[] colorTable = ColorTable.LoadLUT(strLUTFile);

OutputLUT oLUT = new OutputLUT(colorTable);
IPixelData pixelData = PixelDataFactory.Create(di.PixelData, 0);
ImageGraphic ig = new ImageGraphic(pixelData);
Image image = ig.RenderImage(oLUT);
image.Save(@"D:\GreenFireBlue2.jpg");

I want to know where I am going wrong or what I am missing.

I have also attached a zip file here with containing:

  1. LookupTable file (filename: GreenFireBlue.lut)
  2. The image which gets generated from another viewer after LUT application (filename: expected.jpg)
  3. The image which gets generated from my software using the above listed code (filename: actual.jpg).
  4. The original Dicom file to which the LUT is applied in my program and in the other viewer (filename: DicomImage.dcm)

Expected
expected

Actual
actual

Re-format C# code to use Visual Studio default tabbing

Currently, it can be very cumbersome to edit existing fo-dicom source code, since it adheres to tabbing and indentation conventions that are not commonly used with later Visual Studio versions.

To facilitate future development for a group of dedicated developers it is therefore suggested that the source code should be re-formatted to match the following settings in Visual Studio:

Smart indenting
Tab size 4
Indent size 4
Insert spaces

On the same note, I also suggest that opening angle brackets should be placed on separate lines, i.e.

if (condition)
{
  ...

foreach (var item in items)
{
  ...

public double X
{
  get
  {
    return _x;

etc.

Implement asynchronous operations as async/await constructs

Wanted to bring up this issue since it seems like a desirable way to go in terms of asynchronous operations.

If we implement async/await functionality, should we at the same time remove Begin.../End... constructs, or should those be maintained?

Unit tests arbitrarily fail when run in parallel

I have repeatedly experienced that some unit tests fail when the tests are being run in bulk. As a quick-fix, I have in PR #81 configured unit tests to be run in sequence, i.e. I have set the maximum number of parallel threads to 1.

This is of course only a temporary solution; it is crucial to identify the actual cause of unit tests arbitrarily failing when run in parallel, since this could be an indication that the fo-dicom class library is not thread-safe.

Further investigation required, obviously.

Move logging implementation into separate assembly

The Logger abstract used throughout the codebase is great. However it would be nice to move the NLog implementation of Logger into its own assembly. Personally I've switched over to Serilog and fo-DICOM is the only reason I still have NLog referenced in my projects.

So...

I propose we leave the console logger in place as-is.

Then a new assembly is created that has its dependency on NLog. It can register an extension method on the LogManager along the lines of .UseNLog().

We'd also create other assemblies (Serilog, common logging? Log4Net?) that provide concrete LogManager implementations.

Happy to hear the thoughts of others on this

Remove obsolete dictionary, tag and UID code generation

Since DICOM dictionary, pre-defined tag and UID generation are now integrated as T4 templates in the DICOM project, the code generators in the Dicom.Generators have become obsolete.

Since the classes have likely only been used for internal code generation, it is suggested that these obsolete classes are removed from the DICOM project/assembly.

Implement abstraction layer for network operations

To facilitate the transfer of fo-dicom to portable class libraries, the network operations relying on the System.Net and System.Security namespaces should be abstracted, similar to the approach taken for file and directory I/O operations in PR #78 .

The following files are likely to be affected by this change:

  • DicomUIDGenerator.cs
  • Network/DicomClient.cs
  • Network/DicomServer.cs
  • Network/DicomService.cs

Failure to decompress specific JPEG2000 files

Initially reported to Google Groups by Christoph Ernst on July 12, 2015:

Hello all,

i use the latest version(1.1.0.0 with NLOG) and ChangeTransferSyntax to decompress DICOM files and send them to a DICOM SCP.
Unfortunately the decompression does not work on some files.

Here is my code:

df = DicomFile.Open(filename);
df = df.ChangeTransferSyntax(DicomTransferSyntax.ImplicitVRLittleEndian);

On some files i get the error message "Requested 1599034185 bytes past end of file" when opening the file. I guess there is a problem with broken sequences in the file? I tried several DICOM tools and all of them were able to open the image, but not FO DICOM. How can i work around this problem?

A second problem is when decompressing certain JPEG2000 compressed files. At the point when it comes to the decompression, nothing happens. The program just stops and does nothing anymore. There is no error message in the log, even if i set the level to "trace".
I attached a sample file.
Any solution for this two issues?

Thanks,
Christoph

CT Object Crash

EDIT: This issue is a duplicate of #48. Fixed in 1.1.0

I have a CT Object that causes a crash on fo-dicom but not on dcm4che3, dcmtk/dcmdump and dvtk editor. The crash can be demonstrated with the Dump tool, but also occurs in other DICOM store operations.

Make: Philips Brilliance 64 but has various additional private data in it potentially massaged by Primordial and also has various ELSCINT private data.

It exceptions in parsing an SQ element, but by the time this happens, the tag is all incorrect and with a huge length of 375816198.

I will be performing the initial diagnostics and if able to fix will place a pull request.

If you need to see the object, please email me directly to manabu (at) wingumd.com. Though object is sanitized, I will play it safe as it is an actual acquired object.

Code Extension

Initially reported in Google Groups by Mariusz Kowalski on July 10, 2015:

Hi,

I need to test some DICOM files with Japanese characters where code extension is used.
Is fo-dicom doesn't support such cases or do I do something wrong?

I've attached some sample file:

Specific Character Set (0008,0005) \ISO 2022 IR 13\ISO 2022 IR 87

When I open it with DICOM Dump tags where Japanese characters are used are wrong:
Patient's Name, Patient ID, Patient Comments, Additional Patient History

How can I fix it myself or maybe it will be fixed with next release?

Thanks,
Mariusz

Improved memory leak prevention in Dicom.Imaging.Codec.Jpeg.i

Hi everyone!

I thought it would be best to enable the Issues tab as well, to facilitate the logging of fixes and enhancements. I hope everyone is OK with this.

Here is one issue that I want to bring up right away, as it concerns some code that you recently improved, @hdesouky . Please have a look, everyone and tell me what you think; am I drawing the right conclusions?


Regarding Dicom.Imaging.Codec.Jpeg.i, line 508 and above:

... wouldn't it be even safer to move the declaration of frameArray to the outer scope (before try) and place the delete in the finally block instead, like this:

PinnedByteArray^ frameArray = nullptr;
try {
  ...
  frameArray = gcnew PinnedByteArray(frameSize);
  ...
}
finally {
  if (frameArray != nullptr) {
    delete frameArray;
    frameArray = nullptr;
  }
  ...
}

If I am not mistaken, this will ensure that frameArray gets properly cleaned up even if an exception occurs in the latter part of the try block.

Update DICOM dictionary

The dictionaries of DICOM tags, UID:s etc. are outdated. The current DICOM Dictionary.xml file relates to DICOM Standard 2011.

Dictionaries should be updated to reflect the most recent DICOM standard.

Color32.B getter returns incorrect value

Looking at the complete implementation of ARGB getters and setters in the Color32 struct, it is evident that the B getter is incorrectly implemented.

For correctness, the B getter should be implemented as such:

get { return (byte)unchecked(Value & 0x000000ff); }

Wiki

Are we happy to start putting documentation into the GitHub wiki? It seems to be the canonical place for it. Any particular preference for structure or can we just let it grow organically?

I'd like to see a section for "successful integrations" where we can talk about the various bits of equipment with which we've interfaced and any issues that arose.

Another section for fo-DICOM developers to explain the source would be good (as suggested by @anders9ustafsson in #19 around the changes proposed for logging).

Finally, a section for end-users would be good too. It could include a quick "getting started". I know for me, getting started with DICOM was initially intimidating but getting some quick wins where I could grab a dicom file from a machine, extract its images and the patient's name made me realise this wasn't too hard after all :)

Any other thoughts before we start fleshing out the wiki?

Prepare NuGet specification files for 1.1.0 release

In the 1.1.0 release, the NLog dependency has been removed from the DICOM assembly.

My personal view is that we should release three separate NuGet packages:

  • fo-dicom
  • fo-dicom.NLog
  • fo-dicom.SeriLog

where fo-dicom has no dependencies, and the two latter packages have dependencies against fo-dicom and their respective logging framework.

In the 1.0.x releases of fo-dicom the Dump and Compare applications have also been included. In the 1.1.0 release I would like to omit these applications, so that the NuGet package only contains the DICOM.dll and the native codec assemblies.

What are your views on this?

Add logging support for MetroLog

MetroLog is a logging framework with close resemblance to NLog. The main advantage with MetroLog is that it is available as a Portable Class Library, capable of targeting various platforms such as .NET 4.5 and higher, Windows 8.1, Windows Phone 8.1, Windows Universal (Win 10) and even Xamarin.iOS and Xamarin.Android.

It would be a welcome addition to add a separate logging support library for MetroLog, similar to fo-dicom.NLog and fo-dicom.Serilog.

Problem to parse a specific Dicom file

Originally reported by Gustavo Saita as issue cureos/fo-dicom#6, but applies to desktop fo-dicom as well. Here is excerpt from conversation:

Gustavo, Aug 29, 2014:

I'm using it, and I figured out a problem to open a specific Dicom file.
I'm trying to use DicomFile.Open, but it never returns the DicomFile. :(
I've tried to find the problem but I didn't have success until now.
I noted that OnDatasetParseComplete never reaches.

I'm sharing with you the file.
Note that I change the extension to jpg just to upload the file here. (Please, rename it to .dcm if you want)

Any idea what could be the problem? Please, let me know if you have any news!

Anders, Aug 29, 2014:

I will try to have a look at this as soon as possible. For the time being, is this the only file you are having problems with? Which platform are you targeting, Windows 8 or Windows Phone?

Gustavo, Aug 29, 2014:

I've already tested hundreds of series of many patients of many modalities and until now I had no problem at all, except with this specific patient. All images of all series of this kind of patient have the same problem. I thought that was a problem in those files, so I tried to open with some Dicom viewers, but it opened normally.

Currently I'm working with Windows 8 App.
Another detail is that neither exception was fired too in any func of DicomFile.cs or DicomReader.cs.

Anders, Aug 6, 2015

I have come so far as to note that parsing goes into an infinite loop when/after parsing tag (2005,143e). The parser recognizes that a milestone has been reached, and thereafter gets trapped in a loop. Testing on other viewers, it appears like these viewers discards the item with this specific tag?

C++/CLI libraries are targeting .NET 4.5 but lib and sample apps are targeting .NET 4.0

With the solution upgrade to VS 2013, the platform toolset for the two C++/CLI projects DICOM [Native] and DICOM [Native64] was automatically updated to v120, which corresponds to .NET Framework 4.5.

The C# projects (class library and sample apps) are still targeting .NET Framework 4.0, which leads to warnings like these when building sample applications:

C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets(1697,5): warning MSB3274: The primary reference "...\fo-dicom\DICOM [Native]\x64..\Debug\Dicom.Native64.dll" could not be resolved because it was built against the ".NETFramework,Version=v4.5" framework. This is a higher version than the currently targeted framework ".NETFramework,Version=v4.0,Profile=Client".

For consistency, we should either:

  • Downgrade the platform toolset for the C++/CLI projects to v110 (.NET 4.0) or lower, or
  • Upgrade the C# libraries and sample applications to .NET 4.5.

@hdesouky @GMZ @IanYates and other interested parties: what are your recommendations?

Prefer encoding UTF8 over ASCII for increased portability

When porting .NET Framework libraries to Portable Class Libraries, or for that matter Windows 8 (desktop/tablet) and Windows Phone libraries or applications, one often occurring issue is the use of Encoding.ASCII or ASCIIEncoding. This property and class, respectively, are not supported in PCL and the modern platforms. To work around this issue, I have consistently switched over to UTF8 encoding, of which ASCII is a subset.

I have examined the source code in this repository, and UTF8 has been used in most places. Right now there is only one occurrence that would be a conflict if/when porting to PCL and the modern platforms, and it is this line in PDU.cs:

_encoding = Encoding.ASCII;

If you all approve, I would to change this line to:

_encoding = Encoding.UTF8;

Make this repository the base fork of fo-dicom

To help other users finding the "right" fork of fo-dicom, we should find a way to turn this fork into the base fork of fo-dicom.

I have been searching around, but I have not been able to find any instructions on how to reliably change the base fork, especially when there are many sub-forks like in our case.

But here's what I think we need to do to make the base fork switch happen:

  1. Make the current owner of the base fork, @petnet, member of the fo-dicom organization so that he/she can transfer the ownership of the base fork to the organization.
  2. Change the name of the organization's fo-dicom repository (Github does not seem to support ownership transfer if the new owner already has a repo with the same name), for example into fo-dicom-transfer.
  3. @petnet transfers the ownership of his/her fo-dicom fork to the fo-dicom organization.
  4. Merge the commits of fo-dicom-transfer into the new fo-dicom repo, preferably via git rebase.
  5. Remove the fo-dicom-transfer repo.

The side effects I can think of with this approach is that

a) Github users who have already forked fo-dicom/fo-dicom will lose their forks. But these users only need to re-fork, right?
b) We will lose the issue reports made so far to this repo. They will need to be manually transferred to the new repo.

Any thoughts or comments about this? One showstopper is of course to get hold of user @petnet. I am working on that right now.

Explicit VR file parsing failures due to strictness

Parsing of a DICOM file with Explicit Value Representation fail due to missing fall-back behavior when VR is not present for a specific element.

In principle, an omitted VR in an Explicit VR file is invalid, but for maximum usability it is desirable that parsing has a fall-back behavior to handle this scenario as well.

A subsequent problem is reported in issue #42, where parsing of an Explicit VR file fails for a private DICOM tag where VR is not specified and value length is set to undefined. A file illustrating this problem is available here.

Enable configuration of default encoding in the DicomDatasetReaderObserver

As discussed in PR #45, there may be parsing scenarios where the DICOM dataset encoding is not given by the Specific Character Set element, but is still known to be something other than _fo-dicom_´s default encoding, i.e. ASCII.

To reliably enable re-configuration of the encoding used during DICOM dataset parsing, it should be possible to explicitly set the fallback encoding in the DicomDatasetReaderObserver class.

Investigate GitLink

I came across this today: https://github.com/GitTools/GitLink - it allows end users of the library to step through the fo-dicom source when debugging without the need for us to upload symbols anywhere.

It seems fairly straightforward to integrate although I haven't had a good play with it yet.

Opinions, thoughts, etc - express them here :)

Add specific DICOM element classes for new OD, UC and UR value representations

As part of the update to DICOM Standard 2015b/c, three new value representations were introduced, OD, UC and UR. Implement specific DICOM element classes for these value representations, and initialize these objects when the new VRs are encountered in the DicomDatasetReaderObserver.OnElement and DicomDataset.Add<T> methods.

[Nuget] Native binaries are not copied into output folder when fo-dicom package is referenced using Nuget

Description:
Native binaries are not copied into output folder when fo-dicom package is referenced using Nuget.

Steps to reproduce:

  • Create a project and add fo-dicom using nuget
  • Compile the project with x64 or x86 platforms
  • Expected output: native dependencies will be found in the out put folder
  • Actual output: native dependencies are missing. they are added only as references during compilation phase

Version
1.1.0

Warning messages during build

There are a number of warning messages, primarily in C/C++ code, during build of the fo-dicom solution, see e.g. here.

These warning messages need to be reviewed and to largest possible extent removed by modifying the corresponding code.

Improved installation support for DICOM [Native*] libraries

One of the most recurring issues on the Google Groups forum is that the DICOM [Native*] (codec) libraries are not properly recognized when invoking the DICOM library.

I don't have any clear answers on what needs to be done (or even if something needs to be done), but I think it will be good for the user experience of fo-dicom if the usage of the DICOM [Native*] libraries would be more fail-safe.

Perhaps installation via the NuGet package can be improved? It is not entirely straightforward, but it is possible to have conditional installment of NuGet packages based on CPU architecture, see here for example.

Please share your thoughts on this.

Inconsistent handling of Get<T> default values for specific element types

In DICOMElement.cs, the abstract base class DicomElement implements a Get method with the following signature:

public abstract T Get<T>(int item = -1);

Some of the other classes deriving from DicomElement (both abstract and instantiatable), implements the Get method with a different default value, for example:

public abstract class DicomValueElement<Tv> : DicomElement where Tv: struct {
  public override T Get<T>(int item = 0) { ... }
}
...
public class DicomUnsignedShort : DicomValueElement<ushort> {
  public override T Get<T>(int item = 0) { ... }
}

This leads to inconsistent behavior when DicomUnsignedShort represents an array of ushort:s and the Get method is invoked with a default value:

DicomUnsignedShort elem1 = new DicomUnsignedShort(DicomTag.xxx, 1, 2, 3, 4);
DicomElement elem2 = new DicomUnsignedShort(DicomTag.xxx, 5, 6, 7, 8);
...
var firstItem1 = elem1.Get<ushort>();    // OK, default value for DicomUnsignedShort object is 0
var firstItem2 = elem2.Get<ushort>();    // ArgumentOutOfRangeException, default value for DicomElement object is -1

A review of the Get implementations in DicomElement.cs is required to avoid out-of-range exceptions caused by incorrectly handled default values.

Unit test framework?

I personally find the MSTest framework, that fo-dicom uses for its unit tests, rather limited. Furthermore, there are no real signs that the MSTest framework is actively being developed and extended, either.

Therefore, I am thinking it would be productive to switch to another unit test framework.

The one that comes immediately to mind for me is NUnit which I have a large experience with myself.

Another one is xUnit which has the additional benefit that it also supports a large number of non-.NET platforms such as Windows 8 (tablet/desktop), Windows Phone, Xamarin Android and Xamarin iOS. (In my cureos fork of fo-dicom I am actually using xUnit myself, thanks to a very much appreciated contribution from @rickardraysearch.)

There are very few unit tests in fo-dicom right now, so now is a good time to switch unit test framework if we want to. Do we? Everyone, please share your thoughts.

fo-dicom NuGet package should NOT add text files to project

The following text files are currently bundled with the fo-dicom NuGet package and will be added to the project installing fo-dicom from NuGet:

License.txt
README.md
ChangeLog.md

These text files tend to clutter the project contents, and may also conflict with already existing files in the project. Recommendation is therefore to exclude these files from the fo-dicom NuGet package.

Binding Redirect possibly required

I finally got around to using the NuGet package in my web application and have spent a little while trying to get things working properly around codec loading.

I was getting a reflection type load exception where the loader error property of that exception indicated that Dicom.dll version 1.0.0.39 couldn't be find. That's true - Dicom.dll is now at 1.1.0.0.

Adding

      <dependentAssembly>
        <assemblyIdentity name="Dicom" publicKeyToken="3a13f649e28eb09a" />
        <bindingRedirect oldVersion="0.0.0.0-1.1.0.0" newVersion="1.1.0.0"/>
      </dependentAssembly>

to my web.config solved that issue.

Many NuGet packages try to add this binding redirect automatically. Should we think of doing the same? (I'm not sure how this is done - probably some PowerShell?). If not then I'll at least add this to the wiki.

Happy to hear thoughts of others

NuGet package name for NLog support

I suggest we rename the NLog package for fo-dicom. If you search in NuGet for fellow oak, only the main package and the Serilog support appear.
capture

That's because the NLog package is named differently. Searching for dicom finds the main package, Serilog support and the NLog support
capture

The package Id itself can remain as is, as it's consistent with the other packages. Thoughts?

Add log4net logging support

Looking at NuGet statistics, the log4net framework is currently about twice as popular as NLog. To facilitate fo-dicom usage for log4net users, it would be a welcome addition to provide a Dicom.log4net connector with fo-dicom.

API documentation

When building fo-dicom in Release mode, there are thousands of build warnings due to missing API documentation.

The API documentation for public methods and properties should be made as complete as possible.

Remove redundant solution platform "Mixed platforms"

Right now, the DICOM.sln solution file contains two platforms with identical configurations, Any CPU and Mixed platforms.

For increased maintainability, I suggest that we remove Mixed platforms from the solution.

Sign logging assemblies?

The main DICOM assembly is currently signed with the fo-dicom.snk key, whereas the DICOM.NLog and DICOM.Serilog assemblies are not. For consistency, I would recommend that all distributable assemblies are signed. It should suffice to use the same .snk file for all assemblies.

Mono support

We should have clear support for Mono, and hence for either Linux and OS X. Do we have already something like that?
I am to start a big project and I need to put some components in Linux-server and OS X-client, besides Windows. I would love to use fo-dicom across all them.
In Linux environments, I see very fuzzy descriptions about how to compile native libraries, but probably we may only provide a single way to compile, let's say, for an intel-64 CPU with a specific compiler. I think that will cover a big percentage of use-cases.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.