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
Boost Library Array1D, Array2D Test
原文:http://www.cnblogs.com/ILoveOCT/p/6596753.html