DGtal 1.4.0
Loading...
Searching...
No Matches
testArrayImageAdapter.cpp
1
26#include <cstddef>
27#include <iostream>
28#include <new>
29#include <cmath>
30
31#include <DGtal/kernel/SpaceND.h>
32#include <DGtal/kernel/domains/HyperRectDomain.h>
33#include <DGtal/images/ImageContainerBySTLVector.h>
34#include <DGtal/images/CConstImage.h>
35#include <DGtal/images/CImage.h>
36
37#include <DGtal/images/ArrayImageAdapter.h>
38
39#include "DGtalCatch.h"
40
41using namespace DGtal;
42using namespace std;
43
44template < typename TImage, typename TDomain >
45void fillImageWithCounter ( TImage& anImage, TDomain const& aDomain )
46{
47 size_t cnt = 0;
48 for ( auto const& point : aDomain )
49 anImage.setValue( point, cnt++ );
50}
51
52template < typename TImage >
53void fillImageWithCounter ( TImage& anImage )
54{
55 fillImageWithCounter( anImage, anImage.domain() );
56}
57
58template < typename TImage, typename TFunction, typename TDomain >
59void fillImageWithPointFn ( TImage& anImage, TFunction const& aFunction, TDomain const& domain )
60{
61 using Image = TImage;
62 using Value = typename Image::Value;
63 for ( auto const& point : domain )
64 {
65 Value value = 0;
66 for ( Dimension i = 0; i < Image::dimension; ++i )
67 value += aFunction( i, point[i] );
68
69 anImage.setValue(point, value);
70 }
71}
72
73template < typename TImage, typename TFunction >
74void fillImageWithPointFn ( TImage& anImage, TFunction const& aFunction )
75{
76 fillImageWithPointFn ( anImage, aFunction, anImage.domain() );
77}
78
79template < typename TImage, typename TFunction, typename TDomain >
80void incrementImageWithPointFn ( TImage& anImage, TFunction const& aFunction, TDomain const& domain )
81{
82 using Image = TImage;
83 using Value = typename Image::Value;
84 for ( auto const& point : domain )
85 {
86 Value value = anImage(point);
87 for ( Dimension i = 0; i < Image::dimension; ++i )
88 value += aFunction( i, point[i] );
89
90 anImage.setValue(point, value);
91 }
92}
93
94template < typename TImage, typename TFunction >
95void incrementImageWithPointFn ( TImage& anImage, TFunction const& aFunction )
96{
97 incrementImageWithPointFn ( anImage, aFunction, anImage.domain() );
98}
99
100template < typename TDomain, typename TValue, typename TFunction >
101void fastFillImageWithPointFn ( ImageContainerBySTLVector<TDomain, TValue>& anImage, TFunction const& aFunction )
102{
103 typedef ImageContainerBySTLVector<TDomain, TValue> Image; // 'typedef' instead of 'using' because of g++ 4.7.4 bug.
104 using Value = typename Image::Value;
105 auto imgit = anImage.begin();
106 for ( auto const& point : anImage.domain() )
107 {
108 Value value = 0;
109 for ( Dimension i = 0; i < Image::dimension; ++i )
110 value += aFunction( i, point[i] );
111
112 *(imgit++) = value;
113 }
114}
115
116template < typename TIterator, typename TDomain, typename TFunction >
117void fastFillImageWithPointFn ( ArrayImageAdapter<TIterator, TDomain>& anImage, TFunction const& aFunction )
118{
119 typedef ArrayImageAdapter<TIterator, TDomain> Image; // 'typedef' instead of 'using' because of g++ 4.7.4 bug.
120 using Value = typename Image::Value;
121 for ( auto imgit = anImage.begin(); imgit != anImage.end(); ++imgit )
122 {
123 Value value = 0;
124 auto const point = imgit.getPoint();
125
126 for ( Dimension i = 0; i < Image::dimension; ++i )
127 value += aFunction( i, point[i] );
128
129 *imgit = value;
130 }
131}
132
133template < typename TImage >
134void checkImage( TImage& anImage )
135{
136 using Image = TImage;
137 using Value = typename Image::Value;
138 using Domain = typename Image::Domain;
139 using Point = typename Image::Point;
140 using Coordinate = typename Point::Coordinate;
142
143 // Checks CImage concept.
144 BOOST_CONCEPT_ASSERT( (DGtal::concepts::CImage<TImage>) );
145
146 // Full domain
147 auto const domain = anImage.domain();
148
149 // Sub domain
150 Point lowerPt = domain.lowerBound();
151 Point upperPt = domain.upperBound();
152 for ( Dimension i = 0; i < Domain::dimension; ++i )
153 {
154 lowerPt[i] = std::min( upperPt[i]-1, lowerPt[i] + 1 + static_cast<Coordinate>(i) );
155 upperPt[i] = std::max( lowerPt[i]+1, upperPt[i] - static_cast<Coordinate>(Domain::dimension - i) );
156 }
157 auto const sub_domain = Domain( lowerPt, upperPt );
158
159 // Checks that sub domain is not empty and different of full domain
160 REQUIRE( (!sub_domain.isEmpty() && sub_domain.size() != domain.size()) );
161
162 // Reference image
163 RefImage ref_image( domain );
164
165 // The filling function
166 auto const fn = [] (size_t i, Coordinate x) { return cos( static_cast<Value>(pow(100, i)*x ) ); };
167
168 // Fill with function
169 SECTION( "Filling with point dependant function" )
170 {
171 fillImageWithPointFn( ref_image, fn );
172 fillImageWithPointFn( anImage, fn );
173 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
174 }
175
176 // Fill with counter
177 SECTION( "Filling with counter" )
178 {
179 fillImageWithCounter( ref_image );
180 fillImageWithCounter( anImage );
181 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
182 }
183
184 // Fast filling with function
185 SECTION( "Fast filling with point dependant function" )
186 {
187 fastFillImageWithPointFn( ref_image, fn );
188 fastFillImageWithPointFn( anImage, fn );
189 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
190 }
191
192 // Tests that need images to be initialized.
193 SECTION( "Tests on initialized images" )
194 {
195 fastFillImageWithPointFn( ref_image, fn );
196 fastFillImageWithPointFn( anImage, fn );
197 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
198
199 // Increment with function
200 SECTION( "Incrementing with point dependant function" )
201 {
202 incrementImageWithPointFn( ref_image, fn );
203 incrementImageWithPointFn( anImage, fn );
204 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
205 }
206
207 // Partial fill with counter
208 SECTION( "Partial filling with counter" )
209 {
210 auto sub_image = makeArrayImageAdapterFromImage( anImage, sub_domain );
211 fillImageWithCounter( ref_image, sub_domain );
212 fillImageWithCounter( sub_image );
213 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
214 }
215
216 // Partial increment with function
217 SECTION( "Partial increment with point dependant function" )
218 {
219 auto sub_image = makeArrayImageAdapterFromImage( anImage, sub_domain );
220 incrementImageWithPointFn( ref_image, fn, sub_domain );
221 incrementImageWithPointFn( sub_image, fn );
222 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
223 }
224
225 // Fast partial fill with function
226 SECTION( "Fast partial filling with point dependand function" )
227 {
228 auto sub_image = makeArrayImageAdapterFromImage( anImage, sub_domain );
229 fillImageWithPointFn( ref_image, fn, sub_domain );
230 fastFillImageWithPointFn( sub_image, fn );
231 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
232 }
233 }
234}
235
236// Context for each image test
237template < DGtal::Dimension N >
238struct TestImage
239{
240 using Space = SpaceND<N>;
242 using Value = double;
243
244 template < typename TImage >
245 static
246 void checkThat( TImage & anImage )
247 {
248 checkImage(anImage);
249 }
250
251 static const Domain domain;
252 static const Domain subDomain;
253};
254
255// Context data for 3D image tests
256using TestImage3D = TestImage<3>;
257using Point3D = TestImage3D::Domain::Point;
258template <> const TestImage3D::Domain TestImage3D::domain{ Point3D{0, 1, 2}, Point3D{12, 8, 11} };
259template <> const TestImage3D::Domain TestImage3D::subDomain{ Point3D{0, 2, 4}, Point3D{8, 7, 10} };
260
261// Test cases
262TEST_CASE_METHOD( TestImage3D, "Checking ArrayImageAdapter with C-style array", "[CArray][FullDomain]" )
263{
264 Value* data = new Value[domain.size()];
265 auto image = makeArrayImageAdapterFromIterator( data, domain );
266 checkThat(image);
267 delete[] data;
268}
269
270TEST_CASE_METHOD( TestImage3D, "Checking ArrayImageAdapter with C-style array on sub-domain", "[CArray][SubDomain]" )
271{
272 Value* data = new Value[domain.size()];
273 auto image = makeArrayImageAdapterFromIterator( data, domain, subDomain );
274 checkThat(image);
275 delete[] data;
276}
277
278TEST_CASE_METHOD( TestImage3D, "Checking ArrayImageAdapter with ImageContainerBySTLVector", "[ImageSTL][FullDomain]" )
279{
281 auto image_view = makeArrayImageAdapterFromImage( image );
282 checkThat(image_view);
283}
284
285TEST_CASE_METHOD( TestImage3D, "Checking ArrayImageAdapter with ImageContainerBySTLVector on sub-domain", "[ImageSTL][SubDomain]" )
286{
288 auto image_view = makeArrayImageAdapterFromImage( image, subDomain );
289 checkThat(image_view);
290}
291
const Point & lowerBound() const
const Point & upperBound() const
Aim: implements association bewteen points lying in a digital domain and values.
Definition Image.h:70
void setValue(const Point &aPoint, const Value &aValue)
Definition Image.h:247
DGtal is the top-level namespace which contains all DGtal functions and types.
ArrayImageAdapter< TArrayIterator, TDomain > makeArrayImageAdapterFromIterator(TArrayIterator anArrayIterator, TDomain const &aFullDomain, TDomain const &aViewDomain)
ArrayImageAdapter< decltype(((TImage *) nullptr) ->begin()), TDomain > makeArrayImageAdapterFromImage(TImage &anImage, TDomain const &aViewDomain)
DGtal::uint32_t Dimension
Definition Common.h:136
STL namespace.
Aim: Defines the concept describing a read/write image, having an output iterator.
Definition CImage.h:103
MyPointD Point
TEST_CASE_METHOD(Fixture_object_diamond_with_hole, "Basic Graph functions", "[interface]")
Domain domain
ImageContainerBySTLVector< Domain, Value > Image
SECTION("Testing constant forward iterators")
HyperRectDomain< Space > Domain
REQUIRE(domain.isInside(aPoint))