PolyVox  0.3.0-dev
Open source voxel management library
RLECompressor.inl
Go to the documentation of this file.
1 #include <algorithm>
2 #include <cassert>
3 #include <limits>
4 
5 namespace PolyVox
6 {
7  template<typename ValueType, typename LengthType>
9  {
10  }
11 
12  template<typename ValueType, typename LengthType>
14  {
15  }
16 
17  template<typename ValueType, typename LengthType>
19  {
20  // In the worst case we will have a seperate Run (of length one) for each element of the input data.
21  return uUncompressedInputSize * sizeof(Run);
22  }
23 
24  template<typename ValueType, typename LengthType>
25  uint32_t RLECompressor<ValueType, LengthType>::compress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength)
26  {
27  if(uSrcLength % sizeof(ValueType) != 0)
28  {
29  POLYVOX_THROW(std::length_error, "Source length must be a integer multiple of the ValueType size");
30  }
31 
32  // Lengths provided are in bytes, so convert them to be in terms of our types.
33  uSrcLength /= sizeof(ValueType);
34  uDstLength /= sizeof(Run);
35 
36  // Get data pointers in the appropriate type
37  ValueType* pSrcDataAsType = reinterpret_cast<ValueType*>(pSrcData);
38  Run* pDstDataAsRun = reinterpret_cast<Run*>(pDstData);
39 
40  // Pointers to just past the end of the data
41  ValueType* pSrcDataEnd = pSrcDataAsType + uSrcLength;
42  Run* pDstDataEnd = pDstDataAsRun + uDstLength;
43 
44  //Counter for the output length
45  uint32_t uDstLengthInBytes = 0;
46 
47  // Read the first element of the source and set up the first run based on it.
48  pDstDataAsRun->value = *pSrcDataAsType;
49  pSrcDataAsType++;
50  pDstDataAsRun->length = 1;
51  uDstLengthInBytes += sizeof(Run);
52 
53  //Now process all remaining elements of the source.
54  while(pSrcDataAsType < pSrcDataEnd)
55  {
56  // If the value is the same as the current run (and we have not
57  // reached the maximum run length) then extend the current run.
58  if((*pSrcDataAsType == pDstDataAsRun->value) && (pDstDataAsRun->length < (std::numeric_limits<LengthType>::max)()))
59  {
60  pDstDataAsRun->length++;
61  }
62  // Otherwise we need to start a new Run.
63  else
64  {
65  pDstDataAsRun++;
66 
67  // Check if we have enough space in the destination buffer.
68  if(pDstDataAsRun >= pDstDataEnd)
69  {
70  POLYVOX_THROW(std::runtime_error, "Insufficient space in destination buffer.");
71  }
72 
73  // Create the new run.
74  pDstDataAsRun->value = *pSrcDataAsType;
75  pDstDataAsRun->length = 1;
76  uDstLengthInBytes += sizeof(Run);
77  }
78 
79  pSrcDataAsType++;
80  }
81 
82  return uDstLengthInBytes;
83  }
84 
85  template<typename ValueType, typename LengthType>
86  uint32_t RLECompressor<ValueType, LengthType>::decompress(void* pSrcData, uint32_t uSrcLength, void* pDstData, uint32_t uDstLength)
87  {
88  if(uSrcLength % sizeof(Run) != 0)
89  {
90  POLYVOX_THROW(std::length_error, "Source length must be a integer multiple of the Run size");
91  }
92 
93  // Lengths provided are in bytes, so convert them to be in terms of our types.
94  uSrcLength /= sizeof(Run);
95  uDstLength /= sizeof(ValueType);
96 
97  // Get data pointers in the appropriate type
98  Run* pSrcDataAsRun = reinterpret_cast<Run*>(pSrcData);
99  ValueType* pDstDataAsType = reinterpret_cast<ValueType*>(pDstData);
100 
101  // Pointers to just past the end of the data
102  Run* pSrcDataEnd = pSrcDataAsRun + uSrcLength;
103  ValueType* pDstDataEnd = pDstDataAsType + uDstLength;
104 
105  //Counter for the output length
106  uint32_t uDstLengthInBytes = 0;
107 
108  while(pSrcDataAsRun < pSrcDataEnd)
109  {
110  // Check if we have enough space in the destination buffer.
111  if(pDstDataAsType + pSrcDataAsRun->length > pDstDataEnd)
112  {
113  POLYVOX_THROW(std::runtime_error, "Insufficient space in destination buffer.");
114  }
115 
116  // Write the run into the destination
117  std::fill(pDstDataAsType, pDstDataAsType + pSrcDataAsRun->length, pSrcDataAsRun->value);
118  pDstDataAsType += pSrcDataAsRun->length;
119 
120  uDstLengthInBytes += pSrcDataAsRun->length * sizeof(ValueType);
121  pSrcDataAsRun++;
122  }
123 
124  return uDstLengthInBytes;
125  }
126 }