vil_blocked_image_resource.cxx
Go to the documentation of this file.
1 // This is core/vil/vil_blocked_image_resource.cxx
3 
4 #include <cassert>
5 #ifdef _MSC_VER
6 # include <vcl_msvc_warnings.h>
7 #endif
8 #include <vil/vil_property.h>
9 #include <vil/vil_image_view.h>
10 #include <vil/vil_crop.h>
11 #include <vil/vil_copy.h>
12 
13 
15 
17 
19 {
20  unsigned int sbi = size_block_i();
21  if (sbi==0)
22  return 0;
23  return (ni()+sbi -1)/sbi;
24 }
25 
27 {
28  unsigned int sbj = size_block_j();
29  if (sbj==0)
30  return 0;
31  return (nj()+sbj -1)/sbj;
32 }
33 
35 get_blocks(unsigned int start_block_i, unsigned int end_block_i,
36  unsigned int start_block_j, unsigned int end_block_j,
37  std::vector< std::vector< vil_image_view_base_sptr > >& blocks ) const
38 {
39  for (unsigned int bi = start_block_i; bi<=end_block_i; ++bi)
40  {
41  std::vector< vil_image_view_base_sptr > jblocks;
42 
43  for (unsigned int bj = start_block_j; bj<=end_block_j; ++bj)
44  {
46  this->get_block(bi, bj);
47  if (view) jblocks.push_back(view);
48  else
49  return false;
50  }
51  blocks.push_back(jblocks);
52  }
53  return true;
54 }
55 
56 bool vil_blocked_image_resource::put_blocks( unsigned int start_block_i,
57  unsigned int end_block_i,
58  unsigned int start_block_j,
59  unsigned int end_block_j,
60  std::vector< std::vector< vil_image_view_base_sptr > > const& blocks )
61 {
62  for (unsigned int bi = start_block_i; bi<=end_block_i; ++bi)
63  for (unsigned int bj = start_block_j; bj<=end_block_j; ++bj)
64  if (!this->put_block(bi, bj, *blocks[bi][bj]))
65  return false;
66  return true;
67 }
68 
70 glue_blocks_together(const std::vector< std::vector< vil_image_view_base_sptr > >& blocks) const
71 {
73  if (blocks.size()==0)
74  return result;
75 
76  //first calculate the overall size of the output image (all blocks glued together)
77 
78  unsigned int output_width = 0;
79  unsigned int output_height = 0;
80  unsigned int i;
81  for (i = 0 ; i < blocks.size() ; i++) {
82  output_width += blocks[i][0]->ni();
83  }
84  for (i = 0 ; i < blocks[0].size() ; i++) {
85  output_height += blocks[0][i]->nj();
86  }
87 
88  //now paste all the image blocks into their proper location in outImage
89  unsigned int curr_i = 0;
90  unsigned int curr_j = 0;
92  switch (fmt)
93  {
94 #define GLUE_BLOCK_CASE(FORMAT, T) \
95  case FORMAT: { \
96  vil_image_view<T>* output_image = \
97  new vil_image_view<T>(output_width, output_height, 1, nplanes()); \
98  for (unsigned int bi = 0 ; bi < blocks.size() ; bi++) \
99  { \
100  for (unsigned int bj = 0 ; bj < blocks[bi].size() ; bj++)\
101  { \
102  vil_copy_to_window(static_cast<vil_image_view<T>&>(*blocks[bi][bj]), *output_image, curr_i, curr_j); \
103  curr_j += blocks[bi][bj]->nj(); \
104  } \
105  curr_j = 0; \
106  curr_i += blocks[bi][0]->ni();\
107  } \
108  result = output_image; \
109  return result; \
110  }
113 #if VXL_HAS_INT_64
114  GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
115  GLUE_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
116 #endif
124 #undef GLUE_BLOCK_CASE
125 
126  default:
127  assert(!"Unknown vil data type in tiff file format");
128  break;
129  }
130  return result;
131 }
132 
133 // Get the offset from the start of the block row for pixel position i
134 bool vil_blocked_image_resource::block_i_offset(unsigned int block_i, unsigned int i,
135  unsigned int& i_offset) const
136 {
137  i_offset = 0;
138  unsigned int tw = size_block_i();
139  if (tw==0)
140  return false;
141  unsigned int bstrt = tw*block_i;
142  if (i<bstrt)
143  return false;
144  i_offset = i-bstrt;
145  return true;
146 }
147 
148 // Get the offset from the start of the block column for pixel position j
149 bool vil_blocked_image_resource::block_j_offset(unsigned int block_j, unsigned int j,
150  unsigned int& j_offset) const
151 {
152  j_offset = 0;
153  unsigned int tl = size_block_j();
154  if (tl==0)
155  return false;
156  unsigned int bstrt = tl*block_j;
157  if (j<bstrt)
158  return false;
159  j_offset = j-bstrt;
160  return true;
161 }
162 
163 //The blocks may overlap the edges of the requested view
164 //Therefore we need to trim them in order to have the
165 //correct pieces to glue together to form the view.
166 bool vil_blocked_image_resource::trim_border_blocks(unsigned int i0, unsigned int ni,
167  unsigned int j0, unsigned int nj,
168  unsigned int start_block_i,
169  unsigned int start_block_j,
170  std::vector< std::vector< vil_image_view_base_sptr > >& blocks) const
171 {
172  // loop through all the boxes and trim the boxes around the border if necessary.
173  for (unsigned int bi = 0 ; bi < blocks.size() ; bi++) {
174  for (unsigned int bj = 0 ; bj < blocks[bi].size() ; bj++) {
175  if (!blocks[bi][bj]) continue;
176  auto last_col_index = (unsigned int)(blocks.size()-1);
177  auto last_row_index = (unsigned int)(blocks[bi].size()-1);
178  //booleans that tell me whether this box is some sort of border box
179  bool first_block_in_row = bi == 0;
180  bool first_block_in_col = bj == 0;
181  bool last_block_in_row = bi == last_col_index;
182  bool last_block_in_col = bj == last_row_index;
183 
184  //nothing to do if this isn't a border box
185  if (!first_block_in_row && !first_block_in_col &&
186  !last_block_in_row && !last_block_in_col) continue;
187 
188  unsigned int bi0=0, bin=size_block_i()-1;
189  unsigned int bj0=0, bjn=size_block_j()-1;
190  if (first_block_in_row)
191  if (!block_i_offset(start_block_i+bi, i0, bi0))
192  return false;
193  if (last_block_in_row)
194  if (!block_i_offset(start_block_i+bi, i0+ni-1, bin))
195  return false;
196  if (first_block_in_col)
197  if (!block_j_offset(start_block_j+bj, j0, bj0))
198  return false;
199  if (last_block_in_col)
200  if (!block_j_offset(start_block_j+bj, j0+nj-1, bjn))
201  return false;
202 
204  {
205 #define TRIM_BORDER_BLOCK_CASE(FORMAT, T) \
206  case FORMAT: { \
207  vil_image_view< T > currBlock = static_cast<vil_image_view< T >&>(*blocks[bi][bj]);\
208  vil_image_view< T >* croppedBlock = new vil_image_view< T >();\
209  *croppedBlock = vil_crop(currBlock, bi0, bin-bi0+1, bj0, bjn-bj0+1);\
210  blocks[bi][bj] = croppedBlock;\
211  } break
214 #if VXL_HAS_INT_64
215  TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
216  TRIM_BORDER_BLOCK_CASE(VIL_PIXEL_FORMAT_INT_64, vxl_int_64);
217 #endif
225 #undef TRIM_BORDER_BLOCK_CASE
226 
227  default:
228  assert(!"Unknown vil data type.");
229  return false;
230  }
231  }
232  }
233  return true;
234 }
235 
236 //Get blocks including those that might be in the cache
238 get_copy_view(unsigned int i0, unsigned int n_i, unsigned int j0, unsigned int n_j) const
239 {
240  vil_image_view_base_sptr view = nullptr;
241 
242  unsigned int tw = size_block_i(), tl = size_block_j();
243  if (tw==0||tl==0)
244  return view;
245 
246  //block index ranges
247  unsigned int bi_start = i0/tw, bi_end = (i0+n_i-1)/tw;
248  unsigned int bj_start = j0/tl, bj_end = (j0+n_j-1)/tl;
249  //last block index
250  unsigned int lbi = n_block_i()-1, lbj = n_block_j()-1;
251 
252  if (bi_start>lbi||bi_end>lbi||bj_start>lbj||bj_end>lbj)
253  return view;
254 
255  //Get set of blocks covering the view
256  std::vector<std::vector< vil_image_view_base_sptr > > blocks;
257 
258  this->get_blocks(bi_start, bi_end, bj_start, bj_end, blocks);
259  if (!blocks.size())
260  return view;
261  //Trim them if necessary to fit the view
262  if (!trim_border_blocks(i0, n_i, j0, n_j, bi_start, bj_start, blocks))
263  return view;
264  //Assemble them to fill the requested view
265  view = this->glue_blocks_together(blocks);
266 #ifdef DEBUG
267  unsigned int nblocks = (bi_end-bi_start+1)*(bj_end-bj_start+1);
268  if (nblocks>1)
269  std::cout << "Get copy view of " << nblocks << " blocks in "
270  << t.real() << "msecs\n";
271 #endif
272  return view;
273 }
274 
276 {
277  if (!ir)
278  return nullptr;
279  unsigned int sbi=0, sbj=0;
280  if (ir->get_property(vil_property_size_block_i, &sbi)&&
281  ir->get_property(vil_property_size_block_j, &sbj))
282  return (vil_blocked_image_resource*)ir.ptr();
283  else
284  return nullptr;
285 }
unsigned ni() const override=0
Dimensions: Planes x ni x nj.
virtual vil_image_view_base_sptr get_block(unsigned block_index_i, unsigned block_index_j) const =0
Block access.
vil_pixel_format
Describes the type of the concrete data.
vil_pixel_format vil_pixel_format_component_format(enum vil_pixel_format f)
Return the number of components in pixel format f.
virtual unsigned size_block_i() const =0
Block size in columns.
bool block_i_offset(unsigned block_i, unsigned i, unsigned &i_offset) const
Get the offset from the start of the block row for pixel position i.
enum vil_pixel_format pixel_format() const override=0
Pixel Format.
virtual unsigned n_block_i() const
Number of blocks in image width.
#define GLUE_BLOCK_CASE(FORMAT, T)
bool block_j_offset(unsigned block_j, unsigned j, unsigned &j_offset) const
Get the offset from the start of the block column for pixel position j.
virtual bool get_blocks(unsigned start_block_i, unsigned end_block_i, unsigned start_block_j, unsigned end_block_j, std::vector< std::vector< vil_image_view_base_sptr > > &blocks) const
the multiple blocks are in col row order, i.e. blocks[i][j].
A blocked representation of the image_resource.
~vil_blocked_image_resource() override
vil_blocked_image_resource_sptr blocked_image_resource(const vil_image_resource_sptr &ir)
cast to blocked resource if possible.
#define TRIM_BORDER_BLOCK_CASE(FORMAT, T)
#define vil_property_size_block_i
For unblocked images, the following properties are not implemented.
Definition: vil_property.h:76
Various image copying functions.
unsigned nj() const override=0
Dimensions: Planes x ni x nj.
bool trim_border_blocks(unsigned i0, unsigned ni, unsigned j0, unsigned nj, unsigned start_block_i, unsigned start_block_j, std::vector< std::vector< vil_image_view_base_sptr > > &blocks) const
vil_image_view_base_sptr get_copy_view() const
Create a read/write view of a copy of all the data.
A base class reference-counting view of some image data.
virtual unsigned size_block_j() const =0
Block size in rows.
There is no class or function called vil_property.
#define vil_property_size_block_j
Block size in rows.
Definition: vil_property.h:79
virtual bool put_blocks(unsigned start_block_i, unsigned end_block_i, unsigned start_block_j, unsigned end_block_j, std::vector< std::vector< vil_image_view_base_sptr > > const &blocks)
put multiple blocks in raster order, i.e., blocks[i][j].
T * ptr() const
These methods all return the raw/dumb pointer.
virtual bool put_block(unsigned block_index_i, unsigned block_index_j, const vil_image_view_base &view)=0
put the block into the resource at the indicated location.
virtual unsigned n_block_j() const
Number of blocks in image height.
vil_image_view_base_sptr glue_blocks_together(const std::vector< std::vector< vil_image_view_base_sptr > > &blocks) const