ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
Decoder.cpp
Go to the documentation of this file.
1 /*
2  * Original work Copyright 2009 - 2010 Kevin Ackley (kackley@gwi.net)
3  * Modified work Copyright 2018 - 2020 Andy Maloney <asmaloney@gmail.com>
4  *
5  * Permission is hereby granted, free of charge, to any person or organization
6  * obtaining a copy of the software and accompanying documentation covered by
7  * this license (the "Software") to use, reproduce, display, distribute,
8  * execute, and transmit the Software, and to prepare derivative works of the
9  * Software, and to permit third-parties to whom the Software is furnished to
10  * do so, all subject to the following:
11  *
12  * The copyright notices in the Software and this entire statement, including
13  * the above license grant, this restriction and the following disclaimer,
14  * must be included in all copies of the Software, in whole or in part, and
15  * all derivative works of the Software, unless such copies or derivative
16  * works are solely in the form of machine-executable object code generated by
17  * a source language processor.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
22  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
23  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  */
27 
28 #include <algorithm>
29 #include <cstring>
30 
32 #include "Decoder.h"
33 #include "FloatNodeImpl.h"
34 #include "ImageFileImpl.h"
35 #include "IntegerNodeImpl.h"
36 #include "ScaledIntegerNodeImpl.h"
37 #include "SourceDestBufferImpl.h"
38 
39 using namespace e57;
40 
41 std::shared_ptr<Decoder> Decoder::DecoderFactory( unsigned bytestreamNumber,
42  const CompressedVectorNodeImpl *cVector,
43  std::vector<SourceDestBuffer> &dbufs, const ustring & /*codecPath*/ )
44 {
46 
48  NodeImplSharedPtr prototype = cVector->getPrototype();
49  ustring path = dbufs.at( 0 ).pathName();
50  NodeImplSharedPtr decodeNode = prototype->get( path );
51 
52 #ifdef E57_MAX_VERBOSE
53  std::cout << "Node to decode:" << std::endl; //???
54  decodeNode->dump( 2 );
55 #endif
56 
57  uint64_t maxRecordCount = cVector->childCount();
58 
59  switch ( decodeNode->type() )
60  {
61  case E57_INTEGER:
62  {
63  std::shared_ptr<IntegerNodeImpl> ini =
64  std::static_pointer_cast<IntegerNodeImpl>( decodeNode ); // downcast to correct type
65 
67  ImageFileImplSharedPtr imf( decodeNode->destImageFile_ ); //??? should be function for this,
68  // imf->parentFile()
69  //--> ImageFile?
70 
71  unsigned bitsPerRecord = imf->bitsNeeded( ini->minimum(), ini->maximum() );
72 
76  if ( bitsPerRecord == 0 )
77  {
78  std::shared_ptr<Decoder> decoder( new ConstantIntegerDecoder( false, bytestreamNumber, dbufs.at( 0 ),
79  ini->minimum(), 1.0, 0.0, maxRecordCount ) );
80  return decoder;
81  }
82 
83  if ( bitsPerRecord <= 8 )
84  {
85  std::shared_ptr<Decoder> decoder( new BitpackIntegerDecoder<uint8_t>(
86  false, bytestreamNumber, dbufs.at( 0 ), ini->minimum(), ini->maximum(), 1.0, 0.0, maxRecordCount ) );
87  return decoder;
88  }
89 
90  if ( bitsPerRecord <= 16 )
91  {
92  std::shared_ptr<Decoder> decoder( new BitpackIntegerDecoder<uint16_t>(
93  false, bytestreamNumber, dbufs.at( 0 ), ini->minimum(), ini->maximum(), 1.0, 0.0, maxRecordCount ) );
94  return decoder;
95  }
96 
97  if ( bitsPerRecord <= 32 )
98  {
99  std::shared_ptr<Decoder> decoder( new BitpackIntegerDecoder<uint32_t>(
100  false, bytestreamNumber, dbufs.at( 0 ), ini->minimum(), ini->maximum(), 1.0, 0.0, maxRecordCount ) );
101  return decoder;
102  }
103 
104  std::shared_ptr<Decoder> decoder( new BitpackIntegerDecoder<uint64_t>(
105  false, bytestreamNumber, dbufs.at( 0 ), ini->minimum(), ini->maximum(), 1.0, 0.0, maxRecordCount ) );
106  return decoder;
107  }
108 
109  case E57_SCALED_INTEGER:
110  {
111  std::shared_ptr<ScaledIntegerNodeImpl> sini =
112  std::static_pointer_cast<ScaledIntegerNodeImpl>( decodeNode ); // downcast to correct type
113 
115  ImageFileImplSharedPtr imf( decodeNode->destImageFile_ ); //??? should be function for this,
116  // imf->parentFile()
117  //--> ImageFile?
118 
119  unsigned bitsPerRecord = imf->bitsNeeded( sini->minimum(), sini->maximum() );
120 
124  if ( bitsPerRecord == 0 )
125  {
126  std::shared_ptr<Decoder> decoder( new ConstantIntegerDecoder( true, bytestreamNumber, dbufs.at( 0 ),
127  sini->minimum(), sini->scale(),
128  sini->offset(), maxRecordCount ) );
129  return decoder;
130  }
131 
132  if ( bitsPerRecord <= 8 )
133  {
134  std::shared_ptr<Decoder> decoder(
135  new BitpackIntegerDecoder<uint8_t>( true, bytestreamNumber, dbufs.at( 0 ), sini->minimum(),
136  sini->maximum(), sini->scale(), sini->offset(), maxRecordCount ) );
137  return decoder;
138  }
139 
140  if ( bitsPerRecord <= 16 )
141  {
142  std::shared_ptr<Decoder> decoder(
143  new BitpackIntegerDecoder<uint16_t>( true, bytestreamNumber, dbufs.at( 0 ), sini->minimum(),
144  sini->maximum(), sini->scale(), sini->offset(), maxRecordCount ) );
145  return decoder;
146  }
147 
148  if ( bitsPerRecord <= 32 )
149  {
150  std::shared_ptr<Decoder> decoder(
151  new BitpackIntegerDecoder<uint32_t>( true, bytestreamNumber, dbufs.at( 0 ), sini->minimum(),
152  sini->maximum(), sini->scale(), sini->offset(), maxRecordCount ) );
153  return decoder;
154  }
155 
156  std::shared_ptr<Decoder> decoder(
157  new BitpackIntegerDecoder<uint64_t>( true, bytestreamNumber, dbufs.at( 0 ), sini->minimum(),
158  sini->maximum(), sini->scale(), sini->offset(), maxRecordCount ) );
159  return decoder;
160  }
161 
162  case E57_FLOAT:
163  {
164  std::shared_ptr<FloatNodeImpl> fni =
165  std::static_pointer_cast<FloatNodeImpl>( decodeNode ); // downcast to correct type
166 
167  std::shared_ptr<Decoder> decoder(
168  new BitpackFloatDecoder( bytestreamNumber, dbufs.at( 0 ), fni->precision(), maxRecordCount ) );
169  return decoder;
170  }
171 
172  case E57_STRING:
173  {
174  std::shared_ptr<Decoder> decoder(
175  new BitpackStringDecoder( bytestreamNumber, dbufs.at( 0 ), maxRecordCount ) );
176 
177  return decoder;
178  }
179 
180  default:
181  {
182  throw E57_EXCEPTION2( E57_ERROR_BAD_PROTOTYPE, "nodeType=" + toString( decodeNode->type() ) );
183  }
184  }
185 }
186 
187 Decoder::Decoder( unsigned bytestreamNumber ) : bytestreamNumber_( bytestreamNumber )
188 {
189 }
190 
191 BitpackDecoder::BitpackDecoder( unsigned bytestreamNumber, SourceDestBuffer &dbuf, unsigned alignmentSize,
192  uint64_t maxRecordCount ) :
193  Decoder( bytestreamNumber ), maxRecordCount_( maxRecordCount ), destBuffer_( dbuf.impl() ),
194  inBuffer_( 1024 ),
195  inBufferAlignmentSize_( alignmentSize ), bitsPerWord_( 8 * alignmentSize ), bytesPerWord_( alignmentSize )
196 {
197 }
198 
199 void BitpackDecoder::destBufferSetNew( std::vector<SourceDestBuffer> &dbufs )
200 {
201  if ( dbufs.size() != 1 )
202  {
203  throw E57_EXCEPTION2( E57_ERROR_INTERNAL, "dbufsSize=" + toString( dbufs.size() ) );
204  }
205 
206  destBuffer_ = dbufs.at( 0 ).impl();
207 }
208 
209 size_t BitpackDecoder::inputProcess( const char *source, const size_t availableByteCount )
210 {
211 #ifdef E57_MAX_VERBOSE
212  std::cout << "BitpackDecoder::inputprocess() called, source=" << ( source ? source : "none" )
213  << " availableByteCount=" << availableByteCount << std::endl;
214 #endif
215  size_t bytesUnsaved = availableByteCount;
216  size_t bitsEaten = 0;
217  do
218  {
219  size_t byteCount = std::min( bytesUnsaved, inBuffer_.size() - static_cast<size_t>( inBufferEndByte_ ) );
220 
222  if ( byteCount > 0 )
223  {
224  memcpy( &inBuffer_[inBufferEndByte_], source, byteCount );
225 
227  inBufferEndByte_ += byteCount;
228 
230  bytesUnsaved -= byteCount;
231  source += byteCount;
232  }
233 #ifdef E57_MAX_VERBOSE
234  {
235  unsigned i;
236  unsigned firstByte = inBufferFirstBit_ / 8;
237  for ( i = 0; i < byteCount && i < 20; i++ )
238  {
239  std::cout << " inBuffer[" << firstByte + i << "]=" << (unsigned)(unsigned char)( inBuffer_[firstByte + i] )
240  << std::endl;
241  }
242  if ( i < byteCount )
243  {
244  std::cout << " " << byteCount - i << "source bytes unprinted..." << std::endl;
245  }
246  }
247 #endif
248 
256 
257  size_t firstWord = inBufferFirstBit_ / bitsPerWord_;
258  size_t firstNaturalBit = firstWord * bitsPerWord_;
259  size_t endBit = inBufferEndByte_ * 8;
260 #ifdef E57_MAX_VERBOSE
261  std::cout << " feeding aligned decoder " << endBit - inBufferFirstBit_ << " bits." << std::endl;
262 #endif
263  bitsEaten = inputProcessAligned( &inBuffer_[firstWord * bytesPerWord_], inBufferFirstBit_ - firstNaturalBit,
264  endBit - firstNaturalBit );
265 #ifdef E57_MAX_VERBOSE
266  std::cout << " bitsEaten=" << bitsEaten << " firstWord=" << firstWord << " firstNaturalBit=" << firstNaturalBit
267  << " endBit=" << endBit << std::endl;
268 #endif
269 #ifdef E57_DEBUG
270  if ( bitsEaten > endBit - inBufferFirstBit_ )
271  {
272  throw E57_EXCEPTION2( E57_ERROR_INTERNAL, "bitsEaten=" + toString( bitsEaten ) +
273  " endBit=" + toString( endBit ) +
274  " inBufferFirstBit=" + toString( inBufferFirstBit_ ) );
275  }
276 #endif
277  inBufferFirstBit_ += bitsEaten;
278 
282 
285  } while ( bytesUnsaved > 0 && bitsEaten > 0 );
286 
288  return ( availableByteCount - bytesUnsaved );
289 }
290 
292 {
293  inBufferFirstBit_ = 0;
294  inBufferEndByte_ = 0;
295 }
296 
298 {
302  size_t firstWord = inBufferFirstBit_ / bitsPerWord_;
303  size_t firstNaturalByte = firstWord * bytesPerWord_;
304 #ifdef E57_DEBUG
305  if ( firstNaturalByte > inBufferEndByte_ )
306  {
307  throw E57_EXCEPTION2( E57_ERROR_INTERNAL, "firstNaturalByte=" + toString( firstNaturalByte ) +
308  " inBufferEndByte=" + toString( inBufferEndByte_ ) );
309  }
310 #endif
311  size_t byteCount = inBufferEndByte_ - firstNaturalByte;
312  if ( byteCount > 0 )
313  {
314  memmove( &inBuffer_[0], &inBuffer_[firstNaturalByte],
315  byteCount );
316  }
317 
319  inBufferEndByte_ = byteCount;
321 }
322 
323 #ifdef E57_DEBUG
324 void BitpackDecoder::dump( int indent, std::ostream &os )
325 {
326  os << space( indent ) << "bytestreamNumber: " << bytestreamNumber_ << std::endl;
327  os << space( indent ) << "currentRecordIndex: " << currentRecordIndex_ << std::endl;
328  os << space( indent ) << "maxRecordCount: " << maxRecordCount_ << std::endl;
329  os << space( indent ) << "destBuffer:" << std::endl;
330  destBuffer_->dump( indent + 4, os );
331  os << space( indent ) << "inBufferFirstBit: " << inBufferFirstBit_ << std::endl;
332  os << space( indent ) << "inBufferEndByte: " << inBufferEndByte_ << std::endl;
333  os << space( indent ) << "inBufferAlignmentSize: " << inBufferAlignmentSize_ << std::endl;
334  os << space( indent ) << "bitsPerWord: " << bitsPerWord_ << std::endl;
335  os << space( indent ) << "bytesPerWord: " << bytesPerWord_ << std::endl;
336  os << space( indent ) << "inBuffer:" << std::endl;
337  unsigned i;
338  for ( i = 0; i < inBuffer_.size() && i < 20; i++ )
339  {
340  os << space( indent + 4 ) << "inBuffer[" << i
341  << "]: " << static_cast<unsigned>( static_cast<unsigned char>( inBuffer_.at( i ) ) ) << std::endl;
342  }
343  if ( i < inBuffer_.size() )
344  {
345  os << space( indent + 4 ) << inBuffer_.size() - i << " more unprinted..." << std::endl;
346  }
347 }
348 #endif
349 
350 //================================================================
351 
352 BitpackFloatDecoder::BitpackFloatDecoder( unsigned bytestreamNumber, SourceDestBuffer &dbuf, FloatPrecision precision,
353  uint64_t maxRecordCount ) :
354  BitpackDecoder( bytestreamNumber, dbuf, ( precision == E57_SINGLE ) ? sizeof( float ) : sizeof( double ),
355  maxRecordCount ),
356  precision_( precision )
357 {
358 }
359 
360 size_t BitpackFloatDecoder::inputProcessAligned( const char *inbuf, const size_t firstBit, const size_t endBit )
361 {
362 #ifdef E57_MAX_VERBOSE
363  std::cout << "BitpackFloatDecoder::inputProcessAligned() called, inbuf=" << inbuf << " firstBit=" << firstBit
364  << " endBit=" << endBit << std::endl;
365 #endif
368 
369  size_t n = destBuffer_->capacity() - destBuffer_->nextIndex();
370 
371  size_t typeSize = ( precision_ == E57_SINGLE ) ? sizeof( float ) : sizeof( double );
372 
373 #ifdef E57_DEBUG
374 #if 0 // I know no way to do this portably <rs>
375  // Deactivate for now until a better solution is found.
377  if (reinterpret_cast<unsigned>(inbuf) % typeSize) {
379  "inbuf=" + toString(reinterpret_cast<unsigned>(inbuf))
380  + " typeSize=" + toString(typeSize));
381  }
382 #endif
384  if ( firstBit != 0 )
385  {
386  throw E57_EXCEPTION2( E57_ERROR_INTERNAL, "firstBit=" + toString( firstBit ) );
387  }
388 #endif
389 
391  size_t maxInputRecords = ( endBit - firstBit ) / ( 8 * typeSize );
392 
394  if ( n > maxInputRecords )
395  {
396  n = maxInputRecords;
397  }
398 
399  // Can't process more than defined in input file
401  {
402  n = static_cast<unsigned>( maxRecordCount_ - currentRecordIndex_ );
403  }
404 
405 #ifdef E57_MAX_VERBOSE
406  std::cout << " n:" << n << std::endl; //???
407 #endif
408 
409  if ( precision_ == E57_SINGLE )
410  {
412  auto inp = reinterpret_cast<const float *>( inbuf );
413 
415  for ( unsigned i = 0; i < n; i++ )
416  {
417  float value = *inp;
418 
419 #ifdef E57_MAX_VERBOSE
420  std::cout << " got float value=" << value << std::endl;
421 #endif
422  destBuffer_->setNextFloat( value );
423  inp++;
424  }
425  }
426  else
427  {
429  auto inp = reinterpret_cast<const double *>( inbuf );
430 
432  for ( unsigned i = 0; i < n; i++ )
433  {
434  double value = *inp;
435 
436 #ifdef E57_MAX_VERBOSE
437  std::cout << " got double value=" << value << std::endl;
438 #endif
439  destBuffer_->setNextDouble( value );
440  inp++;
441  }
442  }
443 
445  currentRecordIndex_ += n;
446 
448  return ( n * 8 * typeSize );
449 }
450 
451 #ifdef E57_DEBUG
452 void BitpackFloatDecoder::dump( int indent, std::ostream &os )
453 {
454  BitpackDecoder::dump( indent, os );
455  if ( precision_ == E57_SINGLE )
456  {
457  os << space( indent ) << "precision: E57_SINGLE" << std::endl;
458  }
459  else
460  {
461  os << space( indent ) << "precision: E57_DOUBLE" << std::endl;
462  }
463 }
464 #endif
465 
466 //================================================================
467 
469  uint64_t maxRecordCount ) :
470  BitpackDecoder( bytestreamNumber, dbuf, sizeof( char ), maxRecordCount )
471 {
472 }
473 
474 size_t BitpackStringDecoder::inputProcessAligned( const char *inbuf, const size_t firstBit, const size_t endBit )
475 {
476 #ifdef E57_MAX_VERBOSE
477  std::cout << "BitpackStringDecoder::inputProcessAligned() called, inbuf=" << inbuf << " firstBit=" << firstBit
478  << " endBit=" << endBit << std::endl;
479 #endif
482 
483 #ifdef E57_DEBUG
485  if ( firstBit != 0 )
486  {
487  throw E57_EXCEPTION2( E57_ERROR_INTERNAL, "firstBit=" + toString( firstBit ) );
488  }
489 #endif
490 
492  size_t nBytesAvailable = ( endBit - firstBit ) >> 3;
493  size_t nBytesRead = 0;
494 
497  while ( currentRecordIndex_ < maxRecordCount_ && nBytesRead < nBytesAvailable )
498  {
499 #ifdef E57_MAX_VERBOSE
500  std::cout << "read string loop1: readingPrefix=" << readingPrefix_ << " prefixLength=" << prefixLength_
501  << " nBytesPrefixRead=" << nBytesPrefixRead_ << " nBytesStringRead=" << nBytesStringRead_ << std::endl;
502 #endif
503  if ( readingPrefix_ )
504  {
506  while ( nBytesRead < nBytesAvailable && ( nBytesPrefixRead_ == 0 || nBytesPrefixRead_ < prefixLength_ ) )
507  {
510  if ( nBytesPrefixRead_ == 0 )
511  {
512  if ( *inbuf & 0x01 )
513  {
514  prefixLength_ = 8; // 8 byte prefix, length upto 2^63-1
515  }
516  else
517  {
518  prefixLength_ = 1; // 1 byte prefix, length upto 2^7-1
519  }
520  }
521 
523  prefixBytes_[nBytesPrefixRead_] = *inbuf++;
525  nBytesRead++;
526  }
527 
528 #ifdef E57_MAX_VERBOSE
529  std::cout << "read string loop2: readingPrefix=" << readingPrefix_ << " prefixLength=" << prefixLength_
530  << " nBytesPrefixRead=" << nBytesPrefixRead_ << " nBytesStringRead=" << nBytesStringRead_
531  << std::endl;
532 #endif
536  {
537  if ( prefixLength_ == 1 )
538  {
542  stringLength_ = static_cast<uint64_t>( prefixBytes_[0] >> 1 );
543  }
544  else
545  {
549  stringLength_ = ( static_cast<uint64_t>( prefixBytes_[0] ) >> 1 ) +
550  ( static_cast<uint64_t>( prefixBytes_[1] ) << ( 1 * 8 - 1 ) ) +
551  ( static_cast<uint64_t>( prefixBytes_[2] ) << ( 2 * 8 - 1 ) ) +
552  ( static_cast<uint64_t>( prefixBytes_[3] ) << ( 3 * 8 - 1 ) ) +
553  ( static_cast<uint64_t>( prefixBytes_[4] ) << ( 4 * 8 - 1 ) ) +
554  ( static_cast<uint64_t>( prefixBytes_[5] ) << ( 5 * 8 - 1 ) ) +
555  ( static_cast<uint64_t>( prefixBytes_[6] ) << ( 6 * 8 - 1 ) ) +
556  ( static_cast<uint64_t>( prefixBytes_[7] ) << ( 7 * 8 - 1 ) );
557  }
559  readingPrefix_ = false;
560  prefixLength_ = 1;
561  memset( prefixBytes_, 0, sizeof( prefixBytes_ ) );
562  nBytesPrefixRead_ = 0;
563  currentString_ = "";
564  nBytesStringRead_ = 0;
565  }
566 #ifdef E57_MAX_VERBOSE
567  std::cout << "read string loop3: readingPrefix=" << readingPrefix_ << " prefixLength=" << prefixLength_
568  << " nBytesPrefixRead=" << nBytesPrefixRead_ << " nBytesStringRead=" << nBytesStringRead_
569  << std::endl;
570 #endif
571  }
572 
575  if ( !readingPrefix_ )
576  {
578  uint64_t nBytesNeeded = stringLength_ - nBytesStringRead_;
579 
581  size_t nBytesProcess = nBytesAvailable - nBytesRead;
582  if ( nBytesNeeded < static_cast<uint64_t>( nBytesProcess ) )
583  {
584  nBytesProcess = static_cast<unsigned>( nBytesNeeded );
585  }
586 
588  currentString_ += ustring( inbuf, nBytesProcess );
589  inbuf += nBytesProcess;
590  nBytesRead += nBytesProcess;
591  nBytesStringRead_ += nBytesProcess;
592 
595  {
597  destBuffer_->setNextString( currentString_ );
599 
601  readingPrefix_ = true;
602  prefixLength_ = 1;
603  memset( prefixBytes_, 0, sizeof( prefixBytes_ ) );
604  nBytesPrefixRead_ = 0;
605  stringLength_ = 0;
606  currentString_ = "";
607  nBytesStringRead_ = 0;
608  }
609  }
610  }
611 
613  return ( nBytesRead * 8 );
614 }
615 
616 #ifdef E57_DEBUG
617 void BitpackStringDecoder::dump( int indent, std::ostream &os )
618 {
619  BitpackDecoder::dump( indent, os );
620  os << space( indent ) << "readingPrefix: " << readingPrefix_ << std::endl;
621  os << space( indent ) << "prefixLength: " << prefixLength_ << std::endl;
622  os << space( indent ) << "prefixBytes[8]: " << static_cast<unsigned>( prefixBytes_[0] ) << " "
623  << static_cast<unsigned>( prefixBytes_[1] ) << " " << static_cast<unsigned>( prefixBytes_[2] ) << " "
624  << static_cast<unsigned>( prefixBytes_[3] ) << " " << static_cast<unsigned>( prefixBytes_[4] ) << " "
625  << static_cast<unsigned>( prefixBytes_[5] ) << " " << static_cast<unsigned>( prefixBytes_[6] ) << " "
626  << static_cast<unsigned>( prefixBytes_[7] ) << std::endl;
627  os << space( indent ) << "nBytesPrefixRead: " << nBytesPrefixRead_ << std::endl;
628  os << space( indent ) << "stringLength: " << stringLength_ << std::endl;
629  os << space( indent )
630  << "currentString: "
631  ""
632  << currentString_
633  << ""
634  ""
635  << std::endl;
636  os << space( indent ) << "nBytesStringRead: " << nBytesStringRead_ << std::endl;
637 }
638 #endif
639 
640 //================================================================
641 
642 template <typename RegisterT>
643 BitpackIntegerDecoder<RegisterT>::BitpackIntegerDecoder( bool isScaledInteger, unsigned bytestreamNumber,
644  SourceDestBuffer &dbuf, int64_t minimum, int64_t maximum,
645  double scale, double offset, uint64_t maxRecordCount ) :
646  BitpackDecoder( bytestreamNumber, dbuf, sizeof( RegisterT ), maxRecordCount ), isScaledInteger_( isScaledInteger ),
647  minimum_( minimum ), maximum_( maximum ), scale_( scale ), offset_( offset )
648 {
650  ImageFileImplSharedPtr imf( dbuf.impl()->destImageFile() ); //??? should be function for this,
651  // imf->parentFile() --> ImageFile?
652 
653  bitsPerRecord_ = imf->bitsNeeded( minimum_, maximum_ );
654  destBitMask_ = ( bitsPerRecord_ == 64 ) ? ~0 : static_cast<RegisterT>( 1ULL << bitsPerRecord_ ) - 1;
655 }
656 
657 template <typename RegisterT>
658 size_t BitpackIntegerDecoder<RegisterT>::inputProcessAligned( const char *inbuf, const size_t firstBit,
659  const size_t endBit )
660 {
661 #ifdef E57_MAX_VERBOSE
662  std::cout << "BitpackIntegerDecoder::inputProcessAligned() called, inbuf=" << (void *)( inbuf )
663  << " firstBit=" << firstBit << " endBit=" << endBit << std::endl;
664 #endif
665 
668 
669 #ifdef E57_DEBUG
670 #if 0 // I know now way to do this portably
671  // Deactivate for now until a better solution is found.
673  if ((reinterpret_cast<unsigned>(inbuf)) % sizeof(RegisterT))
674  throw E57_EXCEPTION2(E57_ERROR_INTERNAL, "inbuf=" + toString(reinterpret_cast<unsigned>(inbuf)));
675 #endif
677  if ( firstBit >= 8 * sizeof( RegisterT ) )
678  {
679  throw E57_EXCEPTION2( E57_ERROR_INTERNAL, "firstBit=" + toString( firstBit ) );
680  }
681 #endif
682 
683  size_t destRecords = destBuffer_->capacity() - destBuffer_->nextIndex();
684 
688  size_t bitCount = endBit - firstBit;
689  size_t maxInputRecords = bitCount / bitsPerRecord_;
690 
693  size_t recordCount = std::min( destRecords, maxInputRecords );
694 
695  // Can't process more than defined in input file
696  if ( static_cast<uint64_t>( recordCount ) > maxRecordCount_ - currentRecordIndex_ )
697  {
698  recordCount = static_cast<unsigned>( maxRecordCount_ - currentRecordIndex_ );
699  }
700 
701 #ifdef E57_MAX_VERBOSE
702  std::cout << " recordCount=" << recordCount << std::endl;
703 #endif
704 
705  auto inp = reinterpret_cast<const RegisterT *>( inbuf );
706  unsigned wordPosition = 0;
707 
719 
720  size_t bitOffset = firstBit;
721 
722  for ( size_t i = 0; i < recordCount; i++ )
723  {
725  RegisterT low = inp[wordPosition];
726 
727 #ifdef E57_MAX_VERBOSE
728  std::cout << " bitOffset: " << bitOffset << std::endl;
729  std::cout << " low: " << binaryString( low ) << std::endl;
730 #endif
731 
732  RegisterT w;
733  if ( bitOffset > 0 )
734  {
736  RegisterT high = inp[wordPosition + 1];
737 
738 #ifdef E57_MAX_VERBOSE
739  std::cout << " high:" << binaryString( high ) << std::endl;
740 #endif
741 
745  w = ( high << ( 8 * sizeof( RegisterT ) - bitOffset ) ) | ( low >> bitOffset );
746  }
747  else
748  {
751  w = low;
752  }
753 
754 #ifdef E57_MAX_VERBOSE
755  std::cout << " w: " << binaryString( w ) << std::endl;
756 #endif
757 
759  w &= destBitMask_;
760 
762  int64_t value = minimum_ + static_cast<uint64_t>( w );
763 
764 #ifdef E57_MAX_VERBOSE
765  std::cout << " Storing value=" << value << std::endl;
766 #endif
767 
770  if ( isScaledInteger_ )
771  {
772  destBuffer_->setNextInt64( value, scale_, offset_ );
773  }
774  else
775  {
776  destBuffer_->setNextInt64( value );
777  }
778 
780 
782  bitOffset += bitsPerRecord_;
783  if ( bitOffset >= 8 * sizeof( RegisterT ) )
784  {
785  bitOffset -= 8 * sizeof( RegisterT );
786  wordPosition++;
787  }
788 #ifdef E57_MAX_VERBOSE
789  std::cout << " Processed " << i + 1 << " records, wordPosition=" << wordPosition << " decoder:" << std::endl;
790  dump( 4 );
791 #endif
792  }
793 
795  currentRecordIndex_ += recordCount;
796 
798  return ( recordCount * bitsPerRecord_ );
799 }
800 
801 #ifdef E57_DEBUG
802 template <typename RegisterT> void BitpackIntegerDecoder<RegisterT>::dump( int indent, std::ostream &os )
803 {
804  BitpackDecoder::dump( indent, os );
805  os << space( indent ) << "isScaledInteger: " << isScaledInteger_ << std::endl;
806  os << space( indent ) << "minimum: " << minimum_ << std::endl;
807  os << space( indent ) << "maximum: " << maximum_ << std::endl;
808  os << space( indent ) << "scale: " << scale_ << std::endl;
809  os << space( indent ) << "offset: " << offset_ << std::endl;
810  os << space( indent ) << "bitsPerRecord: " << bitsPerRecord_ << std::endl;
811  os << space( indent ) << "destBitMask: " << binaryString( destBitMask_ ) << " = " << hexString( destBitMask_ )
812  << std::endl;
813 }
814 #endif
815 
816 //================================================================
817 
818 ConstantIntegerDecoder::ConstantIntegerDecoder( bool isScaledInteger, unsigned bytestreamNumber, SourceDestBuffer &dbuf,
819  int64_t minimum, double scale, double offset,
820  uint64_t maxRecordCount ) :
821  Decoder( bytestreamNumber ), maxRecordCount_( maxRecordCount ), destBuffer_( dbuf.impl() ),
822  isScaledInteger_( isScaledInteger ), minimum_( minimum ), scale_( scale ), offset_( offset )
823 {
824 }
825 
826 void ConstantIntegerDecoder::destBufferSetNew( std::vector<SourceDestBuffer> &dbufs )
827 {
828  if ( dbufs.size() != 1 )
829  {
830  throw E57_EXCEPTION2( E57_ERROR_INTERNAL, "dbufsSize=" + toString( dbufs.size() ) );
831  }
832 
833  destBuffer_ = dbufs.at( 0 ).impl();
834 }
835 
836 size_t ConstantIntegerDecoder::inputProcess( const char *source, const size_t availableByteCount )
837 {
838 #ifdef E57_MAX_VERBOSE
839  std::cout << "ConstantIntegerDecoder::inputprocess() called, source=" << (void *)( source )
840  << " availableByteCount=" << availableByteCount << std::endl;
841 #endif
842 
845 
847  size_t count = destBuffer_->capacity() - destBuffer_->nextIndex();
848  uint64_t remainingRecordCount = maxRecordCount_ - currentRecordIndex_;
849  if ( static_cast<uint64_t>( count ) > remainingRecordCount )
850  {
851  count = static_cast<unsigned>( remainingRecordCount );
852  }
853 
854  if ( isScaledInteger_ )
855  {
856  for ( size_t i = 0; i < count; i++ )
857  {
858  destBuffer_->setNextInt64( minimum_, scale_, offset_ );
859  }
860  }
861  else
862  {
863  for ( size_t i = 0; i < count; i++ )
864  {
865  destBuffer_->setNextInt64( minimum_ );
866  }
867  }
869  return ( count );
870 }
871 
873 {
874 }
875 
876 #ifdef E57_DEBUG
877 void ConstantIntegerDecoder::dump( int indent, std::ostream &os )
878 {
879  os << space( indent ) << "bytestreamNumber: " << bytestreamNumber_ << std::endl;
880  os << space( indent ) << "currentRecordIndex: " << currentRecordIndex_ << std::endl;
881  os << space( indent ) << "maxRecordCount: " << maxRecordCount_ << std::endl;
882  os << space( indent ) << "isScaledInteger: " << isScaledInteger_ << std::endl;
883  os << space( indent ) << "minimum: " << minimum_ << std::endl;
884  os << space( indent ) << "scale: " << scale_ << std::endl;
885  os << space( indent ) << "offset: " << offset_ << std::endl;
886  os << space( indent ) << "destBuffer:" << std::endl;
887  destBuffer_->dump( indent + 4, os );
888 }
889 #endif
int count
int offset
int offset_
Definition: FilePLY.cpp:36
#define E57_EXCEPTION2(ecode, context)
Definition: Common.h:68
std::vector< char > inBuffer_
Definition: Decoder.h:90
virtual size_t inputProcessAligned(const char *inbuf, const size_t firstBit, const size_t endBit)=0
uint64_t maxRecordCount_
Definition: Decoder.h:86
void stateReset() override
Definition: Decoder.cpp:291
std::shared_ptr< SourceDestBufferImpl > destBuffer_
Definition: Decoder.h:88
BitpackDecoder(unsigned bytestreamNumber, SourceDestBuffer &dbuf, unsigned alignmentSize, uint64_t maxRecordCount)
Definition: Decoder.cpp:191
size_t inBufferFirstBit_
Definition: Decoder.h:91
unsigned int inBufferAlignmentSize_
Definition: Decoder.h:93
uint64_t currentRecordIndex_
Definition: Decoder.h:85
void dump(int indent=0, std::ostream &os=std::cout) override
Definition: Decoder.cpp:324
size_t inBufferEndByte_
Definition: Decoder.h:92
size_t inputProcess(const char *source, const size_t availableByteCount) override
Definition: Decoder.cpp:209
void destBufferSetNew(std::vector< SourceDestBuffer > &dbufs) override
Definition: Decoder.cpp:199
unsigned int bytesPerWord_
Definition: Decoder.h:95
void inBufferShiftDown()
Definition: Decoder.cpp:297
unsigned int bitsPerWord_
Definition: Decoder.h:94
void dump(int indent=0, std::ostream &os=std::cout) override
Definition: Decoder.cpp:452
FloatPrecision precision_
Definition: Decoder.h:110
BitpackFloatDecoder(unsigned bytestreamNumber, SourceDestBuffer &dbuf, FloatPrecision precision, uint64_t maxRecordCount)
Definition: Decoder.cpp:352
size_t inputProcessAligned(const char *inbuf, const size_t firstBit, const size_t endBit) override
Definition: Decoder.cpp:360
BitpackIntegerDecoder(bool isScaledInteger, unsigned bytestreamNumber, SourceDestBuffer &dbuf, int64_t minimum, int64_t maximum, double scale, double offset, uint64_t maxRecordCount)
Definition: Decoder.cpp:643
size_t inputProcessAligned(const char *inbuf, const size_t firstBit, const size_t endBit) override
Definition: Decoder.cpp:658
void dump(int indent=0, std::ostream &os=std::cout) override
Definition: Decoder.cpp:802
BitpackStringDecoder(unsigned bytestreamNumber, SourceDestBuffer &dbuf, uint64_t maxRecordCount)
Definition: Decoder.cpp:468
size_t inputProcessAligned(const char *inbuf, const size_t firstBit, const size_t endBit) override
Definition: Decoder.cpp:474
uint8_t prefixBytes_[8]
Definition: Decoder.h:126
void dump(int indent=0, std::ostream &os=std::cout) override
Definition: Decoder.cpp:617
uint64_t nBytesStringRead_
Definition: Decoder.h:130
NodeImplSharedPtr getPrototype() const
size_t inputProcess(const char *source, const size_t availableByteCount) override
Definition: Decoder.cpp:836
void destBufferSetNew(std::vector< SourceDestBuffer > &dbufs) override
Definition: Decoder.cpp:826
std::shared_ptr< SourceDestBufferImpl > destBuffer_
Definition: Decoder.h:173
ConstantIntegerDecoder(bool isScaledInteger, unsigned bytestreamNumber, SourceDestBuffer &dbuf, int64_t minimum, double scale, double offset, uint64_t maxRecordCount)
Definition: Decoder.cpp:818
void stateReset() override
Definition: Decoder.cpp:872
void dump(int indent=0, std::ostream &os=std::cout) override
Definition: Decoder.cpp:877
static std::shared_ptr< Decoder > DecoderFactory(unsigned bytestreamNumber, const CompressedVectorNodeImpl *cVector, std::vector< SourceDestBuffer > &dbufs, const ustring &codecPath)
Definition: Decoder.cpp:41
unsigned bytestreamNumber() const
Definition: Decoder.h:47
unsigned int bytestreamNumber_
Definition: Decoder.h:58
Decoder()=delete
int min(int a, int b)
Definition: cutil_math.h:53
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
static const std::string path
Definition: PointCloud.cpp:59
std::string binaryString(uint64_t x)
Definition: Common.h:111
std::shared_ptr< class NodeImpl > NodeImplSharedPtr
Definition: Common.h:190
std::shared_ptr< class ImageFileImpl > ImageFileImplSharedPtr
Definition: Common.h:188
FloatPrecision
The IEEE floating point number precisions supported.
Definition: E57Format.h:71
@ E57_SINGLE
32 bit IEEE floating point number format
Definition: E57Format.h:72
@ E57_ERROR_INTERNAL
An unrecoverable inconsistent internal state was detected.
Definition: E57Exception.h:56
@ E57_ERROR_BAD_PROTOTYPE
bad prototype in CompressedVectorNode
Definition: E57Exception.h:79
std::string ustring
UTF-8 encodeded Unicode string.
Definition: E57Format.h:54
@ E57_INTEGER
IntegerNode class.
Definition: E57Format.h:62
@ E57_SCALED_INTEGER
ScaledIntegerNode class.
Definition: E57Format.h:63
@ E57_FLOAT
FloatNode class.
Definition: E57Format.h:64
@ E57_STRING
StringNode class.
Definition: E57Format.h:65
std::string toString(T x)
Definition: Common.h:80
std::string space(size_t n)
Definition: Common.h:73
std::string hexString(uint64_t x)
Definition: Common.h:87