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 |
|
|
|