GCC Code Coverage Report


./
File: libs/filter/dicom/splitter/tag_value_splitter.cpp
Date: 2025-01-21 16:21:04
Lines:
49/58
84.5%
Functions:
3/6
50.0%
Branches:
44/124
35.5%

Line Branch Exec Source
1 /************************************************************************
2 *
3 * Copyright (C) 2009-2023 IRCAD France
4 * Copyright (C) 2012-2019 IHU Strasbourg
5 *
6 * This file is part of Sight.
7 *
8 * Sight is free software: you can redistribute it and/or modify it under
9 * the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Sight is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with Sight. If not, see <https://www.gnu.org/licenses/>.
20 *
21 ***********************************************************************/
22
23 // cspell:ignore NOLINT
24
25 #include "filter/dicom/splitter/tag_value_splitter.hpp"
26
27 #include "filter/dicom/exceptions/filter_failure.hpp"
28 #include "filter/dicom/registry/macros.hpp"
29
30 #include <dcmtk/config/osconfig.h>
31 #include <dcmtk/dcmdata/dcdeftag.h>
32 #include <dcmtk/dcmdata/dcfilefo.h>
33 #include <dcmtk/dcmdata/dcistrmb.h>
34 #include <dcmtk/dcmimgle/dcmimage.h>
35 #include <dcmtk/dcmnet/diutil.h>
36
37 SIGHT_REGISTER_DICOM_FILTER(sight::filter::dicom::splitter::tag_value_splitter);
38
39 namespace sight::filter::dicom::splitter
40 {
41
42 const std::string tag_value_splitter::FILTER_NAME = "Tag value splitter";
43 const std::string tag_value_splitter::FILTER_DESCRIPTION =
44 "Split instances according to a tag value.";
45
46 //-----------------------------------------------------------------------------
47
48 117 tag_value_splitter::tag_value_splitter() :
49 117 m_tag(DCM_UndefinedTagKey)
50 {
51 117 }
52
53 //-----------------------------------------------------------------------------
54
55 234 tag_value_splitter::~tag_value_splitter()
56 = default;
57
58 //-----------------------------------------------------------------------------
59
60 std::string tag_value_splitter::get_name() const
61 {
62 return tag_value_splitter::FILTER_NAME;
63 }
64
65 //-----------------------------------------------------------------------------
66
67 std::string tag_value_splitter::get_description() const
68 {
69 return tag_value_splitter::FILTER_DESCRIPTION;
70 }
71
72 //-----------------------------------------------------------------------------
73
74 bool tag_value_splitter::is_configuration_required() const
75 {
76 return true;
77 }
78
79 //-----------------------------------------------------------------------------
80
81 120 tag_value_splitter::dicom_series_container_t tag_value_splitter::apply(
82 const data::dicom_series::sptr& _series,
83 const core::log::logger::sptr& _logger
84 ) const
85 {
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
120 if(m_tag == DCM_UndefinedTagKey)
87 {
88 const std::string msg = "Unable to split the series, the specified tag is not valid.";
89 throw sight::filter::dicom::exceptions::filter_failure(msg);
90 }
91
92 120 dicom_series_container_t result;
93
94 120 using instance_container_t = std::vector<core::memory::buffer_object::sptr>;
95 120 using instance_group_container = std::map<std::string, instance_container_t>;
96
97 // Create a container to store the groups of instances
98 120 instance_group_container group_container;
99
100 120 OFCondition status;
101 120 OFString data;
102
103
2/2
✓ Branch 0 taken 17003 times.
✓ Branch 1 taken 120 times.
17123 for(const auto& item : _series->get_dicom_container())
104 {
105
1/2
✓ Branch 0 taken 17003 times.
✗ Branch 1 not taken.
17003 const core::memory::buffer_object::sptr buffer_obj = item.second;
106
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 const std::size_t buff_size = buffer_obj->size();
107
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 core::memory::buffer_object::lock_t lock(buffer_obj);
108
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 char* buffer = static_cast<char*>(lock.buffer());
109
110
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 DcmInputBufferStream is;
111
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 is.setBuffer(buffer, offile_off_t(buff_size));
112
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 is.setEos();
113
114
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 DcmFileFormat file_format;
115
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 file_format.transferInit();
116
3/6
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 17003 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17003 times.
17003 if(!file_format.read(is).good())
117 {
118 SIGHT_THROW(
119 "Unable to read Dicom file '" << buffer_obj->get_stream_info().fs_file.string() << "' "
120 << "(slice: '" << item.first << "')"
121 );
122 }
123
124
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 file_format.loadAllDataIntoMemory();
125
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 file_format.transferEnd();
126
127
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 DcmDataset* dataset = file_format.getDataset();
128
129 // Get the value of the instance
130
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 dataset->findAndGetOFStringArray(m_tag, data);
131
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 const std::string value = data.c_str(); // NOLINT(readability-redundant-string-cstr)
132
133 // Add the instance to the group
134
2/4
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 17003 times.
✗ Branch 5 not taken.
17003 group_container[value].push_back(buffer_obj);
135
1/2
✓ Branch 3 taken 17003 times.
✗ Branch 4 not taken.
34006 }
136
137
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 120 times.
250 for(const auto& group : group_container)
138 {
139 // Copy the series
140
1/2
✓ Branch 1 taken 130 times.
✗ Branch 2 not taken.
130 data::dicom_series::sptr dicom_series = std::make_shared<data::dicom_series>();
141
1/4
✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
130 dicom_series->shallow_copy(_series);
142 130 dicom_series->clear_dicom_container();
143
144 130 std::size_t index = 0;
145 // Add the paths to the series
146
2/2
✓ Branch 0 taken 17003 times.
✓ Branch 1 taken 130 times.
17133 for(const core::memory::buffer_object::sptr& buffer : group.second)
147 {
148
1/2
✓ Branch 1 taken 17003 times.
✗ Branch 2 not taken.
17003 dicom_series->add_binary(index++, buffer);
149 }
150
151 // Set number of instances
152
1/2
✓ Branch 1 taken 130 times.
✗ Branch 2 not taken.
130 dicom_series->set_number_of_instances(dicom_series->get_dicom_container().size());
153
154
1/2
✓ Branch 1 taken 130 times.
✗ Branch 2 not taken.
130 result.push_back(dicom_series);
155 130 }
156
157
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 112 times.
120 if(result.size() > 1)
158 {
159
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 std::stringstream ss;
160
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 ss << "Series has been split according to the tag value ("
161
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
8 << std::hex << std::setfill('0') << std::setw(4) << m_tag.getGroup() << ","
162
3/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
8 << std::hex << std::setfill('0') << std::setw(4) << m_tag.getElement() << ").";
163
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 _logger->warning(ss.str());
164 8 }
165
166 120 return result;
167 120 }
168
169 } // namespace sight::filter::dicom::splitter
170