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