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 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
00095
00096
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
00126 {
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 }
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
00141
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
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
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
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
00214 if (levels_.size() == 1)
00215 return true;
00216
00217 vcl_sort(levels_.begin(), levels_.end(), level_compare);
00218
00219 this->normalize_scales();
00220 return true;
00221 }
00222
00223
00224
00225
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
00237
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
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;
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
00320 unsigned si0 = static_cast<unsigned>(fi0);
00321 unsigned sni = static_cast<unsigned>(fni);
00322 if (sni == 0) sni = 1;
00323 unsigned sj0 = static_cast<unsigned>(fj0);
00324 unsigned snj = static_cast<unsigned>(fnj);
00325 if (snj == 0) snj = 1;
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
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
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