00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 #include "vil_pyramid_image_resource.h"
00006
00007
00008 #include <vcl_cassert.h>
00009 #include <vcl_cstring.h>
00010 #include <vcl_vector.h>
00011 #include <vil/vil_property.h>
00012 #include <vil/vil_convert.h>
00013 #include <vil/vil_blocked_image_resource.h>
00014 #include <vil/vil_blocked_image_facade.h>
00015 #include <vil/vil_image_view.h>
00016 #include <vil/vil_new.h>
00017 #include <vil/vil_load.h>
00018
00019
00020 vil_pyramid_image_resource::vil_pyramid_image_resource()
00021 {}
00022
00023 vil_pyramid_image_resource::~vil_pyramid_image_resource()
00024 {}
00025
00026 bool vil_pyramid_image_resource::get_property(char const* tag, void* ) const
00027 {
00028 return vcl_strcmp(vil_property_pyramid, tag)==0;
00029 }
00030
00031
00032
00033
00034 static vil_image_view<float>
00035 decimate_block(vcl_vector<vcl_vector<vil_image_view<float> > > const& blocks)
00036 {
00037 vil_image_view<float> blk = blocks[0][0];
00038 unsigned int sbi = blk.ni(), sbj = blk.nj();
00039 vil_image_view<float> dec_block;
00040 dec_block.set_size(sbi, sbj);
00041 for (unsigned int dj = 0; dj<sbj; ++dj)
00042 {
00043 unsigned int r = 0, j0 = 2*dj;
00044 if (2*dj>=sbj)
00045 {
00046 r = 1;
00047 j0 = 2*dj-sbj;
00048 }
00049 for (unsigned int di = 0; di<sbi; ++di)
00050 {
00051 unsigned int c = 0, i0 = 2*di;
00052 if (2*di>=sbi)
00053 {
00054 c = 1;
00055 i0 = 2*di-sbi;
00056 }
00057 vil_image_view<float> blk = blocks[r][c];
00058 float v =
00059 0.25f*(blk(i0, j0)+blk(i0+1,j0)+blk(i0,j0+1)+blk(i0+1,j0+1));
00060 dec_block(di, dj) = v;
00061 }
00062 }
00063 return dec_block;
00064 }
00065
00066 static
00067 bool convert_multi_plane_to_float(vil_image_view_base_sptr& blk,
00068 vcl_vector<vil_image_view<float> >& fblk)
00069 {
00070 if (!blk) return false;
00071 fblk.clear();
00072 vil_pixel_format fmt = blk->pixel_format();
00073 unsigned int ni = blk->ni(), nj = blk->nj();
00074 unsigned int np = blk->nplanes();
00075 if (fmt == VIL_PIXEL_FORMAT_BYTE)
00076 {
00077 vil_image_view<unsigned char> bv = blk;
00078 for (unsigned int p = 0; p<np; ++p){
00079 vil_image_view<float> bvf(ni, nj);
00080 for (unsigned int j = 0; j<nj; ++j)
00081 for (unsigned int i= 0; i<ni; ++i)
00082 bvf(i,j) = bv(i,j,p);
00083 fblk.push_back(bvf);
00084 }
00085 return true;
00086 }
00087 else if (fmt == VIL_PIXEL_FORMAT_UINT_16)
00088 {
00089 vil_image_view<unsigned short> bv = blk;
00090 for (unsigned int p = 0; p<np; ++p){
00091 vil_image_view<float> bvf(ni, nj);
00092 for (unsigned int j = 0; j<nj; ++j)
00093 for (unsigned int i= 0; i<ni; ++i)
00094 bvf(i,j) = bv(i,j,p);
00095 fblk.push_back(bvf);
00096 }
00097 return true;
00098 }
00099 return false;
00100 }
00101
00102 static
00103 void convert_multi_plane_from_float(vcl_vector<vil_image_view<float> >& fblk,
00104 vil_image_view<unsigned char>& blk)
00105 {
00106 unsigned int ni = fblk[0].ni(), nj = fblk[0].nj();
00107 unsigned int np = (unsigned int)(fblk.size());
00108 for (unsigned int p = 0; p<np; ++p)
00109 for (unsigned int j = 0; j<nj; ++j)
00110 for (unsigned int i= 0; i<ni; ++i)
00111 blk(i,j,p) = static_cast<unsigned char>(fblk[p](i,j));
00112 }
00113
00114 static
00115 void convert_multi_plane_from_float(vcl_vector<vil_image_view<float> >& fblk,
00116 vil_image_view<unsigned short>& blk)
00117 {
00118 unsigned int ni = fblk[0].ni(), nj = fblk[0].nj();
00119 unsigned int np = (unsigned int)(fblk.size());
00120 for (unsigned int p = 0; p<np; ++p)
00121 for (unsigned int j = 0; j<nj; ++j)
00122 for (unsigned int i= 0; i<ni; ++i)
00123 blk(i,j,p) = static_cast<unsigned short>(fblk[p](i,j));
00124 }
00125
00126 bool vil_pyramid_image_resource::
00127 blocked_decimate(vil_blocked_image_resource_sptr const& brsc,
00128 vil_blocked_image_resource_sptr & dec_resc)
00129 {
00130 if (!brsc)
00131 return false;
00132 unsigned int nbi = brsc->n_block_i(), nbj = brsc->n_block_j();
00133 if (nbi==0||nbj==0)
00134 return false;
00135 unsigned int np = brsc->nplanes();
00136
00137
00138 unsigned int sbi_src = brsc->size_block_i(), sbj_src = brsc->size_block_j();
00139 unsigned int sbi_dec = dec_resc->size_block_i(),
00140 sbj_dec = dec_resc->size_block_j();
00141 if (sbi_src!=sbi_dec||sbj_src!=sbj_dec)
00142 return false;
00143 vil_pixel_format fmt = brsc->pixel_format();
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 switch (np)
00163 {
00164 case 1:
00165 {
00166 vcl_vector<vcl_vector<vil_image_view<float> > > buf(2), nbrhd(2);
00167 for (unsigned int k =0; k<2; ++k)
00168 {
00169 buf[k] = vcl_vector<vil_image_view<float> >(nbi);
00170 nbrhd[k] = vcl_vector<vil_image_view<float> >(2);
00171 }
00172 vil_image_view<float> dec_blk;
00173 for (unsigned int bj=0; bj<nbj; bj+=2)
00174 {
00175
00176 for (unsigned int bi = 0; bi<nbi; ++bi)
00177 {
00178 buf[0][bi] = vil_convert_cast(float(),brsc->get_block(bi,bj));
00179
00180 if (bj+1<nbj)
00181 buf[1][bi] = vil_convert_cast(float(),brsc->get_block(bi,bj+1));
00182 else
00183 buf[1][bi]=buf[0][bi];
00184 }
00185 for (unsigned int bi=0; bi<nbi; bi+=2)
00186 {
00187
00188 for (unsigned int r = 0; r<2; ++r)
00189 for (unsigned int c = 0; c<2; ++c)
00190 {
00191 unsigned int ki = bi+c;
00192 if (ki>=nbi)
00193 ki = nbi-1;
00194 nbrhd[r][c] = buf[r][ki];
00195 }
00196
00197 dec_blk = decimate_block(nbrhd);
00198
00199 switch (fmt)
00200 {
00201 #define CONVERT_BLOCK_CASE(FORMAT, T) \
00202 case FORMAT: { \
00203 vil_image_view<T> out_blk; \
00204 vil_convert_cast(dec_blk, out_blk); \
00205 if (!dec_resc->put_block(bi/2, bj/2, out_blk )) \
00206 return false;\
00207 break;\
00208 }
00209 CONVERT_BLOCK_CASE(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00210 #if VXL_HAS_INT_64
00211 CONVERT_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
00212 #endif
00213 CONVERT_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00214 CONVERT_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00215 CONVERT_BLOCK_CASE(VIL_PIXEL_FORMAT_FLOAT, float);
00216 CONVERT_BLOCK_CASE(VIL_PIXEL_FORMAT_DOUBLE, double);
00217 #undef CONVERT_BLOCK_CASE
00218
00219 default:
00220 assert(!"Unknown vil data type in pyramid image construction");
00221 return false;
00222 };
00223 }
00224 }
00225 return true;
00226 }
00227 case 3:
00228 case 4:
00229 {
00230 vcl_vector<vcl_vector<vcl_vector<vil_image_view<float> > > > buf(2);
00231 vcl_vector<vcl_vector<vil_image_view<float> > > nbrhd(2);
00232 for (unsigned int k =0; k<2; ++k)
00233 {
00234 buf[k] = vcl_vector<vcl_vector<vil_image_view<float> > >(nbi);
00235 nbrhd[k] = vcl_vector<vil_image_view<float> >(2);
00236 }
00237
00238
00239
00240 for (unsigned int bj=0; bj<nbj; bj+=2)
00241 {
00242
00243 for (unsigned int bi = 0; bi<nbi; ++bi)
00244 {
00245 vil_image_view_base_sptr bij = brsc->get_block(bi,bj);
00246 vcl_vector<vil_image_view<float> > fbij;
00247
00248 if (!convert_multi_plane_to_float(bij, fbij)) return false;
00249 buf[0][bi]=fbij;
00250 if (bj+2<=nbj)
00251 {
00252 bij = brsc->get_block(bi,bj+1);
00253
00254 if (!convert_multi_plane_to_float(bij, fbij)) return false;
00255 buf[1][bi] = fbij;
00256 }
00257 else
00258 buf[1][bi]=buf[0][bi];
00259 }
00260 for (unsigned int bi=0; bi<nbi; bi+=2)
00261 {
00262 vcl_vector<vil_image_view<float> >dec_fblk(np);
00263
00264 for (unsigned int p = 0; p<np; ++p){
00265 for (unsigned int r = 0; r<2; ++r)
00266 for (unsigned int c = 0; c<2; ++c)
00267 {
00268 unsigned int ki = bi+c;
00269 if (ki>=nbi)
00270 ki = nbi-1;
00271 nbrhd[r][c] = buf[r][ki][p];
00272 }
00273
00274 vil_image_view<float> fplane = decimate_block(nbrhd);
00275 dec_fblk[p]=fplane;
00276 }
00277
00278
00279 if (fmt == VIL_PIXEL_FORMAT_BYTE){
00280 vil_image_view<unsigned char> dblk(sbi_src, sbj_src, np);
00281 convert_multi_plane_from_float(dec_fblk, dblk);
00282 dec_resc->put_block(bi/2, bj/2, dblk);
00283 }
00284 else if (fmt == VIL_PIXEL_FORMAT_UINT_16){
00285 vil_image_view<unsigned short> dblk(sbi_src, sbj_src, np);
00286 convert_multi_plane_from_float(dec_fblk, dblk);
00287 dec_resc->put_block(bi/2, bj/2, dblk);
00288 }
00289 else return false;
00290 }
00291 }
00292 return true;
00293 }
00294 default:
00295 return false;
00296 }
00297 }
00298
00299 vil_image_resource_sptr vil_pyramid_image_resource::
00300 decimate(vil_image_resource_sptr const& resc, char const* filename,
00301 char const* format)
00302 {
00303 if (!resc)
00304 return 0;
00305 vil_pixel_format fmt = resc->pixel_format();
00306 switch (fmt)
00307 {
00308 case VIL_PIXEL_FORMAT_BYTE:
00309 break;
00310 case VIL_PIXEL_FORMAT_UINT_16:
00311 break;
00312 case VIL_PIXEL_FORMAT_UINT_32:
00313 break;
00314 #if VXL_HAS_INT_64
00315 case VIL_PIXEL_FORMAT_UINT_64:
00316 break;
00317 #endif
00318 case VIL_PIXEL_FORMAT_FLOAT:
00319 break;
00320 case VIL_PIXEL_FORMAT_DOUBLE:
00321 break;
00322 default:
00323 vcl_cout << "unrecognized pixel format in vil_pyramid_image_resource::decimate()\n";
00324 return 0;
00325 }
00326
00327 vil_blocked_image_resource_sptr brsc = blocked_image_resource(resc);
00328 if (brsc&&(brsc->size_block_i()%2!=0||brsc->size_block_j()%2!=0))
00329 {
00330 vcl_cout << "Blocked pyramid images must have even block sizes\n";
00331 return 0;
00332 }
00333 if (!brsc)
00334 brsc = new vil_blocked_image_facade(resc);
00335
00336
00337 {
00338 unsigned int rni = resc->ni(), rnj = resc->nj();
00339 unsigned int np = resc->nplanes();
00340
00341 unsigned int dni = rni/2, dnj = rnj/2;
00342
00343 dni += rni%2; dnj += rnj%2;
00344 vil_blocked_image_resource_sptr dec_resc =
00345 vil_new_blocked_image_resource(filename, dni, dnj, np,
00346 fmt, brsc->size_block_i(),
00347 brsc->size_block_j(),
00348 format);
00349
00350 if (!blocked_decimate(brsc, dec_resc))
00351 return 0;
00352 }
00353
00354 vil_image_resource_sptr temp = vil_load_image_resource(filename);
00355 return temp;
00356 }