PCL
Compression.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.7.0
6 // ----------------------------------------------------------------------------
7 // pcl/Compression.h - Released 2024-06-18T15:48:54Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2024 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_Compression_h
53 #define __PCL_Compression_h
54 
56 
57 #include <pcl/Defs.h>
58 #include <pcl/Diagnostics.h>
59 
60 #include <pcl/ByteArray.h>
61 #include <pcl/ParallelProcess.h>
62 #include <pcl/String.h>
63 
64 namespace pcl
65 {
66 
67 // ----------------------------------------------------------------------------
68 
83 class PCL_CLASS Compression : public ParallelProcess
84 {
85 public:
86 
91  struct Subblock
92  {
94  size_type uncompressedSize = 0;
95  uint64 checksum = 0;
96  };
97 
102  struct Performance
103  {
104  float sizeReduction = 0;
105  double throughput = 0;
106  int numberOfThreads = 0;
107  };
108 
113 
133  Compression() = default;
134 
138  Compression( const Compression& ) = default;
139 
143  Compression& operator =( const Compression& ) = default;
144 
148  ~Compression() override
149  {
150  }
151 
155  virtual String AlgorithmName() const = 0;
156 
161  virtual int MinCompressionLevel() const
162  {
163  return 0;
164  }
165 
171  virtual int MaxCompressionLevel() const = 0;
172 
178  virtual int DefaultCompressionLevel() const = 0;
179 
185  int CompressionLevel() const
186  {
187  return m_compressionLevel;
188  }
189 
199  void SetCompressionLevel( int level )
200  {
201  m_compressionLevel = Range( level, 0, MaxCompressionLevel() );
202  }
203 
213  {
214  SetCompressionLevel( 0 );
215  }
216 
223  bool ByteShufflingEnabled() const
224  {
225  return m_byteShuffle;
226  }
227 
241  void EnableByteShuffling( bool enable = true )
242  {
243  m_byteShuffle = enable;
244  }
245 
251  void DisableByteShuffling( bool disable = true )
252  {
253  EnableByteShuffling( !disable );
254  }
255 
264  {
265  return m_itemSize;
266  }
267 
274  void SetItemSize( size_type itemSize )
275  {
276  m_itemSize = pcl::Max( size_type( 1 ), itemSize );
277  }
278 
285  {
286  return m_subblockSize;
287  }
288 
300  {
301  m_subblockSize = Range( size, size_type( 0 ), MaxBlockSize() );
302  }
303 
310  bool ChecksumsEnabled() const
311  {
312  return m_checksums;
313  }
314 
329  void EnableChecksums( bool enable = true )
330  {
331  m_checksums = enable;
332  }
333 
339  void DisableChecksums( bool disable = true )
340  {
341  EnableChecksums( !disable );
342  }
343 
365  subblock_list Compress( const void* data, size_type size, Performance* perf = nullptr ) const;
366 
391  template <class C>
392  subblock_list Compress( const C& data, Performance* perf = nullptr ) const
393  {
394  return Compress( data.Begin(), data.Size(), perf );
395  }
396 
425  size_type Uncompress( void* data, size_type maxSize,
426  const subblock_list& subblocks, Performance* perf = nullptr ) const;
427 
447  ByteArray Uncompress( const subblock_list& subblocks, Performance* perf = nullptr ) const
448  {
449  size_type uncompressedSize = 0;
450  for ( const Subblock& subblock : subblocks )
451  uncompressedSize += subblock.uncompressedSize;
452  ByteArray data( uncompressedSize );
453  (void)Uncompress( data.Begin(), uncompressedSize, subblocks, perf );
454  return data;
455  }
456 
464  ByteArray Uncompress( const ByteArray& compressedData,
465  size_type uncompressedSize, Performance* perf = nullptr ) const
466  {
467  Subblock subblock;
468  subblock.compressedData = compressedData;
469  subblock.uncompressedSize = uncompressedSize;
470  return Uncompress( subblock_list() << subblock, perf );
471  }
472 
473 private:
474 
475  int m_compressionLevel = 0; // 0 = use codec's default
476  size_type m_subblockSize = 0; // 0 = use largest possible subblocks
477  size_type m_itemSize = 1;
478  bool m_byteShuffle = true;
479  bool m_checksums = true;
480 
481 protected:
482 
487  virtual size_type MinBlockSize() const = 0;
488 
493  virtual size_type MaxBlockSize() const = 0;
494 
499  virtual size_type MaxCompressedBlockSize( size_type size ) const = 0;
500 
509  virtual size_type CompressBlock( void* outputData, size_type outputSize,
510  const void* inputData, size_type inputSize, int level ) const = 0;
511 
519  virtual size_type UncompressBlock( void* outputData, size_type outputSize,
520  const void* inputData, size_type inputSize ) const = 0;
521 
527  static ByteArray Shuffle( const uint8* data, size_type size, size_type itemSize )
528  {
529  ByteArray shuffled( size );
530  if ( size > 0 && data != nullptr )
531  {
532  size_type numberOfItems = size / itemSize;
533  ByteArray::iterator s = shuffled.Begin();
534  for ( size_type j = 0; j < itemSize; ++j )
535  {
536  ByteArray::const_iterator u = data + j;
537  for ( size_type i = 0; i < numberOfItems; ++i, ++s, u += itemSize )
538  *s = *u;
539  }
540  ::memcpy( s, data + numberOfItems*itemSize, size % itemSize );
541  }
542  return shuffled;
543  }
544 
550  static ByteArray Unshuffle( const uint8* data, size_type size, size_type itemSize )
551  {
552  ByteArray unshuffled( size );
553  if ( size > 0 && data != nullptr )
554  {
555  size_type numberOfItems = size / itemSize;
556  ByteArray::const_iterator s = data;
557  for ( size_type j = 0; j < itemSize; ++j )
558  {
559  ByteArray::iterator u = unshuffled.At( j );
560  for ( size_type i = 0; i < numberOfItems; ++i, ++s, u += itemSize )
561  *u = *s;
562  }
563  ::memcpy( unshuffled.At( numberOfItems*itemSize ), s, size % itemSize );
564  }
565  return unshuffled;
566  }
567 
573  static void InPlaceUnshuffle( uint8* data, size_type size, size_type itemSize )
574  {
575  if ( size > 0 && data != nullptr )
576  {
577  const ByteArray shuffled( data, data+size );
578  size_type numberOfItems = size / itemSize;
579  ByteArray::const_iterator s = shuffled.Begin();
580  for ( size_type j = 0; j < itemSize; ++j )
581  {
582  ByteArray::iterator u = data + j;
583  for ( size_type i = 0; i < numberOfItems; ++i, ++s, u += itemSize )
584  *u = *s;
585  }
586  }
587  }
588 
593  void Throw( const String& errorMessage ) const;
594 
595  friend class PCL_CompressionEngine;
596  friend class PCL_DecompressionEngine;
597 };
598 
599 // ----------------------------------------------------------------------------
600 
624 class PCL_CLASS ZLibCompression : public Compression
625 {
626 public:
627 
631  String AlgorithmName() const override
632  {
633  return "ZLib";
634  }
635 
638  int MaxCompressionLevel() const override;
639 
642  int DefaultCompressionLevel() const override;
643 
644 
645 private:
646 
649  size_type MinBlockSize() const override;
650 
653  size_type MaxBlockSize() const override;
654 
657  size_type MaxCompressedBlockSize( size_type size ) const override;
658 
661  size_type CompressBlock( void* outputData, size_type outputSize,
662  const void* inputData, size_type inputSize, int level ) const override;
663 
666  size_type UncompressBlock( void* outputData, size_type outputSize,
667  const void* inputData, size_type inputSize ) const override;
668 };
669 
670 // ----------------------------------------------------------------------------
671 
694 class PCL_CLASS LZ4Compression : public Compression
695 {
696 public:
697 
701  String AlgorithmName() const override
702  {
703  return "LZ4";
704  }
705 
708  int MaxCompressionLevel() const override;
709 
712  int DefaultCompressionLevel() const override;
713 
714 
715 private:
716 
719  size_type MinBlockSize() const override;
720 
723  size_type MaxBlockSize() const override;
724 
727  size_type MaxCompressedBlockSize( size_type size ) const override;
728 
731  size_type CompressBlock( void* outputData, size_type outputSize,
732  const void* inputData, size_type inputSize, int level ) const override;
733 
736  size_type UncompressBlock( void* outputData, size_type outputSize,
737  const void* inputData, size_type inputSize ) const override;
738 };
739 
740 // ----------------------------------------------------------------------------
741 
765 class PCL_CLASS LZ4HCCompression : public Compression
766 {
767 public:
768 
772  String AlgorithmName() const override
773  {
774  return "LZ4-HC";
775  }
776 
779  int MaxCompressionLevel() const override;
780 
783  int DefaultCompressionLevel() const override;
784 
785 
786 private:
787 
790  size_type MinBlockSize() const override;
791 
794  size_type MaxBlockSize() const override;
795 
798  size_type MaxCompressedBlockSize( size_type size ) const override;
799 
802  size_type CompressBlock( void* outputData, size_type outputSize,
803  const void* inputData, size_type inputSize, int level ) const override;
804 
807  size_type UncompressBlock( void* outputData, size_type outputSize,
808  const void* inputData, size_type inputSize ) const override;
809 };
810 
811 // ----------------------------------------------------------------------------
812 
837 class PCL_CLASS ZstdCompression : public Compression
838 {
839 public:
840 
844  String AlgorithmName() const override
845  {
846  return "Zstd";
847  }
848 
853  int MinCompressionLevel() const override;
854 
857  int MaxCompressionLevel() const override;
858 
861  int DefaultCompressionLevel() const override;
862 
863 private:
864 
867  size_type MinBlockSize() const override;
868 
871  size_type MaxBlockSize() const override;
872 
875  size_type MaxCompressedBlockSize( size_type size ) const override;
876 
879  size_type CompressBlock( void* outputData, size_type outputSize,
880  const void* inputData, size_type inputSize, int level ) const override;
881 
884  size_type UncompressBlock( void* outputData, size_type outputSize,
885  const void* inputData, size_type inputSize ) const override;
886 };
887 
888 // ----------------------------------------------------------------------------
889 
890 } // pcl
891 
892 #endif // __PCL_Compression_h
893 
894 // ----------------------------------------------------------------------------
895 // EOF pcl/Compression.h - Released 2024-06-18T15:48:54Z
iterator Begin()
Definition: Array.h:426
iterator At(size_type i)
Definition: Array.h:355
uint8 * iterator
Definition: Array.h:113
const uint8 * const_iterator
Definition: Array.h:117
Abstract base class of data compression algorithm implementations.
Definition: Compression.h:84
virtual size_type MaxBlockSize() const =0
virtual size_type CompressBlock(void *outputData, size_type outputSize, const void *inputData, size_type inputSize, int level) const =0
size_type SubblockSize() const
Definition: Compression.h:284
void SetCompressionLevel(int level)
Definition: Compression.h:199
static ByteArray Unshuffle(const uint8 *data, size_type size, size_type itemSize)
Definition: Compression.h:550
void SetSubblockSize(size_type size)
Definition: Compression.h:299
bool ByteShufflingEnabled() const
Definition: Compression.h:223
void EnableChecksums(bool enable=true)
Definition: Compression.h:329
virtual size_type MinBlockSize() const =0
static ByteArray Shuffle(const uint8 *data, size_type size, size_type itemSize)
Definition: Compression.h:527
void SetDefaultCompressionLevel()
Definition: Compression.h:212
Compression(const Compression &)=default
virtual int MaxCompressionLevel() const =0
ByteArray Uncompress(const ByteArray &compressedData, size_type uncompressedSize, Performance *perf=nullptr) const
Definition: Compression.h:464
void EnableByteShuffling(bool enable=true)
Definition: Compression.h:241
virtual size_type UncompressBlock(void *outputData, size_type outputSize, const void *inputData, size_type inputSize) const =0
void Throw(const String &errorMessage) const
Compression()=default
bool ChecksumsEnabled() const
Definition: Compression.h:310
void SetItemSize(size_type itemSize)
Definition: Compression.h:274
virtual int DefaultCompressionLevel() const =0
static void InPlaceUnshuffle(uint8 *data, size_type size, size_type itemSize)
Definition: Compression.h:573
subblock_list Compress(const void *data, size_type size, Performance *perf=nullptr) const
virtual size_type MaxCompressedBlockSize(size_type size) const =0
size_type ItemSize() const
Definition: Compression.h:263
size_type Uncompress(void *data, size_type maxSize, const subblock_list &subblocks, Performance *perf=nullptr) const
virtual String AlgorithmName() const =0
ByteArray Uncompress(const subblock_list &subblocks, Performance *perf=nullptr) const
Definition: Compression.h:447
virtual int MinCompressionLevel() const
Definition: Compression.h:161
int CompressionLevel() const
Definition: Compression.h:185
subblock_list Compress(const C &data, Performance *perf=nullptr) const
Definition: Compression.h:392
~Compression() override
Definition: Compression.h:148
void DisableChecksums(bool disable=true)
Definition: Compression.h:339
void DisableByteShuffling(bool disable=true)
Definition: Compression.h:251
Implementation of the LZ4 compression algorithm.
Definition: Compression.h:695
int DefaultCompressionLevel() const override
String AlgorithmName() const override
Definition: Compression.h:701
int MaxCompressionLevel() const override
Implementation of the LZ4-HC compression algorithm.
Definition: Compression.h:766
int MaxCompressionLevel() const override
String AlgorithmName() const override
Definition: Compression.h:772
int DefaultCompressionLevel() const override
A process using multiple concurrent execution threads.
Unicode (UTF-16) string.
Definition: String.h:8113
Implementation of the ZLib/Deflate compression algorithm.
Definition: Compression.h:625
int MaxCompressionLevel() const override
int DefaultCompressionLevel() const override
String AlgorithmName() const override
Definition: Compression.h:631
Implementation of the Zstandard compression algorithm.
Definition: Compression.h:838
int MinCompressionLevel() const override
String AlgorithmName() const override
Definition: Compression.h:844
int DefaultCompressionLevel() const override
int MaxCompressionLevel() const override
unsigned long long uint64
Definition: Defs.h:682
unsigned char uint8
Definition: Defs.h:642
size_t size_type
Definition: Defs.h:609
constexpr const T & Range(const T &x, const T &a, const T &b) noexcept
Definition: Utility.h:190
constexpr const T & Max(const T &a, const T &b) noexcept
Definition: Utility.h:119
PCL root namespace.
Definition: AbstractImage.h:77
Compression/decompression performance measurements.
Definition: Compression.h:103
Compression subblock data.
Definition: Compression.h:92
ByteArray compressedData
Sub-block compressed data.
Definition: Compression.h:93
size_type uncompressedSize
size in bytes of the uncompressed subblock.
Definition: Compression.h:94