DGtal  1.2.0
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 
41 using namespace DGtal;
42 using namespace std;
43 
44 template < typename TImage, typename TDomain >
45 void 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 
52 template < typename TImage >
53 void fillImageWithCounter ( TImage& anImage )
54 {
55  fillImageWithCounter( anImage, anImage.domain() );
56 }
57 
58 template < typename TImage, typename TFunction, typename TDomain >
59 void 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 
73 template < typename TImage, typename TFunction >
74 void fillImageWithPointFn ( TImage& anImage, TFunction const& aFunction )
75 {
76  fillImageWithPointFn ( anImage, aFunction, anImage.domain() );
77 }
78 
79 template < typename TImage, typename TFunction, typename TDomain >
80 void 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 
94 template < typename TImage, typename TFunction >
95 void incrementImageWithPointFn ( TImage& anImage, TFunction const& aFunction )
96 {
97  incrementImageWithPointFn ( anImage, aFunction, anImage.domain() );
98 }
99 
100 template < typename TDomain, typename TValue, typename TFunction >
101 void 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 
116 template < typename TIterator, typename TDomain, typename TFunction >
117 void 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 
133 template < typename TImage >
134 void 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
238 template < DGtal::Dimension N >
239 struct 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
257 using TestImage3D = TestImage<3>;
258 using Point3D = TestImage3D::Domain::Point;
259 template <> const TestImage3D::Domain TestImage3D::domain{ Point3D{0, 1, 2}, Point3D{12, 8, 11} };
260 template <> const TestImage3D::Domain TestImage3D::subDomain{ Point3D{0, 2, 4}, Point3D{8, 7, 10} };
261 
262 // Test cases
263 TEST_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 
271 TEST_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 
279 TEST_CASE_METHOD( TestImage3D, "Checking ArrayImageAdapter with ImageContainerBySTLVector", "[ImageSTL][FullDomain]" )
280 {
282  auto image_view = makeArrayImageAdapterFromImage( image );
283  checkThat(image_view);
284 }
285 
286 TEST_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
TImageContainer::Point Point
Definition: Image.h:83
TImageContainer::Domain Domain
Definition: Image.h:82
TImageContainer::Value Value
Definition: Image.h:84
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
Aim: Defines the concept describing a read/write image, having an output iterator.
Definition: CImage.h:103
int max(int a, int b)
MyPointD Point
Definition: testClone2.cpp:383
bool checkImage(const Image &a, const Image &b)
TEST_CASE_METHOD(Fixture_object_diamond_with_hole, "Basic Graph functions", "[interface]")
Domain domain
Image image(domain)
ImageContainerBySTLVector< Domain, Value > Image
SECTION("Testing constant forward iterators")
HyperRectDomain< Space > Domain
REQUIRE(domain.isInside(aPoint))