00001 #include "vil_pyramid_image_list.h"
00002
00003
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
00017
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 {
00045
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 }
00070
00071
00072 vil_image_resource_sptr temp = vil_load_image_resource(full_filename.c_str());
00073 copy = blocked_image_resource(temp);
00074 return (bool)copy;
00075 }
00076
00077 static vcl_string level_filename(vcl_string& directory, vcl_string& filename,
00078 float level)
00079 {
00080 vcl_string slash;
00081
00082 #ifdef VCL_WIN32
00083 slash = "\\";
00084 #else
00085 slash = "/";
00086 #endif
00087 vcl_stringstream cs;
00088 cs << level;
00089 return directory + slash + filename + "_" + cs.str();
00090 }
00091
00092
00093
00094
00095 vil_pyramid_image_resource_sptr vil_pyramid_image_list_format::
00096 make_pyramid_image_from_base(char const* directory,
00097 vil_image_resource_sptr const& base_image,
00098 unsigned nlevels,
00099 bool copy_base,
00100 char const* level_file_format,
00101 char const* filename
00102 )
00103 {
00104 if (!vil_image_list::vil_is_directory(directory))
00105 return 0;
00106 vcl_string d = directory;
00107 vcl_string fn = filename;
00108 vcl_string full_filename = level_filename(d,fn, 0.0f) + '.'+ level_file_format;
00109 vil_blocked_image_resource_sptr blk_base;
00110 if (copy_base)
00111 {
00112 if (!copy_base_resc(base_image, full_filename,
00113 level_file_format, blk_base))
00114 return 0;
00115 }
00116 else
00117 {
00118 blk_base =
00119 blocked_image_resource(base_image);
00120 if (!blk_base)
00121 return 0;
00122 }
00123
00124 {
00125 vil_image_resource_sptr image = blk_base.ptr();
00126 for (unsigned L = 1; L<nlevels; ++L)
00127 {
00128 vcl_cout << "Decimating Level " << L << vcl_endl;
00129 full_filename = level_filename(d, fn, float(L)) + '.'+ level_file_format;
00130 image = vil_pyramid_image_resource::decimate(image,full_filename.c_str());
00131 }
00132 }
00133 vil_image_list il(directory);
00134 vcl_vector<vil_image_resource_sptr> rescs = il.resources();
00135 return new vil_pyramid_image_list(rescs);
00136 }
00137
00138
00139
00140 static bool level_compare(pyramid_level* const l1, pyramid_level* const l2)
00141 {
00142 assert(l1&&l2);
00143 return l1->image_->ni() > l2->image_->ni();
00144 }
00145
00146
00147 vil_pyramid_image_list::vil_pyramid_image_list() : directory_("")
00148 {}
00149
00150 vil_pyramid_image_list::vil_pyramid_image_list(char const* directory) : directory_(directory)
00151 {}
00152
00153 vil_pyramid_image_list::vil_pyramid_image_list(vcl_vector<vil_image_resource_sptr> const& images) : directory_("")
00154 {
00155 for (vcl_vector<vil_image_resource_sptr>::const_iterator rit = images.begin();
00156 rit != images.end(); ++rit)
00157 {
00158
00159 vil_blocked_image_resource_sptr brsc = blocked_image_resource(*rit);
00160 if (!brsc)
00161 brsc = new vil_blocked_image_facade(*rit);
00162 vil_cached_image_resource* cimr = new vil_cached_image_resource(brsc, 100);
00163 vil_image_resource_sptr ir = (vil_image_resource*)cimr;
00164 pyramid_level* level = new pyramid_level(ir);
00165 levels_.push_back(level);
00166 }
00167
00168 vcl_sort(levels_.begin(), levels_.end(), level_compare);
00169 this->normalize_scales();
00170 }
00171
00172 vil_pyramid_image_list::~vil_pyramid_image_list()
00173 {
00174 unsigned nlevels = levels_.size();
00175 for (unsigned i = 0; i<nlevels; ++i)
00176 delete levels_[i];
00177 }
00178
00179
00180 void vil_pyramid_image_list::normalize_scales()
00181 {
00182 unsigned nlevels = levels_.size();
00183 if (nlevels==0)
00184 return;
00185 levels_[0]->scale_ = 1.0f;
00186 if (nlevels==1)
00187 return;
00188 float ni0 = static_cast<float>(levels_[0]->image_->ni());
00189 for (unsigned i = 1; i<nlevels; ++i)
00190 levels_[i]->scale_ = static_cast<float>(levels_[i]->image_->ni())/ni0;
00191 }
00192
00193 bool vil_pyramid_image_list::is_same_size(vil_image_resource_sptr const& image)
00194 {
00195 unsigned ni = image->ni(), nj = image->nj();
00196 for (unsigned L = 0; L<this->nlevels(); ++L)
00197 if (levels_[L]->image_->ni()==ni&&levels_[L]->image_->nj()==nj)
00198 return true;
00199 return false;
00200 }
00201
00202 bool
00203 vil_pyramid_image_list::add_resource(vil_image_resource_sptr const& image)
00204 {
00205 if (this->is_same_size(image))
00206 return false;
00207
00208 pyramid_level* level = new pyramid_level(image);
00209 levels_.push_back(level);
00210
00211
00212 if (levels_.size() == 1)
00213 return true;
00214
00215 vcl_sort(levels_.begin(), levels_.end(), level_compare);
00216
00217 this->normalize_scales();
00218 return true;
00219 }
00220
00221
00222
00223
00224 float
00225 vil_pyramid_image_list::find_next_level(vil_image_resource_sptr const& image)
00226 {
00227 unsigned nlevels = this->nlevels();
00228 if (nlevels==0)
00229 return 0.0f;
00230 float base_ni = static_cast<float>(levels_[0]->image_->ni());
00231 return static_cast<float>(image->ni())/base_ni;
00232 }
00233
00234
00235
00236 bool vil_pyramid_image_list::put_resource(vil_image_resource_sptr const& image)
00237 {
00238 if (this->is_same_size(image))
00239 return false;
00240 float level = this->find_next_level(image);
00241 vcl_string copy_name = "copyR";
00242 vcl_string file = level_filename(directory_,copy_name, level);
00243 vcl_string ffmt = "pgm";
00244 if (image->file_format())
00245 ffmt = image->file_format();
00246 file = file +'.'+ ffmt;
00247 unsigned sbi = 0, sbj = 0;
00248 vil_blocked_image_resource_sptr bir = blocked_image_resource(image);
00249 if (bir)
00250 { sbi = bir->size_block_i(); sbj = bir->size_block_j(); }
00251 vil_image_resource_sptr copy;
00252 if (sbi==0||sbj==0)
00253 {
00254 #ifdef VIL_USE_FSTREAM64
00255 vil_stream_fstream64* os = new vil_stream_fstream64(file.c_str(), "w");
00256 #else //VIL_USE_FSTREAM64
00257 vil_stream_fstream* os = new vil_stream_fstream(file.c_str(), "w");
00258 #endif //VIL_USE_FSTREAM64
00259 copy = vil_new_image_resource(os, image->ni(), image->nj(),
00260 image->nplanes(), image->pixel_format(),
00261 ffmt.c_str());
00262 }
00263 else
00264 copy = vil_new_blocked_image_resource(file.c_str(),
00265 image->ni(), image->nj(),
00266 image->nplanes(),
00267 image->pixel_format(),
00268 sbi, sbj,
00269 ffmt.c_str()).ptr();
00270 if (!vil_copy_deep(image, copy))
00271 return false;
00272 return this->add_resource(copy);
00273 }
00274
00275
00276 pyramid_level* vil_pyramid_image_list::closest(const float scale) const
00277 {
00278 unsigned nlevels = levels_.size();
00279 if (nlevels == 0)
00280 return 0;
00281
00282 if (nlevels == 1)
00283 return levels_[0];
00284 float mind = 1.0e08f;
00285 unsigned lmin = 0;
00286 for (unsigned i = 0; i<nlevels; ++i)
00287 {
00288 float ds = vcl_fabs(vcl_log(levels_[i]->scale_ / scale));
00289 if (ds<mind)
00290 {
00291 mind = ds;
00292 lmin = i;
00293 }
00294 }
00295 pyramid_level* pl = levels_[lmin];
00296 if (pl)
00297 pl->cur_level_ = lmin;
00298 return pl;
00299 }
00300
00301 vil_image_view_base_sptr
00302 vil_pyramid_image_list::get_copy_view(unsigned i0, unsigned n_i,
00303 unsigned j0, unsigned n_j,
00304 unsigned level) const
00305 {
00306 if (level>=this->nlevels())
00307 {
00308 vcl_cerr << "pyramid_image_list::get_copy_view(.) level = "
00309 << level << " max level = "
00310 << this->nlevels() -1 << '\n';
00311 return 0;
00312 }
00313 pyramid_level* pl = levels_[level];
00314 float actual_scale = pl->scale_;
00315
00316 float fi0 = actual_scale*i0, fni = actual_scale*n_i, fj0 = actual_scale*j0, fnj = actual_scale*n_j;
00317
00318 unsigned si0 = static_cast<unsigned>(fi0);
00319 unsigned sni = static_cast<unsigned>(fni);
00320 if (sni == 0) sni = 1;
00321 unsigned sj0 = static_cast<unsigned>(fj0);
00322 unsigned snj = static_cast<unsigned>(fnj);
00323 if (snj == 0) snj = 1;
00324 vil_image_view_base_sptr v = pl->image_->get_copy_view(si0, sni, sj0, snj);
00325 if (!v)
00326 {
00327 vcl_cerr << "pyramid_image_list::get_copy_view(.) level = "
00328 << level << "(i0,j0):("
00329 << i0 << ' ' << j0 << ") (ni, nj):("
00330 << n_i << ' ' << n_j << ")\n"
00331 << "Get copy view from level image failed\n";
00332 return 0;
00333 }
00334 return v;
00335 }
00336
00337
00338 vil_image_view_base_sptr
00339 vil_pyramid_image_list::get_copy_view(unsigned i0, unsigned n_i,
00340 unsigned j0, unsigned n_j,
00341 const float scale,
00342 float& actual_scale) const
00343 {
00344
00345 pyramid_level* pl = this->closest(scale);
00346 if (!pl)
00347 {
00348 actual_scale = 0;
00349 return 0;
00350 }
00351 actual_scale = pl->scale_;
00352 unsigned level = pl->cur_level_;
00353 return this->get_copy_view(i0, n_i, j0, n_j, level);
00354 }
00355