2

I successfully compiled DCMTK and used in the Xcode project on macOS 10.15. I can read/decompress JPEG images, but I am not able to read some DICOM files.

Using DicomImage *di = new DicomImage(dfile, xfer , CIF_UsePartialAccessToPixelData, 0,1); returns nil image. Reading dataset->findAndGetUint16(DCM_Rows, rows) returns 0 (for rows or columns), reading pixel data returns 0....

Checking file with dcmdump returns correct data:

# Dicom-File-Format

# Dicom-Meta-Information-Header
# Used TransferSyntax: Unknown Transfer Syntax

# Dicom-Data-Set
# Used TransferSyntax: Little Endian Implicit
(0008,0008) CS [DERIVED\PRIMARY\OTHER]                  #  22, 3 ImageType
(0008,0014) UI [1.2.840.113701.4.1.6653]                #  24, 1 InstanceCreatorUID
(0008,0016) UI =MRImageStorage                          #  26, 1 SOPClassUID
(0008,0018) UI [1.2.840.113701.4.1.6653.3.264.4.9.6.0]  #  38, 1 SOPInstanceUID
---
(0008,0070) LO [Toshiba]                                #   8, 1 Manufacturer
(0008,0080) LO [TOSHIBA Nasu Works. Bay-6653.]          #  30, 1 CompanyName
(0008,1010) SH [FLEXART]                                #   8, 1 StationName
---
(0008,1090) LO [MRT150]                                 #   6, 1 ManufacturerModelName
(0010,0010) PN [GGGGGG^WWWWW]                           #  12, 1 ComponentName
(0010,0020) LO [TMS04]                                  #   6, 1 ComponentIDNumber
(0010,0030) DA [19000100]                               #   8, 1 ComponentManufacturingDate
(0010,0032) TM [000000]                                 #   6, 1 PatientBirthTime
(0010,0040) CS [F]                                      #   2, 1 PatientSex
(0010,1030) DS [79.000000]                              #  10, 1 PatientWeight
---
(0020,0052) UI [1.2.840.113701.4.1.1.1]                 #  22, 1 FrameOfReferenceUID
(0020,4000) LT (no value available)                     #   0, 0 ImageComments
(0028,0002) US 1                                        #   2, 1 SamplesPerPixel
(0028,0004) CS [MONOCHROME2]                            #  12, 1 PhotometricInterpretation
(0028,0010) US 512                                      #   2, 1 Rows
(0028,0011) US 512                                      #   2, 1 Columns
(0028,0030) DS [0.000312\0.000312]                      #  18, 2 PixelSpacing
(0028,0100) US 16                                       #   2, 1 BitsAllocated
(0028,0101) US 16                                       #   2, 1 BitsStored
(0028,0102) US 15                                       #   2, 1 HighBit
(0028,0103) US 0                                        #   2, 1 PixelRepresentation
(0028,0106) US 3                                        #   2, 1 SmallestImagePixelValue
(0028,0107) US 1030                                     #   2, 1 LargestImagePixelValue
(7fe0,0010) OW 8064\8064\8064\8064\8064\8064\8064\8064\8064\8064\8064\8064\8064... # 524288, 1 PixelData

I tried to force dataset to use EXS_LittleEndianExplicit as dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL).bad() but it returns true (unsuccessful).

I have no idea what could be wrong. All DCMTK libraries and apps seem to be compiled correctly, my code is written in Objective-C++ so I can call DCMTK functions without problems. I hope I don't need to write a custom parser. I tried to open the file in Osiri, Miele, Horos.. all imported and displayed image correctly.

I really appreciate any idea... thank you.

Amit Joshi
  • 15,448
  • 21
  • 77
  • 141
