GCC Code Coverage Report


Directory: ./
File: image/morpho_math.cpp
Date: 2026-09-27 03:10:11
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