AttributeDecoder.cpp 23.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/* The copyright in this software is being made available under the BSD
 * Licence, included below.  This software may be subject to other third
 * party and contributor rights, including patent rights, and no such
 * rights are granted under this licence.
 *
 * Copyright (c) 2017-2018, ISO/IEC
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of the ISO/IEC nor the names of its contributors
 *   may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "AttributeDecoder.h"
37

38
#include "DualLutCoder.h"
39
#include "constants.h"
40
#include "entropy.h"
41
#include "io_hls.h"
42
#include "RAHT.h"
43
#include "FixedPoint.h"
44
45
46
47
48
49
50

namespace pcc {

//============================================================================
// An encapsulation of the entropy decoding methods used in attribute coding

struct PCCResidualsDecoder {
51
52
53
54
  EntropyDecoder arithmeticDecoder;
  StaticBitModel binaryModel0;
  AdaptiveBitModel binaryModelDiff[7];
  AdaptiveBitModel binaryModelIsZero[7];
55
  AdaptiveBitModel ctxPredMode[2];
56
57
  AdaptiveBitModel ctxZeroCnt[3];
  AdaptiveBitModel binaryModelIsOne[7];
58
  DualLutCoder<false> symbolCoder[2];
59

60
  void start(const char* buf, int buf_len);
61
  void stop();
62
  int decodePredMode(int max);
63
  int decodeZeroCnt(int max);
64
65
66
  uint32_t decodeSymbol(int k1, int k2);
  void decode(uint32_t values[3]);
  uint32_t decode();
67
68
69
70
};

//----------------------------------------------------------------------------

71
void
72
PCCResidualsDecoder::start(const char* buf, int buf_len)
73
{
74
75
  arithmeticDecoder.setBuffer(buf_len, buf);
  arithmeticDecoder.start();
76
77
78
79
}

//----------------------------------------------------------------------------

80
81
82
void
PCCResidualsDecoder::stop()
{
83
  arithmeticDecoder.stop();
84
85
86
87
}

//----------------------------------------------------------------------------

88
89
int
PCCResidualsDecoder::decodePredMode(int maxMode)
90
{
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  int mode = 0;

  if (maxMode == 0)
    return mode;

  int ctxIdx = 0;
  while (arithmeticDecoder.decode(ctxPredMode[ctxIdx])) {
    ctxIdx = 1;
    mode++;
    if (mode == maxMode)
      break;
  }

  return mode;
105
106
107
108
}

//----------------------------------------------------------------------------

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
int
PCCResidualsDecoder::decodeZeroCnt(int maxMode)
{
  int mode = 0;

  if (maxMode == 0)
    return mode;

  int ctxIdx = 0;
  while (arithmeticDecoder.decode(ctxZeroCnt[ctxIdx])) {
    ctxIdx = (ctxIdx == 0 ? 1 : 2);
    mode++;
    if (mode == maxMode)
      break;
  }
  return mode;
}

//----------------------------------------------------------------------------

129
uint32_t
130
PCCResidualsDecoder::decodeSymbol(int k1, int k2)
131
{
132
  if (arithmeticDecoder.decode(binaryModelIsZero[k1]))
133
    return 0u;
134
135
136

  if (arithmeticDecoder.decode(binaryModelIsOne[k1]))
    return 1u;
137
138

  uint32_t value = symbolCoder[k2].decode(&arithmeticDecoder);
139
  if (value == kAttributeResidualAlphabetSize) {
140
    value +=
141
      arithmeticDecoder.decodeExpGolomb(0, binaryModel0, binaryModelDiff[k1]);
142
  }
143

144
  return value + 2;
145
146
147
148
}

//----------------------------------------------------------------------------

149
150
151
152
153
154
155
156
void
PCCResidualsDecoder::decode(uint32_t value[3])
{
  value[0] = decodeSymbol(0, 0);
  int b0 = value[0] == 0;
  value[1] = decodeSymbol(1 + b0, 1);
  int b1 = value[1] == 0;
  value[2] = decodeSymbol(3 + (b0 << 1) + b1, 1);
157
158
159
160
161

  int d = (value[0] == value[1] && value[0] == value[2]);
  for (int k = 0; k < 3; k++) {
    value[k] += d;
  }
162
163
164
165
}

//----------------------------------------------------------------------------

166
uint32_t
167
PCCResidualsDecoder::decode()
168
{
169
  return decodeSymbol(0, 0) + 1;
170
171
172
173
174
}

//============================================================================
// AttributeDecoder Members

175
void
176
177
178
179
180
AttributeDecoder::decode(
  const AttributeDescription& attr_desc,
  const AttributeParameterSet& attr_aps,
  const PayloadBuffer& payload,
  PCCPointSet3& pointCloud)
181
{
182
  int abhSize;
183
  AttributeBrickHeader abh = parseAbh(attr_aps, payload, &abhSize);
184
  Quantizers qstep = deriveQuantSteps(attr_aps, abh);
185

186
  PCCResidualsDecoder decoder;
187
  decoder.start(payload.data() + abhSize, payload.size() - abhSize);
188

189
  if (attr_desc.attr_num_dimensions == 1) {
190
191
    switch (attr_aps.attr_encoding) {
    case AttributeEncoding::kRAHTransform:
192
      decodeReflectancesRaht(attr_desc, attr_aps, qstep, decoder, pointCloud);
193
      break;
194

195
    case AttributeEncoding::kPredictingTransform:
196
      decodeReflectancesPred(attr_desc, attr_aps, qstep, decoder, pointCloud);
197
      break;
198

199
    case AttributeEncoding::kLiftingTransform:
200
      decodeReflectancesLift(attr_desc, attr_aps, qstep, decoder, pointCloud);
201
202
      break;
    }
203
  } else if (attr_desc.attr_num_dimensions == 3) {
204
205
    switch (attr_aps.attr_encoding) {
    case AttributeEncoding::kRAHTransform:
206
      decodeColorsRaht(attr_desc, attr_aps, qstep, decoder, pointCloud);
207
208
209
      break;

    case AttributeEncoding::kPredictingTransform:
210
      decodeColorsPred(attr_desc, attr_aps, qstep, decoder, pointCloud);
211
212
213
      break;

    case AttributeEncoding::kLiftingTransform:
214
      decodeColorsLift(attr_desc, attr_aps, qstep, decoder, pointCloud);
215
216
217
      break;
    }
  } else {
218
219
220
    assert(
      attr_desc.attr_num_dimensions == 1
      || attr_desc.attr_num_dimensions == 3);
221
  }
222
223
224
225
226
227

  decoder.stop();
}

//----------------------------------------------------------------------------

228
void
229
AttributeDecoder::computeReflectancePredictionWeights(
230
  const AttributeParameterSet& aps,
231
  const PCCPointSet3& pointCloud,
232
  const std::vector<uint32_t>& indexes,
233
234
235
236
237
238
239
  PCCPredictor& predictor,
  PCCResidualsDecoder& decoder)
{
  predictor.computeWeights();
  if (predictor.neighborCount > 1) {
    int64_t minValue = 0;
    int64_t maxValue = 0;
240
241
242
    for (int i = 0; i < predictor.neighborCount; ++i) {
      const uint16_t reflectanceNeighbor = pointCloud.getReflectance(
        indexes[predictor.neighbors[i].predictorIndex]);
243
244
245
246
247
248
249
250
      if (i == 0 || reflectanceNeighbor < minValue) {
        minValue = reflectanceNeighbor;
      }
      if (i == 0 || reflectanceNeighbor > maxValue) {
        maxValue = reflectanceNeighbor;
      }
    }
    const int64_t maxDiff = maxValue - minValue;
251
    if (maxDiff > aps.adaptive_prediction_threshold) {
252
253
      predictor.predMode =
        decoder.decodePredMode(aps.max_num_direct_predictors);
254
255
256
257
258
259
    }
  }
}

//----------------------------------------------------------------------------

260
void
261
AttributeDecoder::decodeReflectancesPred(
262
  const AttributeDescription& desc,
263
  const AttributeParameterSet& aps,
264
  const Quantizers& qstep,
265
266
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
267
{
268
  const size_t pointCount = pointCloud.getPointCount();
269
270
271
  std::vector<PCCPredictor> predictors;
  std::vector<uint32_t> numberOfPointsPerLOD;
  std::vector<uint32_t> indexesLOD;
272
273
274
275
276
277
278
279

  if (!aps.lod_binary_tree_enabled_flag) {
    if (aps.num_detail_levels <= 1) {
      buildPredictorsFastNoLod(
        pointCloud, aps.num_pred_nearest_neighbours, aps.search_range,
        predictors, indexesLOD);
    } else {
      buildPredictorsFast(
280
281
282
283
        pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
        aps.num_detail_levels, aps.num_pred_nearest_neighbours,
        aps.search_range, aps.search_range, predictors, numberOfPointsPerLOD,
        indexesLOD);
284
    }
285
  } else {
286
287
288
289
    buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
    computePredictors(
      pointCloud, numberOfPointsPerLOD, indexesLOD,
      aps.num_pred_nearest_neighbours, predictors);
290
  }
291

292
  const int64_t maxReflectance = (1ll << desc.attr_bitdepth) - 1;
293
  int zero_cnt = decoder.decodeZeroCnt(pointCount);
294
295
296
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
    auto& predictor = predictors[predictorIndex];
297
    const int64_t qs = qstep[0];
298
299
300
301
    computeReflectancePredictionWeights(
      aps, pointCloud, indexesLOD, predictor, decoder);
    const uint32_t pointIndex = indexesLOD[predictorIndex];
    uint16_t& reflectance = pointCloud.getReflectance(pointIndex);
302
303
304
305
306
307
308
    uint32_t attValue0 = 0;
    if (zero_cnt > 0) {
      zero_cnt--;
    } else {
      attValue0 = decoder.decode();
      zero_cnt = decoder.decodeZeroCnt(pointCount);
    }
309
310
    const int64_t quantPredAttValue =
      predictor.predictReflectance(pointCloud, indexesLOD);
311
312
    const int64_t delta =
      PCCInverseQuantization(UIntToInt(attValue0), qs, true);
313
    const int64_t reconstructedQuantAttValue = quantPredAttValue + delta;
314
315
316
317
318
319
320
321
322
    reflectance = uint16_t(
      PCCClip(reconstructedQuantAttValue, int64_t(0), maxReflectance));
  }
}

//----------------------------------------------------------------------------

void
AttributeDecoder::computeColorPredictionWeights(
323
  const AttributeParameterSet& aps,
324
  const PCCPointSet3& pointCloud,
325
  const std::vector<uint32_t>& indexes,
326
327
328
329
330
331
332
  PCCPredictor& predictor,
  PCCResidualsDecoder& decoder)
{
  predictor.computeWeights();
  if (predictor.neighborCount > 1) {
    int64_t minValue[3] = {0, 0, 0};
    int64_t maxValue[3] = {0, 0, 0};
333
    for (int i = 0; i < predictor.neighborCount; ++i) {
334
      const Vec3<uint8_t> colorNeighbor =
335
        pointCloud.getColor(indexes[predictor.neighbors[i].predictorIndex]);
336
337
338
339
340
341
342
343
344
345
346
347
      for (size_t k = 0; k < 3; ++k) {
        if (i == 0 || colorNeighbor[k] < minValue[k]) {
          minValue[k] = colorNeighbor[k];
        }
        if (i == 0 || colorNeighbor[k] > maxValue[k]) {
          maxValue[k] = colorNeighbor[k];
        }
      }
    }
    const int64_t maxDiff = (std::max)(
      maxValue[2] - minValue[2],
      (std::max)(maxValue[0] - minValue[0], maxValue[1] - minValue[1]));
348
    if (maxDiff > aps.adaptive_prediction_threshold) {
349
350
      predictor.predMode =
        decoder.decodePredMode(aps.max_num_direct_predictors);
351
    }
352
353
354
355
356
  }
}

//----------------------------------------------------------------------------

357
void
358
AttributeDecoder::decodeColorsPred(
359
  const AttributeDescription& desc,
360
  const AttributeParameterSet& aps,
361
  const Quantizers& qstep,
362
363
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
364
{
365
  const size_t pointCount = pointCloud.getPointCount();
366
367
368
  std::vector<PCCPredictor> predictors;
  std::vector<uint32_t> numberOfPointsPerLOD;
  std::vector<uint32_t> indexesLOD;
369
370
371
372
373
374
375
376

  if (!aps.lod_binary_tree_enabled_flag) {
    if (aps.num_detail_levels <= 1) {
      buildPredictorsFastNoLod(
        pointCloud, aps.num_pred_nearest_neighbours, aps.search_range,
        predictors, indexesLOD);
    } else {
      buildPredictorsFast(
377
378
379
380
        pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
        aps.num_detail_levels, aps.num_pred_nearest_neighbours,
        aps.search_range, aps.search_range, predictors, numberOfPointsPerLOD,
        indexesLOD);
381
    }
382
  } else {
383
384
385
386
    buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
    computePredictors(
      pointCloud, numberOfPointsPerLOD, indexesLOD,
      aps.num_pred_nearest_neighbours, predictors);
387
  }
388

389
  uint32_t values[3];
390
  int zero_cnt = decoder.decodeZeroCnt(pointCount);
391
392
393
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
    auto& predictor = predictors[predictorIndex];
394
395
    const int64_t qs = qstep[0];
    const int64_t qs2 = qstep[1];
396
397
    computeColorPredictionWeights(
      aps, pointCloud, indexesLOD, predictor, decoder);
398
399
400
401
402
403
404
    if (zero_cnt > 0) {
      values[0] = values[1] = values[2] = 0;
      zero_cnt--;
    } else {
      decoder.decode(values);
      zero_cnt = decoder.decodeZeroCnt(pointCount);
    }
405
    const uint32_t pointIndex = indexesLOD[predictorIndex];
406
407
    Vec3<uint8_t>& color = pointCloud.getColor(pointIndex);
    const Vec3<uint8_t> predictedColor =
408
      predictor.predictColor(pointCloud, indexesLOD);
409
    const int64_t quantPredAttValue = predictedColor[0];
410
411
    const int64_t delta =
      PCCInverseQuantization(UIntToInt(values[0]), qs, true);
412
    const int64_t reconstructedQuantAttValue = quantPredAttValue + delta;
413
    int64_t clipMax = (1 << desc.attr_bitdepth) - 1;
414
    color[0] =
415
      uint8_t(PCCClip(reconstructedQuantAttValue, int64_t(0), clipMax));
416
417
    for (size_t k = 1; k < 3; ++k) {
      const int64_t quantPredAttValue = predictedColor[k];
418
419
      const int64_t delta =
        PCCInverseQuantization(UIntToInt(values[k]), qs2, true);
420
      const int64_t reconstructedQuantAttValue = quantPredAttValue + delta;
421
      color[k] =
422
        uint8_t(PCCClip(reconstructedQuantAttValue, int64_t(0), clipMax));
423
424
425
426
    }
  }
}

427
428
//----------------------------------------------------------------------------

429
430
void
AttributeDecoder::decodeReflectancesRaht(
431
  const AttributeDescription& desc,
432
  const AttributeParameterSet& aps,
433
  const Quantizers& qstep,
434
435
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
436
{
437
  const int voxelCount = int(pointCloud.getPointCount());
438
439
  uint64_t* weight = new uint64_t[voxelCount];
  int* binaryLayer = new int[voxelCount];
440
441
  std::vector<MortonCodeWithIndex> packedVoxel(voxelCount);
  for (int n = 0; n < voxelCount; n++) {
442
    weight[n] = 1;
443
    packedVoxel[n].mortonCode = mortonAddr(pointCloud[n], 0);
444
445
446
447
    packedVoxel[n].index = n;
  }
  sort(packedVoxel.begin(), packedVoxel.end());

448
  // Morton codes
449
  uint64_t* mortonCode = new uint64_t[voxelCount];
450
451
452
453
454
  for (int n = 0; n < voxelCount; n++) {
    mortonCode[n] = packedVoxel[n].mortonCode;
  }

  // Entropy decode
455
456
  const int attribCount = 1;
  int* integerizedAttributes = new int[attribCount * voxelCount];
457
  int zero_cnt = decoder.decodeZeroCnt(voxelCount);
458
  for (int n = 0; n < voxelCount; ++n) {
459
460
461
462
463
464
465
    uint32_t value = 0;
    if (zero_cnt > 0) {
      zero_cnt--;
    } else {
      value = decoder.decode();
      zero_cnt = decoder.decodeZeroCnt(voxelCount);
    }
466
    integerizedAttributes[n] = UIntToInt(value);
467
468
  }

469
  FixedPoint* attributes = new FixedPoint[attribCount * voxelCount];
470
471

  regionAdaptiveHierarchicalInverseTransform(
472
473
    FixedPoint(qstep[0]), mortonCode, attributes, weight, attribCount,
    voxelCount, integerizedAttributes);
474

475
476
  const int64_t maxReflectance = (1 << desc.attr_bitdepth) - 1;
  const int64_t minReflectance = 0;
477
  for (int n = 0; n < voxelCount; n++) {
478
479
480
481
    int64_t val = attributes[attribCount * n].round();
    const uint16_t reflectance =
      (uint16_t)PCCClip(val, minReflectance, maxReflectance);
    pointCloud.setReflectance(packedVoxel[n].index, reflectance);
482
483
484
  }

  // De-allocate arrays.
485
  delete[] binaryLayer;
486
487
488
489
490
491
492
493
  delete[] mortonCode;
  delete[] attributes;
  delete[] integerizedAttributes;
  delete[] weight;
}

//----------------------------------------------------------------------------

494
495
void
AttributeDecoder::decodeColorsRaht(
496
  const AttributeDescription& desc,
497
  const AttributeParameterSet& aps,
498
  const Quantizers& qstep,
499
500
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
501
{
502
  const int voxelCount = int(pointCloud.getPointCount());
503
504
  uint64_t* weight = new uint64_t[voxelCount];
  int* binaryLayer = new int[voxelCount];
505
506
  std::vector<MortonCodeWithIndex> packedVoxel(voxelCount);
  for (int n = 0; n < voxelCount; n++) {
507
    weight[n] = 1;
508
    packedVoxel[n].mortonCode = mortonAddr(pointCloud[n], 0);
509
510
511
512
    packedVoxel[n].index = n;
  }
  sort(packedVoxel.begin(), packedVoxel.end());

513
  // Morton codes
514
  uint64_t* mortonCode = new uint64_t[voxelCount];
515
516
517
518
519
520
  for (int n = 0; n < voxelCount; n++) {
    mortonCode[n] = packedVoxel[n].mortonCode;
  }

  // Entropy decode
  const int attribCount = 3;
521
  int zero_cnt = decoder.decodeZeroCnt(voxelCount);
522
  int* integerizedAttributes = new int[attribCount * voxelCount];
523

524
  for (int n = 0; n < voxelCount; ++n) {
525
526
527
528
529
530
531
532
    uint32_t values[3];
    if (zero_cnt > 0) {
      values[0] = values[1] = values[2] = 0;
      zero_cnt--;
    } else {
      decoder.decode(values);
      zero_cnt = decoder.decodeZeroCnt(voxelCount);
    }
533
534
    for (int d = 0; d < attribCount; ++d) {
      integerizedAttributes[voxelCount * d + n] = UIntToInt(values[d]);
535
536
537
    }
  }

538
539
  FixedPoint* attributes = new FixedPoint[attribCount * voxelCount];

540
  regionAdaptiveHierarchicalInverseTransform(
541
542
    FixedPoint(qstep[0]), mortonCode, attributes, weight, attribCount,
    voxelCount, integerizedAttributes);
543

544
  const int clipMax = (1 << desc.attr_bitdepth) - 1;
545
  for (int n = 0; n < voxelCount; n++) {
546
547
548
    const int r = attributes[attribCount * n].round();
    const int g = attributes[attribCount * n + 1].round();
    const int b = attributes[attribCount * n + 2].round();
549
    Vec3<uint8_t> color;
550
551
552
    color[0] = uint8_t(PCCClip(r, 0, clipMax));
    color[1] = uint8_t(PCCClip(g, 0, clipMax));
    color[2] = uint8_t(PCCClip(b, 0, clipMax));
553
554
555
556
    pointCloud.setColor(packedVoxel[n].index, color);
  }

  // De-allocate arrays.
557
  delete[] binaryLayer;
558
559
560
561
562
563
  delete[] mortonCode;
  delete[] attributes;
  delete[] integerizedAttributes;
  delete[] weight;
}

564
565
566
567
//----------------------------------------------------------------------------

void
AttributeDecoder::decodeColorsLift(
568
  const AttributeDescription& desc,
569
  const AttributeParameterSet& aps,
570
  const Quantizers& qstep,
571
572
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
573
574
{
  const size_t pointCount = pointCloud.getPointCount();
575
  std::vector<PCCPredictor> predictors;
576
577
  std::vector<uint32_t> numberOfPointsPerLOD;
  std::vector<uint32_t> indexesLOD;
578
579
580

  if (!aps.lod_binary_tree_enabled_flag) {
    buildPredictorsFast(
581
582
583
      pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
      aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
      aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
584
585
586
587
588
589
590
  } else {
    buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
    computePredictors(
      pointCloud, numberOfPointsPerLOD, indexesLOD,
      aps.num_pred_nearest_neighbours, predictors);
  }

591
592
593
594
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
    predictors[predictorIndex].computeWeights();
  }
595
  std::vector<uint64_t> weights;
596
  PCCComputeQuantizationWeights(predictors, weights);
597
  const size_t lodCount = numberOfPointsPerLOD.size();
598
  std::vector<Vec3<int64_t>> colors;
599
  colors.resize(pointCount);
600
  // decompress
601
  int zero_cnt = decoder.decodeZeroCnt(pointCount);
602
603
604
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
    uint32_t values[3];
605
606
607
608
609
610
611
    if (zero_cnt > 0) {
      values[0] = values[1] = values[2] = 0;
      zero_cnt--;
    } else {
      decoder.decode(values);
      zero_cnt = decoder.decodeZeroCnt(pointCount);
    }
612
613
614
    const int64_t qs = qstep[0] << (kFixedPointWeightShift / 2);
    const int64_t qs2 = qstep[1] << (kFixedPointWeightShift / 2);
    // + kFixedPointAttributeShift ???
615
    const int64_t quantWeight = weights[predictorIndex];
616
    auto& color = colors[predictorIndex];
617
    const int64_t delta = UIntToInt(values[0]);
618
    const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs);
619
620
    color[0] = reconstructedDelta / quantWeight;
    for (size_t d = 1; d < 3; ++d) {
621
      const int64_t delta = UIntToInt(values[d]);
622
      const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs2);
623
624
625
626
627
628
629
630
631
632
633
      color[d] = reconstructedDelta / quantWeight;
    }
  }

  // reconstruct
  for (size_t lodIndex = 1; lodIndex < lodCount; ++lodIndex) {
    const size_t startIndex = numberOfPointsPerLOD[lodIndex - 1];
    const size_t endIndex = numberOfPointsPerLOD[lodIndex];
    PCCLiftUpdate(predictors, weights, startIndex, endIndex, false, colors);
    PCCLiftPredict(predictors, startIndex, endIndex, false, colors);
  }
634

635
  const int64_t clipMax = (1 << desc.attr_bitdepth) - 1;
636
  for (size_t f = 0; f < pointCount; ++f) {
637
638
    const auto color0 =
      divExp2RoundHalfInf(colors[f], kFixedPointAttributeShift);
639
    Vec3<uint8_t> color;
640
    for (size_t d = 0; d < 3; ++d) {
641
      color[d] = uint8_t(PCCClip(color0[d], int64_t(0), clipMax));
642
    }
643
    pointCloud.setColor(indexesLOD[f], color);
644
645
646
647
648
649
650
  }
}

//----------------------------------------------------------------------------

void
AttributeDecoder::decodeReflectancesLift(
651
  const AttributeDescription& desc,
652
  const AttributeParameterSet& aps,
653
  const Quantizers& qstep,
654
655
  PCCResidualsDecoder& decoder,
  PCCPointSet3& pointCloud)
656
{
657
  const size_t pointCount = pointCloud.getPointCount();
658
  std::vector<PCCPredictor> predictors;
659
660
  std::vector<uint32_t> numberOfPointsPerLOD;
  std::vector<uint32_t> indexesLOD;
661
662
663

  if (!aps.lod_binary_tree_enabled_flag) {
    buildPredictorsFast(
664
665
666
      pointCloud, aps.lod_decimation_enabled_flag, aps.dist2,
      aps.num_detail_levels, aps.num_pred_nearest_neighbours, aps.search_range,
      aps.search_range, predictors, numberOfPointsPerLOD, indexesLOD);
667
668
669
670
671
672
673
  } else {
    buildLevelOfDetailBinaryTree(pointCloud, numberOfPointsPerLOD, indexesLOD);
    computePredictors(
      pointCloud, numberOfPointsPerLOD, indexesLOD,
      aps.num_pred_nearest_neighbours, predictors);
  }

674
675
676
677
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
    predictors[predictorIndex].computeWeights();
  }
678
  std::vector<uint64_t> weights;
679
  PCCComputeQuantizationWeights(predictors, weights);
680
  const size_t lodCount = numberOfPointsPerLOD.size();
681
  std::vector<int64_t> reflectances;
682
  reflectances.resize(pointCount);
683
684

  // decompress
685
  int zero_cnt = decoder.decodeZeroCnt(pointCount);
686
687
  for (size_t predictorIndex = 0; predictorIndex < pointCount;
       ++predictorIndex) {
688
689
690
691
692
693
694
    int64_t detail = 0;
    if (zero_cnt > 0) {
      zero_cnt--;
    } else {
      detail = decoder.decode();
      zero_cnt = decoder.decodeZeroCnt(pointCount);
    }
695
    const int64_t qs = qstep[0] << (kFixedPointWeightShift / 2);
696
    const int64_t quantWeight = weights[predictorIndex];
697
    auto& reflectance = reflectances[predictorIndex];
698
    const int64_t delta = UIntToInt(detail);
699
    const int64_t reconstructedDelta = PCCInverseQuantization(delta, qs);
700
701
702
703
704
705
706
707
708
709
710
    reflectance = reconstructedDelta / quantWeight;
  }

  // reconstruct
  for (size_t lodIndex = 1; lodIndex < lodCount; ++lodIndex) {
    const size_t startIndex = numberOfPointsPerLOD[lodIndex - 1];
    const size_t endIndex = numberOfPointsPerLOD[lodIndex];
    PCCLiftUpdate(
      predictors, weights, startIndex, endIndex, false, reflectances);
    PCCLiftPredict(predictors, startIndex, endIndex, false, reflectances);
  }
711
  const int64_t maxReflectance = (1 << desc.attr_bitdepth) - 1;
712
  for (size_t f = 0; f < pointCount; ++f) {
713
714
    const auto refl =
      divExp2RoundHalfInf(reflectances[f], kFixedPointAttributeShift);
715
    pointCloud.setReflectance(
716
      indexesLOD[f], uint16_t(PCCClip(refl, int64_t(0), maxReflectance)));
717
718
719
  }
}

720
721
//============================================================================

722
} /* namespace pcc */