1 // Copyright (C) 2008  Davis E. King (davis@dlib.net), Nils Labugt
2 // License: Boost Software License   See LICENSE.txt for the full license.
3 #ifndef DLIB_PNG_IMPORT
4 #define DLIB_PNG_IMPORT
5 
6 #include <memory>
7 
8 #include "png_loader_abstract.h"
9 #include "image_loader.h"
10 #include "../pixel.h"
11 #include "../dir_nav.h"
12 #include "../test_for_odr_violations.h"
13 
14 namespace dlib
15 {
16 
17     struct LibpngData;
18     struct PngBufferReaderState;
19     struct FileInfo;
20     class png_loader : noncopyable
21     {
22     public:
23 
24         png_loader( const char* filename );
25         png_loader( const std::string& filename );
26         png_loader( const dlib::file& f );
27         png_loader( const unsigned char* image_buffer, size_t buffer_size );
28         ~png_loader();
29 
30         bool is_gray() const;
31         bool is_graya() const;
32         bool is_rgb() const;
33         bool is_rgba() const;
34 
bit_depth()35         unsigned int bit_depth () const { return bit_depth_; }
36 
37         template<typename T>
get_image(T & t_)38         void get_image( T& t_) const
39         {
40 #ifndef DLIB_PNG_SUPPORT
41             /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
42                 You are getting this error because you are trying to use the png_loader
43                 object but you haven't defined DLIB_PNG_SUPPORT.  You must do so to use
44                 this object.   You must also make sure you set your build environment
45                 to link against the libpng library.
46             !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
47             COMPILE_TIME_ASSERT(sizeof(T) == 0);
48 #endif
49 
50             typedef typename image_traits<T>::pixel_type pixel_type;
51             image_view<T> t(t_);
52             t.set_size( height_, width_ );
53 
54 
55             if (is_gray() && bit_depth_ == 8)
56             {
57                 for ( unsigned n = 0; n < height_;n++ )
58                 {
59                     const unsigned char* v = get_row( n );
60                     for ( unsigned m = 0; m < width_;m++ )
61                     {
62                         unsigned char p = v[m];
63                         assign_pixel( t[n][m], p );
64                     }
65                 }
66             }
67             else if (is_gray() && bit_depth_ == 16)
68             {
69                 for ( unsigned n = 0; n < height_;n++ )
70                 {
71                     const uint16* v = (uint16*)get_row( n );
72                     for ( unsigned m = 0; m < width_;m++ )
73                     {
74                         dlib::uint16 p = v[m];
75                         assign_pixel( t[n][m], p );
76                     }
77                 }
78             }
79             else if (is_graya() && bit_depth_ == 8)
80             {
81                 for ( unsigned n = 0; n < height_;n++ )
82                 {
83                     const unsigned char* v = get_row( n );
84                     for ( unsigned m = 0; m < width_; m++ )
85                     {
86                         unsigned char p = v[m*2];
87                         if (!pixel_traits<pixel_type>::has_alpha)
88                         {
89                             assign_pixel( t[n][m], p );
90                         }
91                         else
92                         {
93                             unsigned char pa = v[m*2+1];
94                             rgb_alpha_pixel pix;
95                             assign_pixel(pix, p);
96                             assign_pixel(pix.alpha, pa);
97                             assign_pixel(t[n][m], pix);
98                         }
99                     }
100                 }
101             }
102             else if (is_graya() && bit_depth_ == 16)
103             {
104                 for ( unsigned n = 0; n < height_;n++ )
105                 {
106                     const uint16* v = (uint16*)get_row( n );
107                     for ( unsigned m = 0; m < width_; m++ )
108                     {
109                         dlib::uint16 p = v[m*2];
110                         if (!pixel_traits<pixel_type>::has_alpha)
111                         {
112                             assign_pixel( t[n][m], p );
113                         }
114                         else
115                         {
116                             dlib::uint16 pa = v[m*2+1];
117                             rgb_alpha_pixel pix;
118                             assign_pixel(pix, p);
119                             assign_pixel(pix.alpha, pa);
120                             assign_pixel(t[n][m], pix);
121                         }
122                     }
123                 }
124             }
125             else if (is_rgb() && bit_depth_ == 8)
126             {
127                 for ( unsigned n = 0; n < height_;n++ )
128                 {
129                     const unsigned char* v = get_row( n );
130                     for ( unsigned m = 0; m < width_;m++ )
131                     {
132                         rgb_pixel p;
133                         p.red = v[m*3];
134                         p.green = v[m*3+1];
135                         p.blue = v[m*3+2];
136                         assign_pixel( t[n][m], p );
137                     }
138                 }
139             }
140             else if (is_rgb() && bit_depth_ == 16)
141             {
142                 for ( unsigned n = 0; n < height_;n++ )
143                 {
144                     const uint16* v = (uint16*)get_row( n );
145                     for ( unsigned m = 0; m < width_;m++ )
146                     {
147                         rgb_pixel p;
148                         p.red   = static_cast<uint8>(v[m*3]);
149                         p.green = static_cast<uint8>(v[m*3+1]);
150                         p.blue  = static_cast<uint8>(v[m*3+2]);
151                         assign_pixel( t[n][m], p );
152                     }
153                 }
154             }
155             else if (is_rgba() && bit_depth_ == 8)
156             {
157                 if (!pixel_traits<pixel_type>::has_alpha)
158                     assign_all_pixels(t,0);
159 
160                 for ( unsigned n = 0; n < height_;n++ )
161                 {
162                     const unsigned char* v = get_row( n );
163                     for ( unsigned m = 0; m < width_;m++ )
164                     {
165                         rgb_alpha_pixel p;
166                         p.red = v[m*4];
167                         p.green = v[m*4+1];
168                         p.blue = v[m*4+2];
169                         p.alpha = v[m*4+3];
170                         assign_pixel( t[n][m], p );
171                     }
172                 }
173             }
174             else if (is_rgba() && bit_depth_ == 16)
175             {
176                 if (!pixel_traits<pixel_type>::has_alpha)
177                     assign_all_pixels(t,0);
178 
179                 for ( unsigned n = 0; n < height_;n++ )
180                 {
181                     const uint16* v = (uint16*)get_row( n );
182                     for ( unsigned m = 0; m < width_;m++ )
183                     {
184                         rgb_alpha_pixel p;
185                         p.red   = static_cast<uint8>(v[m*4]);
186                         p.green = static_cast<uint8>(v[m*4+1]);
187                         p.blue  = static_cast<uint8>(v[m*4+2]);
188                         p.alpha = static_cast<uint8>(v[m*4+3]);
189                         assign_pixel( t[n][m], p );
190                     }
191                 }
192             }
193         }
194 
195     private:
196         const unsigned char* get_row( unsigned i ) const;
197         std::unique_ptr<FileInfo> check_file( const char* filename );
198         void read_image( std::unique_ptr<FileInfo> file_info );
199         unsigned height_, width_;
200         unsigned bit_depth_;
201         int color_type_;
202         std::unique_ptr<LibpngData> ld_;
203         std::unique_ptr<PngBufferReaderState> buffer_reader_state_;
204     };
205 
206 // ----------------------------------------------------------------------------------------
207 
208     template <
209         typename image_type
210         >
load_png(image_type & image,const std::string & file_name)211     void load_png (
212         image_type& image,
213         const std::string& file_name
214     )
215     {
216         png_loader(file_name).get_image(image);
217     }
218 
219     template <
220         typename image_type
221         >
load_png(image_type & image,const unsigned char * image_buffer,size_t buffer_size)222     void load_png (
223         image_type& image,
224         const unsigned char* image_buffer,
225         size_t buffer_size
226     )
227     {
228         png_loader(image_buffer, buffer_size).get_image(image);
229     }
230 
231     template <
232         typename image_type
233         >
load_png(image_type & image,const char * image_buffer,size_t buffer_size)234     void load_png (
235         image_type& image,
236         const char* image_buffer,
237         size_t buffer_size
238     )
239     {
240         png_loader(reinterpret_cast<const unsigned char*>(image_buffer), buffer_size).get_image(image);
241     }
242 
243 
244 // ----------------------------------------------------------------------------------------
245 
246 }
247 
248 #ifdef NO_MAKEFILE
249 #include "png_loader.cpp"
250 #endif
251 
252 #endif // DLIB_PNG_IMPORT
253 
254