31 #ifndef OPENVDB_IO_COMPRESSION_HAS_BEEN_INCLUDED
32 #define OPENVDB_IO_COMPRESSION_HAS_BEEN_INCLUDED
106 template <
typename ValueT,
typename MaskT>
110 static inline bool eq(
const ValueT& a,
const ValueT& b) {
115 const MaskT& valueMask,
const MaskT& childMask,
116 const ValueT* srcBuf,
const ValueT& background)
119 inactiveVal[0] = inactiveVal[1] = background;
120 int numUniqueInactiveVals = 0;
121 for (
typename MaskT::OffIterator it = valueMask.beginOff();
122 numUniqueInactiveVals < 3 && it; ++it)
127 if (childMask.isOn(idx))
continue;
129 const ValueT& val = srcBuf[idx];
130 const bool unique = !(
131 (numUniqueInactiveVals > 0 && MaskCompress::eq(val, inactiveVal[0])) ||
132 (numUniqueInactiveVals > 1 && MaskCompress::eq(val, inactiveVal[1]))
135 if (numUniqueInactiveVals < 2) inactiveVal[numUniqueInactiveVals] = val;
136 ++numUniqueInactiveVals;
142 if (numUniqueInactiveVals == 1) {
143 if (!MaskCompress::eq(inactiveVal[0], background)) {
144 if (MaskCompress::eq(inactiveVal[0],
math::negative(background))) {
150 }
else if (numUniqueInactiveVals == 2) {
152 if (!MaskCompress::eq(inactiveVal[0], background) && !MaskCompress::eq(inactiveVal[1], background)) {
157 }
else if (MaskCompress::eq(inactiveVal[1], background)) {
158 if (MaskCompress::eq(inactiveVal[0],
math::negative(background))) {
169 }
else if (MaskCompress::eq(inactiveVal[0], background)) {
170 if (MaskCompress::eq(inactiveVal[1],
math::negative(background))) {
175 std::swap(inactiveVal[0], inactiveVal[1]);
180 std::swap(inactiveVal[0], inactiveVal[1]);
184 }
else if (numUniqueInactiveVals > 2) {
190 ValueT inactiveVal[2];
201 enum { isReal =
false };
206 enum { isReal =
true };
211 enum { isReal =
true };
217 enum { isReal =
true };
222 enum { isReal =
true };
228 enum { isReal =
true };
233 enum { isReal =
true };
277 const bool seek = data ==
nullptr;
283 if (metadata && seek && hasCompression) {
284 size_t compressedSize = metadata->getCompressedSize(metadataOffset);
285 is.seekg(compressedSize, std::ios_base::cur);
291 is.seekg(
sizeof(T) * count, std::ios_base::cur);
293 is.read(reinterpret_cast<char*>(data),
sizeof(T) * count);
300 readData<std::string>(std::istream& is, std::string* data,
Index count, uint32_t ,
303 for (
Index i = 0; i < count; ++i) {
309 std::string buffer(len+1,
' ');
310 is.read(&buffer[0], len+1);
311 if (data !=
nullptr) data[i].assign(buffer, 0, len);
323 static inline void read(std::istream& is, T* data,
Index count, uint32_t compression,
325 readData(is, data, count, compression, metadata, metadataOffset);
332 static inline void read(std::istream& is, T* data,
Index count, uint32_t compression,
334 if (count < 1)
return;
335 if (data ==
nullptr) {
337 readData<HalfT>(is,
nullptr, count, compression, metadata, metadataOffset);
339 std::vector<HalfT> halfData(count);
340 readData<HalfT>(is, reinterpret_cast<HalfT*>(&halfData[0]), count, compression,
341 metadata, metadataOffset);
343 std::copy(halfData.begin(), halfData.end(), data);
356 return zipToStreamSize(reinterpret_cast<const char*>(data),
sizeof(T) * count);
358 return sizeof(T) * count;
366 writeDataSize<std::string>(
const std::string* data,
Index count,
370 for (
Index i = 0; i < count; ++i) {
371 const size_t len = data[i].size();
372 size +=
sizeof(size_t) + (len+1);
393 bloscToStream(os, reinterpret_cast<const char*>(data),
sizeof(T), count);
395 zipToStream(os, reinterpret_cast<const char*>(data),
sizeof(T) * count);
397 os.write(reinterpret_cast<const char*>(data),
sizeof(T) * count);
404 writeData<std::string>(std::ostream& os,
const std::string* data,
Index count,
407 for (
Index i = 0; i < count; ++i) {
408 const size_t len = data[i].size();
410 os.write(data[i].c_str(), len+1);
423 static inline size_t writeSize(
const T* data,
Index count, uint32_t compression) {
426 static inline void write(std::ostream& os,
const T* data,
Index count, uint32_t compression) {
434 static inline size_t writeSize(
const T* data,
Index count, uint32_t compression) {
435 if (count < 1)
return size_t(0);
437 std::vector<HalfT> halfData(count);
438 for (
Index i = 0; i < count; ++i) halfData[i] = RealToHalf<T>::convert(data[i]);
439 return writeDataSize<HalfT>(reinterpret_cast<const HalfT*>(&halfData[0]), count, compression);
441 static inline void write(std::ostream& os,
const T* data,
Index count, uint32_t compression) {
442 if (count < 1)
return;
444 std::vector<HalfT> halfData(count);
445 for (
Index i = 0; i < count; ++i) halfData[i] = RealToHalf<T>::convert(data[i]);
446 writeData<HalfT>(os, reinterpret_cast<const HalfT*>(&halfData[0]), count, compression);
452 struct HalfWriter<true, double> {
453 using HalfT = RealToHalf<double>::HalfT;
454 static inline size_t writeSize(
const double* data,
Index count, uint32_t compression)
456 if (count < 1)
return size_t(0);
458 std::vector<HalfT> halfData(count);
459 for (
Index i = 0; i < count; ++i) halfData[i] = RealToHalf<double>::convert(data[i]);
460 return writeDataSize<HalfT>(reinterpret_cast<const HalfT*>(&halfData[0]), count, compression);
462 static inline void write(std::ostream& os,
const double* data,
Index count,
463 uint32_t compression)
465 if (count < 1)
return;
467 std::vector<HalfT> halfData(count);
468 for (
Index i = 0; i < count; ++i) halfData[i] = RealToHalf<double>::convert(data[i]);
469 writeData<HalfT>(os, reinterpret_cast<const HalfT*>(&halfData[0]), count, compression);
490 template<
typename ValueT,
typename MaskT>
493 const MaskT& valueMask,
bool fromHalf)
500 const bool seek = (destBuf ==
nullptr);
501 assert(!seek || (!meta || meta->seekable()));
506 uint64_t leafIndex(0);
507 if (seek && meta && meta->delayedLoadMeta()) {
510 leafIndex = meta->leaf();
517 if (seek && !maskCompressed) {
518 is.seekg(1, std::ios_base::cur);
519 }
else if (seek && delayLoadMeta) {
520 metadata = delayLoadMeta->getMask(leafIndex);
521 is.seekg(1, std::ios_base::cur);
523 is.read(reinterpret_cast<char*>(&metadata), 1);
527 ValueT background = zeroVal<ValueT>();
529 background = *static_cast<const ValueT*>(bgPtr);
531 ValueT inactiveVal1 = background;
532 ValueT inactiveVal0 =
541 is.seekg(
sizeof(ValueT), std::ios_base::cur);
543 is.read(reinterpret_cast<char*>(&inactiveVal0),
sizeof(ValueT));
548 is.seekg(
sizeof(ValueT), std::ios_base::cur);
550 is.read(reinterpret_cast<char*>(&inactiveVal1),
sizeof(ValueT));
563 is.seekg(selectionMask.memUsage(), std::ios_base::cur);
565 selectionMask.load(is);
569 ValueT* tempBuf = destBuf;
570 std::unique_ptr<ValueT[]> scopedTempBuf;
572 Index tempCount = destCount;
577 tempCount = valueMask.countOn();
578 if (!seek && tempCount != destCount) {
581 scopedTempBuf.reset(
new ValueT[tempCount]);
582 tempBuf = scopedTempBuf.get();
589 is, (seek ?
nullptr : tempBuf), tempCount, compression, delayLoadMeta.get(), leafIndex);
592 is, (seek ?
nullptr : tempBuf), tempCount, compression, delayLoadMeta.get(), leafIndex);
598 if (!seek && maskCompressed && tempCount != destCount) {
602 for (
Index destIdx = 0, tempIdx = 0; destIdx < MaskT::SIZE; ++destIdx) {
603 if (valueMask.isOn(destIdx)) {
605 destBuf[destIdx] = tempBuf[tempIdx];
609 destBuf[destIdx] = (selectionMask.isOn(destIdx) ? inactiveVal1 : inactiveVal0);
616 template<
typename ValueT,
typename MaskT>
619 const MaskT& valueMask, uint8_t maskMetadata,
bool toHalf, uint32_t compress)
621 using NonConstValueT =
typename std::remove_const<ValueT>::type;
625 Index tempCount = srcCount;
626 ValueT* tempBuf = srcBuf;
627 std::unique_ptr<NonConstValueT[]> scopedTempBuf;
633 Index64 onVoxels = valueMask.countOn();
636 scopedTempBuf.reset(
new NonConstValueT[onVoxels]);
637 NonConstValueT* localTempBuf = scopedTempBuf.get();
640 for (
typename MaskT::OnIterator it = valueMask.beginOn(); it; ++it, ++tempCount) {
641 localTempBuf[tempCount] = srcBuf[it.pos()];
644 tempBuf = scopedTempBuf.get();
651 tempBuf, tempCount, compress);
653 return writeDataSize<NonConstValueT>(tempBuf, tempCount, compress);
670 template<
typename ValueT,
typename MaskT>
673 const MaskT& valueMask,
const MaskT& childMask,
bool toHalf)
679 Index tempCount = srcCount;
680 ValueT* tempBuf = srcBuf;
681 std::unique_ptr<ValueT[]> scopedTempBuf;
686 os.write(reinterpret_cast<const char*>(&metadata), 1);
694 const ValueT zero = zeroVal<ValueT>();
695 ValueT background = zero;
697 background = *static_cast<const ValueT*>(bgPtr);
701 metadata = maskCompressData.
metadata;
703 os.write(reinterpret_cast<const char*>(&metadata), 1);
711 os.write(reinterpret_cast<const char*>(&maskCompressData.
inactiveVal[0]),
sizeof(ValueT));
714 os.write(reinterpret_cast<const char*>(&maskCompressData.
inactiveVal[1]),
sizeof(ValueT));
719 os.write(reinterpret_cast<const char*>(&truncatedVal),
sizeof(ValueT));
723 os.write(reinterpret_cast<const char*>(&truncatedVal),
sizeof(ValueT));
735 scopedTempBuf.reset(
new ValueT[srcCount]);
736 tempBuf = scopedTempBuf.get();
744 for (
typename MaskT::OnIterator it = valueMask.beginOn(); it; ++it, ++tempCount) {
745 tempBuf[tempCount] = srcBuf[it.pos()];
752 for (
Index srcIdx = 0; srcIdx < srcCount; ++srcIdx) {
753 if (valueMask.isOn(srcIdx)) {
754 tempBuf[tempCount] = srcBuf[srcIdx];
758 selectionMask.setOn(srcIdx);
762 assert(tempCount == valueMask.countOn());
765 selectionMask.save(os);
774 writeData(os, tempBuf, tempCount, compress);
782 #endif // OPENVDB_IO_COMPRESSION_HAS_BEEN_INCLUDED