Mercurial > hg > orthanc-stone
diff OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp @ 2169:fe5406abd43f
added separate class Windowing
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 21 Oct 2024 15:40:34 +0200 |
parents | 16c01cc201e7 |
children | 8e3c403cc643 |
line wrap: on
line diff
--- a/OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp Wed Oct 09 12:50:10 2024 +0200 +++ b/OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp Mon Oct 21 15:40:34 2024 +0200 @@ -190,29 +190,29 @@ } } - bool ok = false; + + windowingPresets_.clear(); + + Vector centers, widths; - if (LinearAlgebra::ParseVector(windowingPresetCenters_, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) && - LinearAlgebra::ParseVector(windowingPresetWidths_, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH)) + if (LinearAlgebra::ParseVector(centers, dicom, Orthanc::DICOM_TAG_WINDOW_CENTER) && + LinearAlgebra::ParseVector(widths, dicom, Orthanc::DICOM_TAG_WINDOW_WIDTH)) { - if (windowingPresetCenters_.size() == windowingPresetWidths_.size()) + if (centers.size() == widths.size()) { - ok = true; + windowingPresets_.resize(centers.size()); + + for (size_t i = 0; i < centers.size(); i++) + { + windowingPresets_[i] = Windowing(centers[i], widths[i]); + } } else { LOG(ERROR) << "Mismatch in the number of preset windowing widths/centers, ignoring this"; - ok = false; } } - if (!ok) - { - // Don't use "Vector::clear()", as it has not the same meaning as "std::vector::clear()" - windowingPresetCenters_.resize(0); - windowingPresetWidths_.resize(0); - } - // This computes the "IndexInSeries" metadata from Orthanc (check // out "Orthanc::ServerIndex::Store()") hasIndexInSeries_ = ( @@ -399,18 +399,45 @@ } + Windowing DicomInstanceParameters::GetFallbackWindowing() const + { + double a, b; + if (tags_->ParseDouble(a, Orthanc::DICOM_TAG_SMALLEST_IMAGE_PIXEL_VALUE) && + tags_->ParseDouble(b, Orthanc::DICOM_TAG_LARGEST_IMAGE_PIXEL_VALUE)) + { + const double center = (a + b) / 2.0f; + const double width = (b - a); + return Windowing(center, width); + } + + // Added in Stone Web viewer > 2.5 + uint32_t bitsStored, pixelRepresentation; + if (tags_->ParseUnsignedInteger32(bitsStored, Orthanc::DICOM_TAG_BITS_STORED) && + tags_->ParseUnsignedInteger32(pixelRepresentation, Orthanc::DICOM_TAG_PIXEL_REPRESENTATION)) + { + const bool isSigned = (pixelRepresentation != 0); + const float maximum = powf(2.0, bitsStored); + return Windowing(isSigned ? 0.0f : maximum / 2.0f, maximum); + } + else + { + // Cannot infer a suitable windowing from the available tags + return Windowing(); + } + } + + size_t DicomInstanceParameters::GetWindowingPresetsCount() const { - assert(data_.windowingPresetCenters_.size() == data_.windowingPresetWidths_.size()); - return data_.windowingPresetCenters_.size(); + return data_.windowingPresets_.size(); } - float DicomInstanceParameters::GetWindowingPresetCenter(size_t i) const + Windowing DicomInstanceParameters::GetWindowingPreset(size_t i) const { if (i < GetWindowingPresetsCount()) { - return static_cast<float>(data_.windowingPresetCenters_[i]); + return data_.windowingPresets_[i]; } else { @@ -418,32 +445,8 @@ } } - - float DicomInstanceParameters::GetWindowingPresetWidth(size_t i) const - { - if (i < GetWindowingPresetsCount()) - { - return static_cast<float>(data_.windowingPresetWidths_[i]); - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - } - - - static void GetWindowingBounds(float& low, - float& high, - double center, // in - double width) // in - { - low = static_cast<float>(center - width / 2.0); - high = static_cast<float>(center + width / 2.0); - } - - void DicomInstanceParameters::GetWindowingPresetsUnion(float& center, - float& width) const + Windowing DicomInstanceParameters::GetWindowingPresetsUnion() const { assert(tags_.get() != NULL); size_t s = GetWindowingPresetsCount(); @@ -452,48 +455,29 @@ { // Use the largest windowing given all the preset windowings // that are available in the DICOM tags - float low, high; - GetWindowingBounds(low, high, GetWindowingPresetCenter(0), GetWindowingPresetWidth(0)); + double low, high; + GetWindowingPreset(0).GetBounds(low, high); for (size_t i = 1; i < s; i++) { - float a, b; - GetWindowingBounds(a, b, GetWindowingPresetCenter(i), GetWindowingPresetWidth(i)); + double a, b; + GetWindowingPreset(i).GetBounds(a, b); low = std::min(low, a); high = std::max(high, b); } assert(low <= high); - if (LinearAlgebra::IsNear(low, high)) + if (!LinearAlgebra::IsNear(low, high)) { - // Cannot infer a suitable windowing from the available tags - center = 128.0f; - width = 256.0f; - } - else - { - center = (low + high) / 2.0f; - width = (high - low); + const double center = (low + high) / 2.0f; + const double width = (high - low); + return Windowing(center, width); } } - else - { - float a, b; - if (tags_->ParseFloat(a, Orthanc::DICOM_TAG_SMALLEST_IMAGE_PIXEL_VALUE) && - tags_->ParseFloat(b, Orthanc::DICOM_TAG_LARGEST_IMAGE_PIXEL_VALUE) && - a < b) - { - center = (a + b) / 2.0f; - width = (b - a); - } - else - { - // Cannot infer a suitable windowing from the available tags - center = 128.0f; - width = 256.0f; - } - } + + // No preset, or presets with an empty range + return GetFallbackWindowing(); } @@ -565,7 +549,8 @@ if (GetWindowingPresetsCount() > 0) { - floatTexture.SetCustomWindowing(GetWindowingPresetCenter(0), GetWindowingPresetWidth(0)); + Windowing preset = GetWindowingPreset(0); + floatTexture.SetCustomWindowing(preset.GetCenter(), preset.GetWidth()); } switch (GetImageInformation().GetPhotometricInterpretation())