1 // This is brl/bseg/bvxm/grid/io/bvxm_slab_to_image.h
2 #ifndef bvxm_io_voxel_slab_h
3 #define bvxm_io_voxel_slab_h
4 //:
5 // \file
6 // \brief Converts slab to a vil_image
7 // \author Isabel Restrepo mir@lems.brown.edu
8 // \date  June 26, 2009
9 // \verbatim
10 //  Modifications
11 //   <none yet>
12 // \endverbatim
13 
14 #include <vector>
15 #include <iostream>
16 #include "../bvxm_voxel_slab.h"
17 #include <vnl/vnl_vector_fixed.h>
18 #include <vnl/vnl_float_3.h>
19 #include <vnl/vnl_float_4.h>
20 #include <vil/vil_image_view_base.h>
21 #include <vil/vil_image_view.h>
22 #include <vil/vil_pixel_format.h>
23 #include <vil/vil_save.h> // for debug saving
24 #ifdef _MSC_VER
25 #  include <vcl_msvc_warnings.h>
26 #endif
27 
28 class bvxm_slab_to_image
29 {
30  public:
31   //:Converts slab to a vil_image. Datatype is a vnl_vector_fixed
32   template<class T, unsigned N>
33   static bool slab_to_image(bvxm_voxel_slab<vnl_vector_fixed<T,N> > const &slab, vil_image_view_base_sptr image);
34 
35   //Converts slab to a vil_image. Datatype is a scalar
36   template<class T>
37   static bool slab_to_image(bvxm_voxel_slab<T> const& slab, vil_image_view_base_sptr image);
38 
39   //: Simple function to save a slab into an image. Used for debugging where the type of output image is not so important
40   template<class T>
41   static void write_slab_as_image(bvxm_voxel_slab<T> const& slab_in,std::string filename);
42 
43   //: Simple function to save a slab into an image. Used for debugging where the type of output image is not so important
44   template<class T, unsigned N>
45   static void write_slab_as_image(bvxm_voxel_slab<vnl_vector_fixed<T,N> > const& slab_in,std::string filename);
46 };
47 
48 
49 //:Saves slab to a vil_image. Datatype is a vnl_vector_fixed
50 template<class T, unsigned N>
slab_to_image(bvxm_voxel_slab<vnl_vector_fixed<T,N>> const & slab,vil_image_view_base_sptr image)51 bool bvxm_slab_to_image::slab_to_image(bvxm_voxel_slab<vnl_vector_fixed<T,N> > const &slab, vil_image_view_base_sptr image)
52 {
53   // check image is preallocated to correct size
54   if ( (slab.nx() != image->ni()) || (slab.ny() != image->nj()) )
55   {
56     std::cerr << "error: slab and image are different sizes.\n";
57     return false;
58   }
59 
60   // take care of pixel format issues. might want to specialize this function for rgb, etc
61   switch (image->pixel_format())
62   {
63     case VIL_PIXEL_FORMAT_BYTE:
64       if (image->nplanes() ==N)
65       {
66         if (vil_image_view<unsigned char> *img_view = dynamic_cast<vil_image_view<unsigned char>*>(image.ptr()))
67         {
68           std::vector<vil_image_view<unsigned char>::iterator> img_its;
69           for (unsigned p=0; p<N; ++p)
70           {
71             vil_image_view<unsigned char>::iterator plane_it = img_view->begin() + (p*img_view->planestep());
72             img_its.push_back(plane_it);
73           }
74 
75           typename bvxm_voxel_slab<vnl_vector_fixed<T,N> >::const_iterator slab_it = slab.begin();
76           for (; slab_it != slab.end(); ++slab_it)
77           {
78             for (unsigned p=0; p<N; ++p)
79             {
80               *(img_its[p]) =  (unsigned char)(((*slab_it)[p] * 127.0) + 0.5) + 127;
81               ++(img_its[p]);
82             }
83           }
84         }
85         else
86         {
87           std::cerr << "error in slab_to_image: failed to cast image_view_base to image_view\n";
88           return false;
89         }
90       }
91       else
92       {
93         std::cerr << "error in slab_to_image: incorrect number of image planes\n";
94         return false;
95       }
96       break;
97 
98     case VIL_PIXEL_FORMAT_RGBA_BYTE:
99       if (image->nplanes() ==1)
100       {
101         if (vil_image_view<vil_rgba<unsigned char> > *img_view = dynamic_cast<vil_image_view<vil_rgba<unsigned char> >*>(image.ptr()))
102         {
103           vil_image_view<vil_rgba<unsigned char> >::iterator img_it = img_view->begin();
104 #if 0
105           for (unsigned p=0; p<N; ++p)
106           {
107             vil_image_view<vil_rgba<unsigned char> >::iterator plane_it = img_view->begin();
108             img_its.push_back(plane_it);
109           }
110 #endif
111           typename bvxm_voxel_slab<vnl_vector_fixed<T,N> >::const_iterator slab_it = slab.begin();
112           if (N != 4)
113           {
114             std::cerr << "error in slab_to_image: failed to cast image_view_base to image_view: N should be 4\n";
115             return false;
116           }
117           for (; slab_it != slab.end(); ++slab_it)
118           {
119             (*img_it) = vil_rgba<unsigned char>((unsigned char)(*slab_it)[0],
120                                                 (unsigned char)(*slab_it)[1],
121                                                 (unsigned char)(*slab_it)[2],
122                                                 (unsigned char)std::floor((*slab_it)[3]));
123 #if 0
124             *(img_its[p]) = (unsigned char)(((*slab_it)[p] * 127.0) + 0.5) + 127;
125             std::cout<<(int)(*img_it).R()<<' '<<(int)((unsigned char)(*slab_it)[3])<<std::endl;
126 #endif
127             ++(img_it);
128           }
129         }
130         else
131         {
132           std::cerr << "error in slab_to_image: failed to cast image_view_base to image_view\n";
133           return false;
134         }
135       }
136       else
137       {
138         std::cerr << "error in slab_to_image: incorrect number of image planes\n";
139         return false;
140       }
141       break;
142 
143     case VIL_PIXEL_FORMAT_FLOAT:
144       if (image->nplanes() ==N)
145       {
146           if (vil_image_view<float> *img_view = dynamic_cast<vil_image_view<float>*>(image.ptr()))
147           {
148               std::vector<vil_image_view<float>::iterator> img_its;
149               for (unsigned p=0; p<N; ++p)
150               {
151                   vil_image_view<float>::iterator plane_it = img_view->begin() + (p*img_view->planestep());
152                   img_its.push_back(plane_it);
153               }
154 
155               typename bvxm_voxel_slab<vnl_vector_fixed<T,N> >::const_iterator slab_it = slab.begin();
156               for (; slab_it != slab.end(); ++slab_it)
157               {
158                   for (unsigned p=0; p<N; ++p)
159                   {
160                       *(img_its[p]) = (float)((*slab_it)[p]);
161                       ++(img_its[p]);
162                   }
163               }
164           }
165         else
166         {
167           std::cerr << "error in slab_to_image: failed to cast image_view_base to image_view\n";
168           return false;
169         }
170       }
171       else
172       {
173         std::cerr << "error in slab_to_image: incorrect number of image planes\n";
174         return false;
175       }
176       break;
177 
178     case VIL_PIXEL_FORMAT_RGB_BYTE:
179       if (image->nplanes() ==1)
180       {
181         if (vil_image_view<vil_rgb<unsigned char> > *img_view = dynamic_cast<vil_image_view<vil_rgb<unsigned char> >*>(image.ptr()))
182         {
183           vil_image_view<vil_rgb<unsigned char> >::iterator img_it = img_view->begin();
184 
185           typename bvxm_voxel_slab<vnl_vector_fixed<T,N> >::const_iterator slab_it = slab.begin();
186           if (N != 3)
187           {
188             std::cerr << "error in slab_to_image: failed to cast image_view_base to image_view: N should be 3\n";
189             return false;
190           }
191           for (; slab_it != slab.end(); ++slab_it)
192           {
193             (*img_it) = vil_rgb<unsigned char>((unsigned char)((*slab_it)[0]*127+127),
194                                                 (unsigned char)((*slab_it)[1]*127+127),
195                                                 (unsigned char)((*slab_it)[2]*127+127));
196             ++(img_it);
197           }
198         }
199         else
200         {
201           std::cerr << "error in slab_to_image: failed to cast image_view_base to image_view\n";
202           return false;
203         }
204       }
205       else
206       {
207         std::cerr << "error in slab_to_image: incorrect number of image planes\n";
208         return false;
209       }
210       break;
211 
212 
213     default:
214       std::cerr << "img_to_slab: unsupported pixel type\n";
215       return false;
216       break;
217   }
218 
219   return true;
220 }
221 
222 template<>
223 bool bvxm_slab_to_image::slab_to_image(bvxm_voxel_slab<vnl_float_3> const& slab, vil_image_view_base_sptr image);
224 
225 template<>
226 bool bvxm_slab_to_image::slab_to_image(bvxm_voxel_slab<vnl_float_4> const& slab, vil_image_view_base_sptr image);
227 
228 template<class T>
slab_to_image(bvxm_voxel_slab<T> const & slab,vil_image_view_base_sptr image)229 bool bvxm_slab_to_image::slab_to_image(bvxm_voxel_slab<T> const& slab, vil_image_view_base_sptr image)
230 {
231   // check image is preallocated to correct size
232   if ( (slab.nx() != image->ni()) || (slab.ny() != image->nj()) )
233   {
234     std::cerr << "error: slab and image are different sizes.\n";
235     return false;
236   }
237 
238   // take care of pixel format issues. might want to specialize this function for rgb, etc
239   switch (image->pixel_format())
240   {
241     case VIL_PIXEL_FORMAT_BYTE:
242       if (vil_image_view<unsigned char> *img_view = dynamic_cast<vil_image_view<unsigned char>*>(image.ptr()))
243       {
244         vil_image_view<unsigned char>::iterator img_it = img_view->begin();
245         typename bvxm_voxel_slab<T>::const_iterator slab_it = slab.begin();
246         for (; img_it != img_view->end(); ++img_it, ++slab_it) {
247           *img_it =  (unsigned char)std::floor(((*slab_it)*255));
248         }
249       }
250       else
251       {
252         std::cerr << "error: failed to cast image_view_base to image_view\n";
253         return false;
254       }
255       break;
256 
257     case VIL_PIXEL_FORMAT_FLOAT:
258       if (vil_image_view<float> *img_view = dynamic_cast<vil_image_view<float>*>(image.ptr()))
259       {
260         vil_image_view<float>::iterator img_it = img_view->begin();
261         typename bvxm_voxel_slab<T>::const_iterator slab_it = slab.begin();
262         for (; img_it != img_view->end(); ++img_it, ++slab_it) {
263           *img_it = (float)(*slab_it*255);
264         }
265       }
266       else
267       {
268         std::cerr << "error: failed to cast image_view_base to image_view\n";
269         return false;
270       }
271       break;
272 
273     default:
274       std::cerr << "img_to_slab: unsupported pixel type\n";
275       return false;
276       break;
277   }
278 
279   return true;
280 }
281 
282 // used for debugging
283 template<class T, unsigned N>
write_slab_as_image(bvxm_voxel_slab<vnl_vector_fixed<T,N>> const & slab_in,std::string filename)284 void bvxm_slab_to_image::write_slab_as_image(bvxm_voxel_slab<vnl_vector_fixed<T,N> > const& slab_in,std::string filename)
285 {
286   vil_image_view<T> img(slab_in.nx(),slab_in.ny(),N);
287   std::vector<typename vil_image_view<T>::iterator> img_its;
288   for (unsigned p=0; p < N; ++p) {
289     typename vil_image_view<T>::iterator plane_it = img.begin() + (p*img.planestep());
290     img_its.push_back(plane_it);
291   }
292   typename bvxm_voxel_slab<vnl_vector_fixed<T,N> >::const_iterator slab_it = slab_in.begin();
293   for (; slab_it != slab_in.end(); ++slab_it) {
294     for (unsigned p=0; p<N; ++p) {
295       *(img_its[p]) = (*slab_it)[p];
296       ++(img_its[p]);
297     }
298   }
299   vil_save(img,filename.c_str());
300 
301   return;
302 }
303 
304 // used for debugging
305 template<class T>
write_slab_as_image(bvxm_voxel_slab<T> const & slab_in,std::string filename)306 void bvxm_slab_to_image::write_slab_as_image(bvxm_voxel_slab<T> const& slab_in,std::string filename)
307 {
308   vil_image_view<T> img(slab_in.nx(),slab_in.ny(),1);
309   typename vil_image_view<T>::iterator img_it = img.begin();
310   typename bvxm_voxel_slab<T>::const_iterator slab_it = slab_in.begin();
311   for (; img_it != img.end(); ++img_it, ++slab_it) {
312     *img_it = *slab_it;
313   }
314   vil_save(img,filename.c_str());
315 
316   return;
317 }
318 
319 
320 #endif
321