1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 5 // By downloading, copying, installing or using the software you agree to this license. 6 // If you do not agree to this license, do not download, install, 7 // copy or use the software. 8 // 9 // 10 // License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. 14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved. 15 // Third party copyrights are property of their respective owners. 16 // 17 // Redistribution and use in source and binary forms, with or without modification, 18 // are permitted provided that the following conditions are met: 19 // 20 // * Redistribution's of source code must retain the above copyright notice, 21 // this list of conditions and the following disclaimer. 22 // 23 // * Redistribution's in binary form must reproduce the above copyright notice, 24 // this list of conditions and the following disclaimer in the documentation 25 // and/or other materials provided with the distribution. 26 // 27 // * The name of the copyright holders may not be used to endorse or promote products 28 // derived from this software without specific prior written permission. 29 // 30 // This software is provided by the copyright holders and contributors "as is" and 31 // any express or implied warranties, including, but not limited to, the implied 32 // warranties of merchantability and fitness for a particular purpose are disclaimed. 33 // In no event shall the Intel Corporation or contributors be liable for any direct, 34 // indirect, incidental, special, exemplary, or consequential damages 35 // (including, but not limited to, procurement of substitute goods or services; 36 // loss of use, data, or profits; or business interruption) however caused 37 // and on any theory of liability, whether in contract, strict liability, 38 // or tort (including negligence or otherwise) arising in any way out of 39 // the use of this software, even if advised of the possibility of such damage. 40 // 41 //M*/ 42 43 #include "precomp.hpp" 44 #include "bitstrm.hpp" 45 46 namespace cv 47 { 48 49 const int BS_DEF_BLOCK_SIZE = 1<<15; 50 51 bool bsIsBigEndian( void ) 52 { 53 return (((const int*)"\0\x1\x2\x3\x4\x5\x6\x7")[0] & 255) != 0; 54 } 55 56 ///////////////////////// RBaseStream //////////////////////////// 57 58 bool RBaseStream::isOpened() 59 { 60 return m_is_opened; 61 } 62 63 void RBaseStream::allocate() 64 { 65 if( !m_allocated ) 66 { 67 m_start = new uchar[m_block_size]; 68 m_end = m_start + m_block_size; 69 m_current = m_end; 70 m_allocated = true; 71 } 72 } 73 74 75 RBaseStream::RBaseStream() 76 { 77 m_start = m_end = m_current = 0; 78 m_file = 0; 79 m_block_size = BS_DEF_BLOCK_SIZE; 80 m_is_opened = false; 81 m_allocated = false; 82 } 83 84 85 RBaseStream::~RBaseStream() 86 { 87 close(); // Close files 88 release(); // free buffers 89 } 90 91 92 void RBaseStream::readBlock() 93 { 94 setPos( getPos() ); // normalize position 95 96 if( m_file == 0 ) 97 { 98 if( m_block_pos == 0 && m_current < m_end ) 99 return; 100 throw RBS_THROW_EOS; 101 } 102 103 fseek( m_file, m_block_pos, SEEK_SET ); 104 size_t readed = fread( m_start, 1, m_block_size, m_file ); 105 m_end = m_start + readed; 106 m_current = m_start; 107 108 if( readed == 0 || m_current >= m_end ) 109 throw RBS_THROW_EOS; 110 } 111 112 113 bool RBaseStream::open( const String& filename ) 114 { 115 close(); 116 allocate(); 117 118 m_file = fopen( filename.c_str(), "rb" ); 119 if( m_file ) 120 { 121 m_is_opened = true; 122 setPos(0); 123 readBlock(); 124 } 125 return m_file != 0; 126 } 127 128 bool RBaseStream::open( const Mat& buf ) 129 { 130 close(); 131 if( buf.empty() ) 132 return false; 133 CV_Assert(buf.isContinuous()); 134 m_start = buf.data; 135 m_end = m_start + buf.cols*buf.rows*buf.elemSize(); 136 m_allocated = false; 137 m_is_opened = true; 138 setPos(0); 139 140 return true; 141 } 142 143 void RBaseStream::close() 144 { 145 if( m_file ) 146 { 147 fclose( m_file ); 148 m_file = 0; 149 } 150 m_is_opened = false; 151 if( !m_allocated ) 152 m_start = m_end = m_current = 0; 153 } 154 155 156 void RBaseStream::release() 157 { 158 if( m_allocated ) 159 delete[] m_start; 160 m_start = m_end = m_current = 0; 161 m_allocated = false; 162 } 163 164 165 void RBaseStream::setPos( int pos ) 166 { 167 assert( isOpened() && pos >= 0 ); 168 169 if( !m_file ) 170 { 171 m_current = m_start + pos; 172 m_block_pos = 0; 173 return; 174 } 175 176 int offset = pos % m_block_size; 177 m_block_pos = pos - offset; 178 m_current = m_start + offset; 179 } 180 181 182 int RBaseStream::getPos() 183 { 184 assert( isOpened() ); 185 return m_block_pos + (int)(m_current - m_start); 186 } 187 188 void RBaseStream::skip( int bytes ) 189 { 190 assert( bytes >= 0 ); 191 m_current += bytes; 192 } 193 194 ///////////////////////// RLByteStream //////////////////////////// 195 196 RLByteStream::~RLByteStream() 197 { 198 } 199 200 int RLByteStream::getByte() 201 { 202 uchar *current = m_current; 203 int val; 204 205 if( current >= m_end ) 206 { 207 readBlock(); 208 current = m_current; 209 } 210 211 val = *((uchar*)current); 212 m_current = current + 1; 213 return val; 214 } 215 216 217 int RLByteStream::getBytes( void* buffer, int count ) 218 { 219 uchar* data = (uchar*)buffer; 220 int readed = 0; 221 assert( count >= 0 ); 222 223 while( count > 0 ) 224 { 225 int l; 226 227 for(;;) 228 { 229 l = (int)(m_end - m_current); 230 if( l > count ) l = count; 231 if( l > 0 ) break; 232 readBlock(); 233 } 234 memcpy( data, m_current, l ); 235 m_current += l; 236 data += l; 237 count -= l; 238 readed += l; 239 } 240 return readed; 241 } 242 243 244 //////////// RLByteStream & RMByteStream <Get[d]word>s //////////////// 245 246 RMByteStream::~RMByteStream() 247 { 248 } 249 250 251 int RLByteStream::getWord() 252 { 253 uchar *current = m_current; 254 int val; 255 256 if( current+1 < m_end ) 257 { 258 val = current[0] + (current[1] << 8); 259 m_current = current + 2; 260 } 261 else 262 { 263 val = getByte(); 264 val|= getByte() << 8; 265 } 266 return val; 267 } 268 269 270 int RLByteStream::getDWord() 271 { 272 uchar *current = m_current; 273 int val; 274 275 if( current+3 < m_end ) 276 { 277 val = current[0] + (current[1] << 8) + 278 (current[2] << 16) + (current[3] << 24); 279 m_current = current + 4; 280 } 281 else 282 { 283 val = getByte(); 284 val |= getByte() << 8; 285 val |= getByte() << 16; 286 val |= getByte() << 24; 287 } 288 return val; 289 } 290 291 292 int RMByteStream::getWord() 293 { 294 uchar *current = m_current; 295 int val; 296 297 if( current+1 < m_end ) 298 { 299 val = (current[0] << 8) + current[1]; 300 m_current = current + 2; 301 } 302 else 303 { 304 val = getByte() << 8; 305 val|= getByte(); 306 } 307 return val; 308 } 309 310 311 int RMByteStream::getDWord() 312 { 313 uchar *current = m_current; 314 int val; 315 316 if( current+3 < m_end ) 317 { 318 val = (current[0] << 24) + (current[1] << 16) + 319 (current[2] << 8) + current[3]; 320 m_current = current + 4; 321 } 322 else 323 { 324 val = getByte() << 24; 325 val |= getByte() << 16; 326 val |= getByte() << 8; 327 val |= getByte(); 328 } 329 return val; 330 } 331 332 /////////////////////////// WBaseStream ///////////////////////////////// 333 334 // WBaseStream - base class for output streams 335 WBaseStream::WBaseStream() 336 { 337 m_start = m_end = m_current = 0; 338 m_file = 0; 339 m_block_size = BS_DEF_BLOCK_SIZE; 340 m_is_opened = false; 341 m_buf = 0; 342 } 343 344 345 WBaseStream::~WBaseStream() 346 { 347 close(); 348 release(); 349 } 350 351 352 bool WBaseStream::isOpened() 353 { 354 return m_is_opened; 355 } 356 357 358 void WBaseStream::allocate() 359 { 360 if( !m_start ) 361 m_start = new uchar[m_block_size]; 362 363 m_end = m_start + m_block_size; 364 m_current = m_start; 365 } 366 367 368 void WBaseStream::writeBlock() 369 { 370 int size = (int)(m_current - m_start); 371 372 assert( isOpened() ); 373 if( size == 0 ) 374 return; 375 376 if( m_buf ) 377 { 378 size_t sz = m_buf->size(); 379 m_buf->resize( sz + size ); 380 memcpy( &(*m_buf)[sz], m_start, size ); 381 } 382 else 383 { 384 fwrite( m_start, 1, size, m_file ); 385 } 386 m_current = m_start; 387 m_block_pos += size; 388 } 389 390 391 bool WBaseStream::open( const String& filename ) 392 { 393 close(); 394 allocate(); 395 396 m_file = fopen( filename.c_str(), "wb" ); 397 if( m_file ) 398 { 399 m_is_opened = true; 400 m_block_pos = 0; 401 m_current = m_start; 402 } 403 return m_file != 0; 404 } 405 406 bool WBaseStream::open( std::vector<uchar>& buf ) 407 { 408 close(); 409 allocate(); 410 411 m_buf = &buf; 412 m_is_opened = true; 413 m_block_pos = 0; 414 m_current = m_start; 415 416 return true; 417 } 418 419 void WBaseStream::close() 420 { 421 if( m_is_opened ) 422 writeBlock(); 423 if( m_file ) 424 { 425 fclose( m_file ); 426 m_file = 0; 427 } 428 m_buf = 0; 429 m_is_opened = false; 430 } 431 432 433 void WBaseStream::release() 434 { 435 if( m_start ) 436 delete[] m_start; 437 m_start = m_end = m_current = 0; 438 } 439 440 441 int WBaseStream::getPos() 442 { 443 assert( isOpened() ); 444 return m_block_pos + (int)(m_current - m_start); 445 } 446 447 448 ///////////////////////////// WLByteStream /////////////////////////////////// 449 450 WLByteStream::~WLByteStream() 451 { 452 } 453 454 void WLByteStream::putByte( int val ) 455 { 456 *m_current++ = (uchar)val; 457 if( m_current >= m_end ) 458 writeBlock(); 459 } 460 461 462 void WLByteStream::putBytes( const void* buffer, int count ) 463 { 464 uchar* data = (uchar*)buffer; 465 466 assert( data && m_current && count >= 0 ); 467 468 while( count ) 469 { 470 int l = (int)(m_end - m_current); 471 472 if( l > count ) 473 l = count; 474 475 if( l > 0 ) 476 { 477 memcpy( m_current, data, l ); 478 m_current += l; 479 data += l; 480 count -= l; 481 } 482 if( m_current == m_end ) 483 writeBlock(); 484 } 485 } 486 487 488 void WLByteStream::putWord( int val ) 489 { 490 uchar *current = m_current; 491 492 if( current+1 < m_end ) 493 { 494 current[0] = (uchar)val; 495 current[1] = (uchar)(val >> 8); 496 m_current = current + 2; 497 if( m_current == m_end ) 498 writeBlock(); 499 } 500 else 501 { 502 putByte(val); 503 putByte(val >> 8); 504 } 505 } 506 507 508 void WLByteStream::putDWord( int val ) 509 { 510 uchar *current = m_current; 511 512 if( current+3 < m_end ) 513 { 514 current[0] = (uchar)val; 515 current[1] = (uchar)(val >> 8); 516 current[2] = (uchar)(val >> 16); 517 current[3] = (uchar)(val >> 24); 518 m_current = current + 4; 519 if( m_current == m_end ) 520 writeBlock(); 521 } 522 else 523 { 524 putByte(val); 525 putByte(val >> 8); 526 putByte(val >> 16); 527 putByte(val >> 24); 528 } 529 } 530 531 532 ///////////////////////////// WMByteStream /////////////////////////////////// 533 534 WMByteStream::~WMByteStream() 535 { 536 } 537 538 539 void WMByteStream::putWord( int val ) 540 { 541 uchar *current = m_current; 542 543 if( current+1 < m_end ) 544 { 545 current[0] = (uchar)(val >> 8); 546 current[1] = (uchar)val; 547 m_current = current + 2; 548 if( m_current == m_end ) 549 writeBlock(); 550 } 551 else 552 { 553 putByte(val >> 8); 554 putByte(val); 555 } 556 } 557 558 559 void WMByteStream::putDWord( int val ) 560 { 561 uchar *current = m_current; 562 563 if( current+3 < m_end ) 564 { 565 current[0] = (uchar)(val >> 24); 566 current[1] = (uchar)(val >> 16); 567 current[2] = (uchar)(val >> 8); 568 current[3] = (uchar)val; 569 m_current = current + 4; 570 if( m_current == m_end ) 571 writeBlock(); 572 } 573 else 574 { 575 putByte(val >> 24); 576 putByte(val >> 16); 577 putByte(val >> 8); 578 putByte(val); 579 } 580 } 581 582 } 583