Jared
  • 130
  • 1
  • 7
  • What is the return value of findAndGetUint16()? Did you make sure that the data dictionary is loaded? You could (and actually should) check this with dcmDataDict.isDictionaryLoaded(). – J. Riesmeier Oct 19 '20 at 07:37
  • Alternatively, you could check what di->getStatus() returns. – J. Riesmeier Oct 19 '20 at 07:45
  • dcmDataDict.isDictionaryLoaded() returns 'true' di->getStatus() == EIS_Normal returns 'false' – Jared Oct 19 '20 at 09:39
  • This is one of the files: https://www.dropbox.com/s/iybj5or8vx3dfw3/badunc.dcm?dl=0 – Jared Oct 19 '20 at 09:45
  • It looks as if you have loaded the DICOM dictionary instead of the DICOM dictionary. In DICOM (0010,0010) is PatientName, In DICONDE it is ComponentName – Markus Sabin Oct 19 '20 at 10:28
  • using dcm2pnm on that file exports correct Portable Bitmap Format image. So, there is definitely a bug in my code. – Jared Oct 19 '20 at 10:31
  • loading DICONDE.dic instead of DICOM.dic didn't help. I suppose that for this test I can load only DICONDE.dic, not both. Anyway, DcmTagKey for DCM_Rows is identical in DICOM.dic and DICONDE.dic, so I suppose this is not the problem why I can't read rows or columns... – Jared Oct 19 '20 at 11:00
  • What a mistake... I didn't load dicom.dic.... Why? I suppose this is a default dictionary, that is loaded automatically. I checked all available examples and didn't find a code that loads it explicitly... I am sorry for taking your time :-( – Jared Oct 19 '20 at 11:09
  • ..anyway, how is it possible then that I could load other types of .dcm images without 'dicom.dic' loaded? – Jared Oct 19 '20 at 11:13
  • It is a popular misconception that .dcm stands for DICOM. This is kind of an industry standard, but it has nothing to do with DICOM. The only way to safely determine whether you have a DICOM file or not is checking the preamble – Markus Sabin Oct 19 '20 at 13:47
  • @Jared The DICOM data dictionary "dicom.dic" is loaded by default if the file is stored in the default directory (which is usually the case after calling "make install", e.g. in "/usr/local/share/dcmtk/"). As always, more details can be found in the documentation: https://support.dcmtk.org/docs/file_datadict.html – J. Riesmeier Oct 19 '20 at 13:58
  • @Jared Your sample file (available via dropbox) is not a valid DICOM file but a DICOM dataset (with implicit VR encoding) stored as a file. Anyway, the tool dcm2pnm is able to process it and render the stored pixel data so the DicomImage Class should also be able to do so. – J. Riesmeier Oct 19 '20 at 14:03
  • @Jared You say:"dcmDataDict.isDictionaryLoaded() returns 'true'". Then a data dictionary is loaded, hopefully the standard "dicom.dic" file from the DCMTK. You also say: "di->getStatus() == EIS_Normal returns 'false'". My question was: what is the return value of getStatus(), not whether this method returns EIS_Normal ;-) – J. Riesmeier Oct 19 '20 at 14:20
  • 1
    Excuse my incomplete answer: di->getStatus() returns "EIS_MissingAttribute" when I load "private.dic" only. When "dicom.dic" is loaded, everything works as expected. – Jared Oct 20 '20 at 07:49
  • Thank you for the feedback. The DICOM data dictionary "dicom.dic" is needed for the DCMTK, e.g. in order to process and render a DICOM image. Therefore, it is loaded by default (see above), which does not seem to be the case in your environment. You should either built the data dictionary into your binary (see above referenced "datadict.txt") or make sure that it is available from the expected path (see DCM_DICT_DEFAULT_PATH in "osconfig.h"). As I said, the "dicom.dic" is usually found and loaded automatically when installing the DCMTK with "make install". – J. Riesmeier Oct 20 '20 at 07:57
  • Yes, I fixed that. Thank you again to point me in the right direction. Now I can display almost everything (J2k is the last I have to implement). However, I would like to ask you to give me a short explanation of how to deal with windowing and Hounsfield units. Is there any flag I can use to check if stored data values are in the HU or I just have to check BitsAllocated, BitsStored, and HighBit? Is getInterData() the function that returns normalized data (8bits per pixel after min-max window is applied?). Is DicomImage::setWindow() the function I should use to set my own WWWL? Thank you. – Jared Oct 21 '20 at 08:29
  • The value of the Rescale Type (0028,1054)​ element indicates whether the Pixel Data after the Modality LUT transformation (Rescale Slope/Intercept) is stored in Hounsfield Units (HU) or not (e.g. "US" for unspecified). For the other questions, I would rather recommend to consult the public DCMTK discussion forum. – J. Riesmeier Oct 21 '20 at 09:36

1 Answers1

1

Typical mistakes with DCMTK if compression handling does not work:

  1. Forgot to compile with JPEG support (this is an option you can set in CMake
  2. Forgot to initialize the Codecs

Initializing the codecs simpily works by

DJDecoderRegistration::registerCodecs(); 
DJEncoderRegistration::registerCodecs();

...but have a look at the parameters of these methods which you might set differently from the defaults.

Markus Sabin
  • 3,916
  • 14
  • 32
  • I tried all these. Result still the same: DcmRLEDecoderRegistration::registerCodecs(OFFalse, OFFalse); DJDecoderRegistration::registerCodecs(EDC_guess, EUC_default, EPC_default, OFFalse); DJLSDecoderRegistration::registerCodecs(); And, I can decode files with JPEG compression. I can't decode only some of the files from my test set, which seems to be uncompressed (EXS_LittleEndianExplicit). – Jared Oct 19 '20 at 09:41
  • Image compression is not relevant since the sample image is not compressed. – J. Riesmeier Oct 19 '20 at 14:04
  • I read some posts where somebody said that some manufacturers don't follow DICOM specs and compressed image data in their files has EXS_LittleEndianExplicit transfer syntax. I thought this might be the case, so I tried also decode the data. – Jared Oct 20 '20 at 07:56