DGtal 1.3.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 Dimension = typename Point::Dimension;
141 using Coordinate = typename Point::Coordinate;
143
144 // Checks CImage concept.
145 BOOST_CONCEPT_ASSERT( (DGtal::concepts::CImage<TImage>) );
146
147 // Full domain
148 auto const domain = anImage.domain();
149
150 // Sub domain
151 Point lowerPt = domain.lowerBound();
152 Point upperPt = domain.upperBound();
153 for ( Dimension i = 0; i < Domain::dimension; ++i )
154 {
155 lowerPt[i] = std::min( upperPt[i]-1, lowerPt[i] + 1 + static_cast<Coordinate>(i) );
156 upperPt[i] = std::max( lowerPt[i]+1, upperPt[i] - static_cast<Coordinate>(Domain::dimension - i) );
157 }
158 auto const sub_domain = Domain( lowerPt, upperPt );
159
160 // Checks that sub domain is not empty and different of full domain
161 REQUIRE( (!sub_domain.isEmpty() && sub_domain.size() != domain.size()) );
162
163 // Reference image
164 RefImage ref_image( domain );
165
166 // The filling function
167 auto const fn = [] (size_t i, Coordinate x) { return cos( static_cast<Value>(pow(100, i)*x ) ); };
168
169 // Fill with function
170 SECTION( "Filling with point dependant function" )
171 {
172 fillImageWithPointFn( ref_image, fn );
173 fillImageWithPointFn( anImage, fn );
174 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
175 }
176
177 // Fill with counter
178 SECTION( "Filling with counter" )
179 {
180 fillImageWithCounter( ref_image );
181 fillImageWithCounter( anImage );
182 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
183 }
184
185 // Fast filling with function
186 SECTION( "Fast filling with point dependant function" )
187 {
188 fastFillImageWithPointFn( ref_image, fn );
189 fastFillImageWithPointFn( anImage, fn );
190 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
191 }
192
193 // Tests that need images to be initialized.
194 SECTION( "Tests on initialized images" )
195 {
196 fastFillImageWithPointFn( ref_image, fn );
197 fastFillImageWithPointFn( anImage, fn );
198 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
199
200 // Increment with function
201 SECTION( "Incrementing with point dependant function" )
202 {
203 incrementImageWithPointFn( ref_image, fn );
204 incrementImageWithPointFn( anImage, fn );
205 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
206 }
207
208 // Partial fill with counter
209 SECTION( "Partial filling with counter" )
210 {
211 auto sub_image = makeArrayImageAdapterFromImage( anImage, sub_domain );
212 fillImageWithCounter( ref_image, sub_domain );
213 fillImageWithCounter( sub_image );
214 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
215 }
216
217 // Partial increment with function
218 SECTION( "Partial increment with point dependant function" )
219 {
220 auto sub_image = makeArrayImageAdapterFromImage( anImage, sub_domain );
221 incrementImageWithPointFn( ref_image, fn, sub_domain );
222 incrementImageWithPointFn( sub_image, fn );
223 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
224 }
225
226 // Fast partial fill with function
227 SECTION( "Fast partial filling with point dependand function" )
228 {
229 auto sub_image = makeArrayImageAdapterFromImage( anImage, sub_domain );
230 fillImageWithPointFn( ref_image, fn, sub_domain );
231 fastFillImageWithPointFn( sub_image, fn );
232 REQUIRE( std::equal( ref_image.begin(), ref_image.end(), anImage.begin() ) );
233 }
234 }
235}
236
237// Context for each image test
238template < DGtal::Dimension N >
239struct TestImage
240{
241 using Space = SpaceND<N>;
243 using Value = double;
244
245 template < typename TImage >
246 static
247 void checkThat( TImage & anImage )
248 {
249 checkImage(anImage);
250 }
251
252 static const Domain domain;
253 static const Domain subDomain;
254};
255
256// Context data for 3D image tests
257using TestImage3D = TestImage<3>;
258using Point3D = TestImage3D::Domain::Point;
259template <> const TestImage3D::Domain TestImage3D::domain{ Point3D{0, 1, 2}, Point3D{12, 8, 11} };
260template <> const TestImage3D::Domain TestImage3D::subDomain{ Point3D{0, 2, 4}, Point3D{8, 7, 10} };
261
262// Test cases
263TEST_CASE_METHOD( TestImage3D, "Checking ArrayImageAdapter with C-style array", "[CArray][FullDomain]" )
264{
265 Value* data = new Value[domain.size()];
266 auto image = makeArrayImageAdapterFromIterator( data, domain );
267 checkThat(image);
268 delete[] data;
269}
270
271TEST_CASE_METHOD( TestImage3D, "Checking ArrayImageAdapter with C-style array on sub-domain", "[CArray][SubDomain]" )
272{
273 Value* data = new Value[domain.size()];
274 auto image = makeArrayImageAdapterFromIterator( data, domain, subDomain );
275 checkThat(image);
276 delete[] data;
277}
278
279TEST_CASE_METHOD( TestImage3D, "Checking ArrayImageAdapter with ImageContainerBySTLVector", "[ImageSTL][FullDomain]" )
280{
282 auto image_view = makeArrayImageAdapterFromImage( image );
283 checkThat(image_view);
284}
285
286TEST_CASE_METHOD( TestImage3D, "Checking ArrayImageAdapter with ImageContainerBySTLVector on sub-domain", "[ImageSTL][SubDomain]" )
287{
289 auto image_view = makeArrayImageAdapterFromImage( image, subDomain );
290 checkThat(image_view);
291}
292
const Point & lowerBound() const
const Point & upperBound() const
const Domain & domain() const
Aim: implements association bewteen points lying in a digital domain and values.
Definition: Image.h:70
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:137
STL namespace.
Aim: Defines the concept describing a read/write image, having an output iterator.
Definition: CImage.h:103
MyPointD Point
Definition: testClone2.cpp:383
TEST_CASE_METHOD(Fixture_object_diamond_with_hole, "Basic Graph functions", "[interface]")
Domain domain
SECTION("Testing constant forward iterators")
HyperRectDomain< Space > Domain
REQUIRE(domain.isInside(aPoint))