vil_pyramid_image_resource.cxx
Go to the documentation of this file.
1 // This is core/vil/vil_pyramid_image_resource.cxx
2 #include <cstring>
3 #include <vector>
5 //:
6 // \file
7 #include <cassert>
8 #ifdef _MSC_VER
9 # include <vcl_msvc_warnings.h>
10 #endif
11 #include <vil/vil_property.h>
12 #include <vil/vil_convert.h>
15 #include <vil/vil_image_view.h>
16 #include <vil/vil_new.h>
17 #include <vil/vil_load.h>
18 
19 
21 
23 
24 bool vil_pyramid_image_resource::get_property(char const* tag, void* /*value*/) const
25 {
26  return std::strcmp(vil_property_pyramid, tag)==0;
27 }
28 
29 
30 //: return a decimated block. The input is a 2x2 2d array of blocks.
31 // Assume all the data is valid
33 decimate_block(std::vector<std::vector<vil_image_view<float> > > const& blocks)
34 {
35  vil_image_view<float> blk = blocks[0][0];
36  unsigned int sbi = blk.ni(), sbj = blk.nj();
37  vil_image_view<float> dec_block;
38  dec_block.set_size(sbi, sbj);
39  for (unsigned int dj = 0; dj<sbj; ++dj)
40  {
41  unsigned int r = 0, j0 = 2*dj;
42  if (2*dj>=sbj)
43  {
44  r = 1;
45  j0 = 2*dj-sbj;
46  }
47  for (unsigned int di = 0; di<sbi; ++di)
48  {
49  unsigned int c = 0, i0 = 2*di;
50  if (2*di>=sbi)
51  {
52  c = 1;
53  i0 = 2*di-sbi;
54  }
55  vil_image_view<float> blk = blocks[r][c];
56  float v =
57  0.25f*(blk(i0, j0)+blk(i0+1,j0)+blk(i0,j0+1)+blk(i0+1,j0+1));
58  dec_block(di, dj) = v;
59  }
60  }
61  return dec_block;
62 }
63 
64 static
65 bool convert_multi_plane_to_float(vil_image_view_base_sptr& blk,
66  std::vector<vil_image_view<float> >& fblk)
67 {
68  if (!blk) return false;
69  fblk.clear();
70  vil_pixel_format fmt = blk->pixel_format();
71  unsigned int ni = blk->ni(), nj = blk->nj();
72  unsigned int np = blk->nplanes();
73  if (fmt == VIL_PIXEL_FORMAT_BYTE)
74  {
76  for (unsigned int p = 0; p<np; ++p){
77  vil_image_view<float> bvf(ni, nj);
78  for (unsigned int j = 0; j<nj; ++j)
79  for (unsigned int i= 0; i<ni; ++i)
80  bvf(i,j) = bv(i,j,p);
81  fblk.push_back(bvf);
82  }
83  return true;
84  }
85  else if (fmt == VIL_PIXEL_FORMAT_UINT_16)
86  {
88  for (unsigned int p = 0; p<np; ++p){
89  vil_image_view<float> bvf(ni, nj);
90  for (unsigned int j = 0; j<nj; ++j)
91  for (unsigned int i= 0; i<ni; ++i)
92  bvf(i,j) = bv(i,j,p);
93  fblk.push_back(bvf);
94  }
95  return true;
96  }
97  return false;
98 }
99 
100 static
101 void convert_multi_plane_from_float(std::vector<vil_image_view<float> >& fblk,
103 {
104  unsigned int ni = fblk[0].ni(), nj = fblk[0].nj();
105  auto np = (unsigned int)(fblk.size());
106  for (unsigned int p = 0; p<np; ++p)
107  for (unsigned int j = 0; j<nj; ++j)
108  for (unsigned int i= 0; i<ni; ++i)
109  blk(i,j,p) = static_cast<unsigned char>(fblk[p](i,j));
110 }
111 
112 static
113 void convert_multi_plane_from_float(std::vector<vil_image_view<float> >& fblk,
115 {
116  unsigned int ni = fblk[0].ni(), nj = fblk[0].nj();
117  auto np = (unsigned int)(fblk.size());
118  for (unsigned int p = 0; p<np; ++p)
119  for (unsigned int j = 0; j<nj; ++j)
120  for (unsigned int i= 0; i<ni; ++i)
121  blk(i,j,p) = static_cast<unsigned short>(fblk[p](i,j));
122 }
123 
127 {
128  if (!brsc)
129  return false;
130  unsigned int nbi = brsc->n_block_i(), nbj = brsc->n_block_j();
131  if (nbi==0||nbj==0)
132  return false;
133  unsigned int np = brsc->nplanes();
134 
135  //check for consistent block structure
136  unsigned int sbi_src = brsc->size_block_i(), sbj_src = brsc->size_block_j();
137  unsigned int sbi_dec = dec_resc->size_block_i(),
138  sbj_dec = dec_resc->size_block_j();
139  if (sbi_src!=sbi_dec||sbj_src!=sbj_dec)
140  return false;
141  vil_pixel_format fmt = vil_pixel_format_component_format(brsc->pixel_format());
142 
143  //Set up the block buffer, a 2xnbi set of blocks needed to support 2x2
144  //pixel decimation. The buffer is updated as the next two rows of blocks is
145  //scanned in from the resource.
146  //
147  //|b00 |b01|b02|b03|...|b0,nbi-1|
148  //|b10 |b11|b12|b13|...|b1,nbi-1|
149  //
150  //=======================================================
151  //
152  //Decimate the image using a 2x2 block neighborhood
153  //
154  // | buf[0][0] buf[0][1] |==> [dec_blk]
155  // | buf[1][0] buf[1][1] |
156  //
157  // This neighborhood "slides" along the 2xnbi block buffer,
158  // stepping two blocks each time.
159  //=======================================================
160  switch (np)
161  {
162  case 1: //grey scale images
163  {
164  std::vector<std::vector<vil_image_view<float> > > buf(2), nbrhd(2);
165  for (unsigned int k =0; k<2; ++k)
166  {
167  buf[k] = std::vector<vil_image_view<float> >(nbi);
168  nbrhd[k] = std::vector<vil_image_view<float> >(2);
169  }
170  vil_image_view<float> dec_blk;
171  for (unsigned int bj=0; bj<nbj; bj+=2)
172  {
173  //update the block buffer by stepping down two block rows
174  for (unsigned int bi = 0; bi<nbi; ++bi)
175  {
176  buf[0][bi] = vil_convert_cast(float(),brsc->get_block(bi,bj));
177  //if (bj+2<=nbj)//make sure there are enough block rows
178  if (bj+1<nbj)//make sure there are enough block rows
179  buf[1][bi] = vil_convert_cast(float(),brsc->get_block(bi,bj+1));
180  else
181  buf[1][bi]=buf[0][bi];//otherwise just copy the upper block
182  }
183  for (unsigned int bi=0; bi<nbi; bi+=2)
184  {
185  //construct the 2x2 block neighborhood
186  for (unsigned int r = 0; r<2; ++r)
187  for (unsigned int c = 0; c<2; ++c)
188  {
189  unsigned int ki = bi+c;
190  if (ki>=nbi)//make sure there are enough blocks in the row
191  ki = nbi-1;
192  nbrhd[r][c] = buf[r][ki];//otherwise just copy
193  }
194  //construct the block
195  dec_blk = decimate_block(nbrhd);
196  //convert back to the orignal pixel format
197  switch (fmt)
198  {
199 #define CONVERT_BLOCK_CASE(FORMAT, T) \
200  case FORMAT: { \
201  vil_image_view<T> out_blk; \
202  vil_convert_cast(dec_blk, out_blk); \
203  if (!dec_resc->put_block(bi/2, bj/2, out_blk )) \
204  return false;\
205  break;\
206  }
208 #if VXL_HAS_INT_64
209  CONVERT_BLOCK_CASE(VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64);
210 #endif
215 #undef CONVERT_BLOCK_CASE
216 
217  default:
218  assert(!"Unknown vil data type in pyramid image construction");
219  return false;
220  };
221  }
222  }
223  return true;
224  }// end of nplanes = 1 (grey scale)
225  case 3:
226  case 4:
227  {
228  std::vector<std::vector<std::vector<vil_image_view<float> > > > buf(2);
229  std::vector<std::vector<vil_image_view<float> > > nbrhd(2);
230  for (unsigned int k =0; k<2; ++k)
231  {
232  buf[k] = std::vector<std::vector<vil_image_view<float> > >(nbi);
233  nbrhd[k] = std::vector<vil_image_view<float> >(2);
234  }
235 
236  // The color planes of a block are separated into
237  // individual float views
238  for (unsigned int bj=0; bj<nbj; bj+=2)
239  {
240  //update the block buffer by stepping down two block rows
241  for (unsigned int bi = 0; bi<nbi; ++bi)
242  {
243  vil_image_view_base_sptr bij = brsc->get_block(bi,bj);
244  std::vector<vil_image_view<float> > fbij;
245  //convert to float
246  if (!convert_multi_plane_to_float(bij, fbij)) return false;
247  buf[0][bi]=fbij;
248  if (bj+2<=nbj)//make sure there are enough block rows
249  {
250  bij = brsc->get_block(bi,bj+1);
251  //convert to float
252  if (!convert_multi_plane_to_float(bij, fbij)) return false;
253  buf[1][bi] = fbij;
254  }
255  else
256  buf[1][bi]=buf[0][bi];//otherwise just copy the upper block
257  }
258  for (unsigned int bi=0; bi<nbi; bi+=2)
259  {
260  std::vector<vil_image_view<float> >dec_fblk(np);
261  //create decimated blocks for each plane
262  for (unsigned int p = 0; p<np; ++p){
263  for (unsigned int r = 0; r<2; ++r)
264  for (unsigned int c = 0; c<2; ++c)
265  {
266  unsigned int ki = bi+c;
267  if (ki>=nbi)
268  ki = nbi-1;
269  nbrhd[r][c] = buf[r][ki][p];
270  }
271  //construct the block
272  vil_image_view<float> fplane = decimate_block(nbrhd);
273  dec_fblk[p]=fplane;
274  }
275  //convert back to original format only allow 8 bit and 16 bit
276  //color image formats
277  if (fmt == VIL_PIXEL_FORMAT_BYTE){
278  vil_image_view<unsigned char> dblk(sbi_src, sbj_src, np);
279  convert_multi_plane_from_float(dec_fblk, dblk);
280  dec_resc->put_block(bi/2, bj/2, dblk);
281  }
282  else if (fmt == VIL_PIXEL_FORMAT_UINT_16){
283  vil_image_view<unsigned short> dblk(sbi_src, sbj_src, np);
284  convert_multi_plane_from_float(dec_fblk, dblk);
285  dec_resc->put_block(bi/2, bj/2, dblk);
286  }
287  else return false;
288  }
289  }
290  return true;
291  }// end of nplanes = 3, 4
292  default:
293  return false;
294  }
295 }
296 
298 decimate(vil_image_resource_sptr const& resc, char const* filename,
299  char const* format)
300 {
301  if (!resc)
302  return nullptr;
303  vil_pixel_format fmt = vil_pixel_format_component_format(resc->pixel_format());
304  switch (fmt)
305  {
307  break;
309  break;
311  break;
312 #if VXL_HAS_INT_64
313  case VIL_PIXEL_FORMAT_UINT_64:
314  break;
315 #endif
317  break;
319  break;
320  default:
321  std::cout << "unrecognized pixel format in vil_pyramid_image_resource::decimate()\n";
322  return nullptr;
323  }
324  //first determine if the resource is blocked, if not create a facade
326  if (brsc&&(brsc->size_block_i()%2!=0||brsc->size_block_j()%2!=0))
327  {
328  std::cout << "Blocked pyramid images must have even block sizes\n";
329  return nullptr;
330  }
331  if (!brsc)
332  brsc = new vil_blocked_image_facade(resc);
333 
334  // create the output decimated resource
335  { //file scope to close resource
336  unsigned int rni = resc->ni(), rnj = resc->nj();
337  unsigned int np = resc->nplanes();
338  //if source image has even dimensions then just divide by 2
339  unsigned int dni = rni/2, dnj = rnj/2;
340  //else if the dimension is odd, increase the output size by 1.
341  dni += rni%2; dnj += rnj%2;
343  vil_new_blocked_image_resource(filename, dni, dnj, np,
344  fmt, brsc->size_block_i(),
345  brsc->size_block_j(),
346  format);
347  //fill the resource with decimated blocks.
348  if (!blocked_decimate(brsc, dec_resc))
349  return nullptr;
350  } //file scope to close resource
351  //reopen resource for reading
353  return temp;
354 }
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.
A templated smart pointer class.
Definition: vil_fwd.h:16
#define CONVERT_BLOCK_CASE(FORMAT, T)
Concrete view of image data of type T held in memory.
Definition: vil_fwd.h:13
static vil_image_resource_sptr decimate(vil_image_resource_sptr const &resc, char const *filename, char const *format="tiff")
Utility for decimating a resource to create a new pyramid level.
void set_size(unsigned ni, unsigned nj) override
resize current planes to ni x nj.
void vil_convert_cast(const vil_image_view< inP > &src, vil_image_view< outP > &dest)
Cast one pixel type to another.
Definition: vil_convert.h:245
Some standard conversion functions.
vil_blocked_image_resource_sptr vil_new_blocked_image_resource(vil_stream *os, unsigned ni, unsigned nj, unsigned nplanes, vil_pixel_format format, unsigned size_block_i, unsigned size_block_j, char const *file_format)
Make a new blocked resource file.
Definition: vil_new.cxx:156
read an image from a file
unsigned ni() const
Width.
~vil_pyramid_image_resource() override
unsigned nj() const
Height.
A blocked representation of the image_resource.
#define v
vil_blocked_image_resource_sptr blocked_image_resource(const vil_image_resource_sptr &ir)
cast to blocked resource if possible.
A blocked image facade for any image resource.
Representation of a pyramid resolution hierarchy.
A base class reference-counting view of some image data.
There is no class or function called vil_property.
Make a new image.
vil_image_resource_sptr vil_load_image_resource(char const *filename, bool verbose=true)
Load an image resource object from a file.
Definition: vil_load.cxx:68
static bool blocked_decimate(vil_blocked_image_resource_sptr const &brsc, vil_blocked_image_resource_sptr &dec_resc)
A utility function to decimate a resource using blocks.
bool get_property(char const *tag, void *property_value=nullptr) const override
Extra property information.
#define vil_property_pyramid
true if image resource is a pyramid image.
Definition: vil_property.h:82