31 #ifndef OPENVDB_IO_COMPRESSION_HAS_BEEN_INCLUDED
32 #define OPENVDB_IO_COMPRESSION_HAS_BEEN_INCLUDED
34 #include <openvdb/Types.h>
35 #include <openvdb/math/Math.h>
36 #include <boost/scoped_array.hpp>
100 enum { isReal =
false };
128 is.read(reinterpret_cast<char*>(data),
sizeof(T) * count);
135 readData<std::string>(std::istream& is, std::string* data,
Index count,
bool )
137 for (
Index i = 0; i < count; ++i) {
143 std::string buffer(len+1,
' ');
144 is.read(&buffer[0], len+1 );
145 data[i].assign(buffer, 0, len);
157 static inline void read(std::istream& is, T* data,
Index count,
bool compressed) {
158 readData(is, data, count, compressed);
165 static inline void read(std::istream& is, T* data,
Index count,
bool compressed) {
166 if (count < 1)
return;
167 std::vector<HalfT> halfData(count);
168 readData<HalfT>(is,
reinterpret_cast<HalfT*
>(&halfData[0]), count, compressed);
170 std::copy(halfData.begin(), halfData.end(), data);
187 zipToStream(os, reinterpret_cast<const char*>(data),
sizeof(T) * count);
189 os.write(reinterpret_cast<const char*>(data),
sizeof(T) * count);
197 writeData<std::string>(std::ostream& os,
const std::string* data,
Index count,
bool )
199 for (
Index i = 0; i < count; ++i) {
200 const size_t len = data[i].size();
202 os.write(data[i].c_str(), len+1);
215 static inline void write(std::ostream& os,
const T* data,
Index count,
bool compress) {
223 static inline void write(std::ostream& os,
const T* data,
Index count,
bool compress) {
224 if (count < 1)
return;
226 std::vector<HalfT> halfData(count);
227 std::copy(data, data + count, halfData.begin());
228 writeData<HalfT>(os,
reinterpret_cast<const HalfT*
>(&halfData[0]), count, compress);
234 struct HalfWriter<true, double> {
235 typedef RealToHalf<double>::HalfT HalfT;
236 static inline void write(std::ostream& os,
const double* data,
Index count,
bool compress) {
237 if (count < 1)
return;
239 std::vector<HalfT> halfData(count);
240 for (
Index i = 0; i < count; ++i) halfData[i] =
float(data[i]);
241 writeData<HalfT>(os,
reinterpret_cast<const HalfT*
>(&halfData[0]), count, compress);
262 template<
typename ValueT,
typename MaskT>
265 const MaskT& valueMask,
bool fromHalf)
277 is.read(reinterpret_cast<char*>(&metadata), 1);
280 ValueT background = zeroVal<ValueT>();
282 background = *
static_cast<const ValueT*
>(bgPtr);
284 ValueT inactiveVal1 = background;
285 ValueT inactiveVal0 =
293 is.read(reinterpret_cast<char*>(&inactiveVal0),
sizeof(ValueT));
296 is.read(reinterpret_cast<char*>(&inactiveVal1),
sizeof(ValueT));
307 selectionMask.load(is);
310 ValueT* tempBuf = destBuf;
311 boost::scoped_array<ValueT> scopedTempBuf;
313 Index tempCount = destCount;
315 tempCount = valueMask.countOn();
316 if (tempCount != destCount) {
319 scopedTempBuf.reset(
new ValueT[tempCount]);
320 tempBuf = scopedTempBuf.get();
328 readData<ValueT>(is, tempBuf, tempCount, zipped);
334 if (maskCompressed && tempCount != destCount) {
338 for (
Index destIdx = 0, tempIdx = 0; destIdx < MaskT::BIT_SIZE; ++destIdx) {
339 if (valueMask.isOn(destIdx)) {
341 destBuf[destIdx] = tempBuf[tempIdx];
345 destBuf[destIdx] = (selectionMask.isOn(destIdx) ? inactiveVal1 : inactiveVal0);
364 template<
typename ValueT,
typename MaskT>
367 const MaskT& valueMask,
const MaskT& childMask,
bool toHalf)
371 static inline bool eq(
const ValueT& a,
const ValueT& b) {
382 Index tempCount = srcCount;
383 ValueT* tempBuf = srcBuf;
384 boost::scoped_array<ValueT> scopedTempBuf;
389 os.write(reinterpret_cast<const char*>(&metadata), 1);
397 const ValueT zero = zeroVal<ValueT>();
398 ValueT background = zero;
400 background = *
static_cast<const ValueT*
>(bgPtr);
404 ValueT inactiveVal[2] = { background, background };
405 int numUniqueInactiveVals = 0;
406 for (
typename MaskT::OffIterator it = valueMask.beginOff();
407 numUniqueInactiveVals < 3 && it; ++it)
412 if (childMask.isOn(idx))
continue;
414 const ValueT& val = srcBuf[idx];
415 const bool unique = !(
416 (numUniqueInactiveVals > 0 && Local::eq(val, inactiveVal[0])) ||
417 (numUniqueInactiveVals > 1 && Local::eq(val, inactiveVal[1]))
420 if (numUniqueInactiveVals < 2) inactiveVal[numUniqueInactiveVals] = val;
421 ++numUniqueInactiveVals;
427 if (numUniqueInactiveVals == 1) {
428 if (!Local::eq(inactiveVal[0], background)) {
429 if (Local::eq(inactiveVal[0],
negative(background))) {
435 }
else if (numUniqueInactiveVals == 2) {
437 if (!Local::eq(inactiveVal[0], background) && !Local::eq(inactiveVal[1], background)) {
442 }
else if (Local::eq(inactiveVal[1], background)) {
443 if (Local::eq(inactiveVal[0],
negative(background))) {
454 }
else if (Local::eq(inactiveVal[0], background)) {
455 if (Local::eq(inactiveVal[1],
negative(background))) {
460 std::swap(inactiveVal[0], inactiveVal[1]);
465 std::swap(inactiveVal[0], inactiveVal[1]);
471 os.write(reinterpret_cast<const char*>(&metadata), 1);
478 os.write(reinterpret_cast<const char*>(&inactiveVal[0]),
sizeof(ValueT));
481 os.write(reinterpret_cast<const char*>(&inactiveVal[1]),
sizeof(ValueT));
492 scopedTempBuf.reset(
new ValueT[srcCount]);
493 tempBuf = scopedTempBuf.get();
501 for (
typename MaskT::OnIterator it = valueMask.beginOn(); it; ++it, ++tempCount) {
502 tempBuf[tempCount] = srcBuf[it.pos()];
509 for (
Index srcIdx = 0; srcIdx < srcCount; ++srcIdx) {
510 if (valueMask.isOn(srcIdx)) {
511 tempBuf[tempCount] = srcBuf[srcIdx];
514 if (Local::eq(srcBuf[srcIdx], inactiveVal[1])) {
515 selectionMask.setOn(srcIdx);
519 assert(tempCount == valueMask.countOn());
522 selectionMask.save(os);
539 #endif // OPENVDB_IO_COMPRESSION_HAS_BEEN_INCLUDED