/src/libjxl/lib/jxl/progressive_split.cc
Line | Count | Source (jump to first uncovered line) |
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/progressive_split.h" |
7 | | |
8 | | #include <string.h> |
9 | | |
10 | | #include <algorithm> |
11 | | #include <memory> |
12 | | |
13 | | #include "lib/jxl/common.h" |
14 | | #include "lib/jxl/image.h" |
15 | | |
16 | | namespace jxl { |
17 | | |
18 | | template <typename T> |
19 | | void ProgressiveSplitter::SplitACCoefficients( |
20 | | const T* JXL_RESTRICT block, size_t size, const AcStrategy& acs, size_t bx, |
21 | 92 | size_t by, size_t offset, T* JXL_RESTRICT output[kMaxNumPasses][3]) { |
22 | 92 | auto shift_right_round0 = [&](T v, int shift) { |
23 | 0 | T one_if_negative = static_cast<uint32_t>(v) >> 31; |
24 | 0 | T add = (one_if_negative << shift) - one_if_negative; |
25 | 0 | return (v + add) >> shift; |
26 | 0 | }; Unexecuted instantiation: jxl::ProgressiveSplitter::SplitACCoefficients<int>(int const*, unsigned long, jxl::AcStrategy const&, unsigned long, unsigned long, unsigned long, int* restrict (*) [3])::{lambda(int, int)#1}::operator()(int, int) const Unexecuted instantiation: jxl::ProgressiveSplitter::SplitACCoefficients<short>(short const*, unsigned long, jxl::AcStrategy const&, unsigned long, unsigned long, unsigned long, short* restrict (*) [3])::{lambda(short, int)#1}::operator()(short, int) const |
27 | | // Early quit for the simple case of only one pass. |
28 | 92 | if (mode_.num_passes == 1) { |
29 | 368 | for (size_t c = 0; c < 3; c++) { |
30 | 276 | memcpy(output[0][c] + offset, block + c * size, sizeof(T) * size); |
31 | 276 | } |
32 | 92 | return; |
33 | 92 | } |
34 | 0 | size_t ncoeffs_all_done_from_earlier_passes = 1; |
35 | |
|
36 | 0 | int previous_pass_shift = 0; |
37 | 0 | for (size_t num_pass = 0; num_pass < mode_.num_passes; num_pass++) { // pass |
38 | | // Zero out output block. |
39 | 0 | for (size_t c = 0; c < 3; c++) { |
40 | 0 | memset(output[num_pass][c] + offset, 0, size * sizeof(T)); |
41 | 0 | } |
42 | 0 | const int pass_shift = mode_.passes[num_pass].shift; |
43 | 0 | size_t frame_ncoeffs = mode_.passes[num_pass].num_coefficients; |
44 | 0 | for (size_t c = 0; c < 3; c++) { // color-channel |
45 | 0 | size_t xsize = acs.covered_blocks_x(); |
46 | 0 | size_t ysize = acs.covered_blocks_y(); |
47 | 0 | CoefficientLayout(&ysize, &xsize); |
48 | 0 | for (size_t y = 0; y < ysize * frame_ncoeffs; y++) { // superblk-y |
49 | 0 | for (size_t x = 0; x < xsize * frame_ncoeffs; x++) { // superblk-x |
50 | 0 | size_t pos = y * xsize * kBlockDim + x; |
51 | 0 | if (x < xsize * ncoeffs_all_done_from_earlier_passes && |
52 | 0 | y < ysize * ncoeffs_all_done_from_earlier_passes) { |
53 | | // This coefficient was already included in an earlier pass, |
54 | | // which included a genuinely smaller set of coefficients. |
55 | 0 | continue; |
56 | 0 | } |
57 | 0 | T v = block[c * size + pos]; |
58 | | // Previous pass discarded some bits: do not encode them again. |
59 | 0 | if (previous_pass_shift != 0) { |
60 | 0 | T previous_v = shift_right_round0(v, previous_pass_shift) * |
61 | 0 | (1 << previous_pass_shift); |
62 | 0 | v -= previous_v; |
63 | 0 | } |
64 | 0 | output[num_pass][c][offset + pos] = shift_right_round0(v, pass_shift); |
65 | 0 | } // superblk-x |
66 | 0 | } // superblk-y |
67 | 0 | } // color-channel |
68 | | // We just finished a pass. |
69 | | // Hence, we are now guaranteed to have included all coeffs up to |
70 | | // frame_ncoeffs in every block, unless the current pass is shifted. |
71 | 0 | if (mode_.passes[num_pass].shift == 0) { |
72 | 0 | ncoeffs_all_done_from_earlier_passes = frame_ncoeffs; |
73 | 0 | } |
74 | 0 | previous_pass_shift = mode_.passes[num_pass].shift; |
75 | 0 | } // num_pass |
76 | 0 | } void jxl::ProgressiveSplitter::SplitACCoefficients<int>(int const*, unsigned long, jxl::AcStrategy const&, unsigned long, unsigned long, unsigned long, int* restrict (*) [3]) Line | Count | Source | 21 | 92 | size_t by, size_t offset, T* JXL_RESTRICT output[kMaxNumPasses][3]) { | 22 | 92 | auto shift_right_round0 = [&](T v, int shift) { | 23 | 92 | T one_if_negative = static_cast<uint32_t>(v) >> 31; | 24 | 92 | T add = (one_if_negative << shift) - one_if_negative; | 25 | 92 | return (v + add) >> shift; | 26 | 92 | }; | 27 | | // Early quit for the simple case of only one pass. | 28 | 92 | if (mode_.num_passes == 1) { | 29 | 368 | for (size_t c = 0; c < 3; c++) { | 30 | 276 | memcpy(output[0][c] + offset, block + c * size, sizeof(T) * size); | 31 | 276 | } | 32 | 92 | return; | 33 | 92 | } | 34 | 0 | size_t ncoeffs_all_done_from_earlier_passes = 1; | 35 | |
| 36 | 0 | int previous_pass_shift = 0; | 37 | 0 | for (size_t num_pass = 0; num_pass < mode_.num_passes; num_pass++) { // pass | 38 | | // Zero out output block. | 39 | 0 | for (size_t c = 0; c < 3; c++) { | 40 | 0 | memset(output[num_pass][c] + offset, 0, size * sizeof(T)); | 41 | 0 | } | 42 | 0 | const int pass_shift = mode_.passes[num_pass].shift; | 43 | 0 | size_t frame_ncoeffs = mode_.passes[num_pass].num_coefficients; | 44 | 0 | for (size_t c = 0; c < 3; c++) { // color-channel | 45 | 0 | size_t xsize = acs.covered_blocks_x(); | 46 | 0 | size_t ysize = acs.covered_blocks_y(); | 47 | 0 | CoefficientLayout(&ysize, &xsize); | 48 | 0 | for (size_t y = 0; y < ysize * frame_ncoeffs; y++) { // superblk-y | 49 | 0 | for (size_t x = 0; x < xsize * frame_ncoeffs; x++) { // superblk-x | 50 | 0 | size_t pos = y * xsize * kBlockDim + x; | 51 | 0 | if (x < xsize * ncoeffs_all_done_from_earlier_passes && | 52 | 0 | y < ysize * ncoeffs_all_done_from_earlier_passes) { | 53 | | // This coefficient was already included in an earlier pass, | 54 | | // which included a genuinely smaller set of coefficients. | 55 | 0 | continue; | 56 | 0 | } | 57 | 0 | T v = block[c * size + pos]; | 58 | | // Previous pass discarded some bits: do not encode them again. | 59 | 0 | if (previous_pass_shift != 0) { | 60 | 0 | T previous_v = shift_right_round0(v, previous_pass_shift) * | 61 | 0 | (1 << previous_pass_shift); | 62 | 0 | v -= previous_v; | 63 | 0 | } | 64 | 0 | output[num_pass][c][offset + pos] = shift_right_round0(v, pass_shift); | 65 | 0 | } // superblk-x | 66 | 0 | } // superblk-y | 67 | 0 | } // color-channel | 68 | | // We just finished a pass. | 69 | | // Hence, we are now guaranteed to have included all coeffs up to | 70 | | // frame_ncoeffs in every block, unless the current pass is shifted. | 71 | 0 | if (mode_.passes[num_pass].shift == 0) { | 72 | 0 | ncoeffs_all_done_from_earlier_passes = frame_ncoeffs; | 73 | 0 | } | 74 | 0 | previous_pass_shift = mode_.passes[num_pass].shift; | 75 | 0 | } // num_pass | 76 | 0 | } |
Unexecuted instantiation: void jxl::ProgressiveSplitter::SplitACCoefficients<short>(short const*, unsigned long, jxl::AcStrategy const&, unsigned long, unsigned long, unsigned long, short* restrict (*) [3]) |
77 | | |
78 | | template void ProgressiveSplitter::SplitACCoefficients<int32_t>( |
79 | | const int32_t* JXL_RESTRICT, size_t, const AcStrategy&, size_t, size_t, |
80 | | size_t, int32_t* JXL_RESTRICT[kMaxNumPasses][3]); |
81 | | |
82 | | template void ProgressiveSplitter::SplitACCoefficients<int16_t>( |
83 | | const int16_t* JXL_RESTRICT, size_t, const AcStrategy&, size_t, size_t, |
84 | | size_t, int16_t* JXL_RESTRICT[kMaxNumPasses][3]); |
85 | | |
86 | | } // namespace jxl |