contrib/mul/vimt/vimt_vil_v2i.cxx
Go to the documentation of this file.
00001 //:
00002 // \file
00003 
00004 #include "vimt_vil_v2i.h"
00005 
00006 #include <vcl_cassert.h>
00007 #include <vcl_cstring.h>
00008 #include <vcl_typeinfo.h>
00009 #include <vcl_fstream.h>
00010 
00011 #include <vxl_config.h> // for VXL_BIG_ENDIAN and vxl_byte
00012 
00013 #include <vgl/vgl_point_2d.h>
00014 #include <vgl/vgl_vector_2d.h>
00015 #include <vil/vil_exception.h>
00016 #include <vil/vil_property.h>
00017 #include <vil/vil_copy.h>
00018 #include <vil/vil_stream.h>
00019 #include <vil/vil_stream_fstream.h>
00020 #include <vil/vil_image_resource.h>
00021 #include <vil/vil_image_view.h>
00022 #include <vsl/vsl_binary_io.h>
00023 #include <vsl/vsl_binary_loader.h>
00024 #include <vimt/vimt_image_2d_of.h>
00025 
00026 // v2i magic number
00027 const unsigned V2I_MAGIC = 987123872U;
00028 
00029 
00030 class vimt_vil_fstream: vil_stream_fstream
00031 {
00032  protected:
00033   vcl_fstream& underlying_stream() { return vil_stream_fstream::underlying_stream(); }
00034   friend class vimt_vil_v2i_format;
00035   friend class vimt_vil_v2i_image;
00036  private:
00037   vimt_vil_fstream(): vil_stream_fstream("", "") {} // Will never be constructed
00038 };
00039 
00040 
00041 vil_image_resource_sptr vimt_vil_v2i_format::make_input_image(vil_stream* vs)
00042 {
00043   // First of all hack a vil_stream to get at the underlying
00044   // vcl_stream, in order to create a vsl_b_stream
00045   if (typeid(*vs) != typeid(vil_stream_fstream))
00046   {
00047     vcl_cerr << "vimt_vil_v2i_format::make_input_image() WARNING\n"
00048              << "  Unable to deal with stream type\n";
00049 
00050     return 0;
00051   }
00052   vsl_b_istream vslstream( &reinterpret_cast<vimt_vil_fstream *>(vs)->underlying_stream() );
00053   if (!vslstream) return 0; // Not even a vsl file.
00054   unsigned magic;
00055   vil_streampos start = vs->tell();
00056   vsl_b_read(vslstream, magic);
00057   if (magic == V2I_MAGIC)
00058     return new vimt_vil_v2i_image(vs);
00059 
00060   // This vsl stream may hav been created with vsl_b_wrte(vimt_image) - with no
00061   //  v2i magic number. Check if that is true.
00062   vs->seek(start);
00063   int v_i;
00064   bool v_b;
00065   vsl_b_read(vslstream, v_i);  // vimt_image_2d_of.version
00066   vsl_b_read(vslstream, v_i);  // vil_image_view.version
00067   if (v_i != 1) return 0; // can only handle version 1.
00068   vsl_b_read(vslstream, v_i);  // vil_image_view.ni
00069   if (v_i == 0) return 0; // can't handle empty images.
00070   vsl_b_read(vslstream, v_i);  // vil_image_view.nj
00071   if (v_i == 0) return 0; // can't handle empty images.
00072   vsl_b_read(vslstream, v_i);  // vil_image_view.nplanes
00073   if (v_i == 0) return 0; // can't handle empty images.
00074   vsl_b_read(vslstream, v_i);  // vil_image_view.istep
00075   vsl_b_read(vslstream, v_i);  // vil_image_view.jstep
00076   vsl_b_read(vslstream, v_i);  // vil_image_view.planestep
00077   vsl_b_read(vslstream, v_i);  // vil_smart_ptr.version
00078   if (v_i != 2) return 0; // can only handle version 2.
00079   vsl_b_read(vslstream, v_b);  // vil_smart_ptr.firsttime
00080   if (!v_b) return 0; // can't handle multiple images.
00081   vsl_b_read(vslstream, v_i);  // vil_smart_ptr.id
00082   if (v_i != 1) return 0; // can't handle multiple images.
00083   vsl_b_read(vslstream, v_b);  // vil_memory_chunk*.nonnull
00084   if (!v_b) return 0; // can't handle empty images.
00085   vsl_b_read(vslstream, v_i);  // vil_memory_chunk.version
00086   if (v_i != 2 && v_i != 3) return 0; // can only handle version 2.
00087   vsl_b_read(vslstream, v_i);  //  chunk.pixel_format
00088 
00089   vil_pixel_format f = static_cast<vil_pixel_format>(v_i);
00090   vs->seek(start);
00091   switch (f)
00092   {
00093 #define macro( F , T ) \
00094     case  F : \
00095     { vimt_image_2d_of< T > im; vsl_b_read(vslstream, im); if (!vslstream) return 0; } \
00096     break;
00097 // Don't include versions for which there is no template instantiation of vimt_image_2d_of.
00098 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00099 //macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00100 //macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00101 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00102 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00103 //macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00104 macro(VIL_PIXEL_FORMAT_BOOL , bool )
00105 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00106 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00107 #undef macro
00108     default: return 0; // Unknown pixel type - or more likely not a v2i image.
00109   }
00110   vs->seek(start);
00111   return new vimt_vil_v2i_image(vs, f);
00112 }
00113 
00114 vil_image_resource_sptr vimt_vil_v2i_format::make_output_image(vil_stream* vs,
00115                                                                unsigned ni,
00116                                                                unsigned nj,
00117                                                                unsigned nplanes,
00118                                                                vil_pixel_format format)
00119 {
00120   // First of all hack a vil_stream to get at the underlying
00121   // ccl_stream, in order to create a vsl_b_stream
00122   if (typeid(*vs) != typeid(vil_stream_fstream))
00123   {
00124     vcl_cerr << "vimt_vil_v2i_format::make_output_image() WARNING\n"
00125              << "  Unable to deal with stream type\n";
00126 
00127     return 0;
00128   }
00129   if ( format != VIL_PIXEL_FORMAT_BYTE && format != VIL_PIXEL_FORMAT_SBYTE &&
00130        format != VIL_PIXEL_FORMAT_UINT_32 && format != VIL_PIXEL_FORMAT_INT_32 &&
00131        format != VIL_PIXEL_FORMAT_UINT_16 && format != VIL_PIXEL_FORMAT_INT_16 &&
00132        format != VIL_PIXEL_FORMAT_FLOAT && format != VIL_PIXEL_FORMAT_DOUBLE &&
00133        format != VIL_PIXEL_FORMAT_BOOL)
00134   {
00135     vcl_cerr << "vimt_vil_v2i_format::make_output_image() WARNING\n"
00136              << "  Unable to deal with file format : " << format << vcl_endl;
00137     return 0;
00138   }
00139   return new vimt_vil_v2i_image(vs, ni, nj, nplanes, format);
00140 }
00141 
00142 
00143 /////////////////////////////////////////////////////////////////////////////
00144 
00145 vimt_vil_v2i_image::vimt_vil_v2i_image(vil_stream* vs):
00146   vs_(vs), im_(0), dirty_(false)
00147 {
00148   vs_->ref();
00149   vs_->seek(0L);
00150   vsl_b_istream vslstream(& reinterpret_cast<vimt_vil_fstream *>(vs_)->underlying_stream());
00151 
00152   unsigned magic;
00153   vsl_b_read(vslstream, magic);
00154   assert(magic == V2I_MAGIC);
00155 
00156   short version;
00157   vsl_b_read(vslstream, version);
00158 
00159   switch (version)
00160   {
00161    case 1: {
00162     vimt_image *p_im=0;
00163     vsl_b_read(vslstream, p_im);
00164     if (!vslstream)
00165     {
00166       delete p_im;
00167       vil_exception_warning(vil_exception_corrupt_image_file("Constructor", "v2i", "", "Failed to read file correctly"));
00168       im_=0;
00169       return;
00170     }
00171 
00172     im_ = dynamic_cast<vimt_image_2d *>(p_im);
00173     break;
00174    }
00175    default:
00176     vcl_cerr << "I/O ERROR: vimt_vil_v2i_image::vimt_vil_v2i_image()\n"
00177              << "           Unknown version number "<< version << '\n';
00178     return;
00179   }
00180 }
00181 
00182 
00183 //: Constructor to deal with directly created v2i files.
00184 vimt_vil_v2i_image::vimt_vil_v2i_image(vil_stream* vs, vil_pixel_format f):
00185   vs_(vs), im_(0), dirty_(false)
00186 {
00187   vs_->ref();
00188   vs_->seek(0L);
00189   vsl_b_istream vslstream(& reinterpret_cast<vimt_vil_fstream *>(vs_)->underlying_stream());
00190 
00191 
00192   switch (f)
00193   {
00194 #define macro( F , T ) \
00195     case  F : \
00196     im_ = new vimt_image_2d_of< T >(); \
00197     vsl_b_read(vslstream, *static_cast<vimt_image_2d_of< T >*>(im_)); \
00198     break;
00199 // Don't include versions for which there is no template instantiation of vimt_image_2d_of.
00200 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00201 //macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00202 //macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00203 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00204 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00205 //macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00206 macro(VIL_PIXEL_FORMAT_BOOL , bool )
00207 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00208 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00209 #undef macro
00210     default: throw vil_exception_image_io("vimt_vil_v2i_image::vimt_vil_v2i_image",
00211                                           "v2i", "");
00212   }
00213 
00214   // Fiddle factor - most directly created vsl files have transforms in mm.
00215   vimt_transform_2d tr;
00216   tr.set_zoom_only(1000.0, 0.0, 0.0);
00217   im_->world2im() = im_->world2im() * tr;
00218   assert(! !vslstream);
00219 }
00220 
00221 bool vimt_vil_v2i_image::get_property(char const * key, void * value) const
00222 {
00223   const vimt_transform_2d &tr = im_->world2im();
00224 
00225   if (vcl_strcmp(vil_property_pixel_size, key)==0)
00226   {
00227     vgl_vector_2d<double> p11 = tr.inverse()(1.0, 1.0) - tr.inverse().origin();
00228     //Assume no rotation or shearing.
00229 
00230     float* array =  static_cast<float*>(value);
00231     array[0] = (float) p11.x();
00232     array[1] = (float) p11.y();
00233     return true;
00234   }
00235 
00236   if (vcl_strcmp(vil_property_offset, key)==0)
00237   {
00238     vgl_point_2d<double> origin = tr.origin();
00239     float* array =  static_cast<float*>(value);
00240     array[0] = (float)(origin.x());
00241     array[1] = (float)(origin.y());
00242     return true;
00243   }
00244 
00245   return false;
00246 }
00247 
00248 vimt_vil_v2i_image::vimt_vil_v2i_image(vil_stream* vs, unsigned ni, unsigned nj,
00249                                        unsigned nplanes, vil_pixel_format format):
00250   vs_(vs), im_(0), dirty_(true)
00251 {
00252   vs_->ref();
00253   switch (format)
00254   {
00255 #define macro( F , T ) \
00256    case  F : \
00257     im_ = new vimt_image_2d_of< T > (ni, nj, nplanes); \
00258     break;
00259 // Don't include versions for which there is no template instantiation of vimt_image_2d_of.
00260 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00261 //macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00262 //macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00263 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00264 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00265 //macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00266 macro(VIL_PIXEL_FORMAT_BOOL , bool )
00267 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00268 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00269 #undef macro
00270    default:
00271     vcl_cerr << "I/O ERROR: vimt_vil_v2i_image::vimt_vil_v2i_image()\n"
00272              << "           Unknown vil_pixel_format "<< format << '\n';
00273     vcl_abort();
00274   }
00275 }
00276 
00277 
00278 vimt_vil_v2i_image::~vimt_vil_v2i_image()
00279 {
00280   if (dirty_)
00281   {
00282     vs_->seek(0l);
00283     vsl_b_ostream vslstream(& reinterpret_cast<vimt_vil_fstream *>(vs_)->underlying_stream());
00284 
00285     vsl_b_write(vslstream, V2I_MAGIC);
00286 
00287     const short version = 1;
00288     vsl_b_write(vslstream, version);
00289 
00290 
00291     vimt_image *p_im=im_;
00292     vsl_b_write(vslstream, p_im);
00293   }
00294   //delete vs_;
00295   vs_->unref();
00296   delete im_;
00297 }
00298 
00299 //: Dimensions:  nplanes x ni x nj.
00300 // This concept is treated as a synonym to components.
00301 unsigned vimt_vil_v2i_image::nplanes() const
00302 {
00303   return im_->image_base().nplanes();
00304 }
00305 
00306 //: Dimensions:  nplanes x ni x nj.
00307 // The number of pixels in each row.
00308 unsigned vimt_vil_v2i_image::ni() const
00309 {
00310   return im_->image_base().ni();
00311 }
00312 
00313 //: Dimensions:  nplanes x ni x nj.
00314 // The number of pixels in each column.
00315 unsigned vimt_vil_v2i_image::nj() const
00316 {
00317   return im_->image_base().nj();
00318 }
00319 
00320 //: Pixel Format.
00321 enum vil_pixel_format vimt_vil_v2i_image::pixel_format() const
00322 {
00323   return im_->image_base().pixel_format();
00324 }
00325 
00326 
00327 const vimt_transform_2d & vimt_vil_v2i_image::world2im() const
00328 {
00329   return im_->world2im();
00330 }
00331 
00332 void vimt_vil_v2i_image::set_world2im(const vimt_transform_2d & tr)
00333 {
00334   im_->set_world2im(tr);
00335   dirty_ = true;
00336 }
00337 
00338 //: Set the size of the each pixel in the i,j,k directions.
00339 void vimt_vil_v2i_image::set_pixel_size(float si, float sj)
00340 {
00341   const vimt_transform_2d &tr = im_->world2im();
00342 
00343 // Try to adjust pixel size without modifying rest of transform
00344   vgl_vector_2d<double> w11 = tr(1.0, 1.0) - tr.origin();
00345 
00346   vimt_transform_2d zoom;
00347   zoom.set_zoom_only (w11.x()/si, w11.y()/sj, 0.0, 0.0);
00348 
00349   im_->set_world2im(tr*zoom);
00350 }
00351 
00352 
00353 //: Create a read/write view of a copy of this data.
00354 // Currently not yet implemented.
00355 // \return 0 if unable to get view of correct size.
00356 vil_image_view_base_sptr vimt_vil_v2i_image::get_copy_view(unsigned i0, unsigned ni,
00357                                                            unsigned j0, unsigned nj) const
00358 {
00359   const vil_image_view_base &view = im_->image_base();
00360 
00361   if (i0 + ni > view.ni() || j0 + nj > view.nj() ) return 0;
00362 
00363   switch (view.pixel_format())
00364   {
00365 #define macro( F , T ) \
00366    case  F : { \
00367     const vil_image_view< T > &v = \
00368       static_cast<const vil_image_view< T > &>(view); \
00369     vil_image_view< T > w(v.memory_chunk(), &v(i0,j0), \
00370                           ni, nj, v.nplanes(), \
00371                           v.istep(), v.jstep(), v.planestep()); \
00372     return new vil_image_view< T >(vil_copy_deep(w)); }
00373 // Don't include versions for which there is no template instantiation of vimt_image_2d_of.
00374 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00375 //macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00376 //macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00377 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00378 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00379 //macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00380 macro(VIL_PIXEL_FORMAT_BOOL , bool )
00381 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00382 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00383 #undef macro
00384    default:
00385     return 0;
00386   }
00387 }
00388 
00389 //: Create a read/write view of a copy of this data.
00390 // \return 0 if unable to get view of correct size.
00391 vil_image_view_base_sptr vimt_vil_v2i_image::get_view(unsigned i0, unsigned ni,
00392                                                       unsigned j0, unsigned nj) const
00393 {
00394   const vil_image_view_base &view = im_->image_base();
00395 
00396 
00397   if (i0 + ni > view.ni() || j0 + nj > view.nj()) return 0;
00398 
00399   switch (view.pixel_format())
00400   {
00401 #define macro( F , T ) \
00402    case  F : { \
00403     const vil_image_view< T > &v = \
00404       static_cast<const vil_image_view< T > &>(view); \
00405     return new vil_image_view< T >(v.memory_chunk(), &v(i0,j0), \
00406                                    ni, nj, v.nplanes(), \
00407                                    v.istep(), v.jstep(), v.planestep()); }
00408 // Don't include versions for which there is no template instantiation of vimt_image_2d_of.
00409 macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00410 //macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00411 //macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00412 //macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00413 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00414 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00415 //macro(VIL_PIXEL_FORMAT_BOOL , bool )
00416 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00417 //macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00418 #undef macro
00419    default:
00420     return 0;
00421   }
00422 }
00423 
00424 
00425 //: Set the contents of the volume.
00426 bool vimt_vil_v2i_image::put_view(const vil_image_view_base& vv,
00427                                   unsigned i0, unsigned j0)
00428 {
00429   if (!view_fits(vv, i0, j0))
00430   {
00431     vcl_cerr << "ERROR: " << __FILE__ << ":\n view does not fit\n";
00432     return false;
00433   }
00434 
00435   if (vv.pixel_format() != im_->image_base().pixel_format())
00436   {
00437     vcl_cerr << "ERROR: vimt_vil_v2i_image::put_view(). Pixel formats do not match\n";
00438     return false;
00439   }
00440 
00441 
00442   dirty_ = true;
00443 
00444   switch (vv.pixel_format())
00445   {
00446 #define macro( F , T ) \
00447    case  F : \
00448     vil_copy_to_window(static_cast<vil_image_view< T >const&>(vv), \
00449                        static_cast<vimt_image_2d_of< T >&>(*im_).image(), i0, j0); \
00450     return true;
00451 
00452 // Don't include versions for which there is no template instantiation of vimt_image_2d_of.
00453     macro(VIL_PIXEL_FORMAT_BYTE , vxl_byte )
00454 //  macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00455 //  macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00456 //  macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00457     macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00458     macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00459 //  macro(VIL_PIXEL_FORMAT_BOOL , bool )
00460     macro(VIL_PIXEL_FORMAT_FLOAT , float )
00461 //  macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00462 #undef macro
00463    default:
00464     return false;
00465   }
00466 }