From 1d7f7845726ab0b4e4630575f629a554d5707576 Mon Sep 17 00:00:00 2001 From: frog Date: Mon, 7 Apr 2003 15:04:37 +0000 Subject: [PATCH] Brutal commit. Changelog to come.... Frog --- ChangeLog | 3 + gdcmPython/testSuite.py | 1009 ++++++++++++++++++++------------------- src/gdcm.h | 17 - src/gdcmDict.cxx | 52 +- src/gdcmElValSet.cxx | 388 ++++++--------- src/gdcmElValSet.h | 21 +- src/gdcmFile.cxx | 15 +- src/gdcmFile.h | 2 + src/gdcmHeader.cxx | 178 +++---- src/gdcmHeader.h | 13 +- 10 files changed, 817 insertions(+), 881 deletions(-) diff --git a/ChangeLog b/ChangeLog index 157a564c..801ece7f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2003-04-7 Eric Boix with JPR + * Data/im_00001 renamed to gdcm-MR-PHILIPS-16-Multi-Seq.dcm + 2003-03-31 Eric Boix * src/gdcmHeader.h: LoadElements() is not a public method anymore (to avoid double call by end user). diff --git a/gdcmPython/testSuite.py b/gdcmPython/testSuite.py index 28edf766..06ad408d 100644 --- a/gdcmPython/testSuite.py +++ b/gdcmPython/testSuite.py @@ -3,502 +3,535 @@ import os from gdcmPython import * class gdcmTestCase(unittest.TestCase): - # The files whose name starts with a modality (e.g. CR-MONO1-10-chest.dcm) - # come from Sebastien Barre's Dicom2 highly recommendable site - # http://www.barre.nom.fr/medical/samples/index.html - BarreFiles = [ - #################################### - # CR modality examples: - #################################### - ["CR-MONO1-10-chest.dcm", - [ ["Modality", "CR"], - #"Transfer Syntax UID" is absent. - ["Rows", "440"], - ["Columns", "440"], - ["Bits Stored", "10"], - ["Bits Allocated", "16"], - ["High Bit", "9"], - ["Pixel Representation", "0"], - ["Manufacturer", "FUJI PHOTO FILM CO. LTD."], - ["Manufacturer Model Name", "9000"], - ["7fe0|0010", "gdcm::NotLoaded. Address:776 Length:387200"] ] ], - #################################### - # CT modality examples: - #################################### - ["CT-MONO2-16-brain.dcm", - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # Explicit VR, LE - ["Modality", "CT"], - ["Rows", "512"], - ["Columns", "512"], - ["Bits Stored", "16"], - ["Bits Allocated", "16"], - ["High Bit", "15"], - ["Pixel Representation", "1"], - ["Manufacturer", "Picker International, Inc."], - ["Manufacturer Model Name", "PQ5000"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1680 Length:524288"] ] ], - ["CT-MONO2-16-ort.dcm", - [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit VR, LE - ["Modality", "CT"], - ["Rows", "512"], - ["Columns", "512"], - ["Bits Stored", "16"], - ["Bits Allocated", "16"], - ["High Bit", "15"], - ["Pixel Representation", "1"], - ["Manufacturer", "GE MEDICAL SYSTEMS"], - ["Manufacturer Model Name", "HiSpeed CT/i"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1674 Length:524288"] ] ], - ["CT-MONO2-16-ankle.dcm", - [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit, little - ["Modality", "CT"], - ["Rows", "512"], - ["Columns", "512"], - ["Bits Stored", "16"], - ["Bits Allocated", "16"], - ["High Bit", "15"], - ["Pixel Representation", "1"], - ["Manufacturer", "GE MEDICAL SYSTEMS"], - ["Manufacturer Model Name", "GENESIS_ZEUS"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1148 Length:524288"] ] ], - ["CT-MONO2-8-abdo.dcm", - [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit, little - ["Modality", "CT"], - ["Rows", "512"], - ["Columns", "512"], - ["Bits Stored", "8"], - ["Bits Allocated", "8"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["Manufacturer", "FUJI"], - ["7fe0|0010", "gdcm::NotLoaded. Address:796 Length:262144"] ] ], - ["CT-MONO2-12-lomb-an2.acr2", - [ ["Modality", "CT"], - #"Transfer Syntax UID" and "Photometric Interpretation" are absent. - ["Rows", "512"], - ["Columns", "512"], - ["Bits Stored", "12"], - ["Bits Allocated", "16"], - ["High Bit", "11"], - ["Pixel Representation", "0"], - ["Manufacturer", "SIEMENS"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1230 Length:524288"] ] ], - ["CT-MONO2-16-chest.dcm", - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.70"], # jpeg... - ["Modality", "CT"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "400"], - ["Columns", "512"], - ["Bits Stored", "16"], - ["Bits Allocated", "16"], - ["High Bit", "15"], - ["Pixel Representation", "1"], - ["Manufacturer", "GE MEDICAL SYSTEMS"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1638 Length:143498"] ] ], - #################################### - ### MR modality examples: - #################################### - ["MR-MONO2-12-angio-an1.acr1", - [ ["Recognition Code", "ACR-NEMA 1.0"], - ["Modality", "MR"], - #"Transfer Syntax UID" and "Photometric Interpretation" are absent. - ["Rows", "256"], - ["Columns", "256"], - ["Bits Stored", "12"], - ["Bits Allocated", "12"], - ["High Bit", "11"], - ["Pixel Representation", "0"], - ["Manufacturer", "Philips"], - # Note: 256*256*12/8 = 98304 - ["7fe0|0010", "gdcm::NotLoaded. Address:650 Length:98304"] ] ], - ["MR-MONO2-12-an2.acr2", - [ ["Modality", "MR"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "256"], - ["Columns", "256"], - ["Bits Stored", "12"], - ["Bits Allocated", "16"], - ["High Bit", "11"], - ["Pixel Representation", "0"], - ["Manufacturer", "SIEMENS"], - ["Manufacturer Model Name", "MAGNETOM VISION"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1866 Length:131072"] ] ], - ["MR-MONO2-16-head.dcm", - [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Imp VR, LE - ["Modality", "MR"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "256"], - ["Columns", "256"], - ["Bits Stored", "16"], - ["Bits Allocated", "16"], - ["High Bit", "15"], - ["Pixel Representation", "1"], - ["Manufacturer", "GE MEDICAL SYSTEMS"], - ["Manufacturer Model Name", "GENESIS_SIGNA"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1804 Length:131072"] ] ], - # MR-MONO2-12-shoulder example is present in the Jpeg section. - # MR-MONO2-16-knee is not present in the test suite since it is too - # closely related to MR-MONO2-16-head.dcm to be of interest. - #################################### - # OT modality examples: - #################################### - # OT-MONO2-8-hip is not present in the test suite since it is too - # closely related to OT-MONO2-8-a7 to be of interest. - ["OT-PAL-8-face.dcm", - # Interest: has a color palette - [#"Transfer Syntax UID", and "Manufacturer" are absent. - ["Modality", "OT"], - ["Photometric Interpretation", "PALETTE COLOR"], - ["Rows", "480"], - ["Columns", "640"], - ["Bits Stored", "8"], - ["Bits Allocated", "8"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1654 Length:307200"] ] ], - # OT-MONO2-8-colon is not present in the test suite since it is too - # closely related to OT-MONO2-8-a7 to be of interest. - ["OT-MONO2-8-a7.dcm", - [#"Transfer Syntax UID" is absent. - ["Modality", "OT"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "512"], - ["Columns", "512"], - ["Bits Stored", "8"], - ["Bits Allocated", "8"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["Manufacturer", "Philips Medical Systems"], - ["7fe0|0010", "gdcm::NotLoaded. Address:438 Length:262144"] ] ], - #################################### - # US (Ultra Sound) modality examples: - #################################### - ["US-RGB-8-esopecho.dcm", - # Interest: RGB image - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # Exp VR, LE - ["Modality", "US"], - ["Photometric Interpretation", "RGB"], - ["Rows", "120"], - ["Columns", "256"], - ["Bits Stored", "8"], - ["Bits Allocated", "8"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["Manufacturer", "Acme Products"], - # FIXME: 92160 / (120*256) = 3 bytes per pixel NOT 1. Maybe - # it has something to do with [Samples Per Pixel] = [3] ??? - ["7fe0|0010", "gdcm::NotLoaded. Address:904 Length:92160"] ] ], - ["US-RGB-8-epicard.dcm", - # Interest: Big endian transfert syntax - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.2"], # Big endian - ["Modality", "US"], - ["Photometric Interpretation", "RGB"], - ["Rows", "480"], - ["Columns", "640"], - ["Bits Stored", "8"], - ["Bits Allocated", "8"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["Manufacturer", "G.E. Medical Systems"], - ["Manufacturer Model Name", "LOGIQ 700"], - # FIXME: 921600/(480*640) = 3 bytes per pixel NOT 1. Maybe - # it has something to do with [Samples Per Pixel] = [3] ??? - ["Implementation Version Name", "OFFIS-DCMTK-311"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1012 Length:921600"] ] ], - ] + # The files whose name starts with a modality (e.g. CR-MONO1-10-chest.dcm) + # come from Sebastien Barre's Dicom2 highly recommendable site + # http://www.barre.nom.fr/medical/samples/index.html + BarreFiles = [ + #################################### + # CR modality examples: + #################################### + ["CR-MONO1-10-chest.dcm", + [ ["Modality", "CR"], + #"Transfer Syntax UID" is absent. + ["Rows", "440"], + ["Columns", "440"], + ["Bits Stored", "10"], + ["Bits Allocated", "16"], + ["High Bit", "9"], + ["Pixel Representation", "0"], + ["Manufacturer", "FUJI PHOTO FILM CO. LTD."], + ["Manufacturer Model Name", "9000"], + ["7fe0|0010", "gdcm::NotLoaded. Address:776 Length:387200"] ] ], + #################################### + # CT modality examples: + #################################### + ["CT-MONO2-16-brain.dcm", + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # Explicit VR, LE + ["Modality", "CT"], + ["Rows", "512"], + ["Columns", "512"], + ["Bits Stored", "16"], + ["Bits Allocated", "16"], + ["High Bit", "15"], + ["Pixel Representation", "1"], + ["Manufacturer", "Picker International, Inc."], + ["Manufacturer Model Name", "PQ5000"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1680 Length:524288"] ] ], + ["CT-MONO2-16-ort.dcm", + [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit VR, LE + ["Modality", "CT"], + ["Rows", "512"], + ["Columns", "512"], + ["Bits Stored", "16"], + ["Bits Allocated", "16"], + ["High Bit", "15"], + ["Pixel Representation", "1"], + ["Manufacturer", "GE MEDICAL SYSTEMS"], + ["Manufacturer Model Name", "HiSpeed CT/i"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1674 Length:524288"] ] ], + ["CT-MONO2-16-ankle.dcm", + [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit, little + ["Modality", "CT"], + ["Rows", "512"], + ["Columns", "512"], + ["Bits Stored", "16"], + ["Bits Allocated", "16"], + ["High Bit", "15"], + ["Pixel Representation", "1"], + ["Manufacturer", "GE MEDICAL SYSTEMS"], + ["Manufacturer Model Name", "GENESIS_ZEUS"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1148 Length:524288"] ] ], + ["CT-MONO2-8-abdo.dcm", + [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit, little + ["Modality", "CT"], + ["Rows", "512"], + ["Columns", "512"], + ["Bits Stored", "8"], + ["Bits Allocated", "8"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["Manufacturer", "FUJI"], + ["7fe0|0010", "gdcm::NotLoaded. Address:796 Length:262144"] ] ], + ["CT-MONO2-12-lomb-an2.acr2", + [ ["Modality", "CT"], + #"Transfer Syntax UID" and "Photometric Interpretation" are absent. + ["Rows", "512"], + ["Columns", "512"], + ["Bits Stored", "12"], + ["Bits Allocated", "16"], + ["High Bit", "11"], + ["Pixel Representation", "0"], + ["Manufacturer", "SIEMENS"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1230 Length:524288"] ] ], + ["CT-MONO2-16-chest.dcm", + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.70"], # jpeg... + ["Modality", "CT"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "400"], + ["Columns", "512"], + ["Bits Stored", "16"], + ["Bits Allocated", "16"], + ["High Bit", "15"], + ["Pixel Representation", "1"], + ["Manufacturer", "GE MEDICAL SYSTEMS"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1638 Length:143498"] ] ], + #################################### + ### MR modality examples: + #################################### + ["MR-MONO2-12-angio-an1.acr1", + [ ["Recognition Code", "ACR-NEMA 1.0"], + ["Modality", "MR"], + #"Transfer Syntax UID" and "Photometric Interpretation" are absent. + ["Rows", "256"], + ["Columns", "256"], + ["Bits Stored", "12"], + ["Bits Allocated", "12"], + ["High Bit", "11"], + ["Pixel Representation", "0"], + ["Manufacturer", "Philips"], + # Note: 256*256*12/8 = 98304 + ["7fe0|0010", "gdcm::NotLoaded. Address:650 Length:98304"] ] ], + ["MR-MONO2-12-an2.acr2", + [ ["Modality", "MR"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "256"], + ["Columns", "256"], + ["Bits Stored", "12"], + ["Bits Allocated", "16"], + ["High Bit", "11"], + ["Pixel Representation", "0"], + ["Manufacturer", "SIEMENS"], + ["Manufacturer Model Name", "MAGNETOM VISION"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1866 Length:131072"] ] ], + ["MR-MONO2-16-head.dcm", + [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Imp VR, LE + ["Modality", "MR"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "256"], + ["Columns", "256"], + ["Bits Stored", "16"], + ["Bits Allocated", "16"], + ["High Bit", "15"], + ["Pixel Representation", "1"], + ["Manufacturer", "GE MEDICAL SYSTEMS"], + ["Manufacturer Model Name", "GENESIS_SIGNA"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1804 Length:131072"] ] ], + # MR-MONO2-12-shoulder example is present in the Jpeg section. + # MR-MONO2-16-knee is not present in the test suite since it is too + # closely related to MR-MONO2-16-head.dcm to be of interest. + #################################### + # OT modality examples: + #################################### + # OT-MONO2-8-hip is not present in the test suite since it is too + # closely related to OT-MONO2-8-a7 to be of interest. + ["OT-PAL-8-face.dcm", + # Interest: has a color palette + [#"Transfer Syntax UID", and "Manufacturer" are absent. + ["Modality", "OT"], + ["Photometric Interpretation", "PALETTE COLOR"], + ["Rows", "480"], + ["Columns", "640"], + ["Bits Stored", "8"], + ["Bits Allocated", "8"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1654 Length:307200"] ] ], + # OT-MONO2-8-colon is not present in the test suite since it is too + # closely related to OT-MONO2-8-a7 to be of interest. + ["OT-MONO2-8-a7.dcm", + [#"Transfer Syntax UID" is absent. + ["Modality", "OT"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "512"], + ["Columns", "512"], + ["Bits Stored", "8"], + ["Bits Allocated", "8"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["Manufacturer", "Philips Medical Systems"], + ["7fe0|0010", "gdcm::NotLoaded. Address:438 Length:262144"] ] ], + #################################### + # US (Ultra Sound) modality examples: + #################################### + ["US-RGB-8-esopecho.dcm", + # Interest: RGB image + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # Exp VR, LE + ["Modality", "US"], + ["Photometric Interpretation", "RGB"], + ["Rows", "120"], + ["Columns", "256"], + ["Bits Stored", "8"], + ["Bits Allocated", "8"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["Manufacturer", "Acme Products"], + # FIXME: 92160 / (120*256) = 3 bytes per pixel NOT 1. Maybe + # it has something to do with [Samples Per Pixel] = [3] ??? + ["7fe0|0010", "gdcm::NotLoaded. Address:904 Length:92160"] ] ], + ["US-RGB-8-epicard.dcm", + # Interest: Big endian transfert syntax + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.2"], # Big endian + ["Modality", "US"], + ["Photometric Interpretation", "RGB"], + ["Rows", "480"], + ["Columns", "640"], + ["Bits Stored", "8"], + ["Bits Allocated", "8"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["Manufacturer", "G.E. Medical Systems"], + ["Manufacturer Model Name", "LOGIQ 700"], + # FIXME: 921600/(480*640) = 3 bytes per pixel NOT 1. Maybe + # it has something to do with [Samples Per Pixel] = [3] ??? + ["Implementation Version Name", "OFFIS-DCMTK-311"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1012 Length:921600"] ] ], + ] - MultiFrameFiles = [ - # The number of images is contained in the "Number of Frames" element - ["MR-MONO2-8-16x-heart.dcm", - # Interest: multi-frame - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # ExpVR, LE - ["Number of Frames", "16"], - ["Modality", "MR"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "256"], - ["Columns", "256"], - ["Bits Stored", "8"], - ["Bits Allocated", "8"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["Manufacturer", "Philips"], - # Note: 256*256*16=1048576 (16 is the number of Frames) - ["7fe0|0010", "gdcm::NotLoaded. Address:920 Length:1048576"] ] ], - ["NM-MONO2-16-13x-heart.dcm", - # Interest: NM modality, multi-frame - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # ExpVR, LE - ["Number of Frames", "13"], - ["Modality", "NM"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "64"], - ["Columns", "64"], - ["Bits Stored", "16"], - ["Bits Allocated", "16"], - ["High Bit", "15"], - ["Pixel Representation", "0"], - ["Manufacturer", "ACME Products"], - # Note: 64*64*13*2=106496 - ["7fe0|0010", "gdcm::NotLoaded. Address:1234 Length:106496"] ] ], - ["US-MONO2-8-8x-execho.dcm", - # Interest: multi-frame - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # ExpVR, LE - ["Number of Frames", "8"], - ["Modality", "US"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "120"], - ["Columns", "128"], - ["Bits Stored", "8"], - ["Bits Allocated", "8"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["Manufacturer", "Acme Products"], - ["7fe0|0010", "gdcm::NotLoaded. Address:976 Length:122880"] ] ], - ["US-PAL-8-10x-echo.dcm", - # Interest: RLE (Run Length Encoded) compression, multiframe - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.5"], # RLE - ["Number of Frames", "10"], - ["Modality", "US"], - ["Photometric Interpretation", "PALETTE COLOR"], - ["Rows", "430"], - ["Columns", "600"], - ["Bits Stored", "8"], - ["Bits Allocated", "8"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["Manufacturer", "ACME Products"], - ["7fe0|0010", "gdcm::NotLoaded. Address:2428 Length:481182"] ] ], - ["XA-MONO2-8-12x-catheter.dcm", - # Interest: XA modality, multi-frame - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.70"], # jpeg - ["Number of Frames", "12"], # 12 images - ["Modality", "XA"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "512"], - ["Columns", "512"], - ["Bits Stored", "8"], - ["Bits Allocated", "8"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["Manufacturer", "Acme Products"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1006 Length:920072"] ] ], - ] + MultiFrameFiles = [ + # The number of images is contained in the "Number of Frames" element + ["MR-MONO2-8-16x-heart.dcm", + # Interest: multi-frame + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # ExpVR, LE + ["Number of Frames", "16"], + ["Modality", "MR"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "256"], + ["Columns", "256"], + ["Bits Stored", "8"], + ["Bits Allocated", "8"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["Manufacturer", "Philips"], + # Note: 256*256*16=1048576 (16 is the number of Frames) + ["7fe0|0010", "gdcm::NotLoaded. Address:920 Length:1048576"] ] ], + ["NM-MONO2-16-13x-heart.dcm", + # Interest: NM modality, multi-frame + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # ExpVR, LE + ["Number of Frames", "13"], + ["Modality", "NM"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "64"], + ["Columns", "64"], + ["Bits Stored", "16"], + ["Bits Allocated", "16"], + ["High Bit", "15"], + ["Pixel Representation", "0"], + ["Manufacturer", "ACME Products"], + # Note: 64*64*13*2=106496 + ["7fe0|0010", "gdcm::NotLoaded. Address:1234 Length:106496"] ] ], + ["US-MONO2-8-8x-execho.dcm", + # Interest: multi-frame + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # ExpVR, LE + ["Number of Frames", "8"], + ["Modality", "US"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "120"], + ["Columns", "128"], + ["Bits Stored", "8"], + ["Bits Allocated", "8"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["Manufacturer", "Acme Products"], + ["7fe0|0010", "gdcm::NotLoaded. Address:976 Length:122880"] ] ], + ["US-PAL-8-10x-echo.dcm", + # Interest: RLE (Run Length Encoded) compression, multiframe + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.5"], # RLE + ["Number of Frames", "10"], + ["Modality", "US"], + ["Photometric Interpretation", "PALETTE COLOR"], + ["Rows", "430"], + ["Columns", "600"], + ["Bits Stored", "8"], + ["Bits Allocated", "8"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["Manufacturer", "ACME Products"], + ["7fe0|0010", "gdcm::NotLoaded. Address:2428 Length:481182"] ] ], + ["XA-MONO2-8-12x-catheter.dcm", + # Interest: XA modality, multi-frame + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.70"], # jpeg + ["Number of Frames", "12"], # 12 images + ["Modality", "XA"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "512"], + ["Columns", "512"], + ["Bits Stored", "8"], + ["Bits Allocated", "8"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["Manufacturer", "Acme Products"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1006 Length:920072"] ] ], + ] - GdcmFiles = [ - ["gdcm-MR-SIEMENS-16.acr1", - # Interest: good old Acr-Nema Version 1, see also Oddities below - [ ["Recognition Code", "ACR-NEMA 1.0"], - ["Modality", "MR"], - ["Rows", "256"], - ["Columns", "256"], - ["Bits Stored", "12"], - ["Bits Allocated", "16"], - ["High Bit", "11"], - ["Pixel Representation", "0"], - ["Manufacturer", "SIEMENS"], - ["Manufacturer Model Name", "GBS III"], - # FIXME: this image looks padded at the end. The length of the file - # is 140288. Notice that, 256*256*2 + 1024 = 131072 + 1024 = 132096 - ["7fe0|0010", "gdcm::NotLoaded. Address:8192 Length:132096"], - # Oddities: "Study ID" and "Series Number" are empty - ["Study ID", ""], - ["Series Number", ""] ] ], - # Oddities: "Study" and "Serie Instance UID" are not present - ["gdcm-MR-SIEMENS-16.acr2", - # Interest: Acr-Nema Version 2 - [ ["Recognition Code", "ACR-NEMA 2.0"], - ["Modality", "MR"], - ["Rows", "512"], - ["Columns", "512"], - ["Bits Stored", "12"], - ["Bits Allocated", "16"], - ["High Bit", "11"], - ["Pixel Representation", "0"], - ["Manufacturer", "SIEMENS"], - ["Manufacturer Model Name", "MAGNETOM VISION"], - ["Study Instance UID", - "1.3.12.2.1107.5.2.4.7630.20000918174641000"], - ["Study ID", "1"], - ["Series Instance UID", - "1.3.12.2.1107.5.2.4.7630.20000918175714000007"], - ["Series Number", "7"], - ["7fe0|0010", "gdcm::NotLoaded. Address:6052 Length:524288"] ] ], - ["gdcm-US-ALOKA-16.dcm", - # Interest: - possesses 3 LUTS: a Green (checked), a Red and BLue. - # - announced as implicit VR, but really explicit VR. - [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit VR, LE - ["Modality", "US"], - ["Photometric Interpretation", "PALETTE COLOR"], - ["Segmented Green Palette Color LUT Data", - "gdcm::NotLoaded. Address:89576 Length:113784"], - ["Rows", "480"], - ["Columns", "640"], - ["Bits Stored", "16"], - ["Bits Allocated", "16"], - ["High Bit", "15"], - ["Pixel Representation", "0"], - ["Manufacturer", "ALOKA CO., LTD."], - ["Manufacturer Model Name", "SSD-4000"], - ["7fe0|0010", "gdcm::NotLoaded. Address:258740 Length:614400"] ] ], - ["gdcm-MR-PHILIPS-16.dcm", - # Interest: - possesses a sequence - # - dicom file, with a recognition code of ACR-NEMA1 - [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit VR, LE - ["Recognition Code", "ACR-NEMA 1.0"], - ["Modality", "MR"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "256"], - ["Columns", "256"], - ["Bits Stored", "8"], - ["Bits Allocated", "16"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["Manufacturer", "Philips Medical Systems"], - ["Manufacturer Model Name", "Gyroscan Intera"], - ["Sequence Variant", "OTHER"], - ["7fe0|0010", "gdcm::NotLoaded. Address:6584 Length:131072"] ] ], - ["gdcm-MR-PHILIPS-16-NonRectPix.dcm", - # Interest: - pixels are non rectangular - # - private elements are in explicit VR (which is normal) - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # Explicit VR, LE - ["Modality", "MR"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "64"], - ["Columns", "160"], - ["Bits Stored", "12"], - ["Bits Allocated", "16"], - ["High Bit", "11"], - ["Pixel Representation", "0"], - ["Manufacturer", "Philips Medical Systems"], - ["Manufacturer Model Name", "Gyroscan Intera"], - ["Pixel Spacing", "0.487416\\0.194966"], - ["7fe0|0010", "gdcm::NotLoaded. Address:5010 Length:20480"] ] ], - ["gdcm-CR-DCMTK-16-NonSamplePerPix.dcm", - # Interest: - Misses the "Samples Per Pixel" element which prevents - # e-film from reading it. - # - Misses the Manufacturer related info - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # Explicit VR, LE - ["Modality", "CR"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "750"], - ["Columns", "750"], - ["Bits Stored", "8"], - ["Bits Allocated", "8"], - ["High Bit", "7"], - ["Pixel Representation", "0"], - ["Implementation Version Name", "OFFIS_DCMTK_341"], - ["7fe0|0010", "gdcm::NotLoaded. Address:740 Length:562500"] ] ], - ] + GdcmFiles = [ + ["gdcm-MR-SIEMENS-16.acr1", + # Interest: good old Acr-Nema Version 1, see also Oddities below + [ ["Recognition Code", "ACR-NEMA 1.0"], + ["Modality", "MR"], + ["Rows", "256"], + ["Columns", "256"], + ["Bits Stored", "12"], + ["Bits Allocated", "16"], + ["High Bit", "11"], + ["Pixel Representation", "0"], + ["Manufacturer", "SIEMENS"], + ["Manufacturer Model Name", "GBS III"], + # FIXME: this image looks padded at the end. The length of the file + # is 140288. Notice that, 256*256*2 + 1024 = 131072 + 1024 = 132096 + ["7fe0|0010", "gdcm::NotLoaded. Address:8192 Length:132096"], + # Oddities: "Study ID" and "Series Number" are empty + ["Study ID", ""], + ["Series Number", ""] ] ], + # Oddities: "Study" and "Serie Instance UID" are not present + ["gdcm-MR-SIEMENS-16.acr2", + # Interest: Acr-Nema Version 2 + [ ["Recognition Code", "ACR-NEMA 2.0"], + ["Modality", "MR"], + ["Rows", "512"], + ["Columns", "512"], + ["Bits Stored", "12"], + ["Bits Allocated", "16"], + ["High Bit", "11"], + ["Pixel Representation", "0"], + ["Manufacturer", "SIEMENS"], + ["Manufacturer Model Name", "MAGNETOM VISION"], + ["Study Instance UID", + "1.3.12.2.1107.5.2.4.7630.20000918174641000"], + ["Study ID", "1"], + ["Series Instance UID", + "1.3.12.2.1107.5.2.4.7630.20000918175714000007"], + ["Series Number", "7"], + ["7fe0|0010", "gdcm::NotLoaded. Address:6052 Length:524288"] ] ], + ["gdcm-US-ALOKA-16.dcm", + # Interest: - possesses 3 LUTS: a Green (checked), a Red and BLue. + # - announced as implicit VR, but really explicit VR. + [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit VR, LE + ["Modality", "US"], + ["Photometric Interpretation", "PALETTE COLOR"], + ["Segmented Green Palette Color LUT Data", + "gdcm::NotLoaded. Address:89576 Length:113784"], + ["Rows", "480"], + ["Columns", "640"], + ["Bits Stored", "16"], + ["Bits Allocated", "16"], + ["High Bit", "15"], + ["Pixel Representation", "0"], + ["Manufacturer", "ALOKA CO., LTD."], + ["Manufacturer Model Name", "SSD-4000"], + ["7fe0|0010", "gdcm::NotLoaded. Address:258740 Length:614400"] ] ], + ["gdcm-MR-PHILIPS-16.dcm", + # Interest: - possesses a sequence + # - dicom file, with a recognition code of ACR-NEMA1 + [ ["Transfer Syntax UID", "1.2.840.10008.1.2"], # Implicit VR, LE + ["Recognition Code", "ACR-NEMA 1.0"], + ["Modality", "MR"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "256"], + ["Columns", "256"], + ["Bits Stored", "8"], + ["Bits Allocated", "16"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["Manufacturer", "Philips Medical Systems"], + ["Manufacturer Model Name", "Gyroscan Intera"], + ["Sequence Variant", "OTHER"], + ["7fe0|0010", "gdcm::NotLoaded. Address:6584 Length:131072"] ] ], + ["gdcm-MR-PHILIPS-16-Multi-Seq.dcm", + # Interest: - possesses many sequences in group 0x0029 + # - Big sequence 28808 bytes at (0x0029, 0x263d) + # - dicom file, with a recognition code of ACR-NEMA1 + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], + ["Recognition Code", "ACR-NEMA 1.0"], + ["Modality", "MR"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "128"], + ["Columns", "128"], + ["Bits Stored", "12"], + ["Bits Allocated", "16"], + ["High Bit", "11"], + ["Pixel Representation", "0"], + ["Manufacturer", "Philips Medical Systems"], + ["Manufacturer Model Name", "Gyroscan Intera"], + ["Sequence Variant", "OTHER"], + ["7fe0|0010", "gdcm::NotLoaded. Address:35846 Length:32768"] ] ], + ["gdcm-MR-PHILIPS-16-NonRectPix.dcm", + # Interest: - pixels are non rectangular + # - private elements are in explicit VR (which is normal) + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # Explicit VR, LE + ["Modality", "MR"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "64"], + ["Columns", "160"], + ["Bits Stored", "12"], + ["Bits Allocated", "16"], + ["High Bit", "11"], + ["Pixel Representation", "0"], + ["Manufacturer", "Philips Medical Systems"], + ["Manufacturer Model Name", "Gyroscan Intera"], + ["Pixel Spacing", "0.487416\\0.194966"], + ["7fe0|0010", "gdcm::NotLoaded. Address:5010 Length:20480"] ] ], + ["gdcm-CR-DCMTK-16-NonSamplePerPix.dcm", + # Interest: - Misses the "Samples Per Pixel" element which prevents + # e-film from reading it. + # - Misses the Manufacturer related info + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.1"], # Explicit VR, LE + ["Modality", "CR"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "750"], + ["Columns", "750"], + ["Bits Stored", "8"], + ["Bits Allocated", "8"], + ["High Bit", "7"], + ["Pixel Representation", "0"], + ["Implementation Version Name", "OFFIS_DCMTK_341"], + ["7fe0|0010", "gdcm::NotLoaded. Address:740 Length:562500"] ] ], + ] - GdcmJpegFiles = [ - ["gdcm-JPEG-Extended.dcm", - # Interest: Jpeg compression [Extended (2,4)] - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.51"], - ["Modality", "CT"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "512"], - ["Columns", "512"], - ["Bits Stored", "12"], - ["Bits Allocated", "16"], - ["High Bit", "11"], - ["Pixel Representation", "0"], - ["Manufacturer", "SIEMENS"], - ["Manufacturer Model Name", "Volume Zoom"], - ["7fe0|0010", "gdcm::NotLoaded. Address:2946 Length:192218"] ] ], - ["MR-MONO2-12-shoulder.dcm", - # Interest: Jpeg compression [Lossless, non-hierar. (14)] - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.57"], - ["Modality", "MR"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "1024"], - ["Columns", "1024"], - ["Bits Stored", "12"], - ["Bits Allocated", "16"], - ["High Bit", "11"], - ["Pixel Representation", "0"], - ["Manufacturer", "Philips Medical Systems"], - ["Manufacturer Model Name", "Gyroscan NT"], - ["7fe0|0010", "gdcm::NotLoaded. Address:1580 Length:718948"] ] ], - ["gdcm-JPEG-LossLess3a.dcm", - # Interest: - Jpeg compression [Lossless, hierar., first-order - # pred. 14, Select. Val. 1] - # - contains a sequence [circa (0008,2112)] - # - contains additional data after the pixels ??? - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.70"], - ["Modality", "CT"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "512"], - ["Columns", "512"], - ["Bits Stored", "12"], - ["Bits Allocated", "16"], - ["High Bit", "11"], - ["Pixel Representation", "0"], - ["Manufacturer", "SIEMENS"], - ["Manufacturer Model Name", "Volume Zoom"] ] ], - # FIXME: the pixel data looks like corrupted. As stated by "od -A d -c" - # 0002528 à 177 020 \0 O B \0 \0 ÿ ÿ ÿ ÿ þ ÿ \0 à - # 0002544 \0 \0 \0 \0 þ ÿ \0 à 202 ? 003 \0 ÿ Ø ÿ Ã - # which we interpret as follows: - # - 2528: (à 177, 020 \0) = (0x7fe0, 0x0010) i.e. Pixel Data tag, - # - 2532: OB i.e. encapsulated encoded Pixel Data, - # - 2534: Two bytes reserved, - # - 2536: ÿ ÿ ÿ ÿ = 0xffffffff i.e. data element length is undefined. - # - 2540: (þ ÿ, \0 à) = (0xfffe, 0xe000) i.e. basic offset table - # item tag - # - 2544: \0 \0 \0 \0 i.e. offset table as length zero, i.e. no - # item value for offset table. - # - 2548: (þ ÿ, \0 à) = (0xfffe, 0xe000) i.e. item tag of first - # fragment of (encoded) pixel data. - # - 2552: 202 ? 003 \0 = 212866 bytes i.e. length of first fragment - # of (encoded) pixel data. - # and so the next item tag should be found at the 2556+212866 th - # octet i.e. at address 215422. But, as stated by od, we find: - # 0215408 E u Ö 026 Î É 7 ¬ Ã ¸ ó ¿ ÿ Ù \f ° - # 0215424 ¶ 016 P Ñ 002 016 - # and (\f °, ¶ 016) is NOT an OB item TAG which is required to be - # present (at least there should be a sequence delimiter), refer to - # PS 3.5-2001 page 50. - ["gdcm-JPEG-LossLess3b.dcm", - # Interest: - Jpeg compression [Lossless, hierar., first-order - # pred. 14, Select. Val. 1] - # - encoding is sligthly different from LossLess3a.dcm ??? - [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.70"], - ["Modality", "CR"], - ["Photometric Interpretation", "MONOCHROME2"], - ["Rows", "2076"], - ["Columns", "1876"], - ["Bits Stored", "15"], - ["Bits Allocated", "16"], - ["High Bit", "14"], - ["Pixel Representation", "0"], - ["Manufacturer", "Philips Medical Systems"], - ["Manufacturer Model Name", "Cassette Holder Type 9840 500 35201"], - ["7fe0|0010", "gdcm::NotLoaded. Address:3144 Length:4795668"] ] ], - ] + GdcmJpegFiles = [ + ["gdcm-JPEG-Extended.dcm", + # Interest: Jpeg compression [Extended (2,4)] + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.51"], + ["Modality", "CT"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "512"], + ["Columns", "512"], + ["Bits Stored", "12"], + ["Bits Allocated", "16"], + ["High Bit", "11"], + ["Pixel Representation", "0"], + ["Manufacturer", "SIEMENS"], + ["Manufacturer Model Name", "Volume Zoom"], + ["7fe0|0010", "gdcm::NotLoaded. Address:2946 Length:192218"] ] ], + ["MR-MONO2-12-shoulder.dcm", + # Interest: Jpeg compression [Lossless, non-hierar. (14)] + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.57"], + ["Modality", "MR"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "1024"], + ["Columns", "1024"], + ["Bits Stored", "12"], + ["Bits Allocated", "16"], + ["High Bit", "11"], + ["Pixel Representation", "0"], + ["Manufacturer", "Philips Medical Systems"], + ["Manufacturer Model Name", "Gyroscan NT"], + ["7fe0|0010", "gdcm::NotLoaded. Address:1580 Length:718948"] ] ], + ["gdcm-JPEG-LossLess3a.dcm", + # Interest: - Jpeg compression [Lossless, hierar., first-order + # pred. 14, Select. Val. 1] + # - contains a sequence [circa (0008,2112)] + # - contains additional data after the pixels ??? + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.70"], + ["Modality", "CT"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "512"], + ["Columns", "512"], + ["Bits Stored", "12"], + ["Bits Allocated", "16"], + ["High Bit", "11"], + ["Pixel Representation", "0"], + ["Manufacturer", "SIEMENS"], + ["Manufacturer Model Name", "Volume Zoom"] ] ], + # FIXME: the pixel data looks like corrupted. As stated by "od -A d -c" + # 0002528 à 177 020 \0 O B \0 \0 ÿ ÿ ÿ ÿ þ ÿ \0 à + # 0002544 \0 \0 \0 \0 þ ÿ \0 à 202 ? 003 \0 ÿ Ø ÿ Ã + # which we interpret as follows: + # - 2528: (à 177, 020 \0) = (0x7fe0, 0x0010) i.e. Pixel Data tag, + # - 2532: OB i.e. encapsulated encoded Pixel Data, + # - 2534: Two bytes reserved, + # - 2536: ÿ ÿ ÿ ÿ = 0xffffffff i.e. data element length is undefined. + # - 2540: (þ ÿ, \0 à) = (0xfffe, 0xe000) i.e. basic offset table + # item tag + # - 2544: \0 \0 \0 \0 i.e. offset table as length zero, i.e. no + # item value for offset table. + # - 2548: (þ ÿ, \0 à) = (0xfffe, 0xe000) i.e. item tag of first + # fragment of (encoded) pixel data. + # - 2552: 202 ? 003 \0 = 212866 bytes i.e. length of first fragment + # of (encoded) pixel data. + # and so the next item tag should be found at the 2556+212866 th + # octet i.e. at address 215422. But, as stated by od, we find: + # 0215408 E u Ö 026 Î É 7 ¬ Ã ¸ ó ¿ ÿ Ù \f ° + # 0215424 ¶ 016 P Ñ 002 016 + # and (\f °, ¶ 016) is NOT an OB item TAG which is required to be + # present (at least there should be a sequence delimiter), refer to + # PS 3.5-2001 page 50. + ["gdcm-JPEG-LossLess3b.dcm", + # Interest: - Jpeg compression [Lossless, hierar., first-order + # pred. 14, Select. Val. 1] + # - encoding is sligthly different from LossLess3a.dcm ??? + [ ["Transfer Syntax UID", "1.2.840.10008.1.2.4.70"], + ["Modality", "CR"], + ["Photometric Interpretation", "MONOCHROME2"], + ["Rows", "2076"], + ["Columns", "1876"], + ["Bits Stored", "15"], + ["Bits Allocated", "16"], + ["High Bit", "14"], + ["Pixel Representation", "0"], + ["Manufacturer", "Philips Medical Systems"], + ["Manufacturer Model Name", "Cassette Holder Type 9840 500 35201"], + ["7fe0|0010", "gdcm::NotLoaded. Address:3144 Length:4795668"] ] ], + ] - def _BaseTest(self, FileSet): - for entry in FileSet: - fileName = os.path.join(GDCM_DATA_PATH, entry[0]) - toRead = gdcmHeader(fileName) - valDict = toRead.GetPubElVal() - for subEntry in entry[1]: - element = subEntry[0] - value = subEntry[1] - self.assertEqual(valDict[element], value, - ("Wrong %s for file %s (got %s, shoud be %s)" - % (element,fileName, valDict[element], value)) ) + def _BaseTest(self, FileSet): + for entry in FileSet: + fileName = os.path.join(GDCM_DATA_PATH, entry[0]) + toRead = gdcmHeader(fileName) + valDict = toRead.GetPubElVal() + for subEntry in entry[1]: + element = subEntry[0] + value = subEntry[1] + self.assertEqual(valDict[element], value, + ("Wrong %s for file %s (got %s, shoud be %s)" + % (element,fileName, valDict[element], value)) ) - def testBarre(self): - gdcmTestCase._BaseTest(self, gdcmTestCase.BarreFiles) + def testBarre(self): + gdcmTestCase._BaseTest(self, gdcmTestCase.BarreFiles) - def testMultiFram(self): - gdcmTestCase._BaseTest(self, gdcmTestCase.MultiFrameFiles) + def testMultiFram(self): + gdcmTestCase._BaseTest(self, gdcmTestCase.MultiFrameFiles) - def testFiles(self): - gdcmTestCase._BaseTest(self, gdcmTestCase.GdcmFiles) + def testFiles(self): + gdcmTestCase._BaseTest(self, gdcmTestCase.GdcmFiles) - def testJpeg(self): - gdcmTestCase._BaseTest(self, gdcmTestCase.GdcmJpegFiles) + def testJpeg(self): + gdcmTestCase._BaseTest(self, gdcmTestCase.GdcmJpegFiles) + + def testWrite(self): + import md5 + SourceFileName = os.path.join(GDCM_DATA_PATH, + 'gdcm-MR-PHILIPS-16-Multi-Seq.dcm') + Source = gdcmFile(SourceFileName); + Source.GetImageData() + TargetFileName = "junk" + Target = Source.WriteDcm(TargetFileName) + Sign = 'c7d6bedae1bef3851f35b29952fbbd4b' + ComputeSign = md5.new(open(TargetFileName).read()).hexdigest() + #print ComputeSign + self.assertEqual(ComputeSign, Sign, + ("Wrong signature for file %s (got %s, shoud be %s)" + % (SourceFileName, ComputeSign, Sign)) ) if __name__ == '__main__': - unittest.main() + unittest.main() diff --git a/src/gdcm.h b/src/gdcm.h index 03fde1e8..802f5ed0 100644 --- a/src/gdcm.h +++ b/src/gdcm.h @@ -3,23 +3,6 @@ #ifndef GDCM_H #define GDCM_H -//using namespace std; - -// JPR CLEAN -// En fait, je disais que dans LE Directory Dicom (dans son etat 2001) -// il y a +/- 1600 entrees. -// Une valeur raisonable pour un majorant du nombre d'entrees -// dans une entete DICOM d'une image semble semble etre 300 -// Si on 'decortique' les elements SQ (ce qui ne semble pas etre fait pour le moment) -// on risque en fait de depasser ... un nombre non previsible dans le cas d'une entree SQ -// contenant lui même un tres grand nombre d'entrees ?!?) -// Quant au nombre d'entrees dans un DICOMDIR, c'est encore pire : il n'est limité -// que par la taille d'un CD-ROM (les DVD-ROM ne sont pas encore pris en compte) -// On peut s'attendre a 30 entrees par fichier dicom présent sur le CD-ROM -// REMARQUE : il faudra se pencher sur le pb de la creation du DICOMDIR lorsqu'on voudra -// exporter des images lisibles par les consoles cliniques -// et pas seulement importables dans e-film. - //////////////////////////////////////////////////////////////////////////// // Tag based hash tables. // We shall use as keys the strings (as the C++ type) obtained by diff --git a/src/gdcmDict.cxx b/src/gdcmDict.cxx index 645dcf85..aae1daff 100644 --- a/src/gdcmDict.cxx +++ b/src/gdcmDict.cxx @@ -81,9 +81,6 @@ gdcmDictEntry * gdcmDict::GetTagByKey(guint16 group, guint16 element) { TagKey key = gdcmDictEntry::TranslateToKey(group, element); if ( ! KeyHt.count(key)) return (gdcmDictEntry*)0; - if (KeyHt.count(key) > 1) - dbg.Verbose(0, "gdcmDict::GetTagByName", - "multiple entries for this key (FIXME) !"); return KeyHt.find(key)->second; } @@ -96,63 +93,44 @@ gdcmDictEntry * gdcmDict::GetTagByKey(guint16 group, guint16 element) { gdcmDictEntry * gdcmDict::GetTagByName(TagName name) { if ( ! NameHt.count(name)) return (gdcmDictEntry*)0; - if (NameHt.count(name) > 1) - dbg.Verbose(0, "gdcmDict::GetTagByName", - "multiple entries for this key (FIXME) !"); return NameHt.find(name)->second; } - int gdcmDict::ReplaceEntry(gdcmDictEntry* NewEntry) { - //JPRCLEAN - // au cas ou la NewEntry serait incomplete - // Question : cela peut-il se produire ? - // - // --> NON : voir constructeur - //TagKey key; - //key = NewEntry->GetKey(); - //if (key =="") { - // NewEntry->gdcmDictEntry::SetKey( - // gdcmDictEntry::TranslateToKey(NewEntry->GetGroup(), NewEntry->GetElement()) - // ); - //} - - KeyHt.erase (NewEntry->gdcmDictEntry::GetKey()); - KeyHt[ NewEntry->GetKey()] = NewEntry; - return (1); - // Question(jpr): Dans quel cas ça peut planter ? - // Reponse(frog): dans les mauvais cas... + if ( RemoveEntry(NewEntry->gdcmDictEntry::GetKey()) ) { + KeyHt[ NewEntry->GetKey()] = NewEntry; + return (1); + } + return (0); } - int gdcmDict::AddNewEntry(gdcmDictEntry* NewEntry) { TagKey key; key = NewEntry->GetKey(); - if(KeyHt.count(key) >= 1) { + if(KeyHt.count(key) == 1) { dbg.Verbose(1, "gdcmDict::AddNewEntry allready present", key.c_str()); return(0); } else { KeyHt[NewEntry->GetKey()] = NewEntry; return(1); } - } +} -int gdcmDict::RemoveEntry(TagKey key) { - if(KeyHt.count(key) == 1) { - KeyHt.erase(key); - return (1); - } else { - dbg.Verbose(1, "gdcmDict::RemoveEntry unfound entry", key.c_str()); - return (0); - } +int gdcmDict::RemoveEntry(TagKey key) { + if(KeyHt.count(key) == 1) { + KeyHt.erase(key); + return (1); + } else { + dbg.Verbose(1, "gdcmDict::RemoveEntry unfound entry", key.c_str()); + return (0); + } } int gdcmDict::RemoveEntry (guint16 group, guint16 element) { - return( RemoveEntry(gdcmDictEntry::TranslateToKey(group, element)) ); } diff --git a/src/gdcmElValSet.cxx b/src/gdcmElValSet.cxx index 3dd24f1c..5cc9841c 100644 --- a/src/gdcmElValSet.cxx +++ b/src/gdcmElValSet.cxx @@ -40,93 +40,59 @@ void gdcmElValSet::PrintByName(ostream & os) { } } -gdcmElValue* gdcmElValSet::GetElementByNumber(guint32 group, guint32 element) { +gdcmElValue* gdcmElValSet::GetElementByNumber(guint16 group, guint16 element) { TagKey key = gdcmDictEntry::TranslateToKey(group, element); if ( ! tagHt.count(key)) return (gdcmElValue*)0; - if (tagHt.count(key) > 1) - dbg.Verbose(0, "gdcmElValSet::GetElementByNumber", - "multiple entries for this key (FIXME) !"); return tagHt.find(key)->second; } gdcmElValue* gdcmElValSet::GetElementByName(string TagName) { if ( ! NameHt.count(TagName)) return (gdcmElValue*)0; - if (NameHt.count(TagName) > 1) - dbg.Verbose(0, "gdcmElValSet::GetElement", - "multipe entries for this key (FIXME) !"); return NameHt.find(TagName)->second; } -string gdcmElValSet::GetElValueByNumber(guint32 group, guint32 element) { +string gdcmElValSet::GetElValueByNumber(guint16 group, guint16 element) { TagKey key = gdcmDictEntry::TranslateToKey(group, element); if ( ! tagHt.count(key)) return "gdcm::Unfound"; - if (tagHt.count(key) > 1) - dbg.Verbose(0, "gdcmElValSet::GetElValueByNumber", - "multiple entries for this key (FIXME) !"); return tagHt.find(key)->second->GetValue(); } string gdcmElValSet::GetElValueByName(string TagName) { if ( ! NameHt.count(TagName)) return "gdcm::Unfound"; - if (NameHt.count(TagName) > 1) - dbg.Verbose(0, "gdcmElValSet::GetElValue", - "multipe entries for this key (FIXME) !"); return NameHt.find(TagName)->second->GetValue(); } int gdcmElValSet::SetElValueByNumber(string content, - guint32 group, guint32 element) { - -// TODO : comprendre pourquoi ils sont déclares comme des guint32, alors que c'est des guint16 - + guint16 group, guint16 element) { TagKey key = gdcmDictEntry::TranslateToKey(group, element); if ( ! tagHt.count(key)) return 0; - if (tagHt.count(key) > 1) { - dbg.Verbose(0, "gdcmElValSet::SetElValueByNumber", - "multiple entries for this key (FIXME) !"); - return (0); - } - tagHt[key]->SetValue(content); - - // Question : m à j LgrElem ? - tagHt[key]->SetLength(strlen(content.c_str())); - - // FIXME should we really update the element length ? tagHt[key]->SetLength(content.length()); - - return(1); + return 1; } int gdcmElValSet::SetElValueByName(string content, string TagName) { if ( ! NameHt.count(TagName)) return 0; - if (NameHt.count(TagName) > 1) { - dbg.Verbose(0, "gdcmElValSet::SetElValueByName", - "multipe entries for this key (FIXME) !"); - return 0; - } - NameHt.find(TagName)->second->SetValue(content); - NameHt.find(TagName)->second->SetLength(strlen(content.c_str())); - return(1); + NameHt[TagName]->SetValue(content); + NameHt[TagName]->SetLength(content.length()); + return 1; } /** - * \ingroup gdcmElValSet - * \brief Generate a free TagKey i.e. a TagKey that is not present - * in the TagHt dictionary. One of the potential usage is - * to add gdcm generated additional informartion to the ElValSet - * (see gdcmHeader::AddAndDefaultElements). - * @param group The generated tag must belong to this group. - * @return The element of tag with given group which is fee. + * \ingroup gdcmElValSet + * \brief Generate a free TagKey i.e. a TagKey that is not present + * in the TagHt dictionary. + * @param group The generated tag must belong to this group. + * @return The element of tag with given group which is fee. */ -guint32 gdcmElValSet::GenerateFreeTagKeyInGroup(guint32 group) { +guint32 gdcmElValSet::GenerateFreeTagKeyInGroup(guint16 group) { for (guint32 elem = 0; elem < UINT32_MAX; elem++) { TagKey key = gdcmDictEntry::TranslateToKey(group, elem); if (tagHt.count(key) == 0) @@ -135,50 +101,24 @@ guint32 gdcmElValSet::GenerateFreeTagKeyInGroup(guint32 group) { return UINT32_MAX; } -int gdcmElValSet::SetElValueLengthByNumber(guint32 l, - guint32 group, guint32 element) { +int gdcmElValSet::SetElValueLengthByNumber(guint32 length, + guint16 group, guint16 element) { TagKey key = gdcmDictEntry::TranslateToKey(group, element); if ( ! tagHt.count(key)) return 0; - tagHt[key]->SetLength(l); + tagHt[key]->SetLength(length); return 1 ; } -int gdcmElValSet::SetElValueLengthByName(guint32 l, string TagName) { +int gdcmElValSet::SetElValueLengthByName(guint32 length, string TagName) { if ( ! NameHt.count(TagName)) return 0; - NameHt.find(TagName)->second->SetLength(l); + NameHt.find(TagName)->second->SetLength(length); return 1 ; } -// Sorry for the DEBUG's, but tomorow is gonna be hoter than today - -int gdcmElValSet::Write(FILE * _fp) { - - guint16 gr, el; - guint32 lgr; - const char * val; - string vr; - guint32 val_uint32; - guint16 val_uint16; - - vector tokens; - - void *ptr; - - string implicitVRTransfertSyntax = "1.2.840.10008.1.2"; - - // Utilisées pour le calcul Group Length - guint32 lgrCalcGroupe=0; - gdcmElValue *elem, *elemZ, *elemZPrec; - guint16 grCourant = 0; - - // Question : - // Comment pourrait-on tester si on est TrueDicom ou non , - // (FileType est un champ de gdcmHeader ...) - // - +void gdcmElValSet::UpdateGroupLength(bool SkipSequence) { // On parcourt la table pour recalculer la longueur des 'elements 0x0000' // au cas ou un tag ai été ajouté par rapport à ce qui a été lu // dans l'image native @@ -188,10 +128,12 @@ int gdcmElValSet::Write(FILE * _fp) { // On fait de l'implicit VR little Endian // (pour moins se fairche sur processeur INTEL) // On force le TRANSFERT SYNTAX UID + guint16 gr, el; + string vr; + guint32 lgrCalcGroupe=0; + gdcmElValue *elem, *elemZ, *elemZPrec; + guint16 grCourant = 0; - SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010); - SetElValueLengthByNumber(18, 0x0002, 0x0010); // Le 0 de fin de chaine doit etre stocké, dans ce cas - TagElValueHT::iterator tag = tagHt.begin(); elem = tag->second; @@ -219,7 +161,15 @@ int gdcmElValSet::Write(FILE * _fp) { elem = tag->second; gr = elem->GetGroup(); el = elem->GetElement(); - + vr = elem->GetVR(); + + if (SkipSequence && vr == "SQ") + // pas SEQUENCE en ACR-NEMA + // WARNING : risque de pb + // si on est descendu 'a l'interieur' des SQ + continue; + // + // if ( (gr != grCourant) /*&& // On arrive sur un nv Groupe (el != 0xfffe) */ ) { @@ -252,7 +202,113 @@ int gdcmElValSet::Write(FILE * _fp) { elem->GetLength(), el, lgrCalcGroupe, gr); } } +} + +void gdcmElValSet::WriteElements(FileType type, FILE * _fp) { + guint16 gr, el; + guint32 lgr; + const char * val; + string vr; + guint32 val_uint32; + guint16 val_uint16; + + vector tokens; + + void *ptr; + + for (TagElValueHT::iterator tag2 = tagHt.begin(); + tag2 != tagHt.end(); + ++tag2){ + + gr = tag2->second->GetGroup(); + el = tag2->second->GetElement(); + lgr = tag2->second->GetLength(); + val = tag2->second->GetValue().c_str(); + vr = tag2->second->GetVR(); + if(DEBUG)printf ("%04x %04x [%s] : [%s]\n",gr, el, vr.c_str(), val); + + if ( type == ACR ) { + if (gr < 0x0008) continue; + if (gr %2) continue; + if (vr == "SQ" ) continue; + } + + + fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group + fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element + + if ( (type == ExplicitVR) && (gr <= 0x0002) ) { + // On est en EXPLICIT VR + guint16 z=0, shortLgr; + fwrite (vr.c_str(),(size_t)2 ,(size_t)1 ,_fp); + + if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") ) { + fwrite ( &z, (size_t)2 ,(size_t)1 ,_fp); + fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); + + } else { + shortLgr=lgr; + fwrite ( &shortLgr,(size_t)2 ,(size_t)1 ,_fp); + } + } else { + fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); + } + + tokens.erase(tokens.begin(),tokens.end()); + Tokenize (tag2->second->GetValue(), tokens, "\\"); + + if (vr == "US" || vr == "SS") { + for (unsigned int i=0; i tokens; + + void *ptr; + + string implicitVRTransfertSyntax = "1.2.840.10008.1.2"; + SetElValueByNumber(implicitVRTransfertSyntax, 0x0002, 0x0010); + //FIXME Refer to standards on page 21, chapter 6.2 "Value representation": + // values with a VR of UI shall be padded with a single trailing null + // Dans le cas suivant on doit pader manuellement avec un 0. + SetElValueLengthByNumber(18, 0x0002, 0x0010); + + // Question : + // Comment pourrait-on tester si on est TrueDicom ou non , + // (FileType est un champ de gdcmHeader ...) + // + UpdateGroupLength(); + // restent à tester les echecs en écriture (apres chaque fwrite) for (TagElValueHT::iterator tag2 = tagHt.begin(); @@ -269,8 +325,6 @@ int gdcmElValSet::Write(FILE * _fp) { fwrite ( &gr,(size_t)2 ,(size_t)1 ,_fp); //group fwrite ( &el,(size_t)2 ,(size_t)1 ,_fp); //element - //fwrite ( vr,(size_t)2 ,(size_t)1 ,_fp); //VR - // si on n'est pas en IMPLICIT VR voir pb (lgr + VR) fwrite ( &lgr,(size_t)4 ,(size_t)1 ,_fp); //lgr @@ -278,8 +332,6 @@ int gdcmElValSet::Write(FILE * _fp) { tokens.erase(tokens.begin(),tokens.end()); Tokenize (tag2->second->GetValue(), tokens, "\\"); - //if (tokens.size() > 1) { printf ("size : %d\n",tokens.size());} - if (vr == "US" || vr == "SS") { for (unsigned int i=0; isecond; - gr = elem->GetGroup(); - el = elem->GetElement(); - - if (el != 0x0000) { - if(DEBUG)printf("ajout elem OOOO premiere fois\n"); - gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL"); - elemZPrec = new gdcmElValue(tagZ); // on le cree - elemZPrec->SetLength(4); - Add(elemZPrec); // On l'accroche à sa place - } else { - elemZPrec = elem; - if(DEBUG)printf("Pas d'ajout elem OOOO premiere fois\n"); - } - lgrCalcGroupe = 0; - if(DEBUG)printf("init-1 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr); - grCourant = gr; - - for (tag = ++tagHt.begin(); - tag != tagHt.end(); - ++tag){ - - elem = tag->second; - gr = elem->GetGroup(); - el = elem->GetElement(); - vr = elem->GetVR(); - - if (vr == "SQ") continue; // pas SEQUENCE en ACR-NEMA - // WARNING : risque de pb - // si on est descendu 'a l'interieur' des SQ - - if ( (gr != grCourant) /*&& // On arrive sur un nv Groupe - (el != 0xfffe) */ ) { - - if (el != 0x0000) { - gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL"); - elemZ = new gdcmElValue(tagZ); // on le cree - elemZ->SetLength(4); - Add(elemZ); // On l'accroche à sa place - if(DEBUG)printf("ajout elem OOOO pour gr %04x\n",gr); - } else { - elemZ=elem; - if(DEBUG)printf("maj elmeZ\n"); - } - - ostringstream f; - f << lgrCalcGroupe; - elemZPrec->SetValue(f.str()); - if(DEBUG)printf("ecriture lgr (%d, %s) pour gr %04x\n",lgrCalcGroupe, f.str().c_str(), grCourant); - if(DEBUG)printf ("%04x %04x [%s]\n",elemZPrec->GetGroup(), elemZPrec->GetElement(), - elemZPrec->GetValue().c_str()); - if(DEBUG)cout << "Addresse elemZPrec " << elemZPrec<< endl; - elemZPrec=elemZ; - lgrCalcGroupe = 0; - grCourant = gr; - if(DEBUG)printf("init-2 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr); - } else { // On n'EST PAS sur un nv Groupe - lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength(); // Gr + Num + Lgr + LgrElem - if(DEBUG)printf("increment (%d) el %04x-->lgr (%d) pour gr %04x\n",elem->GetLength(), el, - lgrCalcGroupe, gr); - } - } - // Si on fait de l'implicit VR little Endian // (pour moins se fairche sur processeur INTEL) // penser a forcer le TRANSFERT SYNTAX UID @@ -488,89 +473,24 @@ int gdcmElValSet::WriteExplVR(FILE * _fp) { string explicitVRTransfertSyntax = "1.2.840.10008.1.2.1"; - // Utilisées pour le calcul Group Length - guint32 lgrCalcGroupe=0; - gdcmElValue *elem, *elemZ, *elemZPrec; - guint16 grCourant = 0; // Question : // Comment pourrait-on tester si on est TrueDicom ou non , // (FileType est un champ de gdcmHeader ...) // - // On parcourt la table pour recalculer la longueur des 'elements 0x0000' - // au cas ou un tag ai été ajouté par rapport à ce qui a été lu - // dans l'image native - // - // cf : code IdDcmWriteFile dans libido/src/dcmwrite.c - - // On fait de l'Explicit VR little Endian SetElValueByNumber(explicitVRTransfertSyntax, 0x0002, 0x0010); SetElValueLengthByNumber(20, 0x0002, 0x0010); // Le 0 de fin de chaine doit etre stocké, dans ce cas // ??? - TagElValueHT::iterator tag = tagHt.begin(); - - elem = tag->second; - gr = elem->GetGroup(); - el = elem->GetElement(); - - if (el != 0x0000) { - if(DEBUG)printf("ajout elem OOOO premiere fois\n"); - gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL"); - elemZPrec = new gdcmElValue(tagZ); // on le cree - elemZPrec->SetLength(4); - Add(elemZPrec); // On l'accroche à sa place - } else { - elemZPrec = elem; - if(DEBUG)printf("Pas d'ajout elem OOOO premiere fois\n"); - } - lgrCalcGroupe = 0; - if(DEBUG)printf("init-1 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr); - grCourant = gr; - - for (tag = ++tagHt.begin(); - tag != tagHt.end(); - ++tag){ - - elem = tag->second; - gr = elem->GetGroup(); - el = elem->GetElement(); + // Question : + // Comment pourrait-on tester si on est TrueDicom ou non , + // (FileType est un champ de gdcmHeader ...) + // + UpdateGroupLength(); - if ( (gr != grCourant) /*&& // On arrive sur un nv Groupe - (el != 0xfffe) */ ) { - - if (el != 0x0000) { - gdcmDictEntry * tagZ = new gdcmDictEntry(gr, 0x0000, "UL"); - elemZ = new gdcmElValue(tagZ); // on le cree - elemZ->SetLength(4); - Add(elemZ); // On l'accroche à sa place - if(DEBUG)printf("ajout elem OOOO pour gr %04x\n",gr); - } else { - elemZ=elem; - if(DEBUG)printf("maj elemZ\n"); - } - - ostringstream f; - f << lgrCalcGroupe; - //sprintf(str_lgrCalcGroupe,"%d",lgrCalcGroupe); - elemZPrec->SetValue(f.str()); - if(DEBUG)printf("ecriture lgr (%d, %s) pour gr %04x\n",lgrCalcGroupe, f.str().c_str(), grCourant); - if(DEBUG)printf ("%04x %04x [%s]\n",elemZPrec->GetGroup(), elemZPrec->GetElement(), - elemZPrec->GetValue().c_str()); - if(DEBUG)cout << "Addresse elemZPrec " << elemZPrec<< endl; - elemZPrec=elemZ; - lgrCalcGroupe = 0; - grCourant = gr; - if(DEBUG)printf("init-2 lgr (%d) pour gr %04x\n",lgrCalcGroupe, gr); - } else { // On n'EST PAS sur un nv Groupe - lgrCalcGroupe += 2 + 2 + 4 + elem->GetLength(); // Gr + Num + Lgr + LgrElem - if(DEBUG)printf("increment (%d) el %04x-->lgr (%d) pour gr %04x\n",elem->GetLength(), - el, lgrCalcGroupe, gr); - } - } // restent à tester les echecs en écriture (apres chaque fwrite) diff --git a/src/gdcmElValSet.h b/src/gdcmElValSet.h index b2ff14c6..d5494a7d 100644 --- a/src/gdcmElValSet.h +++ b/src/gdcmElValSet.h @@ -1,4 +1,4 @@ -// $Header: /cvs/public/gdcm/src/Attic/gdcmElValSet.h,v 1.6 2003/04/01 14:07:40 jpr Exp $ +// $Header: /cvs/public/gdcm/src/Attic/gdcmElValSet.h,v 1.7 2003/04/07 15:04:40 frog Exp $ #ifndef GDCMELVALSET_H #define GDCMELVALSET_H @@ -16,6 +16,11 @@ typedef map TagElValueNameHT; class GDCM_EXPORT gdcmElValSet { TagElValueHT tagHt; // Both accesses with a TagKey or with a TagElValueNameHT NameHt; // the DictEntry.Name are required. +//FIXME This is redundant with gdcmHeader::FileType enum. That sux ! +enum FileType { + TrueDicom, + ExplicitVR, + ACR}; public: void Add(gdcmElValue*); // TODO @@ -26,20 +31,24 @@ public: int WriteAcr(FILE *fp); int WriteExplVR(FILE *fp); - gdcmElValue* GetElementByNumber(guint32 group, guint32 element); + gdcmElValue* GetElementByNumber(guint16 group, guint16 element); gdcmElValue* GetElementByName (string); - string GetElValueByNumber(guint32 group, guint32 element); + string GetElValueByNumber(guint16 group, guint16 element); string GetElValueByName (string); TagElValueHT & GetTagHt(void); - int SetElValueByNumber(string content, guint32 group, guint32 element); + int SetElValueByNumber(string content, guint16 group, guint16 element); int SetElValueByName (string content, string TagName); - int SetElValueLengthByNumber(guint32 l, guint32 group, guint32 element); + int SetElValueLengthByNumber(guint32 l, guint16 group, guint16 element); int SetElValueLengthByName (guint32 l, string TagName); + + guint32 GenerateFreeTagKeyInGroup(guint16 group); - guint32 GenerateFreeTagKeyInGroup(guint32 group); +private: + void UpdateGroupLength(bool SkipSequence = false); + void WriteElements(FileType type, FILE *); }; diff --git a/src/gdcmFile.cxx b/src/gdcmFile.cxx index 5ae6e8b7..f6cf79c9 100644 --- a/src/gdcmFile.cxx +++ b/src/gdcmFile.cxx @@ -27,9 +27,13 @@ gdcmFile::gdcmFile(string & filename) { } +gdcmFile::gdcmFile(const char * filename) + :gdcmHeader(filename) +{ +} + ///////////////////////////////////////////////////////////////// -// FIXME JPR: comments in English please ! /** * \ingroup gdcmFile * \brief Renvoie la longueur A ALLOUER pour recevoir les pixels de l'image @@ -397,16 +401,19 @@ int gdcmFile::WriteDcm (string nomFichier) { fclose (fp1); return(1); } + +int gdcmFile::WriteDcm (const char* nomFichier) { + WriteDcm (string (nomFichier)); +} ///////////////////////////////////////////////////////////////// /** * \ingroup gdcmFile - * \ TODO * - * @param + * @param nomFichier TODO JPR * - * @return + * @return TODO JPR */ int gdcmFile::WriteDcmExplVR (string nomFichier) { diff --git a/src/gdcmFile.h b/src/gdcmFile.h index fa41817c..82b02c65 100644 --- a/src/gdcmFile.h +++ b/src/gdcmFile.h @@ -44,6 +44,7 @@ public: // seen as a side effect). gdcmFile(string & filename); + gdcmFile(const char * filename); // For promotion (performs a deepcopy of pointed header object) // TODO Swig gdcmFile(gdcmHeader* header); @@ -90,6 +91,7 @@ public: int WriteRawData (string nomFichier); int WriteDcm (string nomFichier); + int WriteDcm (const char * nomFichier); int WriteDcmExplVR (string nomFichier); int WriteAcr (string nomFichier); }; diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index fdc6dee9..f5f385b2 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -44,7 +44,6 @@ gdcmHeader::gdcmHeader(const char *InFilename, bool exception_on_error) dbg.Error(!fp, "gdcmHeader::gdcmHeader cannot open file", InFilename); ParseHeader(); LoadElements(); - AddAndDefaultElements(); } @@ -146,8 +145,12 @@ void gdcmHeader::CheckSwap() // * the 4 bytes of the first tag (0002, 0000),or (0002, 0001) // i.e. a total of 136 bytes. entCur = deb + 136; + ///// FIXME + ///// Use gdcmHeader::dicom_vr to test all the possibilities + ///// insteadn of just checking for UL, OB and UI !? if( (memcmp(entCur, "UL", (size_t)2) == 0) || - (memcmp(entCur, "OB", (size_t)2) == 0) ) + (memcmp(entCur, "OB", (size_t)2) == 0) || + (memcmp(entCur, "UI", (size_t)2) == 0) ) { filetype = ExplicitVR; dbg.Verbose(1, "gdcmHeader::CheckSwap:", @@ -494,6 +497,18 @@ bool gdcmHeader::IsJPEGSpectralSelectionProcess6_8TransferSyntax(void) { return true; return false; } +/** + * \ingroup gdcmHeader + * \brief Predicate for dicom version 3 file. + * @return True when the file is a dicom version 3. + */ +bool gdcmHeader::IsDicomV3(void) { + if ( (filetype == TrueDicom) + || (filetype == ExplicitVR) + || (filetype == ImplicitVR) ) + return true; + return false; +} /** * \ingroup gdcmHeader @@ -1390,108 +1405,99 @@ void gdcmHeader::ParseHeader(bool exception_on_error) throw(gdcmFormatError) { /** * \ingroup gdcmHeader - * \brief accessor to get Rows nbr + * \brief Retrieve the number of columns of image. + * @return The encountered size when found, 0 by default. */ - -string gdcmHeader::GetYSize(void) { - return (GetElValByName("Rows")); +int gdcmHeader::GetXSize(void) { + // We cannot check for "Columns" because the "Columns" tag is present + // both in IMG (0028,0011) and OLY (6000,0011) sections of the dictionary. + string StrSize = GetPubElValByNumber(0x0028,0x0011); + if (StrSize == "gdcm::Unfound") + return 0; + return atoi(StrSize.c_str()); } /** * \ingroup gdcmHeader - * \brief accessor to get Columns nbr + * \brief Retrieve the number of lines of image. + * \warning The defaulted value is 1 as opposed to gdcmHeader::GetXSize() + * @return The encountered size when found, 1 by default. */ - -string gdcmHeader::GetXSize(void) { - return (GetElValByName("Columns")); +int gdcmHeader::GetYSize(void) { + // We cannot check for "Rows" because the "Rows" tag is present + // both in IMG (0028,0010) and OLY (6000,0010) sections of the dictionary. + string StrSize = GetPubElValByNumber(0x0028,0x0010); + if (StrSize != "gdcm::Unfound") + return atoi(StrSize.c_str()); + if ( IsDicomV3() ) + return 0; + else + // The Rows (0028,0010) entry is optional for ACR/NEMA. It might + // hence be a signal (1d image). So we default to 1: + return 1; } /** * \ingroup gdcmHeader - * \brief accessor to get Planes nbr - * (ACR-NEMA volume file or Multiframe Dicom V3 image file) + * \brief Retrieve the number of planes of volume or the number + * of frames of a multiframe. + * \warning When present we consider the "Number of Frames" as the third + * dimension. When absent we consider the third dimension as + * being the "Planes" tag content. + * @return The encountered size when found, 1 by default. */ - -string gdcmHeader::GetZSize(void) { - string NewVal; - NewVal = GetElValByNumber(0x0028,0x0008); // Number of Frames (DICOM) - - if (NewVal == "gdcm::Unfound") { - NewVal = GetElValByNumber(0x0028,0x0012); // Planes (ACR-NEMA) - // 6000 0012 : US OLY Planes - // 'xxxByName' function not applicable - if (NewVal == "gdcm::Unfound") { - NewVal = "0"; - } - } - return(NewVal); +int gdcmHeader::GetZSize(void) { + // Both in DicomV3 and ACR/Nema the consider the "Number of Frames" + // as the third dimension. + string StrSize = GetPubElValByNumber(0x0028,0x0008); + if (StrSize != "gdcm::Unfound") + return atoi(StrSize.c_str()); + + // We then consider the "Planes" entry as the third dimension [we + // cannot retrieve by name since "Planes tag is present both in + // IMG (0028,0012) and OLY (6000,0012) sections of the dictionary]. + StrSize = GetPubElValByNumber(0x0028,0x0012); + if (StrSize != "gdcm::Unfound") + return atoi(StrSize.c_str()); + return 1; } /** * \ingroup gdcmHeader - * \brief accessor to get Pixel Type - * (U8, S8, U16, S16, U32, S32) - * - * \warning : NOT YET MADE - * + * \brief Build the Pixel Type of the image. + * Possible values are: + * - U8 unsigned 8 bit, + * - S8 signed 8 bit, + * - U16 unsigned 16 bit, + * - S16 signed 16 bit, + * - U32 unsigned 32 bit, + * - S32 signed 32 bit, + * \warning 12 bit images appear as 16 bit. + * @return */ - string gdcmHeader::GetPixelType(void) { - string NewVal; - // TODO - return(NewVal); -} - -/** - * \ingroup gdcmHeader - * \brief Once the header is parsed add some gdcm convenience/helper elements - * in the gdcmElValSet. For example add: - * - gdcmImageType which is an entry containing a short for the - * type of image and whose value ranges in - * I8 (unsigned 8 bit image) - * I16 (unsigned 8 bit image) - * IS16 (signed 8 bit image) - * Replace by U8, S8, U16, S16, U32, S32 - * - * - gdcmXsize, gdcmYsize, gdcmZsize whose values are respectively - * the ones of the official DICOM fields Rows, Columns and [Number of Frames/Planes] - */ -void gdcmHeader::AddAndDefaultElements(void) { - gdcmElValue* NewElVal = (gdcmElValue*)0; - string NewVal; - - NewElVal = NewManualElValToPubDict("gdcmXSize", "US"); - if (!NewElVal) return; - NewVal = GetElValByName("Rows"); - if (NewVal != "gdcm::Unfound") - NewElVal->SetValue(NewVal); - else - NewElVal->SetValue("0"); - - NewElVal = NewManualElValToPubDict("gdcmYSize", "US"); - if (!NewElVal) return; - NewVal = GetElValByName("Columns"); - if (NewVal != "gdcm::Unfound") - NewElVal->SetValue(NewVal); + string BitsAlloc; + BitsAlloc = GetElValByName("Bits Allocated"); + if (BitsAlloc == "gdcm::Unfound") { + dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Bits Allocated"); + BitsAlloc = string("16"); + } + if (BitsAlloc == "12") + BitsAlloc = string("16"); + + string Signed; + Signed = GetElValByName("Pixel Representation"); + if (Signed == "gdcm::Unfound") { + dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Pixel Representation"); + BitsAlloc = string("0"); + } + if (Signed == "0") + Signed = string("U"); else - NewElVal->SetValue("0"); - - - NewElVal = NewManualElValToPubDict("gdcmZSize", "US"); - if (!NewElVal) return; - NewVal = GetElValByNumber(0x0028,0x0008); // 0028 0008 IS IMG Number of Frames (DICOM) - if (NewVal == "gdcm::Unfound") { - NewVal = GetElValByNumber(0x0028,0x0012); // 028 0012 US IMG Planes (ACR-NEMA) - if (NewVal == "gdcm::Unfound") { // Warning !!! : 6000 0012 US OLY Planes - NewElVal->SetValue("0"); - } else { - NewElVal->SetValue(NewVal); - } - } else { - NewElVal->SetValue(NewVal); - } // length is still wrong -} // do we care about it? + Signed = string("S"); + return( BitsAlloc + Signed); +} /** * \ingroup gdcmHeader @@ -1518,13 +1524,11 @@ bool gdcmHeader::IsReadable(void) { return true; } - /** * \ingroup gdcmHeader * \brief Small utility function that creates a new manually crafted * (as opposed as read from the file) gdcmElValue with user * specified name and adds it to the public tag hash table. - * Refer to gdcmHeader::AddAndDefaultElements for a typical usage. * \note A fake TagKey is generated so the PubDict can keep it's coherence. * @param NewTagName The name to be given to this new tag. * @param VR The Value Representation to be given to this new tag. diff --git a/src/gdcmHeader.h b/src/gdcmHeader.h index c733cd54..b69cb7f7 100644 --- a/src/gdcmHeader.h +++ b/src/gdcmHeader.h @@ -79,8 +79,8 @@ private: void CheckSwap(void); void InitVRDict(void); void SwitchSwapToBigEndian(void); + // CLEAN ME: NewManualElValToPubDict is NOT called any more. gdcmElValue* NewManualElValToPubDict(string NewTagName, string VR); - void AddAndDefaultElements(void); void SetMaxSizeLoadElementValue(long); gdcmDictEntry * GetDictEntryByKey(guint16, guint16); @@ -109,6 +109,7 @@ private: bool IsJPEGSpectralSelectionProcess6_8TransferSyntax(void); bool IsJPEGLossless(void); + bool IsDicomV3(void); protected: // FIXME: is this enum still necessary ?? @@ -169,13 +170,9 @@ public: gdcmElValSet GetPubElValSet() { return(PubElValSet); } - // a mettre en inline - // --> ou met-on les doxygeneries ? - - string GetXSize(void); - string GetYSize(void); - - string GetZSize(void); + int GetXSize(void); + int GetYSize(void); + int GetZSize(void); string GetPixelType(void); }; -- 2.48.1