core/vil/file_formats/vil_pyramid_image_list.cxx

Go to the documentation of this file.
00001 #include "vil_pyramid_image_list.h"
00002 //:
00003 // \file
00004 #include <vcl_algorithm.h>
00005 #include <vcl_cmath.h>
00006 #include <vcl_cassert.h>
00007 #include <vcl_sstream.h>
00008 #include <vil/vil_stream_fstream.h>
00009 #include <vil/vil_image_list.h>
00010 #include <vil/vil_blocked_image_facade.h>
00011 #include <vil/vil_cached_image_resource.h>
00012 #include <vil/vil_new.h>
00013 #include <vil/vil_load.h>
00014 #include <vil/vil_copy.h>
00015 
00016 //:Load a pyramid image.  The path should correspond to a directory.
00017 //If not, return a null resource.
00018 vil_pyramid_image_resource_sptr
00019 vil_pyramid_image_list_format::make_input_pyramid_image(char const* directory)
00020 {
00021   vil_image_list il(directory);
00022   vcl_vector<vil_image_resource_sptr> rescs = il.resources();
00023   unsigned nr = rescs.size();
00024   if (nr < 2)
00025     return 0;
00026   vil_pyramid_image_list* pil = new vil_pyramid_image_list(rescs);
00027   pil->set_directory(directory);
00028   return pil;
00029 }
00030 
00031 vil_pyramid_image_resource_sptr
00032 vil_pyramid_image_list_format::make_pyramid_output_image(char const* file)
00033 {
00034   if (!vil_image_list::vil_is_directory(file))
00035     return 0;
00036   return new vil_pyramid_image_list(file);
00037 }
00038 
00039 static bool copy_base_resc(vil_image_resource_sptr const& base_image,
00040                            vcl_string full_filename,
00041                            char const* file_format,
00042                            vil_blocked_image_resource_sptr& copy)
00043 {
00044   { //scope for closing resource
00045   //Create a new blocked base image resource
00046   vcl_cout << "Copying base resource\n";
00047   vil_blocked_image_resource_sptr brsc = blocked_image_resource(base_image);
00048   if (!brsc||brsc->size_block_i()%2!=0||brsc->size_block_i()%2!=0)
00049     brsc = new vil_blocked_image_facade(base_image);
00050   vil_blocked_image_resource_sptr out_resc =
00051     vil_new_blocked_image_resource(full_filename.c_str(),
00052                                    brsc->ni(), brsc->nj(),
00053                                    brsc->nplanes(),
00054                                    brsc->pixel_format(),
00055                                    brsc->size_block_i(),
00056                                    brsc->size_block_j(),
00057                                    file_format);
00058   if (!out_resc)
00059     return false;
00060   for (unsigned j = 0; j<brsc->n_block_j(); ++j)
00061     for (unsigned i = 0; i<brsc->n_block_i(); ++i)
00062     {
00063       vil_image_view_base_sptr blk = brsc->get_block(i,j);
00064       if (!blk)
00065         return 0;
00066       if (!out_resc->put_block(i, j, *blk))
00067         return 0;
00068     }
00069   }//end scope for out resource
00070   //
00071   //reopen the resource for reading.
00072   vil_image_resource_sptr temp = vil_load_image_resource(full_filename.c_str());
00073   copy = blocked_image_resource(temp);
00074   if (!copy)
00075     return false;
00076   return true;
00077 }
00078 
00079 static vcl_string level_filename(vcl_string& directory, vcl_string& filename,
00080                                  float level)
00081 {
00082   vcl_string slash;
00083 
00084 #ifdef VCL_WIN32
00085   slash =  "\\";
00086 #else
00087   slash = "/";
00088 #endif
00089   vcl_stringstream cs;
00090   cs << level;
00091   return directory + slash + filename + "_" + cs.str();
00092 }
00093 
00094 //: Construct pyramid image files in the directory
00095 //  Each level has the same scale ratio (0.5) to the preceeding level.
00096 //  Level 0 is the original base image.
00097 vil_pyramid_image_resource_sptr vil_pyramid_image_list_format::
00098     make_pyramid_image_from_base(char const* directory,
00099                                  vil_image_resource_sptr const& base_image,
00100                                  unsigned nlevels,
00101                                  bool copy_base,
00102                                  char const* level_file_format,
00103                                  char const* filename
00104                                 )
00105 {
00106   if (!vil_image_list::vil_is_directory(directory))
00107     return 0;
00108   vcl_string d = directory;
00109   vcl_string fn = filename;
00110   vcl_string full_filename = level_filename(d,fn, 0.0f) + '.'+ level_file_format;
00111   vil_blocked_image_resource_sptr blk_base;
00112   if (copy_base)
00113   {
00114     if (!copy_base_resc(base_image, full_filename,
00115                         level_file_format, blk_base))
00116       return 0;
00117   }
00118   else
00119   {
00120     blk_base =
00121       blocked_image_resource(base_image);
00122     if (!blk_base)
00123       return 0;
00124   }
00125   //Create the other pyramid levels
00126   { //program scope to close resource files
00127     vil_image_resource_sptr image = blk_base.ptr();
00128     for (unsigned L = 1; L<nlevels; ++L)
00129     {
00130       vcl_cout << "Decimating Level " << L << vcl_endl;
00131       full_filename = level_filename(d, fn, float(L)) + '.'+ level_file_format;
00132       image = vil_pyramid_image_resource::decimate(image,full_filename.c_str());
00133     }
00134   } //end program scope to close resource files
00135   vil_image_list il(directory);
00136   vcl_vector<vil_image_resource_sptr> rescs = il.resources();
00137   return new vil_pyramid_image_list(rescs);
00138 }
00139 
00140 ///==============  start vil_pyramid_image_list  =========================
00141 //comparison of level scales
00142 static bool level_compare(pyramid_level* const l1, pyramid_level* const l2)
00143 {
00144   assert(l1&&l2);
00145   return l1->image_->ni() > l2->image_->ni();
00146 }
00147 
00148 
00149 vil_pyramid_image_list::vil_pyramid_image_list() : directory_("")
00150 {}
00151 
00152 vil_pyramid_image_list::vil_pyramid_image_list(char const* directory) : directory_(directory)
00153 {}
00154 
00155 vil_pyramid_image_list::vil_pyramid_image_list(vcl_vector<vil_image_resource_sptr> const& images) : directory_("")
00156 {
00157   for (vcl_vector<vil_image_resource_sptr>::const_iterator rit = images.begin();
00158        rit != images.end(); ++rit)
00159   {
00160     //if the resource is blocked use a cached access
00161     vil_blocked_image_resource_sptr brsc = blocked_image_resource(*rit);
00162     if (!brsc)
00163       brsc = new vil_blocked_image_facade(*rit);
00164     vil_cached_image_resource* cimr = new vil_cached_image_resource(brsc, 100);
00165     vil_image_resource_sptr ir = (vil_image_resource*)cimr;
00166     pyramid_level* level = new pyramid_level(ir);
00167     levels_.push_back(level);
00168   }
00169   //sort on image width
00170   vcl_sort(levels_.begin(), levels_.end(), level_compare);
00171   this->normalize_scales();
00172 }
00173 
00174 vil_pyramid_image_list::~vil_pyramid_image_list()
00175 {
00176   unsigned nlevels = levels_.size();
00177   for (unsigned i = 0; i<nlevels; ++i)
00178     delete levels_[i];
00179 }
00180 
00181 //: Assumes that the image in level 0 is the largest
00182 void vil_pyramid_image_list::normalize_scales()
00183 {
00184   unsigned nlevels = levels_.size();
00185   if (nlevels==0)
00186     return;
00187   levels_[0]->scale_ = 1.0f;
00188   if (nlevels==1)
00189     return;
00190   float ni0 = static_cast<float>(levels_[0]->image_->ni());
00191   for (unsigned i = 1; i<nlevels; ++i)
00192     levels_[i]->scale_ = static_cast<float>(levels_[i]->image_->ni())/ni0;
00193 }
00194 
00195 bool vil_pyramid_image_list::is_same_size(vil_image_resource_sptr const& image)
00196 {
00197   unsigned ni = image->ni(), nj = image->nj();
00198   for (unsigned L = 0; L<this->nlevels(); ++L)
00199     if (levels_[L]->image_->ni()==ni&&levels_[L]->image_->nj()==nj)
00200       return true;
00201   return false;
00202 }
00203 
00204 bool
00205 vil_pyramid_image_list::add_resource(vil_image_resource_sptr const& image)
00206 {
00207   if (this->is_same_size(image))
00208     return false;
00209 
00210   pyramid_level* level = new pyramid_level(image);
00211   levels_.push_back(level);
00212 
00213   //is this the first image added?
00214   if (levels_.size() == 1)
00215     return true;
00216   //sort the pyramid
00217   vcl_sort(levels_.begin(), levels_.end(), level_compare);
00218   //normalize the scales
00219   this->normalize_scales();
00220   return true;
00221 }
00222 
00223 //: Find an appropriate filename extension for the image.
00224 // If the size of the image lies between existing scales then use
00225 // the fractional amount in the name
00226 float
00227 vil_pyramid_image_list::find_next_level(vil_image_resource_sptr const& image)
00228 {
00229   unsigned nlevels = this->nlevels();
00230   if (nlevels==0)
00231     return 0.0f;
00232   float base_ni = static_cast<float>(levels_[0]->image_->ni());
00233   return static_cast<float>(image->ni())/base_ni;
00234 }
00235 
00236 //: This method copies the resource into the pyramid.
00237 // Use add_resource if the existing resource is to be just inserted into the level stack.
00238 bool vil_pyramid_image_list::put_resource(vil_image_resource_sptr const& image)
00239 {
00240   if (this->is_same_size(image))
00241     return false;
00242   float level = this->find_next_level(image);
00243   vcl_string copy_name = "copyR";
00244   vcl_string file = level_filename(directory_,copy_name, level);
00245   vcl_string ffmt = "pgm";
00246   if (image->file_format())
00247     ffmt = image->file_format();
00248   file = file +'.'+ ffmt;
00249   unsigned sbi = 0, sbj = 0;
00250   vil_blocked_image_resource_sptr bir = blocked_image_resource(image);
00251   if (bir)
00252   { sbi = bir->size_block_i(); sbj = bir->size_block_j(); }
00253   vil_image_resource_sptr copy;
00254   if (sbi==0||sbj==0)
00255   {
00256 #ifdef VIL_USE_FSTREAM64
00257     vil_stream_fstream64* os = new vil_stream_fstream64(file.c_str(), "w");
00258 #else //VIL_USE_FSTREAM64
00259     vil_stream_fstream* os = new vil_stream_fstream(file.c_str(), "w");
00260 #endif //VIL_USE_FSTREAM64
00261     copy = vil_new_image_resource(os, image->ni(), image->nj(),
00262                                   image->nplanes(), image->pixel_format(),
00263                                   ffmt.c_str());
00264   }
00265   else
00266     copy = vil_new_blocked_image_resource(file.c_str(),
00267                                           image->ni(), image->nj(),
00268                                           image->nplanes(),
00269                                           image->pixel_format(),
00270                                           sbi, sbj,
00271                                           ffmt.c_str()).ptr();
00272   if (!vil_copy_deep(image, copy))
00273     return false;
00274   return this->add_resource(copy);
00275 }
00276 
00277 //:find the level closest to the specified scale
00278 pyramid_level* vil_pyramid_image_list::closest(const float scale) const
00279 {
00280   unsigned nlevels = levels_.size();
00281   if (nlevels == 0)
00282     return 0;
00283 
00284   if (nlevels == 1)
00285     return levels_[0];
00286   float mind = 1.0e08f;//huge scale;
00287   unsigned lmin = 0;
00288   for (unsigned i = 0; i<nlevels; ++i)
00289   {
00290     float ds = vcl_fabs(vcl_log(levels_[i]->scale_ / scale));
00291     if (ds<mind)
00292     {
00293       mind = ds;
00294       lmin = i;
00295     }
00296   }
00297   pyramid_level* pl = levels_[lmin];
00298   if (pl)
00299     pl->cur_level_ = lmin;
00300   return pl;
00301 }
00302 
00303 vil_image_view_base_sptr
00304 vil_pyramid_image_list::get_copy_view(unsigned i0, unsigned n_i,
00305                                       unsigned j0, unsigned n_j,
00306                                       unsigned level) const
00307 {
00308   if (level>=this->nlevels())
00309   {
00310     vcl_cerr << "pyramid_image_list::get_copy_view(.) level = "
00311              << level << " max level = "
00312              << this->nlevels() -1 << '\n';
00313     return 0;
00314   }
00315   pyramid_level* pl = levels_[level];
00316   float actual_scale = pl->scale_;
00317 
00318   float fi0 = actual_scale*i0, fni = actual_scale*n_i, fj0 = actual_scale*j0, fnj = actual_scale*n_j;
00319   //transform image coordinates by actual scale
00320   unsigned si0 = static_cast<unsigned>(fi0);
00321   unsigned sni = static_cast<unsigned>(fni);
00322   if (sni == 0) sni = 1;//can't have less than one pixel
00323   unsigned sj0 = static_cast<unsigned>(fj0);
00324   unsigned snj = static_cast<unsigned>(fnj);
00325   if (snj == 0) snj = 1;//can't have less than one pixel
00326   vil_image_view_base_sptr v = pl->image_->get_copy_view(si0, sni, sj0, snj);
00327   if (!v)
00328   {
00329     vcl_cerr << "pyramid_image_list::get_copy_view(.) level = "
00330              << level << "(i0,j0):("
00331              << i0 << ' ' << j0 << ") (ni, nj):("
00332              << n_i << ' ' << n_j << ")\n"
00333              << "Get copy view from level image failed\n";
00334     return 0;
00335   }
00336   return v;
00337 }
00338 
00339 //:return a view with image scale that is closest to scale.
00340 vil_image_view_base_sptr
00341 vil_pyramid_image_list::get_copy_view(unsigned i0, unsigned n_i,
00342                                       unsigned j0, unsigned n_j,
00343                                       const float scale,
00344                                       float& actual_scale) const
00345 {
00346   //find the resource that is closest to the specified scale
00347   pyramid_level* pl = this->closest(scale);
00348   if (!pl)
00349   {
00350     actual_scale = 0;
00351     return 0;
00352   }
00353   actual_scale = pl->scale_;
00354   unsigned level = pl->cur_level_;
00355   return this->get_copy_view(i0, n_i, j0, n_j, level);
00356 }
00357 

Generated on Sat Nov 7 05:08:32 2009 for core/vil by  doxygen 1.5.1