OpenVDB  3.0.0
Compression.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2014 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 
31 #ifndef OPENVDB_IO_COMPRESSION_HAS_BEEN_INCLUDED
32 #define OPENVDB_IO_COMPRESSION_HAS_BEEN_INCLUDED
33 
34 #include <openvdb/Types.h>
35 #include <openvdb/math/Math.h> // for negative()
36 #include "io.h" // for getDataCompression(), etc.
37 #include <boost/scoped_array.hpp>
38 #include <algorithm>
39 #include <iostream>
40 #include <string>
41 #include <vector>
42 
43 
44 namespace openvdb {
46 namespace OPENVDB_VERSION_NAME {
47 namespace io {
48 
77 enum {
79  COMPRESS_ZIP = 0x1,
82 };
83 
85 OPENVDB_API std::string compressionToString(uint32_t flags);
86 
87 
89 
90 
93 enum {
94  /*0*/ NO_MASK_OR_INACTIVE_VALS, // no inactive vals, or all inactive vals are +background
95  /*1*/ NO_MASK_AND_MINUS_BG, // all inactive vals are -background
96  /*2*/ NO_MASK_AND_ONE_INACTIVE_VAL, // all inactive vals have the same non-background val
97  /*3*/ MASK_AND_NO_INACTIVE_VALS, // mask selects between -background and +background
98  /*4*/ MASK_AND_ONE_INACTIVE_VAL, // mask selects between backgd and one other inactive val
99  /*5*/ MASK_AND_TWO_INACTIVE_VALS, // mask selects between two non-background inactive vals
100  /*6*/ NO_MASK_AND_ALL_VALS // > 2 inactive vals, so no mask compression at all
101 };
102 
103 
105 
106 
109 template<typename T>
110 struct RealToHalf {
111  enum { isReal = false }; // unless otherwise specified, type T is not a floating-point type
112  typedef T HalfT; // type T's half float analogue is T itself
113 };
114 template<> struct RealToHalf<float> { enum { isReal = true }; typedef half HalfT; };
115 template<> struct RealToHalf<double> { enum { isReal = true }; typedef half HalfT; };
116 template<> struct RealToHalf<Vec2s> { enum { isReal = true }; typedef Vec2H HalfT; };
117 template<> struct RealToHalf<Vec2d> { enum { isReal = true }; typedef Vec2H HalfT; };
118 template<> struct RealToHalf<Vec3s> { enum { isReal = true }; typedef Vec3H HalfT; };
119 template<> struct RealToHalf<Vec3d> { enum { isReal = true }; typedef Vec3H HalfT; };
120 
121 
123 template<typename T>
124 inline T
125 truncateRealToHalf(const T& val)
126 {
127  return T(typename RealToHalf<T>::HalfT(val));
128 }
129 
130 
132 
133 
134 OPENVDB_API void zipToStream(std::ostream&, const char* data, size_t numBytes);
135 OPENVDB_API void unzipFromStream(std::istream&, char* data, size_t numBytes);
136 OPENVDB_API void bloscToStream(std::ostream&, const char* data, size_t valSize, size_t numVals);
137 OPENVDB_API void bloscFromStream(std::istream&, char* data, size_t numBytes);
138 
149 template<typename T>
150 inline void
151 readData(std::istream& is, T* data, Index count, uint32_t compression)
152 {
153  if (compression & COMPRESS_BLOSC) {
154 #ifdef OPENVDB_USE_BLOSC
155  bloscFromStream(is, reinterpret_cast<char*>(data), sizeof(T) * count);
156 #else
157  OPENVDB_THROW(IoError, "Blosc decoding is not supported");
158 #endif
159  } else if (compression & COMPRESS_ZIP) {
160  unzipFromStream(is, reinterpret_cast<char*>(data), sizeof(T) * count);
161  } else {
162  is.read(reinterpret_cast<char*>(data), sizeof(T) * count);
163  }
164 }
165 
167 template<>
168 inline void
169 readData<std::string>(std::istream& is, std::string* data, Index count, uint32_t /*compression*/)
170 {
171  for (Index i = 0; i < count; ++i) {
172  size_t len = 0;
173  is >> len;
174  //data[i].resize(len);
175  //is.read(&(data[i][0]), len);
176 
177  std::string buffer(len+1, ' ');
178  is.read(&buffer[0], len+1 );
179  data[i].assign(buffer, 0, len);
180  }
181 }
182 
187 template<bool IsReal, typename T> struct HalfReader;
189 template<typename T>
190 struct HalfReader</*IsReal=*/false, T> {
191  static inline void read(std::istream& is, T* data, Index count, uint32_t compression) {
192  readData(is, data, count, compression);
193  }
194 };
196 template<typename T>
197 struct HalfReader</*IsReal=*/true, T> {
198  typedef typename RealToHalf<T>::HalfT HalfT;
199  static inline void read(std::istream& is, T* data, Index count, uint32_t compression) {
200  if (count < 1) return;
201  std::vector<HalfT> halfData(count); // temp buffer into which to read half float values
202  readData<HalfT>(is, reinterpret_cast<HalfT*>(&halfData[0]), count, compression);
203  // Copy half float values from the temporary buffer to the full float output array.
204  std::copy(halfData.begin(), halfData.end(), data);
205  }
206 };
207 
208 
219 template<typename T>
220 inline void
221 writeData(std::ostream &os, const T *data, Index count, uint32_t compression)
222 {
223  if (compression & COMPRESS_BLOSC) {
224 #ifdef OPENVDB_USE_BLOSC
225  bloscToStream(os, reinterpret_cast<const char*>(data), sizeof(T), count);
226 #else
227  OPENVDB_THROW(IoError, "Blosc encoding is not supported");
228 #endif
229  } else if (compression & COMPRESS_ZIP) {
230  zipToStream(os, reinterpret_cast<const char*>(data), sizeof(T) * count);
231  } else {
232  os.write(reinterpret_cast<const char*>(data), sizeof(T) * count);
233  }
234 }
235 
237 template<>
238 inline void
239 writeData<std::string>(std::ostream& os, const std::string* data, Index count,
240  uint32_t /*compression*/)
241 {
242  for (Index i = 0; i < count; ++i) {
243  const size_t len = data[i].size();
244  os << len;
245  os.write(data[i].c_str(), len+1);
246  //os.write(&(data[i][0]), len );
247  }
248 }
249 
254 template<bool IsReal, typename T> struct HalfWriter;
256 template<typename T>
257 struct HalfWriter</*IsReal=*/false, T> {
258  static inline void write(std::ostream& os, const T* data, Index count, uint32_t compression) {
259  writeData(os, data, count, compression);
260  }
261 };
263 template<typename T>
264 struct HalfWriter</*IsReal=*/true, T> {
265  typedef typename RealToHalf<T>::HalfT HalfT;
266  static inline void write(std::ostream& os, const T* data, Index count, uint32_t compression) {
267  if (count < 1) return;
268  // Convert full float values to half float, then output the half float array.
269  std::vector<HalfT> halfData(count);
270  for (Index i = 0; i < count; ++i) halfData[i] = static_cast<HalfT>(data[i]);
271  writeData<HalfT>(os, reinterpret_cast<const HalfT*>(&halfData[0]), count, compression);
272  }
273 };
274 #ifdef _MSC_VER
275 template<>
277 struct HalfWriter</*IsReal=*/true, double> {
278  typedef RealToHalf<double>::HalfT HalfT;
279  static inline void write(std::ostream& os, const double* data, Index count,
280  uint32_t compression)
281  {
282  if (count < 1) return;
283  // Convert full float values to half float, then output the half float array.
284  std::vector<HalfT> halfData(count);
285  for (Index i = 0; i < count; ++i) halfData[i] = float(data[i]);
286  writeData<HalfT>(os, reinterpret_cast<const HalfT*>(&halfData[0]), count, compression);
287  }
288 };
289 #endif // _MSC_VER
290 
291 
293 
294 
307 template<typename ValueT, typename MaskT>
308 inline void
309 readCompressedValues(std::istream& is, ValueT* destBuf, Index destCount,
310  const MaskT& valueMask, bool fromHalf)
311 {
312  // Get the stream's compression settings.
313  const uint32_t compression = getDataCompression(is);
314  const bool maskCompressed = compression & COMPRESS_ACTIVE_MASK;
315 
316  int8_t metadata = NO_MASK_AND_ALL_VALS;
318  // Read the flag that specifies what, if any, additional metadata
319  // (selection mask and/or inactive value(s)) is saved.
320  is.read(reinterpret_cast<char*>(&metadata), /*bytes=*/1);
321  }
322 
323  ValueT background = zeroVal<ValueT>();
324  if (const void* bgPtr = getGridBackgroundValuePtr(is)) {
325  background = *static_cast<const ValueT*>(bgPtr);
326  }
327  ValueT inactiveVal1 = background;
328  ValueT inactiveVal0 =
329  ((metadata == NO_MASK_OR_INACTIVE_VALS) ? background : math::negative(background));
330 
331  if (metadata == NO_MASK_AND_ONE_INACTIVE_VAL ||
332  metadata == MASK_AND_ONE_INACTIVE_VAL ||
333  metadata == MASK_AND_TWO_INACTIVE_VALS)
334  {
335  // Read one of at most two distinct inactive values.
336  is.read(reinterpret_cast<char*>(&inactiveVal0), sizeof(ValueT));
337  if (metadata == MASK_AND_TWO_INACTIVE_VALS) {
338  // Read the second of two distinct inactive values.
339  is.read(reinterpret_cast<char*>(&inactiveVal1), sizeof(ValueT));
340  }
341  }
342 
343  MaskT selectionMask;
344  if (metadata == MASK_AND_NO_INACTIVE_VALS ||
345  metadata == MASK_AND_ONE_INACTIVE_VAL ||
346  metadata == MASK_AND_TWO_INACTIVE_VALS)
347  {
348  // For use in mask compression (only), read the bitmask that selects
349  // between two distinct inactive values.
350  selectionMask.load(is);
351  }
352 
353  ValueT* tempBuf = destBuf;
354  boost::scoped_array<ValueT> scopedTempBuf;
355 
356  Index tempCount = destCount;
357  if (maskCompressed && metadata != NO_MASK_AND_ALL_VALS
359  {
360  tempCount = valueMask.countOn();
361  if (tempCount != destCount) {
362  // If this node has inactive voxels, allocate a temporary buffer
363  // into which to read just the active values.
364  scopedTempBuf.reset(new ValueT[tempCount]);
365  tempBuf = scopedTempBuf.get();
366  }
367  }
368 
369  // Read in the buffer.
370  if (fromHalf) {
371  HalfReader<RealToHalf<ValueT>::isReal, ValueT>::read(is, tempBuf, tempCount, compression);
372  } else {
373  readData<ValueT>(is, tempBuf, tempCount, compression);
374  }
375 
376  // If mask compression is enabled and the number of active values read into
377  // the temp buffer is smaller than the size of the destination buffer,
378  // then there are missing (inactive) values.
379  if (maskCompressed && tempCount != destCount) {
380  // Restore inactive values, using the background value and, if available,
381  // the inside/outside mask. (For fog volumes, the destination buffer is assumed
382  // to be initialized to background value zero, so inactive values can be ignored.)
383  for (Index destIdx = 0, tempIdx = 0; destIdx < MaskT::SIZE; ++destIdx) {
384  if (valueMask.isOn(destIdx)) {
385  // Copy a saved active value into this node's buffer.
386  destBuf[destIdx] = tempBuf[tempIdx];
387  ++tempIdx;
388  } else {
389  // Reconstruct an unsaved inactive value and copy it into this node's buffer.
390  destBuf[destIdx] = (selectionMask.isOn(destIdx) ? inactiveVal1 : inactiveVal0);
391  }
392  }
393  }
394 }
395 
396 
409 template<typename ValueT, typename MaskT>
410 inline void
411 writeCompressedValues(std::ostream& os, ValueT* srcBuf, Index srcCount,
412  const MaskT& valueMask, const MaskT& childMask, bool toHalf)
413 {
414  struct Local {
415  // Comparison function for values
416  static inline bool eq(const ValueT& a, const ValueT& b) {
417  return math::isExactlyEqual(a, b);
418  }
419  };
420 
421  // Get the stream's compression settings.
422  const uint32_t compress = getDataCompression(os);
423  const bool maskCompress = compress & COMPRESS_ACTIVE_MASK;
424 
425  Index tempCount = srcCount;
426  ValueT* tempBuf = srcBuf;
427  boost::scoped_array<ValueT> scopedTempBuf;
428 
429  int8_t metadata = NO_MASK_AND_ALL_VALS;
430 
431  if (!maskCompress) {
432  os.write(reinterpret_cast<const char*>(&metadata), /*bytes=*/1);
433  } else {
434  // A valid level set's inactive values are either +background (outside)
435  // or -background (inside), and a fog volume's inactive values are all zero.
436  // Rather than write out all of these values, we can store just the active values
437  // (given that the value mask specifies their positions) and, if necessary,
438  // an inside/outside bitmask.
439 
440  const ValueT zero = zeroVal<ValueT>();
441  ValueT background = zero;
442  if (const void* bgPtr = getGridBackgroundValuePtr(os)) {
443  background = *static_cast<const ValueT*>(bgPtr);
444  }
445 
447  ValueT inactiveVal[2] = { background, background };
448  int numUniqueInactiveVals = 0;
449  for (typename MaskT::OffIterator it = valueMask.beginOff();
450  numUniqueInactiveVals < 3 && it; ++it)
451  {
452  const Index32 idx = it.pos();
453 
454  // Skip inactive values that are actually child node pointers.
455  if (childMask.isOn(idx)) continue;
456 
457  const ValueT& val = srcBuf[idx];
458  const bool unique = !(
459  (numUniqueInactiveVals > 0 && Local::eq(val, inactiveVal[0])) ||
460  (numUniqueInactiveVals > 1 && Local::eq(val, inactiveVal[1]))
461  );
462  if (unique) {
463  if (numUniqueInactiveVals < 2) inactiveVal[numUniqueInactiveVals] = val;
464  ++numUniqueInactiveVals;
465  }
466  }
467 
468  metadata = NO_MASK_OR_INACTIVE_VALS;
469 
470  if (numUniqueInactiveVals == 1) {
471  if (!Local::eq(inactiveVal[0], background)) {
472  if (Local::eq(inactiveVal[0], math::negative(background))) {
473  metadata = NO_MASK_AND_MINUS_BG;
474  } else {
475  metadata = NO_MASK_AND_ONE_INACTIVE_VAL;
476  }
477  }
478  } else if (numUniqueInactiveVals == 2) {
479  metadata = NO_MASK_OR_INACTIVE_VALS;
480  if (!Local::eq(inactiveVal[0], background) && !Local::eq(inactiveVal[1], background)) {
481  // If neither inactive value is equal to the background, both values
482  // need to be saved, along with a mask that selects between them.
483  metadata = MASK_AND_TWO_INACTIVE_VALS;
484 
485  } else if (Local::eq(inactiveVal[1], background)) {
486  if (Local::eq(inactiveVal[0], math::negative(background))) {
487  // If the second inactive value is equal to the background and
488  // the first is equal to -background, neither value needs to be saved,
489  // but save a mask that selects between -background and +background.
490  metadata = MASK_AND_NO_INACTIVE_VALS;
491  } else {
492  // If the second inactive value is equal to the background, only
493  // the first value needs to be saved, along with a mask that selects
494  // between it and the background.
495  metadata = MASK_AND_ONE_INACTIVE_VAL;
496  }
497  } else if (Local::eq(inactiveVal[0], background)) {
498  if (Local::eq(inactiveVal[1], math::negative(background))) {
499  // If the first inactive value is equal to the background and
500  // the second is equal to -background, neither value needs to be saved,
501  // but save a mask that selects between -background and +background.
502  metadata = MASK_AND_NO_INACTIVE_VALS;
503  std::swap(inactiveVal[0], inactiveVal[1]);
504  } else {
505  // If the first inactive value is equal to the background, swap it
506  // with the second value and save only that value, along with a mask
507  // that selects between it and the background.
508  std::swap(inactiveVal[0], inactiveVal[1]);
509  metadata = MASK_AND_ONE_INACTIVE_VAL;
510  }
511  }
512  } else if (numUniqueInactiveVals > 2) {
513  metadata = NO_MASK_AND_ALL_VALS;
514  }
515 
516  os.write(reinterpret_cast<const char*>(&metadata), /*bytes=*/1);
517 
518  if (metadata == NO_MASK_AND_ONE_INACTIVE_VAL ||
519  metadata == MASK_AND_ONE_INACTIVE_VAL ||
520  metadata == MASK_AND_TWO_INACTIVE_VALS)
521  {
522  if (!toHalf) {
523  // Write one of at most two distinct inactive values.
524  os.write(reinterpret_cast<const char*>(&inactiveVal[0]), sizeof(ValueT));
525  if (metadata == MASK_AND_TWO_INACTIVE_VALS) {
526  // Write the second of two distinct inactive values.
527  os.write(reinterpret_cast<const char*>(&inactiveVal[1]), sizeof(ValueT));
528  }
529  } else {
530  // Write one of at most two distinct inactive values.
531  ValueT truncatedVal = static_cast<ValueT>(truncateRealToHalf(inactiveVal[0]));
532  os.write(reinterpret_cast<const char*>(&truncatedVal), sizeof(ValueT));
533  if (metadata == MASK_AND_TWO_INACTIVE_VALS) {
534  // Write the second of two distinct inactive values.
535  truncatedVal = truncateRealToHalf(inactiveVal[1]);
536  os.write(reinterpret_cast<const char*>(&truncatedVal), sizeof(ValueT));
537  }
538  }
539  }
540 
541  if (metadata == NO_MASK_AND_ALL_VALS) {
542  // If there are more than two unique inactive values, the entire input buffer
543  // needs to be saved (both active and inactive values).
546  } else {
547  // Create a new array to hold just the active values.
548  scopedTempBuf.reset(new ValueT[srcCount]);
549  tempBuf = scopedTempBuf.get();
550 
551  if (metadata == NO_MASK_OR_INACTIVE_VALS ||
552  metadata == NO_MASK_AND_MINUS_BG ||
553  metadata == NO_MASK_AND_ONE_INACTIVE_VAL)
554  {
555  // Copy active values to the contiguous array.
556  tempCount = 0;
557  for (typename MaskT::OnIterator it = valueMask.beginOn(); it; ++it, ++tempCount) {
558  tempBuf[tempCount] = srcBuf[it.pos()];
559  }
560  } else {
561  // Copy active values to a new, contiguous array and populate a bitmask
562  // that selects between two distinct inactive values.
563  MaskT selectionMask;
564  tempCount = 0;
565  for (Index srcIdx = 0; srcIdx < srcCount; ++srcIdx) {
566  if (valueMask.isOn(srcIdx)) { // active value
567  tempBuf[tempCount] = srcBuf[srcIdx];
568  ++tempCount;
569  } else { // inactive value
570  if (Local::eq(srcBuf[srcIdx], inactiveVal[1])) {
571  selectionMask.setOn(srcIdx); // inactive value 1
572  } // else inactive value 0
573  }
574  }
575  assert(tempCount == valueMask.countOn());
576 
577  // Write out the mask that selects between two inactive values.
578  selectionMask.save(os);
579  }
580  }
581  }
582 
583  // Write out the buffer.
584  if (toHalf) {
585  HalfWriter<RealToHalf<ValueT>::isReal, ValueT>::write(os, tempBuf, tempCount, compress);
586  } else {
587  writeData(os, tempBuf, tempCount, compress);
588  }
589 }
590 
591 } // namespace io
592 } // namespace OPENVDB_VERSION_NAME
593 } // namespace openvdb
594 
595 #endif // OPENVDB_IO_COMPRESSION_HAS_BEEN_INCLUDED
596 
597 // Copyright (c) 2012-2014 DreamWorks Animation LLC
598 // All rights reserved. This software is distributed under the
599 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
#define OPENVDB_API
Helper macros for defining library symbol visibility.
Definition: Platform.h:187
T truncateRealToHalf(const T &val)
Return the given value truncated to 16-bit float precision.
Definition: Compression.h:125
Definition: Mat.h:146
OPENVDB_API void zipToStream(std::ostream &, const char *data, size_t numBytes)
half HalfT
Definition: Compression.h:114
OPENVDB_API uint32_t getDataCompression(std::ios_base &)
Return a bitwise OR of compression option flags (COMPRESS_ZIP, COMPRESS_ACTIVE_MASK, etc.) specifying whether and how input data is compressed or output data should be compressed.
Definition: Compression.h:81
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
void writeData(std::ostream &os, const T *data, Index count, uint32_t compression)
Definition: Compression.h:221
static void read(std::istream &is, T *data, Index count, uint32_t compression)
Definition: Compression.h:199
static void write(std::ostream &os, const T *data, Index count, uint32_t compression)
Definition: Compression.h:258
void readData(std::istream &is, T *data, Index count, uint32_t compression)
Read data from a stream.
Definition: Compression.h:151
static void read(std::istream &is, T *data, Index count, uint32_t compression)
Definition: Compression.h:191
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
Definition: Compression.h:411
#define OPENVDB_VERSION_NAME
Definition: version.h:43
Definition: Compression.h:100
OPENVDB_API void unzipFromStream(std::istream &, char *data, size_t numBytes)
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
Definition: Compression.h:95
Index32 Index
Definition: Types.h:59
OPENVDB_API void bloscFromStream(std::istream &, char *data, size_t numBytes)
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition: Compression.h:309
Definition: Exceptions.h:39
Definition: Vec2.h:48
Definition: Compression.h:79
static void write(std::ostream &os, const T *data, Index count, uint32_t compression)
Definition: Compression.h:266
Vec3< double > Vec3d
Definition: Vec3.h:629
T HalfT
Definition: Compression.h:112
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:107
OPENVDB_API const void * getGridBackgroundValuePtr(std::ios_base &)
Return a pointer to the background value of the grid currently being read from or written to the give...
Definition: Exceptions.h:81
Definition: Compression.h:78
Definition: Compression.h:254
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:391
Vec2< float > Vec2s
Definition: Vec2.h:520
OPENVDB_API void bloscToStream(std::ostream &, const char *data, size_t valSize, size_t numVals)
RealToHalf< T >::HalfT HalfT
Definition: Compression.h:198
uint32_t Index32
Definition: Types.h:57
RealToHalf< T >::HalfT HalfT
Definition: Compression.h:265
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
Vec3< float > Vec3s
Definition: Vec3.h:628
Definition: Compression.h:80
RealToHalf and its specializations define a mapping from floating-point data types to analogous half ...
Definition: Compression.h:110
Vec2< double > Vec2d
Definition: Vec2.h:521
OPENVDB_API std::string compressionToString(uint32_t flags)
Return a string describing the given compression flags.
Definition: Compression.h:187
half HalfT
Definition: Compression.h:115