Commit 12cb66f2 authored by David Flynn's avatar David Flynn
Browse files

geometry: unify multiple coding methods

This commit aims to reduce te amount of copy+paste code used to
support the three different geometry coding modes by unifying them
into a single flow.
parent 0ffb70ab
......@@ -405,7 +405,7 @@ class PCCPointSet3 {
if (!buf.empty()) tokens.push_back(buf);
return !tokens.empty();
}
bool write(const std::string &fileName, const bool asAscii = false) {
bool write(const std::string &fileName, const bool asAscii = false) const {
std::ofstream fout(fileName, std::ofstream::out);
if (!fout.is_open()) {
return false;
......
......@@ -54,6 +54,9 @@ namespace pcc {
struct DecoderParameters {
bool roundOutputPositions;
// Filename for saving pre inverse scaled point cloud.
std::string preInvScalePath;
};
class PCCTMC3Decoder3 {
......@@ -70,7 +73,7 @@ class PCCTMC3Decoder3 {
boundingBox.max = uint32_t(0);
}
int decompressWithLosslessGeometry(
int decompress(
const DecoderParameters& params,
PCCBitstream &bitstream,
PCCPointSet3 &pointCloud
......@@ -92,79 +95,32 @@ class PCCTMC3Decoder3 {
// determine the geometry codec type
uint8_t geometryCodecRaw;
PCCReadFromBuffer<uint8_t>(bitstream.buffer, geometryCodecRaw, bitstream.size);
GeometryCodecType geometryCodec{GeometryCodecType(geometryCodecRaw)};
uint8_t hasColors = 0;
PCCReadFromBuffer<uint8_t>(bitstream.buffer, hasColors, bitstream.size);
uint8_t hasReflectances = 0;
PCCReadFromBuffer<uint8_t>(bitstream.buffer, hasReflectances, bitstream.size);
if (hasColors) {
pointCloud.addColors();
} else {
pointCloud.removeColors();
}
if (hasReflectances) {
pointCloud.addReflectances();
} else {
pointCloud.removeReflectances();
}
AttributeDecoder attrDecoder;
if (pointCloud.hasColors()) {
uint64_t colorsSize = bitstream.size;
attrDecoder.decodeHeader("color", bitstream);
attrDecoder.buildPredictors(pointCloud);
attrDecoder.decodeColors(bitstream, pointCloud);
colorsSize = bitstream.size - colorsSize;
std::cout << "colors bitstream size " << colorsSize << " B" << std::endl;
std::cout << std::endl;
if (geometryCodec == GeometryCodecType::kBypass) {
uint8_t hasColors = 0;
PCCReadFromBuffer<uint8_t>(bitstream.buffer, hasColors, bitstream.size);
uint8_t hasReflectances = 0;
PCCReadFromBuffer<uint8_t>(bitstream.buffer, hasReflectances, bitstream.size);
pointCloud.addRemoveAttributes(hasColors, hasReflectances);
}
if (pointCloud.hasReflectances()) {
uint64_t reflectancesSize = bitstream.size;
if (geometryCodec != GeometryCodecType::kBypass) {
uint64_t positionsSize = bitstream.size;
attrDecoder.decodeHeader("reflectance", bitstream);
attrDecoder.buildPredictors(pointCloud);
attrDecoder.decodeReflectances(bitstream, pointCloud);
if (geometryCodec == GeometryCodecType::kOctree) {
decodePositionsHeader(bitstream, pointCloud);
decodePositions(bitstream, pointCloud);
}
if (geometryCodec == GeometryCodecType::kTriSoup) {
decodeTrisoupHeader(bitstream, pointCloud);
if (decodeTrisoup(bitstream, pointCloud))
return -1;
}
reflectancesSize = bitstream.size - reflectancesSize;
std::cout << "reflectances bitstream size " << reflectancesSize << " B" << std::endl;
positionsSize = bitstream.size - positionsSize;
std::cout << "positions bitstream size " << positionsSize << " B" << std::endl;
}
return 0;
}
int decompress(
const DecoderParameters& params,
PCCBitstream &bitstream,
PCCPointSet3 &pointCloud
) {
init();
uint32_t magicNumber = 0;
uint32_t formatVersion = 0;
PCCReadFromBuffer<uint32_t>(bitstream.buffer, magicNumber, bitstream.size);
if (magicNumber != PCCTMC3MagicNumber) {
std::cout << "Error: corrupted bistream!" << std::endl;
return -1;
}
PCCReadFromBuffer<uint32_t>(bitstream.buffer, formatVersion, bitstream.size);
if (formatVersion != PCCTMC3FormatVersion) {
std::cout << "Error: bistream version not supported!" << std::endl;
return -1;
}
// determine the geometry codec type
uint8_t geometryCodecRaw;
PCCReadFromBuffer<uint8_t>(bitstream.buffer, geometryCodecRaw, bitstream.size);
uint64_t positionsSize = bitstream.size;
decodePositionsHeader(bitstream, pointCloud);
decodePositions(bitstream, pointCloud);
positionsSize = bitstream.size - positionsSize;
std::cout << "positions bitstream size " << positionsSize << " B" << std::endl;
if (pointCloud.hasColors()) {
AttributeDecoder attrDecoder;
......@@ -191,109 +147,17 @@ class PCCTMC3Decoder3 {
std::cout << "reflectances bitstream size " << reflectancesSize << " B" << std::endl;
}
inverseQuantization(pointCloud, params.roundOutputPositions);
return 0;
}
int decompressWithTrisoupGeometry(
const DecoderParameters& params,
PCCBitstream &bitstream,
PCCPointSet3 &pointCloud
) {
init();
uint32_t magicNumber = 0;
uint32_t formatVersion = 0;
PCCReadFromBuffer<uint32_t>(bitstream.buffer, magicNumber, bitstream.size);
if (magicNumber != PCCTMC3MagicNumber) {
std::cout << "Error: corrupted bistream!" << std::endl;
return -1;
}
PCCReadFromBuffer<uint32_t>(bitstream.buffer, formatVersion, bitstream.size);
if (formatVersion != PCCTMC3FormatVersion) {
std::cout << "Error: bistream version not supported!" << std::endl;
return -1;
// Dump the decoded colour using the pre inverse scaled geometry
if (!params.preInvScalePath.empty()) {
pcc::PCCPointSet3 tempPointCloud(pointCloud);
tempPointCloud.convertYUVToRGB();
tempPointCloud.write(params.preInvScalePath);
}
// determine the geometry codec type
uint8_t geometryCodecRaw;
PCCReadFromBuffer<uint8_t>(bitstream.buffer, geometryCodecRaw, bitstream.size);
uint64_t positionsSize = bitstream.size;
size_t depth;
size_t level;
double intToOrigScale;
PCCPoint3D intToOrigTranslation;
decodeTrisoupHeader(
bitstream, pointCloud,
depth, level, intToOrigScale, intToOrigTranslation);
// Write out TMC1 geometry bitstream from the converged TMC13 bitstream.
uint32_t binSize = 0;
PCCReadFromBuffer<uint32_t>(bitstream.buffer, binSize, bitstream.size);
std::ofstream fout("outbin/outbin_0000.bin", std::ios::binary);
if (!fout.is_open()) {
// maybe because directory does not exist; try again...
pcc::mkdir("outbin");
fout.open("outbin/outbin_0000.bin", std::ios::binary);
if (!fout.is_open()) return -1;
}
fout.write(reinterpret_cast<char *>(&bitstream.buffer[bitstream.size]), binSize);
if (!fout) {
return -1;
}
bitstream.size += binSize;
fout.close();
positionsSize = bitstream.size - positionsSize;
std::cout << "positions bitstream size " << positionsSize << " B" << std::endl;
// Decompress geometry with TMC1.
std::string cmd;
cmd = "7z e -aoa -bso0 -ooutbin outbin/outbin_0000.bin";
system(cmd.c_str());
cmd = "TMC1_geometryDecode -inbin outbin\\outbin -outref refinedVerticesDecoded.ply";
cmd += " -depth " + std::to_string(depth) + " -level " + std::to_string(level) +
" -format binary_little_endian";
system(cmd.c_str());
cmd = "TMC1_voxelize -inref refinedVerticesDecoded.ply -outvox quantizedPointCloudDecoded.ply";
cmd += " -depth " + std::to_string(depth) + " -format binary_little_endian";
system(cmd.c_str());
pointCloud.read("quantizedPointCloudDecoded.ply");
pointCloud.addColors();
pointCloud.removeReflectances();
if (pointCloud.hasColors()) {
AttributeDecoder attrDecoder;
uint64_t colorsSize = bitstream.size;
attrDecoder.decodeHeader("color", bitstream);
attrDecoder.buildPredictors(pointCloud);
attrDecoder.decodeColors(bitstream, pointCloud);
colorsSize = bitstream.size - colorsSize;
std::cout << "colors bitstream size " << colorsSize << " B" << std::endl;
std::cout << std::endl;
}
if (pointCloud.hasReflectances()) {
AttributeDecoder attrDecoder;
uint64_t reflectancesSize = bitstream.size;
attrDecoder.decodeHeader("reflectance", bitstream);
attrDecoder.buildPredictors(pointCloud);
attrDecoder.decodeReflectances(bitstream, pointCloud);
reflectancesSize = bitstream.size - reflectancesSize;
std::cout << "reflectances bitstream size " << reflectancesSize << " B" << std::endl;
if (geometryCodec != GeometryCodecType::kBypass) {
inverseQuantization(pointCloud, params.roundOutputPositions);
}
// Optionally write out point cloud with lossy geometry and lossy color, for later comparison.
pcc::PCCPointSet3 tempPointCloud(pointCloud);
tempPointCloud.convertYUVToRGB();
tempPointCloud.write("decodedVoxelsAndDecodedColors.ply");
inverseQuantization(pointCloud, params.roundOutputPositions);
return 0;
}
......@@ -332,8 +196,7 @@ class PCCTMC3Decoder3 {
}
}
void decodeTrisoupHeader(PCCBitstream &bitstream, PCCPointSet3 &pointCloud, size_t &depth,
size_t &level, double &intToOrigScale, PCCPoint3D &intToOrigTranslation) {
void decodeTrisoupHeader(PCCBitstream &bitstream, PCCPointSet3 &pointCloud) {
uint32_t pointCount = 0;
PCCReadFromBuffer<uint32_t>(bitstream.buffer, pointCount, bitstream.size);
uint8_t hasColors = 0;
......@@ -355,10 +218,59 @@ class PCCTMC3Decoder3 {
if (fabs(positionQuantizationScale) < minPositionQuantizationScale) {
positionQuantizationScale = 1.0;
}
PCCReadFromBuffer<size_t>(bitstream.buffer, depth, bitstream.size);
PCCReadFromBuffer<size_t>(bitstream.buffer, level, bitstream.size);
PCCReadFromBuffer<double>(bitstream.buffer, intToOrigScale, bitstream.size);
PCCReadFromBuffer<PCCPoint3D>(bitstream.buffer, intToOrigTranslation, bitstream.size);
PCCReadFromBuffer<size_t>(bitstream.buffer, triSoup.depth, bitstream.size);
PCCReadFromBuffer<size_t>(bitstream.buffer, triSoup.level, bitstream.size);
PCCReadFromBuffer<double>(bitstream.buffer, triSoup.intToOrigScale, bitstream.size);
PCCReadFromBuffer<PCCPoint3D>(bitstream.buffer, triSoup.intToOrigTranslation, bitstream.size);
}
//--------------------------------------------------------------------------
int decodeTrisoup(PCCBitstream &bitstream, PCCPointSet3 &pointCloud) {
// Write out TMC1 geometry bitstream from the converged TMC13 bitstream.
uint32_t binSize = 0;
PCCReadFromBuffer<uint32_t>(bitstream.buffer, binSize, bitstream.size);
std::ofstream fout("outbin/outbin_0000.bin", std::ios::binary);
if (!fout.is_open()) {
// maybe because directory does not exist; try again...
pcc::mkdir("outbin");
fout.open("outbin/outbin_0000.bin", std::ios::binary);
if (!fout.is_open()) return -1;
}
fout.write(reinterpret_cast<char *>(&bitstream.buffer[bitstream.size]), binSize);
if (!fout) {
return -1;
}
bitstream.size += binSize;
fout.close();
// Decompress geometry with TMC1.
std::string cmd;
cmd = "7z e -aoa -bso0 -ooutbin outbin/outbin_0000.bin";
system(cmd.c_str());
cmd =
"TMC1_geometryDecode"
" -inbin outbin/outbin"
" -outref refinedVerticesDecoded.ply"
" -depth " + std::to_string(triSoup.depth) +
" -level " + std::to_string(triSoup.level) +
" -format binary_little_endian";
system(cmd.c_str());
cmd =
"TMC1_voxelize"
" -inref refinedVerticesDecoded.ply"
" -outvox quantizedPointCloudDecoded.ply"
" -depth " + std::to_string(triSoup.depth) +
" -format binary_little_endian";
system(cmd.c_str());
bool hasColors = pointCloud.hasColors();
bool hasReflectances = pointCloud.hasReflectances();
pointCloud.read("quantizedPointCloudDecoded.ply");
pointCloud.addRemoveAttributes(hasColors, hasReflectances);
return 0;
}
//-------------------------------------------------------------------------
......@@ -703,6 +615,13 @@ class PCCTMC3Decoder3 {
// Controls the use of early termination of the geometry tree
// by directly coding the position of isolated points.
bool inferredDirectCodingModeEnabled;
struct TriSoup {
size_t depth;
size_t level;
double intToOrigScale;
PCCPoint3D intToOrigTranslation;
} triSoup;
};
}
......
......@@ -85,6 +85,9 @@ struct PCCTMC3Encoder3Parameters {
std::vector<double> intToOrigTranslation;
} triSoup;
// Filename for saving recoloured point cloud.
std::string postRecolorPath;
std::map<std::string, PCCAttributeEncodeParamaters> attributeEncodeParameters;
//--------------------------------------------------------------------------
......@@ -128,58 +131,6 @@ class PCCTMC3Encoder3 {
return bitstreamSize;
}
int compressWithLosslessGeometry(const PCCPointSet3 &inputPointCloud,
const PCCTMC3Encoder3Parameters &params, PCCBitstream &bitstream,
PCCPointSet3 *reconstructedCloud = nullptr) {
init();
auto paramsColor =
params.getAttrParams(inputPointCloud.hasColors(), "color");
auto paramsReflectance =
params.getAttrParams(inputPointCloud.hasReflectances(), "reflectance");
pointCloud = inputPointCloud;
pointCloud.addRemoveAttributes(!!paramsColor, !!paramsReflectance);
PCCWriteToBuffer<uint32_t>(PCCTMC3MagicNumber, bitstream.buffer, bitstream.size);
PCCWriteToBuffer<uint32_t>(PCCTMC3FormatVersion, bitstream.buffer, bitstream.size);
PCCWriteToBuffer<uint8_t>(int(params.geometryCodec), bitstream.buffer, bitstream.size);
PCCWriteToBuffer<uint8_t>(uint8_t(pointCloud.hasColors()), bitstream.buffer, bitstream.size);
PCCWriteToBuffer<uint8_t>(uint8_t(pointCloud.hasReflectances()), bitstream.buffer,
bitstream.size);
if (paramsColor) {
AttributeEncoder attrEncoder;
uint64_t colorsSize = bitstream.size;
attrEncoder.encodeHeader(*paramsColor, "color", bitstream);
attrEncoder.buildPredictors(*paramsColor, pointCloud);
attrEncoder.encodeColors(*paramsColor, pointCloud, bitstream);
colorsSize = bitstream.size - colorsSize;
std::cout << "colors bitstream size " << colorsSize << " B ("
<< (8.0 * colorsSize) / inputPointCloud.getPointCount() << " bpp)" << std::endl;
}
if (paramsReflectance) {
AttributeEncoder attrEncoder;
uint64_t reflectancesSize = bitstream.size;
attrEncoder.encodeHeader(*paramsReflectance, "reflectance", bitstream);
attrEncoder.buildPredictors(*paramsReflectance, pointCloud);
attrEncoder.encodeReflectances(*paramsReflectance, pointCloud, bitstream);
reflectancesSize = bitstream.size - reflectancesSize;
std::cout << "reflectances bitstream size " << reflectancesSize << " B ("
<< (8.0 * reflectancesSize) / inputPointCloud.getPointCount() << " bpp)"
<< std::endl;
}
if (reconstructedCloud) {
(*reconstructedCloud) = pointCloud;
}
return 0;
}
int compress(const PCCPointSet3 &inputPointCloud, const PCCTMC3Encoder3Parameters &params,
PCCBitstream &bitstream, PCCPointSet3 *reconstructedCloud = nullptr) {
init();
......@@ -187,146 +138,73 @@ class PCCTMC3Encoder3 {
PCCWriteToBuffer<uint32_t>(PCCTMC3FormatVersion, bitstream.buffer, bitstream.size);
PCCWriteToBuffer<uint8_t>(int(params.geometryCodec), bitstream.buffer, bitstream.size);
if (int ret = quantization(inputPointCloud, params)) {
return ret;
}
uint64_t positionsSize = bitstream.size;
encodePositionsHeader(params, bitstream);
encodePositions(params, bitstream);
positionsSize = bitstream.size - positionsSize;
std::cout << "positions bitstream size " << positionsSize << " B ("
<< (8.0 * positionsSize) / inputPointCloud.getPointCount() << " bpp)" << std::endl;
auto paramsColor =
params.getAttrParams(pointCloud.hasColors(), "color");
if (paramsColor) {
AttributeEncoder attrEncoder;
uint64_t colorsSize = bitstream.size;
attrEncoder.encodeHeader(*paramsColor, "color", bitstream);
attrEncoder.buildPredictors(*paramsColor, pointCloud);
attrEncoder.encodeColors(*paramsColor, pointCloud, bitstream);
colorsSize = bitstream.size - colorsSize;
std::cout << "colors bitstream size " << colorsSize << " B ("
<< (8.0 * colorsSize) / inputPointCloud.getPointCount() << " bpp)" << std::endl;
}
auto paramsReflectance =
params.getAttrParams(pointCloud.hasReflectances(), "reflectance");
if (paramsReflectance) {
AttributeEncoder attrEncoder;
uint64_t reflectancesSize = bitstream.size;
attrEncoder.encodeHeader(*paramsReflectance, "reflectance", bitstream);
attrEncoder.buildPredictors(*paramsReflectance, pointCloud);
attrEncoder.encodeReflectances(*paramsReflectance, pointCloud, bitstream);
reflectancesSize = bitstream.size - reflectancesSize;
std::cout << "reflectances bitstream size " << reflectancesSize << " B ("
<< (8.0 * reflectancesSize) / inputPointCloud.getPointCount() << " bpp)"
<< std::endl;
}
reconstructedPointCloud(params, reconstructedCloud);
return 0;
}
int compressWithTrisoupGeometry(const PCCPointSet3 &inputPointCloud,
const PCCTMC3Encoder3Parameters &params, PCCBitstream &bitstream,
PCCPointSet3 *reconstructedCloud = nullptr) {
init();
PCCWriteToBuffer<uint32_t>(PCCTMC3MagicNumber, bitstream.buffer, bitstream.size);
PCCWriteToBuffer<uint32_t>(PCCTMC3FormatVersion, bitstream.buffer, bitstream.size);
PCCWriteToBuffer<uint8_t>(int(params.geometryCodec), bitstream.buffer, bitstream.size);
// Write out inputPointCloud file, just so that we can get it into the TMC1 pipeline.
pcc::PCCPointSet3 tempPointCloud(inputPointCloud);
tempPointCloud.write("verticesInWorldCoords.ply", true);
// Compress geometry with TMC1.
pcc::mkdir("outbin");
std::string cmd;
cmd =
"TMC1_coordinateTransform -inworld verticesInWorldCoords.ply -outframe "
"verticesInFrameCoords.ply";
cmd += " -depth " + std::to_string(params.triSoup.depth) + " -scale " +
std::to_string(params.triSoup.intToOrigScale) + " -format binary_little_endian";
system(cmd.c_str());
cmd =
"TMC1_geometryEncode -inframe verticesInFrameCoords.ply -outbin outbin -outref "
"refinedVertices.ply";
cmd += " -depth " + std::to_string(params.triSoup.depth) + " -level " + std::to_string(params.triSoup.level) +
" -format binary_little_endian";
system(cmd.c_str());
cmd = "TMC1_voxelize -inref refinedVertices.ply -outvox voxelizedVertices.ply";
cmd += " -depth " + std::to_string(params.triSoup.depth) + " -format binary_little_endian";
system(cmd.c_str());
// Read in quantizedPointCloud file, so that we can recolor it.
pointCloud.read("voxelizedVertices.ply");
// Transform from integer to original coordinates.
const size_t pointCount = pointCloud.getPointCount();
for (size_t pointIndex = 0; pointIndex < pointCount; ++pointIndex) {
pointCloud[pointIndex] *= params.triSoup.intToOrigScale;
// Should add intToOrigTranslation here.
}
auto paramsColor =
params.getAttrParams(inputPointCloud.hasColors(), "color");
auto paramsReflectance =
params.getAttrParams(inputPointCloud.hasReflectances(), "reflectance");
if (paramsColor) {
pointCloud.addColors();
int32_t searchRange = paramsColor->searchRange;
if (!PCCTransfertColors(inputPointCloud, searchRange, pointCloud)) {
std::cout << "Error: can't transfer colors!" << std::endl;
return -1;
// geometry compression consists of the following stages:
// - prefilter/quantize geometry (non-normative)
// - recolour
// - encode geometry
if (params.geometryCodec == GeometryCodecType::kBypass) {
// todo(df): this should go away now that reporting counts attribute bits
pointCloud = inputPointCloud;
pointCloud.addRemoveAttributes(!!paramsColor, !!paramsReflectance);
}
if (params.geometryCodec == GeometryCodecType::kOctree) {
quantization(inputPointCloud, params);
}
if (params.geometryCodec == GeometryCodecType::kTriSoup) {
// todo(?): this ought to be replaced with quantization(...)
inputPointCloud.write("verticesInWorldCoords.ply", true);
std::string cmd =
"TMC1_coordinateTransform"
" -inworld verticesInWorldCoords.ply"
" -outframe verticesInFrameCoords.ply"
" -depth " + std::to_string(params.triSoup.depth) +
" -scale " + std::to_string(params.triSoup.intToOrigScale) +
" -format binary_little_endian";
system(cmd.c_str());
}
// geometry encoding
if (params.geometryCodec == GeometryCodecType::kBypass) {
// only a header is sent in this case
PCCWriteToBuffer<uint8_t>(uint8_t(pointCloud.hasColors()), bitstream.buffer, bitstream.size);
PCCWriteToBuffer<uint8_t>(uint8_t(pointCloud.hasReflectances()), bitstream.buffer, bitstream.size);
} else {
uint64_t positionsSize = bitstream.size;
if (params.geometryCodec == GeometryCodecType::kOctree) {
encodePositionsHeader(params, bitstream);
encodePositions(params, bitstream);
}
if (params.geometryCodec == GeometryCodecType::kTriSoup) {
bool hasColor = !!paramsColor;
bool hasReflectance = !!paramsReflectance;
encodeTrisoupHeader(params, hasColor, hasReflectance, bitstream);
if (encodeTrisoup(params, hasColor, hasReflectance, bitstream))
return -1;
if (recolorTrisoup(params, paramsColor, paramsReflectance, inputPointCloud))
return -1;
}
}
// Transform from original to integer coordinates.
for (size_t pointIndex = 0; pointIndex < pointCount; ++pointIndex) {
// Should subtract intToOrigTranslation here.
pointCloud[pointIndex] /= params.triSoup.intToOrigScale;
positionsSize = bitstream.size - positionsSize;
std::cout << "positions bitstream size " << positionsSize << " B ("
<< (8.0 * positionsSize) / inputPointCloud.getPointCount() << " bpp)" << std::endl;
}
// Optionally write out point cloud with lossy geometry and lossless color, for later
// comparison.
tempPointCloud = pointCloud; // deep copy
tempPointCloud.convertYUVToRGB();
tempPointCloud.write("decodedVoxelsAndTransferredColors.ply");
// attributeCoding
// Encode positions.
uint64_t positionsSize = bitstream.size;
encodeTrisoupHeader(params, bitstream);
// Read in TMC1 geometry bitstream and put it into the converged TMC13 bitstream.
std::ifstream fin("outbin/outbin_0000.bin", std::ios::binary);
if (!fin.is_open()) {
return -1;
}
fin.seekg(0, std::ios::end);
uint64_t binSize = fin.tellg();
fin.seekg(0, std::ios::beg);
std::unique_ptr<uint8_t[]> tempbuf(new uint8_t[binSize]);
PCCWriteToBuffer<uint32_t>(uint32_t(binSize), bitstream.buffer, bitstream.size);
fin.read(reinterpret_cast<char *>(&bitstream.buffer[bitstream.size]), binSize);
if (!fin) {
return -1;
// dump recoloured point cloud
if (!params.postRecolorPath.empty()) {
PCCPointSet3 tempPointCloud(pointCloud);
tempPointCloud.convertYUVToRGB();
tempPointCloud.write(params.postRecolorPath);
}
bitstream.size += binSize;
fin.close();
positionsSize = bitstream.size - positionsSize;
std::cout << "positions bitstream size " << positionsSize << " B ("
<< (8.0 * positionsSize) / inputPointCloud.getPointCount() << " bpp)" << std::endl;
if (paramsColor