Mercurial > hg > orthanc-stone
diff OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp @ 2174:2410a171ebfb
refactoring using DicomWebDataset and OrthancNativeDataset
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 22 Oct 2024 21:52:34 +0200 |
parents | 8e3c403cc643 |
children | 43ef60388fa2 |
line wrap: on
line diff
--- a/OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp Tue Oct 22 15:41:38 2024 +0200 +++ b/OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp Tue Oct 22 21:52:34 2024 +0200 @@ -27,6 +27,9 @@ #include "../Scene2D/FloatTextureSceneLayer.h" #include "GeometryToolbox.h" #include "ImageToolbox.h" +#include "OrthancDatasets/DicomDatasetReader.h" +#include "OrthancDatasets/DicomWebDataset.h" +#include "OrthancDatasets/OrthancNativeDataset.h" #include <Images/Image.h> #include <Images/ImageProcessing.h> @@ -231,68 +234,103 @@ { instanceNumber_ = 0; } + } + void DicomInstanceParameters::InjectSequenceTags(const IDicomDataset& dataset) + { + /** + * Use DICOM tag "SequenceOfUltrasoundRegions" (0018,6011) in + * order to derive the pixel spacing on ultrasound (US) images + **/ + + static const Orthanc::DicomTag DICOM_TAG_SEQUENCE_OF_ULTRASOUND_REGIONS(0x0018, 0x6011); + static const Orthanc::DicomTag DICOM_TAG_PHYSICAL_UNITS_X_DIRECTION(0x0018, 0x6024); + static const Orthanc::DicomTag DICOM_TAG_PHYSICAL_UNITS_Y_DIRECTION(0x0018, 0x6026); + static const Orthanc::DicomTag DICOM_TAG_PHYSICAL_DELTA_X(0x0018, 0x602c); + static const Orthanc::DicomTag DICOM_TAG_PHYSICAL_DELTA_Y(0x0018, 0x602e); + + DicomDatasetReader reader(dataset); + + size_t size; + + if (!data_.hasPixelSpacing_ && + dataset.GetSequenceSize(size, Orthanc::DicomPath(DICOM_TAG_SEQUENCE_OF_ULTRASOUND_REGIONS)) && + size == 1) + { + int directionX, directionY; + double deltaX, deltaY; + + if (reader.GetIntegerValue(directionX, Orthanc::DicomPath(DICOM_TAG_SEQUENCE_OF_ULTRASOUND_REGIONS, + 0, DICOM_TAG_PHYSICAL_UNITS_X_DIRECTION)) && + reader.GetIntegerValue(directionY, Orthanc::DicomPath(DICOM_TAG_SEQUENCE_OF_ULTRASOUND_REGIONS, + 0, DICOM_TAG_PHYSICAL_UNITS_Y_DIRECTION)) && + reader.GetDoubleValue(deltaX, Orthanc::DicomPath(DICOM_TAG_SEQUENCE_OF_ULTRASOUND_REGIONS, + 0, DICOM_TAG_PHYSICAL_DELTA_X)) && + reader.GetDoubleValue(deltaY, Orthanc::DicomPath(DICOM_TAG_SEQUENCE_OF_ULTRASOUND_REGIONS, + 0, DICOM_TAG_PHYSICAL_DELTA_Y)) && + directionX == 0x0003 && // Centimeters + directionY == 0x0003) // Centimeters + { + // Scene coordinates are expressed in millimeters => multiplication by 10 + SetPixelSpacing(10.0 * deltaX, 10.0 * deltaY); + } + } + + + /** + * New in Stone Web viewer 2.2: Deal with Philips multiframe + * (cf. mail from Tomas Kenda on 2021-08-17). This cannot be done + * in LoadSeriesDetailsFromInstance, as the "Per Frame Functional + * Groups Sequence" is not available at that point. + **/ + static const Orthanc::DicomTag DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE(0x5200, 0x9230); static const Orthanc::DicomTag DICOM_TAG_FRAME_VOI_LUT_SEQUENCE_ATTRIBUTE(0x0028, 0x9132); - const Orthanc::DicomValue* frames = dicom.TestAndGetValue(DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE); - if (frames != NULL && - hasNumberOfFrames_ && - frames->IsSequence()) + if (dataset.GetSequenceSize(size, Orthanc::DicomPath(DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE))) { - /** - * New in Stone Web viewer 2.2: Deal with Philips multiframe - * (cf. mail from Tomas Kenda on 2021-08-17). This cannot be done - * in LoadSeriesDetailsFromInstance, as the "Per Frame Functional Groups Sequence" - * is not available at that point. - **/ - - const Json::Value& sequence = frames->GetSequenceContent(); - - perFrameWindowing_.resize(numberOfFrames_); + data_.perFrameWindowing_.resize(data_.numberOfFrames_); // This corresponds to "ParsedDicomFile::GetDefaultWindowing()" - for (Json::ArrayIndex i = 0; i < sequence.size(); i++) + for (size_t i = 0; i < size; i++) { - if (i < numberOfFrames_ && - sequence[i].isMember(DICOM_TAG_FRAME_VOI_LUT_SEQUENCE_ATTRIBUTE.Format())) - { - const Json::Value& v = sequence[i][DICOM_TAG_FRAME_VOI_LUT_SEQUENCE_ATTRIBUTE.Format()]; - - static const char* KEY_VALUE = "Value"; + size_t tmp; + double center, width; - if (v.isMember(KEY_VALUE) && - v[KEY_VALUE].type() == Json::arrayValue && - v[KEY_VALUE].size() >= 1 && - v[KEY_VALUE][0].isMember(Orthanc::DICOM_TAG_WINDOW_CENTER.Format()) && - v[KEY_VALUE][0].isMember(Orthanc::DICOM_TAG_WINDOW_WIDTH.Format()) && - v[KEY_VALUE][0][Orthanc::DICOM_TAG_WINDOW_CENTER.Format()].isMember(KEY_VALUE) && - v[KEY_VALUE][0][Orthanc::DICOM_TAG_WINDOW_WIDTH.Format()].isMember(KEY_VALUE)) - { - const Json::Value& scenter = v[KEY_VALUE][0][Orthanc::DICOM_TAG_WINDOW_CENTER.Format()][KEY_VALUE]; - const Json::Value& swidth = v[KEY_VALUE][0][Orthanc::DICOM_TAG_WINDOW_WIDTH.Format()][KEY_VALUE]; - - double center, width; - if (scenter.isString() && - swidth.isString() && - Orthanc::SerializationToolbox::ParseDouble(center, scenter.asString()) && - Orthanc::SerializationToolbox::ParseDouble(width, swidth.asString())) - { - perFrameWindowing_[i] = Windowing(center, width); - } - else if (scenter.isNumeric() && - swidth.isNumeric()) - { - perFrameWindowing_[i] = Windowing(scenter.asDouble(), swidth.asDouble()); - } - } + if (dataset.GetSequenceSize(tmp, Orthanc::DicomPath(DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE, i, + DICOM_TAG_FRAME_VOI_LUT_SEQUENCE_ATTRIBUTE)) && + tmp == 1 && + reader.GetDoubleValue(center, Orthanc::DicomPath(DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE, i, + DICOM_TAG_FRAME_VOI_LUT_SEQUENCE_ATTRIBUTE, 0, + Orthanc::DICOM_TAG_WINDOW_CENTER)) && + reader.GetDoubleValue(width, Orthanc::DicomPath(DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE, i, + DICOM_TAG_FRAME_VOI_LUT_SEQUENCE_ATTRIBUTE, 0, + Orthanc::DICOM_TAG_WINDOW_WIDTH))) + { + data_.perFrameWindowing_[i] = Windowing(center, width); } } } } + DicomInstanceParameters::DicomInstanceParameters(const DicomInstanceParameters& other) : + data_(other.data_), + tags_(other.tags_->Clone()) + { + } + + + DicomInstanceParameters::DicomInstanceParameters(const Orthanc::DicomMap& dicom) : + data_(dicom), + tags_(dicom.Clone()) + { + OrthancNativeDataset dataset(dicom); + InjectSequenceTags(dataset); + } + + double DicomInstanceParameters::GetSliceThickness() const { if (data_.hasSliceThickness_) @@ -814,38 +852,8 @@ void DicomInstanceParameters::EnrichUsingDicomWeb(const Json::Value& dicomweb) { - /** - * Use DICOM tag "SequenceOfUltrasoundRegions" (0018,6011) in - * order to derive the pixel spacing on ultrasound (US) images - **/ - - if (!data_.hasPixelSpacing_) - { - const Json::Value* region = LookupDicomWebSingleValue(dicomweb, "00186011", "SQ"); - if (region != NULL) - { - const Json::Value* physicalUnitsXDirection = LookupDicomWebSingleValue(*region, "00186024", "US"); - const Json::Value* physicalUnitsYDirection = LookupDicomWebSingleValue(*region, "00186026", "US"); - const Json::Value* physicalDeltaX = LookupDicomWebSingleValue(*region, "0018602C", "FD"); - const Json::Value* physicalDeltaY = LookupDicomWebSingleValue(*region, "0018602E", "FD"); - - if (physicalUnitsXDirection != NULL && - physicalUnitsYDirection != NULL && - physicalDeltaX != NULL && - physicalDeltaY != NULL && - physicalUnitsXDirection->type() == Json::intValue && - physicalUnitsYDirection->type() == Json::intValue && - physicalUnitsXDirection->asInt() == 0x0003 && // Centimeters - physicalUnitsYDirection->asInt() == 0x0003 && // Centimeters - physicalDeltaX->isNumeric() && - physicalDeltaY->isNumeric()) - { - // Scene coordinates are expressed in millimeters => multiplication by 10 - SetPixelSpacing(10.0 * physicalDeltaX->asDouble(), - 10.0 * physicalDeltaY->asDouble()); - } - } - } + DicomWebDataset dataset(dicomweb); + InjectSequenceTags(dataset); }