Boost Library Array1D, Array2D Test

 

  1 /*********************************************************************/
  2 /* Arrays.h                                                          */
  3 /* Author: Tim Borer                                                 */
  4 /* This version 11th July 2011                                       */
  5 /*                                                                   */
  6 /* Declares stuff related to mulitdimensional arrays.                */
  7 /* Copyright (c) BBC 2011-2015 -- For license see the LICENSE file   */
  8 /*********************************************************************/
  9 
 10 #ifndef ARRAYS_25FEB10
 11 #define ARRAYS_25FEB10
 12 
 13 #include <iosfwd>
 14 #include "boost/multi_array.hpp"
 15 #include "boost/array.hpp"
 16 
 17 using boost::extents; // An extents generator object used to define array sizes
 18 using boost::indices; // An index generator object used to define array views
 19 
 20 typedef boost::multi_array_types::index_range Range; // Range(bottom, top+1, stride)
 21 
 22 typedef boost::multi_array_types::index Index;
 23 
 24 // Shape2D is a 1D Array used to store the size of a picture
 25 typedef boost::array<Index, 2> Shape2D;
 26 
 27 // Array1D is (surprise) a one dimensional array or vector
 28 typedef boost::multi_array<int, 1> Array1D;
 29 
 30 // Array2D is a 2D array for holding picture or coefficient samples
 31 typedef boost::multi_array<int, 2> Array2D;
 32 
 33 // View2D is a view of a Array2D,
 34 // that is a synonym for a subset of array values
 35 typedef Array2D::array_view<2>::type View2D;
 36 
 37 // ConstView2D is a constant view of a Array2D,
 38 typedef Array2D::const_array_view<2>::type ConstView2D;
 39 
 40 // BlockVector is a 1D Array (i.e. vector) of 2D arrays (each element is, itself, a little 2D array)
 41 // A BlockVector may be used for storing an array of wavelet transform subbands (each subband is,
 42 // itself, a 2D array of coefficients).
 43 typedef boost::multi_array<Array2D, 1> BlockVector;
 44 
 45 // BlockArray is a 2D array of 2D arrays (each block is a little 2D array)
 46 typedef boost::multi_array<Array2D, 2> BlockArray;
 47 
 48 // ArrayIndices2D specifies the subset of array elements which define a view,
 49 // that is it specifies the subsampling factor and subsampling phase.
 50 typedef boost::detail::multi_array::index_gen<2, 2> ArrayIndices2D;
 51 
 52 // Get the shape of a 2D array
 53 const Shape2D shape(const Array2D&);
 54 const Shape2D shape(const View2D&);
 55 const Shape2D shape(const ConstView2D&);
 56 const Shape2D shape(const BlockArray&);
 57 
 58 // Splits a large 2D array into an array of smaller 2D arrays (blocks)
 59 // Note that if the number of blocks is not a sub-multiple of the input array dimensions then
 60 // the blocks will have different sizes!
 61 // yBlocks and xBlocks are the number of blocks in the vertical and horizontal dimension respectively.
 62 // Splits a picture into slices or a subband into codeblocks.
 63 const BlockArray split_into_blocks(const Array2D& picture, int yBlocks, int xBlocks);
 64 
 65 // Converts an array of blocks back to a single 2D array
 66 // This is the inverse of "split_into_blocks()"
 67 // The array of blocks might represent slices or codeblocks
 68 const Array2D merge_blocks(const BlockArray& blocks);
 69 
 70 // Clip an array to specified limits
 71 const Array2D clip(const Array2D& values, const int min_value, const int max_value);
 72 
 73 //**************** Array IO declarations ****************//
 74 
 75 namespace arrayio {
 76 
 77   enum ioFormat {UNSIGNED, SIGNED, OFFSET};
 78 
 79   // Format manipulator - sets io format
 80   class format {
 81     public:
 82       format(ioFormat f): iof(f) {}; 
 83       void operator () (std::ios_base& stream) const;
 84     private:
 85       const ioFormat iof;
 86   };
 87 
 88   // Format manipulator - sets number of bytes per element
 89   class wordWidth {
 90     public:
 91       wordWidth(int b): no_of_bytes(b) {}; 
 92       void operator () (std::ios_base& stream) const;
 93     private:
 94       const int no_of_bytes;
 95   };
 96 
 97   // Format manipulator - sets number of bits used for data
 98   class bitDepth {
 99     public:
100       bitDepth(int b): no_of_bits(b) {}; 
101       void operator () (std::ios_base& stream) const;
102     private:
103       const int no_of_bits;
104   };
105 
106   // Format manipulator - sets the offset for offset binary
107   // (Default offset, if not explicitly set, is half range)
108   class offset {
109     public:
110       offset(int z): zeroValue(z) {}; 
111       void operator () (std::ios_base& stream) const;
112     private:
113       const int zeroValue;
114   };
115 
116   // Set data to be left justified within the data word
117   std::ostream& left_justified(std::ostream& stream);
118 
119   // Set data to be left justified within the data word
120   std::istream& left_justified(std::istream& stream);
121 
122   // Set data to be right justified within the data word
123   std::ostream& right_justified(std::ostream& stream);
124 
125   // Set data to be right justified within the data word
126   std::istream& right_justified(std::istream& stream);
127 
128   // Set data format to offset binary
129   std::ostream& offset_binary(std::ostream& stream);
130 
131   // Set data format to offset binary
132   std::istream& offset_binary(std::istream& stream);
133 
134   // Set data format to signed binary (two's complement)
135   std::ostream& signed_binary(std::ostream& stream);
136 
137   // Set data format to signed binary (two's complement)
138   std::istream& signed_binary(std::istream& stream);
139 
140   // Set data format to unsigned binary
141   std::ostream& unsigned_binary(std::ostream& stream);
142 
143   // Set data format to unsigned binary
144   std::istream& unsigned_binary(std::istream& stream);
145 
146   // Set data format to text
147   std::ostream& text(std::ostream& stream);
148 
149   // Set data format to text
150   std::istream& text(std::istream& stream);
151 
152 } // end namespace arrayio
153 
154 // ostream io format manipulator
155 std::ostream& operator << (std::ostream& stream, arrayio::format f);
156 
157 // istream io format manipulator
158 std::istream& operator >> (std::istream& stream, arrayio::format f);
159 
160 // ostream wordWidth format manipulator
161 std::ostream& operator << (std::ostream& stream, arrayio::wordWidth w);
162 
163 // istream wordWidth format manipulator
164 std::istream& operator >> (std::istream& stream, arrayio::wordWidth w);
165 
166 // ostream bit depth format manipulator
167 std::ostream& operator << (std::ostream& stream, arrayio::bitDepth d);
168 
169 // istream bit depth format manipulator
170 std::istream& operator >> (std::istream& stream, arrayio::bitDepth d);
171 
172 // ostream offset format manipulator
173 std::ostream& operator << (std::ostream& stream, arrayio::offset z);
174 
175 // istream offset format manipulator
176 std::istream& operator >> (std::istream& stream, arrayio::offset z);
177 
178 std::istream& operator >> (std::istream& stream, Array2D& array);
179 
180 std::ostream& operator << (std::ostream& stream, const Array2D& array);
181   
182 #endif //ARRAYS_25FEB10
  1 /***********************************************************************/
  2 /* Arrays.cpp                                                          */
  3 /* Author: Tim Borer                                                   */
  4 /* This version 8th August 2011                                        */
  5 /*                                                                     */
  6 /* Defines stuff related to mulitdimensional arrays.                   */
  7 /* 20th June 2011: File copied from version 7th October 2010, IO added */
  8 /* Copyright (c) BBC 2011-2015 -- For license see the LICENSE file   */
  9 /***********************************************************************/
 10 
 11 #include <ostream>
 12 #include <istream>
 13 #include <stdexcept>
 14 
 15 #include "Arrays.h"
 16 #include "Utils.h"
 17 
 18 using utils::pow;
 19 
 20 // Get the shape of a 2D array
 21 const Shape2D shape(const Array2D& arg) {
 22   const Shape2D result = {{static_cast<Index>(arg.shape()[0]), static_cast<Index>(arg.shape()[1])}};
 23   return result;
 24 }
 25 
 26 const Shape2D shape(const View2D& arg) {
 27   const Shape2D result = {{static_cast<Index>(arg.shape()[0]), static_cast<Index>(arg.shape()[1])}};
 28   return result;
 29 }
 30 
 31 const Shape2D shape(const ConstView2D& arg) {
 32   const Shape2D result = {{static_cast<Index>(arg.shape()[0]), static_cast<Index>(arg.shape()[1])}};
 33   return result;
 34 }
 35 
 36 const Shape2D shape(const BlockArray& arg) {
 37   const Shape2D result = {{static_cast<Index>(arg.shape()[0]), static_cast<Index>(arg.shape()[1])}};
 38   return result;
 39 }
 40 
 41 const Array2D clip(const Array2D& values, const int min_value, const int max_value) {
 42   Array2D result(values.ranges());
 43   const Index height = values.shape()[0];
 44   const Index width = values.shape()[1];
 45   for (int y=0; y<height; ++y) {
 46     for (int x=0; x<width; ++x) {
 47       if (values[y][x]<min_value) result[y][x] = min_value;
 48       else if (values[y][x]>max_value) result[y][x] =  max_value;
 49       else result[y][x] = values[y][x];
 50     }
 51   }
 52   return result;
 53 }
 54 
 55 // Splits a large 2D array into an array of smaller 2D arrays (blocks)
 56 // Note that if the number of blocks is not a sub-multiple of the input array dimensions then
 57 // the blocks will have different sizes!
 58 // yBlocks and xBlocks are the number of blocks in the vertical and horizontal dimension respectively.
 59 // Splits a picture into slices or a subband into codeblocks.
 60 const BlockArray split_into_blocks(const Array2D& picture, int yBlocks, int xBlocks) {
 61   // Define array of yBlocks by xBlocks
 62   BlockArray blocks(extents[yBlocks][xBlocks]);
 63   const int pictureHeight = picture.shape()[0];
 64   const int pictureWidth = picture.shape()[1];
 65   // Note Range(left, right) defines the half open range [left, right),
 66   // i.e. the rightmost element is not included
 67   for (int y=0, top=0, bottom=pictureHeight/yBlocks;
 68        y<yBlocks;
 69        ++y, top=bottom, bottom=((y+1)*pictureHeight/yBlocks) ) {
 70     for (int x=0, left=0, right=pictureWidth/xBlocks;
 71          x<xBlocks;
 72          ++x, left=right, right=((x+1)*pictureWidth/xBlocks) ) {
 73       // Assign region of picture to block
 74       blocks[y][x] = picture[indices[Range(top,bottom)][Range(left,right)]];
 75     }
 76   }
 77   return blocks;
 78 }
 79 
 80 // Converts an array of blocks back to a single 2D array
 81 // This is the inverse of "split_into_blocks()"
 82 // The array of blocks might represent slices or codeblocks
 83 const Array2D merge_blocks(const BlockArray& blocks) {
 84   // First find picture dimensions
 85   int pictureHeight = 0;
 86   int pictureWidth = 0;
 87   const int yBlocks = blocks.shape()[0];
 88   const int xBlocks = blocks.shape()[1];
 89   for (int y=0; y<yBlocks; ++y) pictureHeight += blocks[y][0].shape()[0];
 90   for (int x=0; x<xBlocks; ++x) pictureWidth += blocks[0][x].shape()[1];
 91   // Define Array2D pictureHeight by PictureWidth
 92   Array2D picture(extents[pictureHeight][pictureWidth]);
 93   // Now merge the block together
 94   // Note Range(top, bottom) and Range(left, right) define half open ranges either
 95   // [top, bottom) or [left, right), i.e. the bottom/rightmost element is not included
 96   int bottom;
 97   for (int y=0, top=0;
 98        y<yBlocks;
 99        ++y, top=bottom) {
100     bottom = top + blocks[y][0].shape()[0];
101     int right;
102     for (int x=0, left=0;
103          x<xBlocks;
104          ++x, left=right) {
105       right = left + blocks[0][x].shape()[1];
106       // Copy block into a view of the picture
107       picture[indices[Range(top,bottom)][Range(left,right)]] = blocks[y][x];
108     }
109   }
110   return picture;
111 }
112 
113 //**************** IO functions ****************//
114 
115 namespace {
116 
117   // Functions to extract stored values from streams
118   // Note the default values are zero if they have not been explicitly set
119 
120   long& word_width(std::ios_base& stream) {
121       static const int i = std::ios_base::xalloc();
122       return stream.iword(i);
123   }
124 
125   long& bit_depth(std::ios_base& stream) {
126       static const int i = std::ios_base::xalloc();
127       return stream.iword(i);
128   }
129 
130   long& is_signed(std::ios_base& stream) {
131       static const int i = std::ios_base::xalloc();
132       return stream.iword(i);
133   }
134 
135   long& is_offset(std::ios_base& stream) {
136       static const int i = std::ios_base::xalloc();
137       return stream.iword(i);
138   }
139 
140   long& is_right_justified(std::ios_base& stream) {
141       static const int i = std::ios_base::xalloc();
142       return stream.iword(i);
143   }
144 
145 #if 0
146   long& is_text(std::ios_base& stream) {
147       static const int i = std::ios_base::xalloc();
148       return stream.iword(i);
149   }
150 #endif
151 
152   long& zero_level_set(std::ios_base& stream) {
153       static const int i = std::ios_base::xalloc();
154       return stream.iword(i);
155   }
156 
157   long& zero_level(std::ios_base& stream) {
158       static const int i = std::ios_base::xalloc();
159       return stream.iword(i);
160   }
161 
162   const int ioBytes(std::ios_base& stream) {
163     return (word_width(stream) ? word_width(stream) : sizeof(int));
164   }
165 
166   const int ioDepth(std::ios_base& stream) {
167     return (bit_depth(stream) ? bit_depth(stream) : 8*ioBytes(stream));
168   }
169 
170   const int ioShift(std::ios_base& stream) {
171     return (is_right_justified(stream) ? 0 : 8*ioBytes(stream)-ioDepth(stream));
172   }
173 
174   const int ioZero(std::ios_base& stream) {
175     const int zeroLevel =
176       (zero_level_set(stream) ? zero_level(stream) : pow(2, ioDepth(stream)-1));
177     return (is_offset(stream) ? zeroLevel : 0);
178   }
179 
180 } // end unnamed namespace
181 
182 // io format manipulator to set the io data format
183 void arrayio::format::operator()(std::ios_base& stream) const {
184   switch (iof) {
185     case UNSIGNED:
186       is_signed(stream) = static_cast<long>(false);
187       is_offset(stream) = static_cast<long>(false);
188       break;
189     case SIGNED:
190       is_signed(stream) = static_cast<long>(true);
191       is_offset(stream) = static_cast<long>(false);
192       break;
193     case OFFSET:
194       is_signed(stream) = static_cast<long>(false);
195       is_offset(stream) = static_cast<long>(true);
196       break;
197     default:
198       throw std::invalid_argument("invalid array io format");
199       break;
200   }
201 }
202 
203 // ostream ioformat format manipulator
204 std::ostream& operator << (std::ostream& stream, arrayio::format f) {
205   f(stream);
206   return stream;
207 }
208 
209 // istream ioformat format manipulator
210 std::istream& operator >> (std::istream& stream, arrayio::format f) {
211   f(stream);
212   return stream;
213 }
214 
215 // wordWidth manipulator to set number of bytes per word
216 void arrayio::wordWidth::operator()(std::ios_base& stream) const {
217   word_width(stream) = static_cast<long>(no_of_bytes);
218 }
219 
220 // ostream wordWidth format manipulator
221 std::ostream& operator << (std::ostream& stream, arrayio::wordWidth w) {
222   w(stream);
223   return stream;
224 }
225 
226 // istream wordWidth format manipulator
227 std::istream& operator >> (std::istream& stream, arrayio::wordWidth w) {
228   w(stream);
229   return stream;
230 }
231 
232 // bitDepth manipulator to set number of bits per word
233 void arrayio::bitDepth::operator()(std::ios_base& stream) const {
234   bit_depth(stream) = static_cast<long>(no_of_bits);
235 }
236 
237 // ostream bitDepth format manipulator
238 std::ostream& operator << (std::ostream& stream, arrayio::bitDepth d) {
239   d(stream);
240   return stream;
241 }
242 
243 // istream bitDepth format manipulator
244 std::istream& operator >> (std::istream& stream, arrayio::bitDepth d) {
245   d(stream);
246   return stream;
247 }
248 
249 // bitDepth manipulator to set number of bits per word
250 void arrayio::offset::operator()(std::ios_base& stream) const {
251   zero_level_set(stream) = static_cast<long>(true);
252   zero_level(stream) = static_cast<long>(zeroValue);
253 }
254 
255 // ostream bitDepth format manipulator
256 std::ostream& operator << (std::ostream& stream, arrayio::offset z) {
257   z(stream);
258   return stream;
259 }
260 
261 // istream bitDepth format manipulator
262 std::istream& operator >> (std::istream& stream, arrayio::offset z) {
263   z(stream);
264   return stream;
265 }
266 
267 // ostream left justified format manipulator
268 std::ostream& arrayio::left_justified(std::ostream& stream) {
269   is_right_justified(stream) = static_cast<long>(false);
270   return stream;
271 }
272 
273 // istream left justified format manipulator
274 std::istream& arrayio::left_justified(std::istream& stream) {
275   is_right_justified(stream) = static_cast<long>(false);
276   return stream;
277 }
278 
279 // ostream right justified format manipulator
280 std::ostream& arrayio::right_justified(std::ostream& stream) {
281   is_right_justified(stream) = static_cast<long>(true);
282   return stream;
283 }
284 
285 // istream right justified format manipulator
286 std::istream& arrayio::right_justified(std::istream& stream) {
287   is_right_justified(stream) = static_cast<long>(true);
288   return stream;
289 }
290 
291 // Set data format to offset binary
292 std::ostream& arrayio::offset_binary(std::ostream& stream) {
293   is_signed(stream) = static_cast<long>(false);
294   is_offset(stream) = static_cast<long>(true);
295   return stream;
296 }
297 
298 // Set data format to offset binary
299 std::istream& arrayio::offset_binary(std::istream& stream) {
300   is_signed(stream) = static_cast<long>(false);
301   is_offset(stream) = static_cast<long>(true);
302   return stream;
303 }
304 
305 // Set data format to signed binary
306 std::ostream& arrayio::signed_binary(std::ostream& stream) {
307   is_signed(stream) = static_cast<long>(true);
308   is_offset(stream) = static_cast<long>(false);
309   return stream;
310 }
311 
312 // Set data format to signed binary
313 std::istream& arrayio::signed_binary(std::istream& stream) {
314   is_signed(stream) = static_cast<long>(true);
315   is_offset(stream) = static_cast<long>(false);
316   return stream;
317 }
318 
319 // Set data format to unsigned binary
320 std::ostream& arrayio::unsigned_binary(std::ostream& stream) {
321   is_signed(stream) = static_cast<long>(false);
322   is_offset(stream) = static_cast<long>(false);
323   return stream;
324 }
325 
326 // Set data format to unsigned binary
327 std::istream& arrayio::unsigned_binary(std::istream& stream) {
328   is_signed(stream) = static_cast<long>(false);
329   is_offset(stream) = static_cast<long>(false);
330   return stream;
331 }
332 
333 std::istream& operator >> (std::istream& stream, Array2D& array) {
334   // Get word width and bit depth from stream
335   // Default word width is size of int, default bit depth fills word width
336   const int wordBytes = ioBytes(stream);
337 
338   //Create reference for input stream buffer (input via stream buffer for efficiency).
339   std::streambuf& inbuf = *(stream.rdbuf());
340   // Read wordBytes bytes per array element
341   const int size = wordBytes*array.num_elements();
342   unsigned char *inBuffer = new unsigned char[size];
343   std::istream::sentry s(stream, true);
344   if (s) {
345     if ( inbuf.sgetn(reinterpret_cast<char*>(inBuffer), size) < size )
346       stream.setstate(std::ios_base::eofbit|std::ios_base::failbit);
347   }
348 
349   const int height = array.shape()[0];
350   const int width = array.shape()[1];
351   const int shift = ioShift(stream);
352   const int offset = ioZero(stream);
353   unsigned int value, byte = 0;
354   for (int y=0; y<height; ++y) {
355     for (int x=0; x<width; ++x) {
356       value = 0;
357       switch (wordBytes) {
358         // Only allowed 4 bytes word width in 32 bit systems
359         case 4:
360           value |= (inBuffer[byte++]<<24);
361         case 3:
362           value |= (inBuffer[byte++]<<16);
363         case 2:
364           value |= (inBuffer[byte++]<<8);
365         case 1:
366           value |= inBuffer[byte++];
367           break;
368         default:
369           throw std::domain_error("Word width of input stream must be in range 1 to 4");
370       }
371       if (!is_signed(stream)) value >>= shift; //Use logical shift for unsigned data (value is unsigned int)
372       array[y][x] = value;
373       if (is_signed(stream)) array[y][x] >>= shift; //Use arithmetic shift for signed data (array[y][x] is int)
374       if (is_offset(stream)) array[y][x] -= offset;
375     }
376   }
377   delete[] inBuffer;
378   return stream;
379 }
380 
381 std::ostream& operator << (std::ostream& stream, const Array2D& array) {
382   // Get word width and bit depth from stream
383   // Default word width is size of int, default bit depth fills word width
384   const int wordBytes = ioBytes(stream);
385   
386   // Write wordBytes bytes per array element
387   const int size = wordBytes*array.num_elements();
388   unsigned char *outBuffer = new unsigned char[size];
389   const int height = array.shape()[0];
390   const int width = array.shape()[1];
391   const int shift = ioShift(stream);
392   const int offset = ioZero(stream);
393   unsigned int value, byte = 0;
394   for (int y=0; y<height; ++y) {
395     for (int x=0; x<width; ++x) {
396       value = array[y][x]+offset;
397       value <<= shift;
398       switch (wordBytes) {
399         // Only allowed 4 bytes word width in 32 bit systems
400         case 4:
401           outBuffer[byte++] = (value>>24);
402         case 3:
403           outBuffer[byte++] = (value>>16);
404         case 2:
405           outBuffer[byte++] = (value>>8);
406         case 1:
407           outBuffer[byte++] = value;
408           break;
409         default:
410           throw std::domain_error("Word width of input stream must be in range 1 to 4");
411           ;
412       }
413     }
414   }
415 
416   //Create reference for output stream buffer (output via stream buffer for efficiency).
417   std::streambuf& outbuf = *(stream.rdbuf());
418   std::ostream::sentry s(stream);
419   if (s) {
420     if ( outbuf.sputn(reinterpret_cast<char*>(outBuffer), size) < size )
421       stream.setstate(std::ios_base::eofbit|std::ios_base::failbit);
422   }
423   delete[] outBuffer;
424 
425   return stream;
426 }

./Boost_Array_Test
******  Boost Library Array1D Test ******
0 1 2 3 4 5 6 7 8 9
******  Boost Library Array1D Test ******
0 -1 -2 -3 -4 -5 -6 -7
1 0 -1 -2 -3 -4 -5 -6
2 1 0 -1 -2 -3 -4 -5
3 2 1 0 -1 -2 -3 -4

posted @ 2017-03-21 21:19  souwang  阅读(266)  评论(0编辑  收藏  举报