contrib/brl/bbas/vidl2/vidl2_convert.cxx

Go to the documentation of this file.
00001 // This is brl/bbas/vidl2/vidl2_convert.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author Matt Leotta
00008 // \date   20 Jan 2006
00009 //
00010 // \verbatim
00011 //  Modifications
00012 //   10 Jul.2008 - Antonio Garrido - Added convertions for RGB_24(P),MONO8 and YUYV_422
00013 // \endvarbatim
00014 //
00015 //-----------------------------------------------------------------------------
00016 
00017 #include "vidl2_convert.h"
00018 #include "vidl2_frame.h"
00019 #include "vidl2_pixel_format.h"
00020 #include "vidl2_pixel_iterator.txx"
00021 #include "vidl2_color.h"
00022 #include <vil/vil_convert.h>
00023 #include <vil/vil_memory_chunk.h>
00024 #include <vcl_cstring.h>
00025 #include <vcl_cassert.h>
00026 #include <vcl_memory.h>
00027 
00028 //--------------------------------------------------------------------------------
00029 
00030 
00031 namespace {
00032 
00033 //: Define the function pointer for pixel format conversion functions
00034 typedef bool (*converter_func)(const vidl2_frame& in_frame, vidl2_frame& out_frame);
00035 
00036 
00037 //: Default pixel format conversion - it fails
00038 bool default_conversion(const vidl2_frame& in_frame, vidl2_frame& out_frame)
00039 {
00040   vcl_cerr << "No routine to convert " << in_frame.pixel_format()
00041            << " to " << out_frame.pixel_format() << vcl_endl;
00042   return false;
00043 }
00044 
00045 
00046 //: Use memcpy when the formats are the same
00047 bool copy_conversion(const vidl2_frame& in_frame, vidl2_frame& out_frame)
00048 {
00049   assert(in_frame.pixel_format() == out_frame.pixel_format());
00050   assert(in_frame.size() == out_frame.size());
00051   vcl_memcpy(out_frame.data(), in_frame.data(), in_frame.size());
00052   return true;
00053 }
00054 
00055 
00056 //: Convert to an intermediate RGB_24 frame
00057 // This is inefficient, but will provide the functionality until
00058 // an optimized version is written
00059 // defined later because it uses conversion_table
00060 bool intermediate_rgb24_conversion(const vidl2_frame& in_frame, vidl2_frame& out_frame);
00061 
00062 
00063 // Default pixel format conversion - it fails
00064 template <vidl2_pixel_format in_Fmt, vidl2_pixel_format out_Fmt>
00065 struct convert
00066 {
00067   enum { defined = false };
00068   static inline bool apply(const vidl2_frame& /*in_frame*/,
00069                            vidl2_frame& /*out_frame*/)
00070   {
00071     return false;
00072   }
00073 };
00074 
00075 //=============================================================================
00076 // Start of generic pixel conversions
00077 
00078 
00079 //: The generic pixel conversion function
00080 bool convert_generic(const vidl2_frame& in_frame,
00081                      vidl2_frame& out_frame)
00082 {
00083   // create pixel iterators for each frame
00084   vcl_auto_ptr<vidl2_pixel_iterator> in_pitr(vidl2_make_pixel_iterator(in_frame));
00085   if (!in_pitr.get())
00086     return false;
00087   vcl_auto_ptr<vidl2_pixel_iterator> out_pitr(vidl2_make_pixel_iterator(out_frame));
00088   if (!out_pitr.get())
00089     return false;
00090 
00091   vidl2_pixel_iterator& in_itr = *in_pitr;
00092   vidl2_pixel_iterator& out_itr = *out_pitr;
00093 
00094   vidl2_pixel_traits in_t = vidl2_pixel_format_traits(in_frame.pixel_format());
00095   vidl2_pixel_traits out_t = vidl2_pixel_format_traits(out_frame.pixel_format());
00096 
00097   // find the color conversion function
00098   vidl2_color_conv_fptr color_conv =
00099       vidl2_color_converter_func( in_t.color,  in_t.bits_per_pixel,
00100                                   out_t.color, out_t.bits_per_pixel);
00101   if (!color_conv)
00102     return false;
00103 
00104   const unsigned int num_pix = in_frame.ni() * in_frame.nj();
00105   vxl_byte in_pixel[4], out_pixel[4]; // assume pixels are no more than 4 bytes
00106   for (unsigned int c=0; c<num_pix; ++c, ++in_itr, ++out_itr){
00107     in_itr.get_data(in_pixel);
00108     color_conv(in_pixel, out_pixel);
00109     out_itr.set_data(out_pixel);
00110   }
00111   return true;
00112 }
00113 
00114 
00115 //=============================================================================
00116 // Start of pixel conversion specializations
00117 // Write optimized conversion specializations below
00118 
00119 // RGB_24 to UYVY_422
00120 VCL_DEFINE_SPECIALIZATION
00121 struct convert<VIDL2_PIXEL_FORMAT_RGB_24, VIDL2_PIXEL_FORMAT_UYVY_422>
00122 {
00123   enum { defined = true };
00124   static inline bool apply(const vidl2_frame& in_frame,
00125                            vidl2_frame& out_frame)
00126   {
00127     assert(in_frame.pixel_format()==VIDL2_PIXEL_FORMAT_RGB_24);
00128     assert(out_frame.pixel_format()==VIDL2_PIXEL_FORMAT_UYVY_422);
00129     const vxl_byte* rgb = reinterpret_cast<const vxl_byte*>(in_frame.data());
00130     vxl_byte* uyvy = reinterpret_cast<vxl_byte*>(out_frame.data());
00131     unsigned int num_half_pix = (in_frame.ni() * in_frame.nj() + 1)/2;
00132     for (unsigned int c=0; c<num_half_pix; ++c){
00133       const vxl_byte& r1 = *(rgb++);
00134       const vxl_byte& g1 = *(rgb++);
00135       const vxl_byte& b1 = *(rgb++);
00136       const vxl_byte& r2 = *(rgb++);
00137       const vxl_byte& g2 = *(rgb++);
00138       const vxl_byte& b2 = *(rgb++);
00139       vxl_byte y1,u1,v1,y2,u2,v2;
00140       vidl2_color_convert_rgb2yuv(r1,g1,b1,y1,u1,v1);
00141       vidl2_color_convert_rgb2yuv(r2,g2,b2,y2,u2,v2);
00142       *(uyvy++) = (u1+u2)/2;
00143       *(uyvy++) = y1;
00144       *(uyvy++) = (v1+v2)/2;
00145       *(uyvy++) = y2;
00146     }
00147     return true;
00148   }
00149 };
00150 
00151 
00152 // UYVY_422 to RGB_24
00153 VCL_DEFINE_SPECIALIZATION
00154 struct convert<VIDL2_PIXEL_FORMAT_UYVY_422, VIDL2_PIXEL_FORMAT_RGB_24>
00155 {
00156   enum { defined = true };
00157   static inline bool apply(const vidl2_frame& in_frame,
00158                            vidl2_frame& out_frame)
00159   {
00160     assert(in_frame.pixel_format()==VIDL2_PIXEL_FORMAT_UYVY_422);
00161     assert(out_frame.pixel_format()==VIDL2_PIXEL_FORMAT_RGB_24);
00162     const vxl_byte* uyvy = reinterpret_cast<const vxl_byte*>(in_frame.data());
00163     vxl_byte* rgb = reinterpret_cast<vxl_byte*>(out_frame.data());
00164     unsigned int num_half_pix = (in_frame.ni() * in_frame.nj() + 1)/2;
00165     for (unsigned int c=0; c<num_half_pix; ++c){
00166       const vxl_byte& u1 = *(uyvy++);
00167       const vxl_byte& y1 = *(uyvy++);
00168       const vxl_byte& v1 = *(uyvy++);
00169       const vxl_byte& y2 = *(uyvy++);
00170       vxl_byte r,g,b;
00171       vidl2_color_convert_yuv2rgb(y1,u1,v1,r,g,b);
00172       *(rgb++) = r;
00173       *(rgb++) = g;
00174       *(rgb++) = b;
00175       vidl2_color_convert_yuv2rgb(y2,u1,v1,r,g,b);
00176       *(rgb++) = r;
00177       *(rgb++) = g;
00178       *(rgb++) = b;
00179     }
00180     return true;
00181   }
00182 };
00183 
00184 
00185 // UYVY_422 to MONO_8
00186 VCL_DEFINE_SPECIALIZATION
00187 struct convert<VIDL2_PIXEL_FORMAT_UYVY_422, VIDL2_PIXEL_FORMAT_MONO_8>
00188 {
00189   enum { defined = true };
00190   static inline bool apply(const vidl2_frame& in_frame,
00191                            vidl2_frame& out_frame)
00192   {
00193     assert(in_frame.pixel_format()==VIDL2_PIXEL_FORMAT_UYVY_422);
00194     assert(out_frame.pixel_format()==VIDL2_PIXEL_FORMAT_MONO_8);
00195     const vxl_byte* uyvy = reinterpret_cast<const vxl_byte*>(in_frame.data());
00196     vxl_byte* mono = reinterpret_cast<vxl_byte*>(out_frame.data());
00197     unsigned int num_half_pix = (in_frame.ni() * in_frame.nj() + 1)/2;
00198     for (unsigned int c=0; c<num_half_pix; ++c){
00199       ++uyvy;
00200       const vxl_byte& y1 = *(uyvy++);
00201       ++uyvy;
00202       const vxl_byte& y2 = *(uyvy++);
00203       *(mono++) = y1;
00204       *(mono++) = y2;
00205     }
00206     return true;
00207   }
00208 };
00209 
00210 
00211 // RGB_24 to YUYV_422
00212 VCL_DEFINE_SPECIALIZATION
00213 struct convert<VIDL2_PIXEL_FORMAT_RGB_24, VIDL2_PIXEL_FORMAT_YUYV_422>
00214 {
00215   enum { defined = true };
00216   static inline bool apply(const vidl2_frame& in_frame,
00217                            vidl2_frame& out_frame)
00218   {
00219     assert(in_frame.pixel_format()==VIDL2_PIXEL_FORMAT_RGB_24);
00220     assert(out_frame.pixel_format()==VIDL2_PIXEL_FORMAT_YUYV_422);
00221     const vxl_byte* rgb = reinterpret_cast<const vxl_byte*>(in_frame.data());
00222     vxl_byte* yuyv = reinterpret_cast<vxl_byte*>(out_frame.data());
00223     unsigned int num_half_pix = (in_frame.ni() * in_frame.nj() + 1)/2;
00224     for (unsigned int c=0; c<num_half_pix; ++c){
00225       const vxl_byte& r1 = *(rgb++);
00226       const vxl_byte& g1 = *(rgb++);
00227       const vxl_byte& b1 = *(rgb++);
00228       const vxl_byte& r2 = *(rgb++);
00229       const vxl_byte& g2 = *(rgb++);
00230       const vxl_byte& b2 = *(rgb++);
00231       vxl_byte y1,u1,v1,y2,u2,v2;
00232       vidl2_color_convert_rgb2yuv(r1,g1,b1,y1,u1,v1);
00233       vidl2_color_convert_rgb2yuv(r2,g2,b2,y2,u2,v2);
00234       *(yuyv++) = y1;
00235       *(yuyv++) = (u1+u2)/2;
00236       *(yuyv++) = y2;
00237       *(yuyv++) = (v1+v2)/2;
00238     }
00239     return true;
00240   }
00241 };
00242 
00243 
00244 // YUYV_422 to RGB_24
00245 VCL_DEFINE_SPECIALIZATION
00246 struct convert<VIDL2_PIXEL_FORMAT_YUYV_422, VIDL2_PIXEL_FORMAT_RGB_24>
00247 {
00248   enum { defined = true };
00249   static inline bool apply(const vidl2_frame& in_frame,
00250                            vidl2_frame& out_frame)
00251   {
00252     assert(in_frame.pixel_format()==VIDL2_PIXEL_FORMAT_YUYV_422);
00253     assert(out_frame.pixel_format()==VIDL2_PIXEL_FORMAT_RGB_24);
00254     const vxl_byte* yuyv = reinterpret_cast<const vxl_byte*>(in_frame.data());
00255     vxl_byte* rgb = reinterpret_cast<vxl_byte*>(out_frame.data());
00256     unsigned int num_half_pix = (in_frame.ni() * in_frame.nj() + 1)/2;
00257     for (unsigned int c=0; c<num_half_pix; ++c){
00258       const vxl_byte& y1 = *(yuyv++);
00259       const vxl_byte& u1 = *(yuyv++);
00260       const vxl_byte& y2 = *(yuyv++);
00261       const vxl_byte& v1 = *(yuyv++);
00262       vxl_byte r,g,b;
00263       vidl2_color_convert_yuv2rgb(y1,u1,v1,r,g,b);
00264       *(rgb++) = r;
00265       *(rgb++) = g;
00266       *(rgb++) = b;
00267       vidl2_color_convert_yuv2rgb(y2,u1,v1,r,g,b);
00268       *(rgb++) = r;
00269       *(rgb++) = g;
00270       *(rgb++) = b;
00271     }
00272     return true;
00273   }
00274 };
00275 
00276 
00277 // RGB_24P to YUYV_422
00278 VCL_DEFINE_SPECIALIZATION
00279 struct convert<VIDL2_PIXEL_FORMAT_RGB_24P, VIDL2_PIXEL_FORMAT_YUYV_422>
00280 {
00281   enum { defined = true };
00282   static inline bool apply(const vidl2_frame& in_frame,
00283                            vidl2_frame& out_frame)
00284   {
00285     assert(in_frame.pixel_format()==VIDL2_PIXEL_FORMAT_RGB_24P);
00286     assert(out_frame.pixel_format()==VIDL2_PIXEL_FORMAT_YUYV_422);
00287     const vxl_byte* red = reinterpret_cast<const vxl_byte*>(in_frame.data());
00288     const vxl_byte* green= red+in_frame.ni() * in_frame.nj();
00289     const vxl_byte* blue= green+in_frame.ni() * in_frame.nj();
00290     vxl_byte* yuyv = reinterpret_cast<vxl_byte*>(out_frame.data());
00291     unsigned int num_half_pix = (in_frame.ni() * in_frame.nj() + 1)/2;
00292     for (unsigned int c=0; c<num_half_pix; ++c){
00293       const vxl_byte& r1 = *(red++);
00294       const vxl_byte& g1 = *(green++);
00295       const vxl_byte& b1 = *(blue++);
00296       const vxl_byte& r2 = *(red++);
00297       const vxl_byte& g2 = *(green++);
00298       const vxl_byte& b2 = *(blue++);
00299       vxl_byte y1,u1,v1,y2,u2,v2;
00300       vidl2_color_convert_rgb2yuv(r1,g1,b1,y1,u1,v1);
00301       vidl2_color_convert_rgb2yuv(r2,g2,b2,y2,u2,v2);
00302       *(yuyv++) = y1;
00303       *(yuyv++) = (u1+u2)/2;
00304       *(yuyv++) = y2;
00305       *(yuyv++) = (v1+v2)/2;
00306     }
00307     return true;
00308   }
00309 };
00310 
00311 // YUYV_422 to RGB_24P
00312 VCL_DEFINE_SPECIALIZATION
00313 struct convert<VIDL2_PIXEL_FORMAT_YUYV_422, VIDL2_PIXEL_FORMAT_RGB_24P>
00314 {
00315   enum { defined = true };
00316   static inline bool apply(const vidl2_frame& in_frame,
00317                            vidl2_frame& out_frame)
00318   {
00319     assert(in_frame.pixel_format()==VIDL2_PIXEL_FORMAT_YUYV_422);
00320     assert(out_frame.pixel_format()==VIDL2_PIXEL_FORMAT_RGB_24P);
00321     const vxl_byte* yuyv = reinterpret_cast<const vxl_byte*>(in_frame.data());
00322     vxl_byte* red = reinterpret_cast<vxl_byte*>(out_frame.data());
00323     vxl_byte* green = red+out_frame.ni()*out_frame.nj();
00324     vxl_byte* blue = green+out_frame.ni()*out_frame.nj();
00325     unsigned int num_half_pix = (in_frame.ni() * in_frame.nj() + 1)/2;
00326     for (unsigned int c=0; c<num_half_pix; ++c){
00327       const vxl_byte& y1 = *(yuyv++);
00328       const vxl_byte& u1 = *(yuyv++);
00329       const vxl_byte& y2 = *(yuyv++);
00330       const vxl_byte& v1 = *(yuyv++);
00331       vxl_byte r,g,b;
00332       vidl2_color_convert_yuv2rgb(y1,u1,v1,r,g,b);
00333       *(red++) = r;
00334       *(green++) = g;
00335       *(blue++) = b;
00336       vidl2_color_convert_yuv2rgb(y2,u1,v1,r,g,b);
00337       *(red++) = r;
00338       *(green++) = g;
00339       *(blue++) = b;
00340     }
00341     return true;
00342   }
00343 };
00344 
00345 // YUYV_422 to MONO_8
00346 VCL_DEFINE_SPECIALIZATION
00347 struct convert<VIDL2_PIXEL_FORMAT_YUYV_422, VIDL2_PIXEL_FORMAT_MONO_8>
00348 {
00349   enum { defined = true };
00350   static inline bool apply(const vidl2_frame& in_frame,
00351                            vidl2_frame& out_frame)
00352   {
00353     assert(in_frame.pixel_format()==VIDL2_PIXEL_FORMAT_YUYV_422);
00354     assert(out_frame.pixel_format()==VIDL2_PIXEL_FORMAT_MONO_8);
00355     const vxl_byte* yuyv = reinterpret_cast<const vxl_byte*>(in_frame.data());
00356     vxl_byte* mono = reinterpret_cast<vxl_byte*>(out_frame.data());
00357     unsigned int num_half_pix = (in_frame.ni() * in_frame.nj() + 1)/2;
00358     for (unsigned int c=0; c<num_half_pix; ++c){
00359       const vxl_byte& y1 = *(yuyv++);
00360       ++yuyv;
00361       const vxl_byte& y2 = *(yuyv++);
00362       ++yuyv;
00363       *(mono++) = y1;
00364       *(mono++) = y2;
00365     }
00366     return true;
00367   }
00368 };
00369 
00370 
00371 // End of pixel conversion specializations
00372 //=============================================================================
00373 
00374 
00375 //: Generates an entry into the table of pixel format conversions functions
00376 // This is called for every pair for pixel formats to build the table
00377 template <vidl2_pixel_format in_Fmt, vidl2_pixel_format out_Fmt>
00378 struct table_entry_init
00379 {
00380   static inline void set_entry(converter_func& table_entry)
00381   {
00382     // This should be done at compile time with partial specialization
00383     // This run time code generates many functions that are never actually used
00384     if (in_Fmt == out_Fmt)
00385       table_entry = &copy_conversion;
00386     else if (convert<in_Fmt,out_Fmt>::defined)
00387       table_entry = &convert<in_Fmt,out_Fmt>::apply;
00388     else if (vidl2_pixel_iterator_valid<in_Fmt>::value &&
00389             vidl2_pixel_iterator_valid<out_Fmt>::value)
00390       table_entry = &convert_generic;
00391     else
00392       table_entry = &default_conversion;
00393   }
00394 };
00395 
00396 //: Recursive template metaprogram to generate conditionals for converting each pair of pixel types
00397 template <int Fmt_Code>
00398 struct table_init
00399 {
00400   static inline void populate(converter_func table[VIDL2_PIXEL_FORMAT_ENUM_END][VIDL2_PIXEL_FORMAT_ENUM_END])
00401   {
00402     const vidl2_pixel_format in_fmt = vidl2_pixel_format(Fmt_Code/VIDL2_PIXEL_FORMAT_ENUM_END);
00403     const vidl2_pixel_format out_fmt = vidl2_pixel_format(Fmt_Code%VIDL2_PIXEL_FORMAT_ENUM_END);
00404     table_entry_init<in_fmt,out_fmt>::set_entry(table[in_fmt][out_fmt]);
00405     table_init<Fmt_Code-1>::populate(table);
00406   }
00407 };
00408 
00409 
00410 //: The base case
00411 VCL_DEFINE_SPECIALIZATION
00412 struct table_init<0>
00413 {
00414   static inline void populate(converter_func table[VIDL2_PIXEL_FORMAT_ENUM_END][VIDL2_PIXEL_FORMAT_ENUM_END])
00415   {
00416     const vidl2_pixel_format in_fmt = vidl2_pixel_format(0);
00417     const vidl2_pixel_format out_fmt = vidl2_pixel_format(0);
00418     table_entry_init<in_fmt,out_fmt>::set_entry(table[in_fmt][out_fmt]);
00419   }
00420 };
00421 
00422 
00423 //: A table of all conversion functions
00424 class converter
00425 {
00426  public:
00427   //: Constructor - generate the table
00428   converter()
00429   {
00430     // generate the table of function pointers
00431     table_init<VIDL2_PIXEL_FORMAT_ENUM_END*VIDL2_PIXEL_FORMAT_ENUM_END-1>::populate(table);
00432   }
00433 
00434   //: Apply the conversion
00435   bool operator()(const vidl2_frame& in_frame, vidl2_frame& out_frame) const
00436   {
00437     return (*table[in_frame.pixel_format()][out_frame.pixel_format()])(in_frame, out_frame);
00438   }
00439  private:
00440   //: Table of conversion functions
00441   converter_func table[VIDL2_PIXEL_FORMAT_ENUM_END][VIDL2_PIXEL_FORMAT_ENUM_END];
00442 };
00443 
00444 //: Instantiate a global conversion function table
00445 converter conversion_table;
00446 
00447 //: Convert to an intermediate RGB_24 frame
00448 // Defined here because it uses conversion_table
00449 bool intermediate_rgb24_conversion(const vidl2_frame& in_frame, vidl2_frame& out_frame)
00450 {
00451   unsigned int ni = in_frame.ni(), nj = in_frame.nj();
00452   vil_memory_chunk_sptr memory = new vil_memory_chunk(ni*nj*3, VIL_PIXEL_FORMAT_BYTE);
00453   vidl2_memory_chunk_frame temp_frame(ni,nj,VIDL2_PIXEL_FORMAT_RGB_24,memory);
00454   return conversion_table(in_frame, temp_frame) &&
00455       conversion_table(temp_frame, out_frame);
00456 }
00457 
00458 } // end anonymous namespace
00459 
00460 //--------------------------------------------------------------------------------
00461 
00462 //: Convert the pixel format of a frame
00463 //
00464 // The \p in_frame->data() is converted from \p in_frame->pixel_format()
00465 // to \p out_frame->pixel_format() and stored in \p out_frame->data()
00466 // \returns false if the output frame data is not the correct size.
00467 bool vidl2_convert_frame(const vidl2_frame& in_frame,
00468                                vidl2_frame& out_frame)
00469 {
00470   vidl2_pixel_format in_fmt = in_frame.pixel_format();
00471   vidl2_pixel_format out_fmt = out_frame.pixel_format();
00472 
00473   if (in_fmt == VIDL2_PIXEL_FORMAT_UNKNOWN ||
00474      out_fmt == VIDL2_PIXEL_FORMAT_UNKNOWN)
00475     return false;
00476 
00477   unsigned ni = in_frame.ni();
00478   unsigned nj = in_frame.nj();
00479   unsigned out_size = vidl2_pixel_format_buffer_size(ni,nj,out_fmt);
00480 
00481   if (out_frame.size() != out_size ||
00482      out_frame.ni() != ni ||
00483      out_frame.nj() != nj ||
00484      !out_frame.data() )
00485     return false;
00486 
00487   // call the appropriate function in the conversion table
00488   return conversion_table(in_frame, out_frame);
00489 }
00490 
00491 
00492 //: Convert the pixel format of a frame
00493 //
00494 // The convert \p in_frame to a \p format by allocating
00495 // a new frame buffer
00496 vidl2_frame_sptr vidl2_convert_frame(const vidl2_frame_sptr& in_frame,
00497                                      vidl2_pixel_format format)
00498 {
00499   if (format == VIDL2_PIXEL_FORMAT_UNKNOWN)
00500     return NULL;
00501 
00502   unsigned ni = in_frame->ni();
00503   unsigned nj = in_frame->nj();
00504   unsigned size = vidl2_pixel_format_buffer_size(ni,nj,format);
00505   vil_memory_chunk_sptr memory = new vil_memory_chunk(size, VIL_PIXEL_FORMAT_BYTE);
00506   vidl2_frame_sptr out_frame = new vidl2_memory_chunk_frame(ni, nj, format, memory);
00507 
00508   if (vidl2_convert_frame(*in_frame, *out_frame))
00509     return out_frame;
00510 
00511   return NULL;
00512 }
00513 
00514 
00515 //: Convert the image view to a frame
00516 // Will wrap the memory if possible, if not the image is converted to
00517 // the closest vidl2_pixel_format
00518 vidl2_frame_sptr vidl2_convert_to_frame(const vil_image_view_base_sptr& image)
00519 {
00520   if (!image)
00521     return NULL;
00522 
00523   // try to wrap the image memory in a frame
00524   vidl2_frame_sptr frame = new vidl2_memory_chunk_frame(*image);
00525   if (frame->pixel_format() != VIDL2_PIXEL_FORMAT_UNKNOWN)
00526     return frame;
00527 
00528   // if the image could not be wrapped convert it
00529   unsigned ni = image->ni(), nj = image->nj(), np = image->nplanes();
00530 
00531   // special case for 16 bit images
00532   if (image->pixel_format() == VIL_PIXEL_FORMAT_UINT_16)
00533   {
00534     if (np != 1)
00535       return NULL;
00536     vil_image_view<vxl_uint_16> img(ni,nj);
00537     img.deep_copy(vil_image_view<vxl_uint_16>(*image));
00538     return new vidl2_memory_chunk_frame(ni, nj, VIDL2_PIXEL_FORMAT_MONO_16,
00539                                         img.memory_chunk());
00540   }
00541 
00542   vidl2_pixel_format format = VIDL2_PIXEL_FORMAT_UNKNOWN;
00543   if (np == 1)
00544     format = VIDL2_PIXEL_FORMAT_MONO_8;
00545   else if (np == 3)
00546     format = VIDL2_PIXEL_FORMAT_RGB_24P;
00547   else if (np == 4)
00548     format = VIDL2_PIXEL_FORMAT_RGBA_32P;
00549   else
00550     return NULL;
00551 
00552   vil_image_view<vxl_byte> img;
00553   if (image->pixel_format() == VIL_PIXEL_FORMAT_BYTE)
00554     img.deep_copy(vil_image_view<vxl_byte>(*image));
00555   else
00556   {
00557     vil_image_view_base_sptr bimage = vil_convert_cast(vxl_byte(),image);
00558     if (!bimage)
00559       return NULL;
00560     img = *bimage;
00561   }
00562   return new vidl2_memory_chunk_frame(ni, nj, format,
00563                                       img.memory_chunk());
00564 }
00565 
00566 
00567 //: convert the frame into an image view
00568 // possibly converts the pixel data type
00569 // always create a deep copy of the data
00570 bool vidl2_convert_to_view(const vidl2_frame& frame,
00571                            vil_image_view_base& image,
00572                            vidl2_pixel_color require_color)
00573 {
00574   if (frame.pixel_format() == VIDL2_PIXEL_FORMAT_UNKNOWN ||
00575       frame.data() == NULL)
00576     return false;
00577 
00578   vidl2_pixel_color in_color = vidl2_pixel_format_color(frame.pixel_format());
00579   if (require_color == VIDL2_PIXEL_COLOR_UNKNOWN)
00580     require_color = in_color;
00581 
00582   unsigned ni = frame.ni(), nj = frame.nj();
00583   unsigned np = vidl2_pixel_color_num_channels(require_color);
00584 
00585   // resize the image if necessary
00586   image.set_size(ni,nj,np);
00587 
00588   // special case for MONO_16
00589   if (frame.pixel_format() == VIDL2_PIXEL_FORMAT_MONO_16){
00590     vil_image_view<vxl_uint_16> wrapper(static_cast<const vxl_uint_16*>(frame.data()),
00591                                         ni,nj,1,1,ni,ni*nj);
00592     if (image.pixel_format() == VIL_PIXEL_FORMAT_UINT_16){
00593       vil_image_view<vxl_uint_16>& img = static_cast<vil_image_view<vxl_uint_16>&>(image);
00594       img.deep_copy(vil_image_view<vxl_uint_16>(wrapper));
00595       return true;
00596     }
00597 
00598     switch ( vil_pixel_format_component_format(image.pixel_format()) ){
00599 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00600 #define macro(F , T) \
00601     case F: {\
00602       vil_image_view<T> & dest_ref = static_cast<vil_image_view<T> &>(image); \
00603       vil_convert_cast( wrapper, dest_ref); break;}
00604 
00605 #if VXL_HAS_INT_64
00606     macro( VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64 );
00607     macro( VIL_PIXEL_FORMAT_INT_64, vxl_int_64 );
00608 #endif
00609     macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 );
00610     macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 );
00611     macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 );
00612     macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte );
00613     macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte );
00614     macro( VIL_PIXEL_FORMAT_FLOAT, float );
00615     macro( VIL_PIXEL_FORMAT_DOUBLE, double );
00616     macro( VIL_PIXEL_FORMAT_BOOL, bool );
00617 #undef macro
00618 #endif // DOXYGEN_SHOULD_SKIP_THIS
00619       default:
00620         return false;
00621     }
00622     return true;
00623   }
00624 
00625   vidl2_pixel_format default_format = VIDL2_PIXEL_FORMAT_UNKNOWN;
00626   if (image.pixel_format() == VIL_PIXEL_FORMAT_BYTE)
00627   {
00628     vil_image_view<vxl_byte>& img = static_cast<vil_image_view<vxl_byte>&>(image);
00629     bool interleaved = (img.planestep() == 1);
00630 
00631     switch (require_color) {
00632       case VIDL2_PIXEL_COLOR_MONO:
00633         default_format = VIDL2_PIXEL_FORMAT_MONO_8; break;
00634       case VIDL2_PIXEL_COLOR_RGB:
00635         default_format = interleaved?VIDL2_PIXEL_FORMAT_RGB_24
00636                                     :VIDL2_PIXEL_FORMAT_RGB_24P; break;
00637       case VIDL2_PIXEL_COLOR_RGBA:
00638         default_format = interleaved?VIDL2_PIXEL_FORMAT_RGBA_32
00639                                     :VIDL2_PIXEL_FORMAT_RGBA_32P; break;
00640       case VIDL2_PIXEL_COLOR_YUV:
00641         default_format = interleaved?VIDL2_PIXEL_FORMAT_UYV_444
00642                                     :VIDL2_PIXEL_FORMAT_YUV_444P; break;
00643       default:
00644         break;
00645     }
00646   }
00647 
00648   vidl2_frame_sptr out_frame = new vidl2_memory_chunk_frame(image,default_format);
00649   // if the image can be wrapped as a frame
00650   if (out_frame->pixel_format() != VIDL2_PIXEL_FORMAT_UNKNOWN){
00651     vidl2_convert_frame(frame, *out_frame);
00652     return true;
00653   }
00654 
00655   // use an intermediate format
00656   vidl2_pixel_format out_fmt;
00657   switch (in_color) {
00658     case VIDL2_PIXEL_COLOR_MONO:
00659       out_fmt = VIDL2_PIXEL_FORMAT_MONO_8; break;
00660     case VIDL2_PIXEL_COLOR_RGB:
00661       out_fmt = VIDL2_PIXEL_FORMAT_RGB_24P; break;
00662     case VIDL2_PIXEL_COLOR_RGBA:
00663       out_fmt = VIDL2_PIXEL_FORMAT_RGBA_32P; break;
00664     case VIDL2_PIXEL_COLOR_YUV:
00665       out_fmt = VIDL2_PIXEL_FORMAT_YUV_444P; break;
00666     default:
00667       return false;
00668   }
00669 
00670   vil_image_view<vxl_byte> temp(ni,nj,np);
00671   out_frame = new vidl2_memory_chunk_frame(ni,nj,out_fmt,temp.memory_chunk());
00672   vidl2_convert_frame(frame, *out_frame);
00673 
00674   switch ( vil_pixel_format_component_format(image.pixel_format()) ){
00675 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00676 #define macro(F , T) \
00677     case F: {\
00678       vil_image_view<T> & dest_ref = static_cast<vil_image_view<T> &>(image); \
00679       vil_convert_cast( temp, dest_ref); break;}
00680 
00681 #if VXL_HAS_INT_64
00682     macro( VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64 );
00683     macro( VIL_PIXEL_FORMAT_INT_64, vxl_int_64 );
00684 #endif
00685     macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 );
00686     macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 );
00687     macro( VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16 );
00688     macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 );
00689     macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte );
00690     macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte );
00691     macro( VIL_PIXEL_FORMAT_FLOAT, float );
00692     macro( VIL_PIXEL_FORMAT_DOUBLE, double );
00693     macro( VIL_PIXEL_FORMAT_BOOL, bool );
00694 #undef macro
00695 #endif // DOXYGEN_SHOULD_SKIP_THIS
00696     default:
00697       return false;
00698   }
00699   return true;
00700 }
00701 
00702 
00703 //: Wrap the frame buffer in an image view if supported
00704 // Returns a null pointer if not possible
00705 vil_image_view_base_sptr
00706 vidl2_convert_wrap_in_view(const vidl2_frame& frame)
00707 {
00708   vidl2_pixel_format format = frame.pixel_format();
00709   vidl2_pixel_traits pt =  vidl2_pixel_format_traits(format);
00710   if ( pt.chroma_shift_x != 0 || pt.chroma_shift_y != 0 ||
00711        pt.bits_per_pixel % pt.num_channels != 0)
00712     return NULL;
00713 
00714   unsigned ni = frame.ni(), nj = frame.nj();
00715   unsigned np = pt.num_channels;
00716   vcl_ptrdiff_t i_step, j_step, p_step;
00717   switch (pt.arrangement) {
00718     case VIDL2_PIXEL_ARRANGE_SINGLE:
00719       i_step = np;
00720       j_step = np*ni;
00721       p_step = 1;
00722       break;
00723     case VIDL2_PIXEL_ARRANGE_PLANAR:
00724       i_step = 1;
00725       j_step = ni;
00726       p_step = ni*nj;
00727       break;
00728     default:
00729       // Cannot wrap other pixel arrangements
00730       return NULL;
00731   }
00732   vcl_ptrdiff_t top_left_offset = 0;
00733 
00734   if (format == VIDL2_PIXEL_FORMAT_BGR_24){
00735     top_left_offset = 3;
00736     p_step = -1;
00737   }
00738 
00739   // Create a view of a memory chunk frame
00740   if ( const vidl2_memory_chunk_frame* cf =
00741        dynamic_cast<const vidl2_memory_chunk_frame*>(&frame) )
00742   {
00743     vil_memory_chunk_sptr chunk = cf->memory_chunk();
00744     if (format == VIDL2_PIXEL_FORMAT_MONO_16){
00745       const vxl_uint_16* top_left = static_cast<const vxl_uint_16*>(cf->data()) + top_left_offset;
00746       return new vil_image_view<vxl_uint_16>(chunk,top_left, ni,nj,np, i_step,j_step,p_step);
00747     }
00748     else if (format == VIDL2_PIXEL_FORMAT_MONO_1){
00749       const bool* top_left = static_cast<const bool*>(cf->data()) + top_left_offset;
00750       return new vil_image_view<bool>(chunk,top_left, ni,nj,np, i_step,j_step,p_step);
00751     }
00752     const vxl_byte* top_left = static_cast<const vxl_byte*>(cf->data()) + top_left_offset;
00753     return new vil_image_view<vxl_byte>(chunk,top_left, ni,nj,np, i_step,j_step,p_step);
00754   }
00755 
00756   // Create a view of a frame (without ownership of the data)
00757   if (format == VIDL2_PIXEL_FORMAT_MONO_16){
00758     const vxl_uint_16* top_left = static_cast<const vxl_uint_16*>(frame.data()) + top_left_offset;
00759     return new vil_image_view<vxl_uint_16>(top_left, ni,nj,np, i_step,j_step,p_step);
00760   }
00761   else if (format == VIDL2_PIXEL_FORMAT_MONO_1){
00762     const bool* top_left = static_cast<const bool*>(frame.data()) + top_left_offset;
00763     return new vil_image_view<bool>(top_left, ni,nj,np, i_step,j_step,p_step);
00764   }
00765   const vxl_byte* top_left = static_cast<const vxl_byte*>(frame.data()) + top_left_offset;
00766   return new vil_image_view<vxl_byte>(top_left, ni,nj,np, i_step,j_step,p_step);
00767 }

Generated on Wed Dec 3 05:21:02 2008 for contrib/brl/bbas/vidl2 by  doxygen 1.5.1