Per-frame lift: open each file in the frame list once, extract the requested private element, and build a DICOMCachedValueLookupTable keyed by frame index (with the descriptor's frame -> (t, s) mapping computed inline). Returns true only if every frame yielded a non-empty value; on any missing frame it returns false and attaches nothing (all-or-nothing), leaving the caller to fall back.
| 139 | // value; on any missing frame it returns false and attaches nothing |
| 140 | // (all-or-nothing), leaving the caller to fall back. |
| 141 | bool LiftPrivateTagPerFrame(const mitk::DICOMImageBlockDescriptor& desc, |
| 142 | Uint16 group, const char* creator, Uint16 elementOffset, |
| 143 | mitk::DICOMCachedValueLookupTable& outTable) |
| 144 | { |
| 145 | const auto& frameList = desc.GetImageFrameList(); |
| 146 | if (frameList.empty()) return false; |
| 147 | const int framesPerTimeStep = desc.GetNumberOfFramesPerTimeStep(); |
| 148 | if (framesPerTimeStep <= 0) return false; |
| 149 | |
| 150 | bool anyValue = false; |
| 151 | for (std::size_t i = 0; i < frameList.size(); ++i) |
| 152 | { |
| 153 | const auto& frame = frameList[i]; |
| 154 | if (frame.IsNull() || frame->Filename.empty()) return false; |
| 155 | |
| 156 | DcmFileFormat dff; |
| 157 | // ERM_autoDetect (default): we need the dataset, not just the file |
| 158 | // meta header. The vendor private tags live in groups 0x0071 / 0x0009 |
| 159 | // in the dataset, which ERM_metaOnly skips. |
| 160 | if (!dff.loadFile(frame->Filename.c_str(), EXS_Unknown, |
| 161 | EGL_noChange, DCM_MaxReadLength, |
| 162 | ERM_autoDetect).good()) |
| 163 | { |
| 164 | return false; |
| 165 | } |
| 166 | DcmDataset* ds = dff.getDataset(); |
| 167 | if (nullptr == ds) return false; |
| 168 | |
| 169 | const std::string v = ReadPrivateString(ds, group, creator, elementOffset); |
| 170 | if (v.empty()) return false; |
| 171 | |
| 172 | const unsigned int t = |
| 173 | static_cast<unsigned int>(i) / static_cast<unsigned int>(framesPerTimeStep); |
| 174 | const unsigned int s = |
| 175 | static_cast<unsigned int>(i) % static_cast<unsigned int>(framesPerTimeStep); |
| 176 | outTable.SetTableValue(static_cast<int>(i), { t, s, v }); |
| 177 | anyValue = true; |
| 178 | } |
| 179 | return anyValue; |
| 180 | } |
| 181 | |
| 182 | // Convenience: per-frame lift + property attach in one step. Returns |
| 183 | // true when the lift succeeded and the property was attached. |
no test coverage detected