core/vil/vil_blocked_image_resource.cxx
Go to the documentation of this file.
00001 // This is core/vil/vil_blocked_image_resource.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 #include "vil_blocked_image_resource.h"
00006 
00007 #include <vcl_cassert.h>
00008 #include <vil/vil_property.h>
00009 #include <vil/vil_image_view.h>
00010 #include <vil/vil_crop.h>
00011 #include <vil/vil_copy.h>
00012 
00013 
00014 vil_blocked_image_resource::vil_blocked_image_resource()
00015 {}
00016 
00017 vil_blocked_image_resource::~vil_blocked_image_resource()
00018 {}
00019 
00020 unsigned int vil_blocked_image_resource::n_block_i() const
00021 {
00022   unsigned int sbi = size_block_i();
00023   if (sbi==0)
00024     return 0;
00025   return (ni()+sbi -1)/sbi;
00026 }
00027 
00028 unsigned int vil_blocked_image_resource::n_block_j() const
00029 {
00030   unsigned int sbj = size_block_j();
00031   if (sbj==0)
00032     return 0;
00033   return (nj()+sbj -1)/sbj;
00034 }
00035 
00036 bool vil_blocked_image_resource::
00037 get_blocks(unsigned int start_block_i, unsigned int end_block_i,
00038            unsigned int start_block_j, unsigned int end_block_j,
00039            vcl_vector< vcl_vector< vil_image_view_base_sptr > >& blocks ) const
00040 {
00041   for (unsigned int bi = start_block_i; bi<=end_block_i; ++bi)
00042   {
00043     vcl_vector< vil_image_view_base_sptr > jblocks;
00044 
00045     for (unsigned int bj = start_block_j; bj<=end_block_j; ++bj)
00046     {
00047       vil_image_view_base_sptr view =
00048         this->get_block(bi, bj);
00049       if (view) jblocks.push_back(view);
00050       else
00051         return false;
00052     }
00053     blocks.push_back(jblocks);
00054   }
00055   return true;
00056 }
00057 
00058 bool vil_blocked_image_resource::put_blocks( unsigned int start_block_i,
00059                                              unsigned int end_block_i,
00060                                              unsigned int start_block_j,
00061                                              unsigned int end_block_j,
00062                                              vcl_vector< vcl_vector< vil_image_view_base_sptr > > const& blocks )
00063 {
00064   for (unsigned int bi = start_block_i; bi<=end_block_i; ++bi)
00065     for (unsigned int bj = start_block_j; bj<=end_block_j; ++bj)
00066       if (!this->put_block(bi, bj, *blocks[bi][bj]))
00067         return false;
00068   return true;
00069 }
00070 
00071 vil_image_view_base_sptr vil_blocked_image_resource::
00072 glue_blocks_together(const vcl_vector< vcl_vector< vil_image_view_base_sptr > >& blocks) const
00073 {
00074   vil_image_view_base_sptr result;
00075   if (blocks.size()==0)
00076     return result;
00077 
00078   //first calculate the overall size of the output image (all blocks glued together)
00079 
00080   unsigned int output_width  = 0;
00081   unsigned int output_height = 0;
00082   unsigned int i;
00083   for (i = 0 ; i < blocks.size() ; i++) {
00084     output_width += blocks[i][0]->ni();
00085   }
00086   for (i = 0 ; i < blocks[0].size() ; i++) {
00087     output_height += blocks[0][i]->nj();
00088   }
00089 
00090   //now paste all the image blocks into their proper location in outImage
00091   unsigned int curr_i = 0;
00092   unsigned int curr_j = 0;
00093   vil_pixel_format fmt = vil_pixel_format_component_format(this->pixel_format());
00094   switch (fmt)
00095   {
00096 #define GLUE_BLOCK_CASE(FORMAT, T) \
00097    case FORMAT: { \
00098     vil_image_view<T>* output_image = \
00099       new vil_image_view<T>(output_width, output_height, 1, nplanes()); \
00100     for (unsigned int bi = 0 ; bi < blocks.size() ; bi++) \
00101     { \
00102       for (unsigned int bj = 0 ; bj < blocks[bi].size() ; bj++)\
00103       { \
00104         vil_copy_to_window(static_cast<vil_image_view<T>&>(*blocks[bi][bj]), *output_image, curr_i, curr_j); \
00105         curr_j += blocks[bi][bj]->nj(); \
00106       } \
00107       curr_j = 0; \
00108       curr_i += blocks[bi][0]->ni();\
00109     } \
00110     result = output_image; \
00111     return result; \
00112    }
00113     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00114     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte);
00115 #if VXL_HAS_INT_64
00116     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
00117     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
00118 #endif
00119     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00120     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_32, vxl_int_32);
00121     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00122     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_16, vxl_int_16);
00123     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_BOOL, bool);
00124     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_FLOAT, float);
00125     GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_DOUBLE, double);
00126 #undef GLUE_BLOCK_CASE
00127 
00128    default:
00129     assert(!"Unknown vil data type in tiff file format");
00130     break;
00131   }
00132   return result;
00133 }
00134 
00135 // Get the offset from the start of the block row for pixel position i
00136 bool vil_blocked_image_resource::block_i_offset(unsigned int block_i, unsigned int i,
00137                                                 unsigned int& i_offset) const
00138 {
00139   i_offset = 0;
00140   unsigned int tw = size_block_i();
00141   if (tw==0)
00142     return false;
00143   unsigned int bstrt = tw*block_i;
00144   if (i<bstrt)
00145     return false;
00146   i_offset = i-bstrt;
00147   return true;
00148 }
00149 
00150 // Get the offset from the start of the block column for pixel position j
00151 bool vil_blocked_image_resource::block_j_offset(unsigned int block_j, unsigned int j,
00152                                                 unsigned int& j_offset) const
00153 {
00154   j_offset = 0;
00155   unsigned int tl = size_block_j();
00156   if (tl==0)
00157     return false;
00158   unsigned int bstrt = tl*block_j;
00159   if (j<bstrt)
00160     return false;
00161   j_offset = j-bstrt;
00162   return true;
00163 }
00164 
00165 //The blocks may overlap the edges of the requested view
00166 //Therefore we need to trim them in order to have the
00167 //correct pieces to glue together to form the view.
00168 bool vil_blocked_image_resource::trim_border_blocks(unsigned int i0, unsigned int ni,
00169                                                     unsigned int j0, unsigned int nj,
00170                                                     unsigned int start_block_i,
00171                                                     unsigned int start_block_j,
00172                                                     vcl_vector< vcl_vector< vil_image_view_base_sptr > >& blocks) const
00173 {
00174   // loop through all the boxes and trim the boxes around the border if necessary.
00175   for (unsigned int bi = 0 ; bi < blocks.size() ; bi++) {
00176     for (unsigned int bj = 0 ; bj < blocks[bi].size() ; bj++) {
00177       if (!blocks[bi][bj]) continue;
00178       unsigned int last_col_index = (unsigned int)(blocks.size()-1);
00179       unsigned int last_row_index = (unsigned int)(blocks[bi].size()-1);
00180       //booleans that tell me whether this box is some sort of border box
00181       bool first_block_in_row = bi == 0;
00182       bool first_block_in_col = bj == 0;
00183       bool last_block_in_row = bi  == last_col_index;
00184       bool last_block_in_col = bj == last_row_index;
00185 
00186       //nothing to do if this isn't a border box
00187       if (!first_block_in_row && !first_block_in_col &&
00188           !last_block_in_row && !last_block_in_col) continue;
00189 
00190       unsigned int bi0=0, bin=size_block_i()-1;
00191       unsigned int bj0=0, bjn=size_block_j()-1;
00192       if (first_block_in_row)
00193         if (!block_i_offset(start_block_i+bi, i0, bi0))
00194           return false;
00195       if (last_block_in_row)
00196         if (!block_i_offset(start_block_i+bi, i0+ni-1, bin))
00197           return false;
00198       if (first_block_in_col)
00199         if (!block_j_offset(start_block_j+bj, j0, bj0))
00200           return false;
00201       if (last_block_in_col)
00202         if (!block_j_offset(start_block_j+bj, j0+nj-1, bjn))
00203           return false;
00204 
00205       switch (vil_pixel_format_component_format(pixel_format()))
00206       {
00207 #define TRIM_BORDER_BLOCK_CASE(FORMAT, T) \
00208        case FORMAT: { \
00209         vil_image_view< T > currBlock = static_cast<vil_image_view< T >&>(*blocks[bi][bj]);\
00210         vil_image_view< T >* croppedBlock = new vil_image_view< T >();\
00211         *croppedBlock = vil_crop(currBlock, bi0, bin-bi0+1, bj0, bjn-bj0+1);\
00212         blocks[bi][bj] = croppedBlock;\
00213        } break
00214         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_BYTE, vxl_byte);
00215         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte);
00216 #if VXL_HAS_INT_64
00217         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
00218         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
00219 #endif
00220         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32);
00221         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_32, vxl_int_32);
00222         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16);
00223         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_16, vxl_int_16);
00224         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_BOOL, bool);
00225         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_FLOAT, float);
00226         TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_DOUBLE, double);
00227 #undef TRIM_BORDER_BLOCK_CASE
00228 
00229        default:
00230         assert(!"Unknown vil data type.");
00231         return false;
00232       }
00233     }
00234   }
00235   return true;
00236 }
00237 
00238 //Get blocks including those that might be in the cache
00239 vil_image_view_base_sptr vil_blocked_image_resource::
00240 get_copy_view(unsigned int i0, unsigned int n_i, unsigned int j0, unsigned int n_j) const
00241 {
00242   vil_image_view_base_sptr view = 0;
00243 
00244   unsigned int tw = size_block_i(), tl = size_block_j();
00245   if (tw==0||tl==0)
00246     return view;
00247 
00248   //block index ranges
00249   unsigned int bi_start = i0/tw, bi_end = (i0+n_i-1)/tw;
00250   unsigned int bj_start = j0/tl, bj_end = (j0+n_j-1)/tl;
00251   //last block index
00252   unsigned int lbi = n_block_i()-1, lbj = n_block_j()-1;
00253 
00254   if (bi_start>lbi||bi_end>lbi||bj_start>lbj||bj_end>lbj)
00255     return view;
00256 
00257   //Get set of blocks covering the view
00258   vcl_vector<vcl_vector< vil_image_view_base_sptr > > blocks;
00259 
00260   this->get_blocks(bi_start, bi_end, bj_start, bj_end, blocks);
00261   if (!blocks.size())
00262     return view;
00263   //Trim them if necessary to fit the view
00264   if (!trim_border_blocks(i0, n_i, j0, n_j, bi_start, bj_start, blocks))
00265     return view;
00266   //Assemble them to fill the requested view
00267   view = this->glue_blocks_together(blocks);
00268 #ifdef DEBUG
00269   unsigned int nblocks = (bi_end-bi_start+1)*(bj_end-bj_start+1);
00270   if (nblocks>1)
00271     vcl_cout << "Get copy view of " << nblocks << " blocks in "
00272              << t.real() << "msecs\n";
00273 #endif
00274   return view;
00275 }
00276 
00277 vil_blocked_image_resource_sptr blocked_image_resource(const vil_image_resource_sptr& ir)
00278 {
00279   if (!ir)
00280     return 0;
00281   unsigned int sbi=0, sbj=0;
00282   if (ir->get_property(vil_property_size_block_i, &sbi)&&
00283       ir->get_property(vil_property_size_block_j, &sbj))
00284     return (vil_blocked_image_resource*)ir.ptr();
00285   else
00286     return 0;
00287 }