Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libjxl/lib/jxl/ac_strategy.cc
Line
Count
Source
1
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
2
//
3
// Use of this source code is governed by a BSD-style
4
// license that can be found in the LICENSE file.
5
6
#include "lib/jxl/ac_strategy.h"
7
8
#include <jxl/memory_manager.h>
9
10
#include <algorithm>
11
#include <cstdint>
12
#include <cstring>
13
#include <utility>
14
15
#include "lib/jxl/base/bits.h"
16
#include "lib/jxl/base/compiler_specific.h"
17
#include "lib/jxl/base/status.h"
18
#include "lib/jxl/coeff_order_fwd.h"
19
#include "lib/jxl/frame_dimensions.h"
20
#include "lib/jxl/image.h"
21
22
namespace jxl {
23
24
// Tries to generalize zig-zag order to non-square blocks. Surprisingly, in
25
// square block frequency along the (i + j == const) diagonals is roughly the
26
// same. For historical reasons, consecutive diagonals are traversed
27
// in alternating directions - so called "zig-zag" (or "snake") order.
28
template <bool is_lut>
29
91.8k
static void CoeffOrderAndLut(AcStrategy acs, coeff_order_t* out) {
30
91.8k
  size_t cx = acs.covered_blocks_x();
31
91.8k
  size_t cy = acs.covered_blocks_y();
32
91.8k
  CoefficientLayout(&cy, &cx);
33
34
  // CoefficientLayout ensures cx >= cy.
35
  // We compute the zigzag order for a cx x cx block, then discard all the
36
  // lines that are not multiple of the ratio between cx and cy.
37
91.8k
  size_t xs = cx / cy;
38
91.8k
  size_t xsm = xs - 1;
39
91.8k
  size_t xss = CeilLog2Nonzero(xs);
40
  // First half of the block
41
91.8k
  size_t cur = cx * cy;
42
1.88M
  for (size_t i = 0; i < cx * kBlockDim; i++) {
43
39.7M
    for (size_t j = 0; j <= i; j++) {
44
37.9M
      size_t x = j;
45
37.9M
      size_t y = i - j;
46
37.9M
      if (i % 2) std::swap(x, y);
47
37.9M
      if ((y & xsm) != 0) continue;
48
28.8M
      y >>= xss;
49
28.8M
      size_t val = 0;
50
28.8M
      if (x < cx && y < cy) {
51
873k
        val = y * cx + x;
52
27.9M
      } else {
53
27.9M
        val = cur++;
54
27.9M
      }
55
28.8M
      if (is_lut) {
56
1.35M
        out[y * cx * kBlockDim + x] = val;
57
27.5M
      } else {
58
27.5M
        out[val] = y * cx * kBlockDim + x;
59
27.5M
      }
60
28.8M
    }
61
1.79M
  }
62
  // Second half
63
1.79M
  for (size_t ip = cx * kBlockDim - 1; ip > 0; ip--) {
64
1.70M
    size_t i = ip - 1;
65
37.8M
    for (size_t j = 0; j <= i; j++) {
66
36.1M
      size_t x = cx * kBlockDim - 1 - (i - j);
67
36.1M
      size_t y = cx * kBlockDim - 1 - j;
68
36.1M
      if (i % 2) std::swap(x, y);
69
36.1M
      if ((y & xsm) != 0) continue;
70
27.0M
      y >>= xss;
71
27.0M
      size_t val = cur++;
72
27.0M
      if (is_lut) {
73
1.18M
        out[y * cx * kBlockDim + x] = val;
74
25.8M
      } else {
75
25.8M
        out[val] = y * cx * kBlockDim + x;
76
25.8M
      }
77
27.0M
    }
78
1.70M
  }
79
91.8k
}
ac_strategy.cc:void jxl::CoeffOrderAndLut<false>(jxl::AcStrategy, unsigned int*)
Line
Count
Source
29
80.3k
static void CoeffOrderAndLut(AcStrategy acs, coeff_order_t* out) {
30
80.3k
  size_t cx = acs.covered_blocks_x();
31
80.3k
  size_t cy = acs.covered_blocks_y();
32
80.3k
  CoefficientLayout(&cy, &cx);
33
34
  // CoefficientLayout ensures cx >= cy.
35
  // We compute the zigzag order for a cx x cx block, then discard all the
36
  // lines that are not multiple of the ratio between cx and cy.
37
80.3k
  size_t xs = cx / cy;
38
80.3k
  size_t xsm = xs - 1;
39
80.3k
  size_t xss = CeilLog2Nonzero(xs);
40
  // First half of the block
41
80.3k
  size_t cur = cx * cy;
42
1.70M
  for (size_t i = 0; i < cx * kBlockDim; i++) {
43
37.8M
    for (size_t j = 0; j <= i; j++) {
44
36.2M
      size_t x = j;
45
36.2M
      size_t y = i - j;
46
36.2M
      if (i % 2) std::swap(x, y);
47
36.2M
      if ((y & xsm) != 0) continue;
48
27.5M
      y >>= xss;
49
27.5M
      size_t val = 0;
50
27.5M
      if (x < cx && y < cy) {
51
834k
        val = y * cx + x;
52
26.6M
      } else {
53
26.6M
        val = cur++;
54
26.6M
      }
55
27.5M
      if (is_lut) {
56
0
        out[y * cx * kBlockDim + x] = val;
57
27.5M
      } else {
58
27.5M
        out[val] = y * cx * kBlockDim + x;
59
27.5M
      }
60
27.5M
    }
61
1.62M
  }
62
  // Second half
63
1.62M
  for (size_t ip = cx * kBlockDim - 1; ip > 0; ip--) {
64
1.54M
    size_t i = ip - 1;
65
36.1M
    for (size_t j = 0; j <= i; j++) {
66
34.5M
      size_t x = cx * kBlockDim - 1 - (i - j);
67
34.5M
      size_t y = cx * kBlockDim - 1 - j;
68
34.5M
      if (i % 2) std::swap(x, y);
69
34.5M
      if ((y & xsm) != 0) continue;
70
25.8M
      y >>= xss;
71
25.8M
      size_t val = cur++;
72
25.8M
      if (is_lut) {
73
0
        out[y * cx * kBlockDim + x] = val;
74
25.8M
      } else {
75
25.8M
        out[val] = y * cx * kBlockDim + x;
76
25.8M
      }
77
25.8M
    }
78
1.54M
  }
79
80.3k
}
ac_strategy.cc:void jxl::CoeffOrderAndLut<true>(jxl::AcStrategy, unsigned int*)
Line
Count
Source
29
11.4k
static void CoeffOrderAndLut(AcStrategy acs, coeff_order_t* out) {
30
11.4k
  size_t cx = acs.covered_blocks_x();
31
11.4k
  size_t cy = acs.covered_blocks_y();
32
11.4k
  CoefficientLayout(&cy, &cx);
33
34
  // CoefficientLayout ensures cx >= cy.
35
  // We compute the zigzag order for a cx x cx block, then discard all the
36
  // lines that are not multiple of the ratio between cx and cy.
37
11.4k
  size_t xs = cx / cy;
38
11.4k
  size_t xsm = xs - 1;
39
11.4k
  size_t xss = CeilLog2Nonzero(xs);
40
  // First half of the block
41
11.4k
  size_t cur = cx * cy;
42
176k
  for (size_t i = 0; i < cx * kBlockDim; i++) {
43
1.90M
    for (size_t j = 0; j <= i; j++) {
44
1.73M
      size_t x = j;
45
1.73M
      size_t y = i - j;
46
1.73M
      if (i % 2) std::swap(x, y);
47
1.73M
      if ((y & xsm) != 0) continue;
48
1.35M
      y >>= xss;
49
1.35M
      size_t val = 0;
50
1.35M
      if (x < cx && y < cy) {
51
39.6k
        val = y * cx + x;
52
1.31M
      } else {
53
1.31M
        val = cur++;
54
1.31M
      }
55
1.35M
      if (is_lut) {
56
1.35M
        out[y * cx * kBlockDim + x] = val;
57
1.35M
      } else {
58
0
        out[val] = y * cx * kBlockDim + x;
59
0
      }
60
1.35M
    }
61
165k
  }
62
  // Second half
63
165k
  for (size_t ip = cx * kBlockDim - 1; ip > 0; ip--) {
64
153k
    size_t i = ip - 1;
65
1.72M
    for (size_t j = 0; j <= i; j++) {
66
1.57M
      size_t x = cx * kBlockDim - 1 - (i - j);
67
1.57M
      size_t y = cx * kBlockDim - 1 - j;
68
1.57M
      if (i % 2) std::swap(x, y);
69
1.57M
      if ((y & xsm) != 0) continue;
70
1.18M
      y >>= xss;
71
1.18M
      size_t val = cur++;
72
1.18M
      if (is_lut) {
73
1.18M
        out[y * cx * kBlockDim + x] = val;
74
1.18M
      } else {
75
0
        out[val] = y * cx * kBlockDim + x;
76
0
      }
77
1.18M
    }
78
153k
  }
79
11.4k
}
80
81
80.3k
void AcStrategy::ComputeNaturalCoeffOrder(coeff_order_t* order) const {
82
80.3k
  CoeffOrderAndLut</*is_lut=*/false>(*this, order);
83
80.3k
}
84
11.4k
void AcStrategy::ComputeNaturalCoeffOrderLut(coeff_order_t* lut) const {
85
11.4k
  CoeffOrderAndLut</*is_lut=*/true>(*this, lut);
86
11.4k
}
87
88
#if JXL_CXX_LANG < JXL_CXX_17
89
constexpr size_t AcStrategy::kMaxCoeffBlocks;
90
constexpr size_t AcStrategy::kMaxBlockDim;
91
constexpr size_t AcStrategy::kMaxCoeffArea;
92
#endif
93
94
StatusOr<AcStrategyImage> AcStrategyImage::Create(
95
176k
    JxlMemoryManager* memory_manager, size_t xsize, size_t ysize) {
96
176k
  AcStrategyImage img;
97
176k
  JXL_ASSIGN_OR_RETURN(img.layers_,
98
176k
                       ImageB::Create(memory_manager, xsize, ysize));
99
176k
  img.row_ = img.layers_.Row(0);
100
176k
  img.stride_ = img.layers_.PixelsPerRow();
101
176k
  return img;
102
176k
}
103
104
0
size_t AcStrategyImage::CountBlocks(AcStrategyType type) const {
105
0
  size_t ret = 0;
106
0
  for (size_t y = 0; y < layers_.ysize(); y++) {
107
0
    const uint8_t* JXL_RESTRICT row = layers_.ConstRow(y);
108
0
    for (size_t x = 0; x < layers_.xsize(); x++) {
109
0
      if (row[x] == ((static_cast<uint8_t>(type) << 1) | 1)) ret++;
110
0
    }
111
0
  }
112
0
  return ret;
113
0
}
114
115
}  // namespace jxl