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/aux_out.h"
7 
8 #include <stdint.h>
9 
10 #include <numeric>  // accumulate
11 
12 #include "lib/jxl/aux_out_fwd.h"
13 #include "lib/jxl/enc_bit_writer.h"
14 
15 namespace jxl {
16 
Print(size_t num_inputs) const17 void AuxOut::Print(size_t num_inputs) const {
18   if (num_inputs == 0) return;
19 
20   LayerTotals all_layers;
21   for (size_t i = 0; i < layers.size(); ++i) {
22     all_layers.Assimilate(layers[i]);
23   }
24 
25   printf("Average butteraugli iters: %10.2f\n",
26          num_butteraugli_iters * 1.0 / num_inputs);
27 
28   for (size_t i = 0; i < layers.size(); ++i) {
29     if (layers[i].total_bits != 0) {
30       printf("Total layer bits %-10s\t", LayerName(i));
31       printf("%10f%%", 100.0 * layers[i].total_bits / all_layers.total_bits);
32       layers[i].Print(num_inputs);
33     }
34   }
35   printf("Total image size           ");
36   all_layers.Print(num_inputs);
37 
38   const uint32_t dc_pred_total =
39       std::accumulate(dc_pred_usage.begin(), dc_pred_usage.end(), 0u);
40   const uint32_t dc_pred_total_xb =
41       std::accumulate(dc_pred_usage_xb.begin(), dc_pred_usage_xb.end(), 0u);
42   if (dc_pred_total + dc_pred_total_xb != 0) {
43     printf("\nDC pred     Y                XB:\n");
44     for (size_t i = 0; i < dc_pred_usage.size(); ++i) {
45       printf("  %6u (%5.2f%%)    %6u (%5.2f%%)\n", dc_pred_usage[i],
46              100.0 * dc_pred_usage[i] / dc_pred_total, dc_pred_usage_xb[i],
47              100.0 * dc_pred_usage_xb[i] / dc_pred_total_xb);
48     }
49   }
50 
51   size_t total_blocks = 0;
52   size_t total_positions = 0;
53   if (total_blocks != 0 && total_positions != 0) {
54     printf("\n\t\t  Blocks\t\tPositions\t\t\tBlocks/Position\n");
55     printf(" Total:\t\t    %7zu\t\t     %7zu \t\t\t%10f%%\n\n", total_blocks,
56            total_positions, 100.0 * total_blocks / total_positions);
57   }
58 }
59 
DumpCoeffImage(const char * label,const Image3S & coeff_image) const60 void AuxOut::DumpCoeffImage(const char* label,
61                             const Image3S& coeff_image) const {
62   JXL_ASSERT(coeff_image.xsize() % 64 == 0);
63   Image3S reshuffled(coeff_image.xsize() / 8, coeff_image.ysize() * 8);
64   for (size_t c = 0; c < 3; c++) {
65     for (size_t y = 0; y < coeff_image.ysize(); y++) {
66       for (size_t x = 0; x < coeff_image.xsize(); x += 64) {
67         for (size_t i = 0; i < 64; i++) {
68           reshuffled.PlaneRow(c, 8 * y + i / 8)[x / 8 + i % 8] =
69               coeff_image.PlaneRow(c, y)[x + i];
70         }
71       }
72     }
73   }
74   DumpImage(label, reshuffled);
75 }
76 
ReclaimAndCharge(BitWriter * JXL_RESTRICT writer,BitWriter::Allotment * JXL_RESTRICT allotment,size_t layer,AuxOut * JXL_RESTRICT aux_out)77 void ReclaimAndCharge(BitWriter* JXL_RESTRICT writer,
78                       BitWriter::Allotment* JXL_RESTRICT allotment,
79                       size_t layer, AuxOut* JXL_RESTRICT aux_out) {
80   size_t used_bits, unused_bits;
81   allotment->PrivateReclaim(writer, &used_bits, &unused_bits);
82 
83 #if 0
84   printf("Layer %s bits: max %zu used %zu unused %zu\n", LayerName(layer),
85          allotment->MaxBits(), used_bits, unused_bits);
86 #endif
87 
88   // This may be a nested call with aux_out == null. Whenever we know that
89   // aux_out is null, we can call ReclaimUnused directly.
90   if (aux_out != nullptr) {
91     aux_out->layers[layer].total_bits += used_bits;
92     aux_out->layers[layer].histogram_bits += allotment->HistogramBits();
93   }
94 }
95 
96 }  // namespace jxl
97