1 // Copyright (C) 2014  Davis E. King (davis@dlib.net)
2 // License: Boost Software License   See LICENSE.txt for the full license.
3 #ifndef DLIB_GeNERIC_IMAGE_Hh_
4 #define DLIB_GeNERIC_IMAGE_Hh_
5 
6 #include "../assert.h"
7 #include "../pixel.h"
8 #include <type_traits>
9 
10 namespace dlib
11 {
12 
13     /*!
14         In dlib, an "image" is any object that implements the generic image interface.  In
15         particular, this simply means that an image type (let's refer to it as image_type
16         from here on) has the following seven global functions defined for it:
17             - long        num_rows      (const image_type& img)
18             - long        num_columns   (const image_type& img)
19             - void        set_image_size(      image_type& img, long rows, long cols)
20             - void*       image_data    (      image_type& img)
21             - const void* image_data    (const image_type& img)
22             - long        width_step    (const image_type& img)
23             - void        swap          (      image_type& a, image_type& b)
24         And also provides a specialization of the image_traits template that looks like:
25             namespace dlib
26             {
27                 template <>
28                 struct image_traits<image_type>
29                 {
30                     typedef the_type_of_pixel_used_in_image_type pixel_type;
31                 };
32             }
33 
34         Additionally, an image object must be default constructable.  This means that
35         expressions of the form:
36             image_type img;
37         Must be legal.
38 
39         Finally, the type of pixel in image_type must have a pixel_traits specialization.
40         That is, pixel_traits<typename image_traits<image_type>::pixel_type> must be one of
41         the specializations of pixel_traits.
42 
43 
44         To be very precise, the seven functions defined above are defined thusly:
45 
46             long num_rows(
47                 const image_type& img
48             );
49             /!*
50                 ensures
51                     - returns the number of rows in the given image
52             *!/
53 
54             long num_columns(
55                 const image_type& img
56             );
57             /!*
58                 ensures
59                     - returns the number of columns in the given image
60             *!/
61 
62             void set_image_size(
63                 image_type& img,
64                 long rows,
65                 long cols
66             );
67             /!*
68                 requires
69                     - rows >= 0 && cols >= 0
70                 ensures
71                     - num_rows(#img) == rows
72                     - num_columns(#img) == cols
73             *!/
74 
75             void* image_data(
76                 image_type& img
77             );
78             /!*
79                 ensures
80                     - returns a non-const pointer to the pixel at row and column position 0,0
81                       in the given image.  Or if the image has zero rows or columns in it
82                       then this function returns NULL.
83                     - The image lays pixels down in row major order.  However, there might
84                       be padding at the end of each row.  The amount of padding is given by
85                       width_step(img).
86             *!/
87 
88             const void* image_data(
89                 const image_type& img
90             );
91             /!*
92                 ensures
93                     - returns a const pointer to the pixel at row and column position 0,0 in
94                       the given image.  Or if the image has zero rows or columns in it then
95                       this function returns NULL.
96                     - The image lays pixels down in row major order.  However, there might
97                       be padding at the end of each row.  The amount of padding is given by
98                       width_step(img).
99             *!/
100 
101             long width_step(
102                 const image_type& img
103             );
104             /!*
105                 ensures
106                     - returns the size of one row of the image, in bytes.  More precisely,
107                       return a number N such that: (char*)image_data(img) + N*R == a
108                       pointer to the first pixel in the R-th row of the image. This means
109                       that the image must lay its pixels down in row major order.
110             *!/
111 
112             void swap(
113                 image_type& a,
114                 image_type& b
115             );
116             /!*
117                 ensures
118                     - swaps the state of a and b
119             *!/
120     !*/
121 
122 // ----------------------------------------------------------------------------------------
123 
124     template <typename image_type>
125     struct image_traits;
126     /*!
127         WHAT THIS OBJECT REPRESENTS
128             This is a traits class for generic image objects.  You can use it to find out
129             the pixel type contained within an image via an expression of the form:
130                 image_traits<image_type>::pixel_type
131     !*/
132 
133     template <typename image_type>
134     struct is_rgb_image { const static bool value = pixel_traits<typename image_traits<image_type>::pixel_type>::rgb; };
135 
136     template <typename image_type>
137     struct is_color_space_cartesian_image { const static bool value =
138         pixel_traits<typename image_traits<image_type>::pixel_type>::rgb ||
139         pixel_traits<typename image_traits<image_type>::pixel_type>::lab ||
140         pixel_traits<typename image_traits<image_type>::pixel_type>::grayscale; };
141     /*
142         Tells if all color components of image pixels are in cartesian coordinates, compared to e.g. polar coordinates.
143         Polar coordinates that may require more complicated blending.
144     */
145 
146     template <typename image_type>
147     struct is_grayscale_image { const static bool value = pixel_traits<typename image_traits<image_type>::pixel_type>::grayscale; };
148 
149 
150     // Check if T has image_traits<T> defined for it.
151     template <typename T, typename enabled = size_t>
152     struct is_image_type : public std::false_type{};
153     template <typename T>
154     struct is_image_type<T, decltype(sizeof(image_traits<typename std::decay<T>::type>))> : public std::true_type{};
155 
156 // ----------------------------------------------------------------------------------------
157 // ----------------------------------------------------------------------------------------
158 //                   UTILITIES TO MAKE ACCESSING IMAGE PIXELS SIMPLER
159 // ----------------------------------------------------------------------------------------
160 // ----------------------------------------------------------------------------------------
161 
162     template <
163         typename image_type
164         >
165     class image_view
166     {
167         /*!
168             REQUIREMENTS ON image_type
169                 image_type must be an image object as defined at the top of this file.
170 
171             WHAT THIS OBJECT REPRESENTS
172                 This object takes an image object and wraps it with an interface that makes
173                 it look like a dlib::array2d.  That is, it makes it look similar to a
174                 regular 2-dimensional C style array, making code which operates on the
175                 pixels simple to read.
176 
177                 Note that an image_view instance is valid until the image given to its
178                 constructor is modified through an interface other than the image_view
179                 instance.  This is because, for example, someone might cause the underlying
180                 image object to reallocate its memory, thus invalidating the pointer to its
181                 pixel data stored in the image_view.
182 
183                 As an side, the reason why this object stores a pointer to the image
184                 object's data and uses that pointer instead of calling image_data() each
185                 time a pixel is accessed is to allow for image objects to implement
186                 complex, and possibly slow, image_data() functions.  For example, an image
187                 object might perform some kind of synchronization between a GPU and the
188                 host memory during a call to image_data().  Therefore, we call image_data()
189                 only in image_view's constructor to avoid the performance penalty of
190                 calling it for each pixel access.
191         !*/
192 
193     public:
194         typedef typename image_traits<image_type>::pixel_type pixel_type;
195 
196         image_view(
197             image_type& img
198         ) :
199             _data(reinterpret_cast<char*>(image_data(img))),
200             _width_step(width_step(img)),
201             _nr(num_rows(img)),
202             _nc(num_columns(img)),
203             _img(&img)
204         {}
205 
206         long nr() const { return _nr; }
207         /*!
208             ensures
209                 - returns the number of rows in this image.
210         !*/
211 
212         long nc() const { return _nc; }
213         /*!
214             ensures
215                 - returns the number of columns in this image.
216         !*/
217 
218         unsigned long size() const { return static_cast<unsigned long>(nr()*nc()); }
219         /*!
220             ensures
221                 - returns the number of pixels in this image.
222         !*/
223 
224 #ifndef ENABLE_ASSERTS
225         pixel_type* operator[] (long row) { return (pixel_type*)(_data+_width_step*row); }
226         /*!
227             requires
228                 - 0 <= row < nr()
229             ensures
230                 - returns a pointer to the first pixel in the row-th row.  Therefore, the
231                   pixel at row and column position r,c can be accessed via (*this)[r][c].
232         !*/
233 
234         const pixel_type* operator[] (long row) const { return (const pixel_type*)(_data+_width_step*row); }
235         /*!
236             requires
237                 - 0 <= row < nr()
238             ensures
239                 - returns a const pointer to the first pixel in the row-th row.  Therefore,
240                   the pixel at row and column position r,c can be accessed via
241                   (*this)[r][c].
242         !*/
243 #else
244         // If asserts are enabled then we need to return a proxy class so we can make sure
245         // the column accesses don't go out of bounds.
246         struct pix_row
247         {
248             pix_row(pixel_type* data_, long nc_) : data(data_),_nc(nc_) {}
249             const pixel_type& operator[] (long col) const
250             {
251                 DLIB_ASSERT(0 <= col && col < _nc,
252                     "\t The given column index is out of range."
253                     << "\n\t col: " << col
254                     << "\n\t _nc: " << _nc);
255                 return data[col];
256             }
257             pixel_type& operator[] (long col)
258             {
259                 DLIB_ASSERT(0 <= col && col < _nc,
260                     "\t The given column index is out of range."
261                     << "\n\t col: " << col
262                     << "\n\t _nc: " << _nc);
263                 return data[col];
264             }
265         private:
266             pixel_type* const data;
267             const long _nc;
268         };
269         pix_row operator[] (long row)
270         {
271             DLIB_ASSERT(0 <= row && row < _nr,
272                 "\t The given row index is out of range."
273                 << "\n\t row: " << row
274                 << "\n\t _nr: " << _nr);
275             return pix_row((pixel_type*)(_data+_width_step*row), _nc);
276         }
277         const pix_row operator[] (long row) const
278         {
279             DLIB_ASSERT(0 <= row && row < _nr,
280                 "\t The given row index is out of range."
281                 << "\n\t row: " << row
282                 << "\n\t _nr: " << _nr);
283             return pix_row((pixel_type*)(_data+_width_step*row), _nc);
284         }
285 #endif
286 
287         void set_size(long rows, long cols)
288         /*!
289             requires
290                 - rows >= 0 && cols >= 0
291             ensures
292                 - Tells the underlying image to resize itself to have the given number of
293                   rows and columns.
294                 - #nr() == rows
295                 - #nc() == cols
296         !*/
297         {
298             DLIB_ASSERT((cols >= 0 && rows >= 0),
299                         "\t image_view::set_size(long rows, long cols)"
300                         << "\n\t The images can't have negative rows or columns."
301                         << "\n\t cols: " << cols
302                         << "\n\t rows: " << rows
303             );
304             set_image_size(*_img, rows, cols); *this = *_img;
305         }
306 
307         void clear() { set_size(0,0); }
308         /*!
309             ensures
310                 - sets the image to have 0 pixels in it.
311         !*/
312 
313         long get_width_step() const { return _width_step; }
314 
315     private:
316 
317         char* _data;
318         long _width_step;
319         long _nr;
320         long _nc;
321         image_type* _img;
322     };
323 
324 // ----------------------------------------------------------------------------------------
325 
326     template <typename image_type>
327     class const_image_view
328     {
329         /*!
330             REQUIREMENTS ON image_type
331                 image_type must be an image object as defined at the top of this file.
332 
333             WHAT THIS OBJECT REPRESENTS
334                 This object is just like the image_view except that it provides a "const"
335                 view into an image.  That is, it has the same interface as image_view
336                 except that you can't modify the image through a const_image_view.
337         !*/
338 
339     public:
340         typedef typename image_traits<image_type>::pixel_type pixel_type;
341 
342         const_image_view(
343             const image_type& img
344         ) :
345             _data(reinterpret_cast<const char*>(image_data(img))),
346             _width_step(width_step(img)),
347             _nr(num_rows(img)),
348             _nc(num_columns(img))
349         {}
350 
351         long nr() const { return _nr; }
352         long nc() const { return _nc; }
353         unsigned long size() const { return static_cast<unsigned long>(nr()*nc()); }
354 #ifndef ENABLE_ASSERTS
355         const pixel_type* operator[] (long row) const { return (const pixel_type*)(_data+_width_step*row); }
356 #else
357         // If asserts are enabled then we need to return a proxy class so we can make sure
358         // the column accesses don't go out of bounds.
359         struct pix_row
360         {
361             pix_row(pixel_type* data_, long nc_) : data(data_),_nc(nc_) {}
362             const pixel_type& operator[] (long col) const
363             {
364                 DLIB_ASSERT(0 <= col && col < _nc,
365                     "\t The given column index is out of range."
366                     << "\n\t col: " << col
367                     << "\n\t _nc: " << _nc);
368                 return data[col];
369             }
370         private:
371             pixel_type* const data;
372             const long _nc;
373         };
374         const pix_row operator[] (long row) const
375         {
376             DLIB_ASSERT(0 <= row && row < _nr,
377                 "\t The given row index is out of range."
378                 << "\n\t row: " << row
379                 << "\n\t _nr: " << _nr);
380             return pix_row((pixel_type*)(_data+_width_step*row), _nc);
381         }
382 #endif
383 
384         long get_width_step() const { return _width_step; }
385 
386     private:
387         const char* _data;
388         long _width_step;
389         long _nr;
390         long _nc;
391     };
392 
393 // ----------------------------------------------------------------------------------------
394 
395     template <typename image_type>
396     image_view<image_type> make_image_view ( image_type& img)
397     { return image_view<image_type>(img); }
398     /*!
399         requires
400             - image_type == an image object that implements the interface defined at the
401               top of this file.
402         ensures
403             - constructs an image_view from an image object
404     !*/
405 
406     template <typename image_type>
407     const_image_view<image_type> make_image_view (const image_type& img)
408     { return const_image_view<image_type>(img); }
409     /*!
410         requires
411             - image_type == an image object that implements the interface defined at the
412               top of this file.
413         ensures
414             - constructs a const_image_view from an image object
415     !*/
416 
417 
418     // Don't stack image views on image views since that's pointless and just slows the
419     // compilation.
420     template <typename T> image_view<T>&             make_image_view ( image_view<T>& img)             { return img; }
421     template <typename T> const image_view<T>&       make_image_view ( const image_view<T>& img)       { return img; }
422     template <typename T> const_image_view<T>&       make_image_view ( const_image_view<T>& img)       { return img; }
423     template <typename T> const const_image_view<T>& make_image_view ( const const_image_view<T>& img) { return img; }
424 
425 // ----------------------------------------------------------------------------------------
426 
427     template <typename image_type>
428     inline unsigned long image_size(
429         const image_type& img
430     ) { return num_columns(img)*num_rows(img); }
431     /*!
432         requires
433             - image_type == an image object that implements the interface defined at the
434               top of this file.
435         ensures
436             - returns the number of pixels in the given image.
437     !*/
438 
439 // ----------------------------------------------------------------------------------------
440 
441     template <typename image_type>
442     inline long num_rows(
443         const image_type& img
444     ) { return img.nr(); }
445     /*!
446         ensures
447             - By default, try to use the member function .nr() to determine the number
448               of rows in an image.  However, as stated at the top of this file, image
449               objects should provide their own overload of num_rows() if needed.
450     !*/
451 
452     template <typename image_type>
453     inline long num_columns(
454         const image_type& img
455     ) { return img.nc(); }
456     /*!
457         ensures
458             - By default, try to use the member function .nc() to determine the number
459               of columns in an image.  However, as stated at the top of this file, image
460               objects should provide their own overload of num_rows() if needed.
461     !*/
462 
463     template <typename image_type1, typename image_type2>
464     typename std::enable_if<is_image_type<image_type1>::value&&is_image_type<image_type2>::value, bool>::type
465     have_same_dimensions (
466         const image_type1& img1,
467         const image_type2& img2
468     ) { return num_rows(img1)==num_rows(img2) && num_columns(img1)==num_columns(img2); }
469     /*!
470         ensures
471             - returns true if and only if the two given images have the same dimensions.
472     !*/
473 
474     template <typename image_type1, typename image_type2, typename ...T>
475     typename std::enable_if<is_image_type<image_type1>::value&&is_image_type<image_type2>::value, bool>::type
476     have_same_dimensions (
477         const image_type1& img1,
478         const image_type2& img2,
479         T&& ...args
480     ) { return have_same_dimensions(img1,img2) && have_same_dimensions(img1,args...); }
481 
482 // ----------------------------------------------------------------------------------------
483 // ----------------------------------------------------------------------------------------
484 //            Make the image views implement the generic image interface
485 // ----------------------------------------------------------------------------------------
486 // ----------------------------------------------------------------------------------------
487 
488     template <typename T>
489     struct image_traits<image_view<T>>
490     {
491         typedef typename image_traits<T>::pixel_type pixel_type;
492     };
493     template <typename T>
494     struct image_traits<const image_view<T>>
495     {
496         typedef typename image_traits<T>::pixel_type pixel_type;
497     };
498 
499     template <typename T>
500     inline long num_rows( const image_view<T>& img) { return img.nr(); }
501     template <typename T>
502     inline long num_columns( const image_view<T>& img) { return img.nc(); }
503 
504     template <typename T>
505     inline void set_image_size( image_view<T>& img, long rows, long cols ) { img.set_size(rows,cols); }
506 
507     template <typename T>
508     inline void* image_data( image_view<T>& img)
509     {
510         if (img.size() != 0)
511             return &img[0][0];
512         else
513             return 0;
514     }
515 
516     template <typename T>
517     inline const void* image_data(
518         const image_view<T>& img
519     )
520     {
521         if (img.size() != 0)
522             return &img[0][0];
523         else
524             return 0;
525     }
526 
527     template <typename T>
528     inline long width_step( const image_view<T>& img) { return img.get_width_step(); }
529 
530 // ----------------------------------------------------------------------------------------
531 
532     template <typename T>
533     struct image_traits<const_image_view<T>>
534     {
535         typedef typename image_traits<T>::pixel_type pixel_type;
536     };
537     template <typename T>
538     struct image_traits<const const_image_view<T>>
539     {
540         typedef typename image_traits<T>::pixel_type pixel_type;
541     };
542 
543     template <typename T>
544     inline long num_rows( const const_image_view<T>& img) { return img.nr(); }
545     template <typename T>
546     inline long num_columns( const const_image_view<T>& img) { return img.nc(); }
547 
548     template <typename T>
549     inline const void* image_data(
550         const const_image_view<T>& img
551     )
552     {
553         if (img.size() != 0)
554             return &img[0][0];
555         else
556             return 0;
557     }
558 
559     template <typename T>
560     inline long width_step( const const_image_view<T>& img) { return img.get_width_step(); }
561 
562 // ----------------------------------------------------------------------------------------
563 
564 }
565 
566 #endif // DLIB_GeNERIC_IMAGE_Hh_
567 
568