GCC Code Coverage Report


Directory: ./
File: lib/geogram/image/morpho_math.cpp
Date: 2026-09-07 02:25:23
Exec Total Coverage
Lines: 0 64 0.0%
Functions: 0 6 0.0%
Branches: 0 56 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40 #include <geogram/image/morpho_math.h>
41 #include <geogram/image/image.h>
42 #include <vector>
43 #include <string.h>
44
45 namespace GEO {
46
47 static inline bool has_value(Memory::byte* p, size_t bytes_per_pixel_) {
48 bool result = false;
49 switch(bytes_per_pixel_) {
50 case 1:
51 result = (*p != 0);
52 break;
53 case 3:
54 result = (p[0] != 0 || p[1] != 0 || p[2] != 0);
55 break;
56 case 4:
57 result = (p[3] != 0);
58 break;
59 default:
60 geo_assert_not_reached;
61 }
62 return result;
63 }
64
65 void StructuringElement::convolve(
66 Memory::byte* from, Memory::byte* to
67 ) const {
68 if(has_value(from, bytes_per_pixel_)) {
69 for(size_t i=0; i<bytes_per_pixel_; i++) {
70 to[i] = from[i];
71 }
72 } else {
73 int rgb[4];
74 int nb_neigh = 0;
75 rgb[0] = 0;
76 rgb[1] = 0;
77 rgb[2] = 0;
78 rgb[3] = 0;
79
80 for(index_t i=0; i<offset_.size(); i++) {
81 for(size_t j=0; j<bytes_per_pixel_; j++) {
82 rgb[j] += (from + offset_[i])[j];
83 }
84 if(has_value(from + offset_[i], bytes_per_pixel_)) {
85 nb_neigh++;
86 }
87 }
88
89 if(nb_neigh == 0) {
90 nb_neigh = 1;
91 }
92
93 for(size_t j=0; j<bytes_per_pixel_; j++) {
94 to[j] = Memory::byte(rgb[j] / nb_neigh);
95 }
96
97 }
98 }
99
100
101 MorphoMath::MorphoMath(Image* target) {
102 target_ = target;
103 geo_assert(target_->component_encoding() == Image::BYTE);
104 width_ = target_->width();
105 height_ = target_->height();
106 bytes_per_pixel_ = target_->bytes_per_pixel();
107 bytes_per_line_ = bytes_per_pixel_ * width_;
108 graph_mem_ = target_->base_mem();
109 }
110
111 MorphoMath::~MorphoMath() {
112 target_ = nullptr;
113 }
114
115 void MorphoMath::dilate(index_t nb_iterations) {
116 StructuringElement str(target_);
117 str.add_neighbor(-1,-1);
118 str.add_neighbor(-1, 0);
119 str.add_neighbor(-1, 1);
120 str.add_neighbor( 0,-1);
121 str.add_neighbor( 0, 0);
122 str.add_neighbor( 0, 1);
123 str.add_neighbor( 1,-1);
124 str.add_neighbor( 1, 0);
125 str.add_neighbor( 1, 1);
126 dilate(str, nb_iterations);
127 }
128
129 void MorphoMath::dilate(
130 const StructuringElement& str, index_t nb_iterations
131 ) {
132 Image_var tmp = new Image(
133 target_->color_encoding(),
134 target_->component_encoding(),
135 target_->width(),
136 target_->height()
137 );
138 Memory::copy(tmp->base_mem(), target_->base_mem(), target_->bytes());
139
140 index_t R = str.radius();
141
142 index_t line_offset = (R * index_t(bytes_per_pixel_));
143
144 for(index_t iter=0; iter<nb_iterations; iter++) {
145 Memory::byte* from_line =
146 target_->base_mem() + R * bytes_per_line_;
147 Memory::byte* to_line =
148 tmp->base_mem() + R * bytes_per_line_;
149 for(index_t y=R; y<height_ - R; ++y) {
150 Memory::byte* from = from_line + line_offset;
151 Memory::byte* to = to_line + line_offset;
152 for(index_t x=R; x<width_ - R; ++x) {
153 from += bytes_per_pixel_;
154 to += bytes_per_pixel_;
155 str.convolve(from, to);
156 }
157 from_line += bytes_per_line_;
158 to_line += bytes_per_line_;
159 }
160 Memory::copy(
161 target_->base_mem(), tmp->base_mem(),
162 target_->bytes()
163 );
164 }
165 }
166 }
167