| 97 | } |
| 98 | |
| 99 | void mitk::LabelSetImageVtkMapper2D::GenerateLookupTable(mitk::BaseRenderer* renderer) |
| 100 | { |
| 101 | LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); |
| 102 | mitk::DataNode* node = this->GetDataNode(); |
| 103 | auto* image = dynamic_cast<mitk::MultiLabelSegmentation*>(node->GetData()); |
| 104 | assert(image && image->IsInitialized()); |
| 105 | |
| 106 | localStorage->m_LabelLookupTable = image->GetLookupTable()->Clone(); |
| 107 | auto lookUpTable = localStorage->m_LabelLookupTable->GetVtkLookupTable(); |
| 108 | const auto labelValues = image->GetAllLabelValues(); |
| 109 | |
| 110 | mitk::IntVectorProperty::Pointer prop = dynamic_cast<mitk::IntVectorProperty*>(node->GetNonConstProperty(LabelHighlightGuard::PROPERTY_NAME_LABELS_HIGHLIGHTED())); |
| 111 | const auto highlightedLabelValues = prop.IsNotNull() ? prop->GetValue() : std::vector<int>({}); |
| 112 | const auto highlightEnd = highlightedLabelValues.cend(); |
| 113 | const bool highlightingActive = !highlightedLabelValues.empty(); |
| 114 | |
| 115 | mitk::BoolProperty::Pointer boolProp = dynamic_cast<mitk::BoolProperty*>(node->GetNonConstProperty(LabelHighlightGuard::PROPERTY_NAME_HIGHLIGHT_INVISIBLE())); |
| 116 | const bool highlightInvisibleLabels = boolProp.IsNull() ? false : boolProp->GetValue(); |
| 117 | |
| 118 | float nodeOpacity = 1.0f; |
| 119 | node->GetOpacity(nodeOpacity, renderer, "opacity"); |
| 120 | const float opacityFactor = this->GetOpacityFactor(); |
| 121 | |
| 122 | // Node "opacity" times the "opacity factor" preference define the base (normal) |
| 123 | // opacity. It is baked into the LUT alpha here rather than applied at the layer actor, |
| 124 | // so a hovered label can be spotlit above the base (see GenerateDataForRenderer, which |
| 125 | // keeps the actor opacity fixed at 1.0). |
| 126 | const double base = static_cast<double>(nodeOpacity) * opacityFactor; |
| 127 | |
| 128 | double rgba[4]; |
| 129 | for (const auto& value : labelValues) |
| 130 | { |
| 131 | lookUpTable->GetTableValue(value, rgba); |
| 132 | |
| 133 | // The segmentation LUT stores each label's own opacity in alpha (0 = hidden). |
| 134 | const double labelOpacity = rgba[3]; |
| 135 | const double normalOpacity = labelOpacity * base; |
| 136 | |
| 137 | if (highlightingActive) |
| 138 | { |
| 139 | const bool isHighlightedValue = highlightEnd != std::find(highlightedLabelValues.begin(), highlightedLabelValues.end(), value); |
| 140 | if (isHighlightedValue) |
| 141 | { |
| 142 | // Spotlight the hovered label at full opacity, decoupled from the base so it |
| 143 | // pops regardless of how transparent the segmentation is. A hidden label is |
| 144 | // only revealed when explicitly requested (Shift-highlight of invisible labels). |
| 145 | rgba[3] = (labelOpacity != 0.0 || highlightInvisibleLabels) ? HIGHLIGHTED_LABEL_OPACITY : 0.0; |
| 146 | } |
| 147 | else |
| 148 | { |
| 149 | // Fade the other labels to a low floor, but never above their normal appearance. |
| 150 | rgba[3] = std::min(FADED_LABEL_OPACITY, normalOpacity); |
| 151 | } |
| 152 | } |
| 153 | else |
| 154 | { |
| 155 | rgba[3] = normalOpacity; |
| 156 | } |
no test coverage detected