GCC Code Coverage Report


./
File: libs/filter/image/line_drawer.cpp
Date: 2025-01-21 16:21:04
Lines:
57/65
87.7%
Functions:
4/4
100.0%
Branches:
36/61
59.0%

Line Branch Exec Source
1 /************************************************************************
2 *
3 * Copyright (C) 2018-2023 IRCAD France
4 * Copyright (C) 2018-2021 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 #include "filter/image/line_drawer.hpp"
24
25 #include <core/spy_log.hpp>
26
27 #include <data/helper/medical_image.hpp>
28
29 #include <utility>
30
31 namespace sight::filter::image
32 {
33
34 //-----------------------------------------------------------------------------
35
36 5 line_drawer::line_drawer(data::image::sptr _img, data::image::csptr _roi) :
37
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 m_image(std::move(_img)),
38 5 m_roi_image(std::move(_roi))
39 {
40
5/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 4 times.
6 m_use_roi = data::helper::medical_image::check_image_validity(m_roi_image);
41
42
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5 m_image_type_size = std::uint8_t(m_image->type().size());
43
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
5 m_roi_type_size = m_use_roi ? std::uint8_t(m_roi_image->type().size()) : 0;
44 5 const auto& size = m_image->size();
45 5 m_y_pitch = size[0];
46 5 m_z_pitch = size[1] * m_y_pitch;
47
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5 }
48
49 //-----------------------------------------------------------------------------
50
51 5 bool line_drawer::draw_ellipse(
52 const line_drawer::coordinates_t& _c,
53 data::image::buffer_t* _value,
54 const double _radius,
55 const std::size_t _first_dim,
56 const std::size_t _second_dim,
57 const bool _overwrite,
58 image_diff& _diff
59 )
60 {
61 5 bool modified = false;
62
63
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 const auto& spacing = m_image->spacing();
64
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 const auto& size = m_image->size();
65
66
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 const double width = _radius / spacing[_first_dim];
67 5 const double height = _radius / spacing[_second_dim];
68
69 5 int orig_x = static_cast<int>(_c[_first_dim]);
70 5 int orig_y = static_cast<int>(_c[_second_dim]);
71
72 5 line_drawer::coordinates_t point = _c;
73
74
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 int w_begin = std::max(static_cast<int>(-width), -orig_x);
75
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 int h_begin = std::max(static_cast<int>(-height), -orig_y);
76
77
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 int w_end = std::min(static_cast<int>(width), static_cast<int>(size[_first_dim]) - 1 - orig_x);
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 int h_end = std::min(static_cast<int>(height), static_cast<int>(size[_second_dim]) - 1 - orig_y);
79
80
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 5 times.
20 for(int y = h_begin ; y <= h_end ; y++)
81 {
82
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 15 times.
116 for(int x = w_begin ; x <= w_end ; x++)
83 {
84 101 double dx = x / width;
85 101 double dy = y / height;
86
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 12 times.
101 if(dx * dx + dy * dy <= 1)
87 {
88 89 point[_first_dim] = static_cast<data::image::index_t>(orig_x) + static_cast<data::image::index_t>(x);
89 89 point[_second_dim] = static_cast<data::image::index_t>(orig_y) + static_cast<data::image::index_t>(y);
90
91 89 const data::image::index_t index = point[0] + point[1] * m_y_pitch + point[2] * m_z_pitch;
92
93 89 modified |= this->draw_pixel(index, _value, _overwrite, _diff);
94 }
95 }
96 }
97
98 5 return modified;
99 }
100
101 //-----------------------------------------------------------------------------
102
103 89 bool line_drawer::draw_pixel(
104 const data::image::index_t _index,
105 data::image::buffer_t* _value,
106 const bool _overwrite,
107 image_diff& _diff
108 )
109 {
110 89 const data::image::buffer_t* pix_buf =
111 89 reinterpret_cast<data::image::buffer_t*>(m_image->get_pixel(_index));
112
113
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 68 times.
89 if(m_use_roi)
114 {
115 21 const auto* roi_val =
116 21 reinterpret_cast<const data::image::buffer_t*>(m_roi_image->get_pixel(_index));
117
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if(data::helper::medical_image::is_buf_null(roi_val, m_roi_type_size))
118 {
119 return false;
120 }
121 }
122
123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 if(std::equal(pix_buf, pix_buf + m_image_type_size, _value))
124 {
125 return false;
126 }
127
128
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
89 if(!_overwrite && !data::helper::medical_image::is_buf_null(pix_buf, m_image_type_size))
129 {
130 return false;
131 }
132
133 89 _diff.add_diff(_index, pix_buf, _value);
134 89 m_image->set_pixel(_index, _value);
135
136 89 return true;
137 }
138
139 //-----------------------------------------------------------------------------
140
141 5 image_diff line_drawer::draw(
142 const bresenham_line::Orientation _orientation,
143 const coordinates_t& _start_coord,
144 const coordinates_t& _end_coord,
145 data::image::buffer_t* _value,
146 const double _thickness,
147 const bool _overwrite
148 )
149 {
150 5 image_diff diff(m_image_type_size, 128);
151
152 5 std::size_t dim0 = 0;
153 5 std::size_t dim1 = 0;
154
155
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 switch(_orientation)
156 {
157 case bresenham_line::Orientation::z_axis:
158 dim0 = 0;
159 dim1 = 1;
160 break;
161
162 case bresenham_line::Orientation::y_axis:
163 dim0 = 2;
164 dim1 = 0;
165 break;
166
167 case bresenham_line::Orientation::x_axis:
168 dim0 = 1;
169 dim1 = 2;
170 break;
171
172 default:
173 SIGHT_ASSERT("Unknown axis", false);
174 dim0 = 0;
175 dim1 = 1;
176 }
177
178
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 bresenham_line::path_t path = bresenham_line::draw(_orientation, _start_coord, _end_coord);
179
180 5 auto pixel = path.begin();
181 5 auto end_pixel = path.end();
182
183 5 bool modified = false;
184
185
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 for( ; pixel != end_pixel ; ++pixel)
186 {
187
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 modified = this->draw_ellipse(*pixel, _value, _thickness / 2.0, dim0, dim1, _overwrite, diff) || modified;
188 }
189
190 5 return diff;
191 }
192
193 } // namespace sight::filter::image
194