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