Coverage Report

Created: 2025-07-12 06:19

/src/guetzli/guetzli/output_image.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2016 Google Inc.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#ifndef GUETZLI_OUTPUT_IMAGE_H_
18
#define GUETZLI_OUTPUT_IMAGE_H_
19
20
#include <stdint.h>
21
#include <vector>
22
23
#include "guetzli/jpeg_data.h"
24
25
namespace guetzli {
26
27
class OutputImageComponent {
28
 public:
29
  OutputImageComponent(int w, int h);
30
31
  void Reset(int factor_x, int factor_y);
32
33
0
  int width() const { return width_; }
34
0
  int height() const { return height_; }
35
2.00M
  int factor_x() const { return factor_x_; }
36
2.00M
  int factor_y() const { return factor_y_; }
37
13.6M
  int width_in_blocks() const { return width_in_blocks_; }
38
14.1M
  int height_in_blocks() const { return height_in_blocks_; }
39
409k
  const coeff_t* coeffs() const { return &coeffs_[0]; }
40
2.56M
  const int* quant() const { return &quant_[0]; }
41
  bool IsAllZero() const;
42
43
  // Fills in block[] with the 8x8 coefficient block with block coordinates
44
  // (block_x, block_y).
45
  // NOTE: If the component is 2x2 subsampled, this corresponds to the 16x16
46
  // pixel area with upper-left corner (16 * block_x, 16 * block_y).
47
  void GetCoeffBlock(int block_x, int block_y,
48
                     coeff_t block[kDCTBlockSize]) const;
49
50
  // Fills in out[] array with the 8-bit pixel view of this component cropped
51
  // to the specified window. The window's upper-left corner, (xmin, ymin) must
52
  // be within the image, but the window may extend past the image. In that
53
  // case the edge pixels are duplicated.
54
  void ToPixels(int xmin, int ymin, int xsize, int ysize,
55
                uint8_t* out, int stride) const;
56
57
  // Fills in out[] array with the floating-point precision pixel view of the
58
  // component.
59
  // REQUIRES: factor_x() == 1 and factor_y() == 1.
60
  void ToFloatPixels(float* out, int stride) const;
61
62
  // Sets the 8x8 coefficient block with block coordinates (block_x, block_y)
63
  // to block[].
64
  // NOTE: If the component is 2x2 subsampled, this corresponds to the 16x16
65
  // pixel area with upper-left corner (16 * block_x, 16 * block_y).
66
  // REQUIRES: block[k] % quant()[k] == 0 for each coefficient index k.
67
  void SetCoeffBlock(int block_x, int block_y,
68
                     const coeff_t block[kDCTBlockSize]);
69
70
  // Requires that comp is not downsampled.
71
  void CopyFromJpegComponent(const JPEGComponent& comp,
72
                             int factor_x, int factor_y,
73
                             const int* quant);
74
75
  void ApplyGlobalQuantization(const int q[kDCTBlockSize]);
76
77
 private:
78
  void UpdatePixelsForBlock(int block_x, int block_y,
79
                            const uint8_t idct[kDCTBlockSize]);
80
81
  const int width_;
82
  const int height_;
83
  int factor_x_;
84
  int factor_y_;
85
  int width_in_blocks_;
86
  int height_in_blocks_;
87
  int num_blocks_;
88
  std::vector<coeff_t> coeffs_;
89
  std::vector<uint16_t> pixels_;
90
  // Same as last argument of ApplyGlobalQuantization() (default is all 1s).
91
  int quant_[kDCTBlockSize];
92
};
93
94
class OutputImage {
95
 public:
96
  OutputImage(int w, int h);
97
98
6.08M
  int width() const { return width_; }
99
5.99M
  int height() const { return height_; }
100
101
19.0M
  OutputImageComponent& component(int c) { return components_[c]; }
102
1.14M
  const OutputImageComponent& component(int c) const { return components_[c]; }
103
104
  // Requires that jpg is in YUV444 format.
105
  void CopyFromJpegData(const JPEGData& jpg);
106
107
  void ApplyGlobalQuantization(const int q[3][kDCTBlockSize]);
108
109
  // If sharpen or blur are enabled, preprocesses image before downsampling U or
110
  // V to improve butteraugli score and/or reduce file size.
111
  // u_sharpen: sharpen the u channel in red areas to improve score (not as
112
  // effective as v_sharpen, blue is not so important)
113
  // u_blur: blur the u channel in some areas to reduce file size
114
  // v_sharpen: sharpen the v channel in red areas to improve score
115
  // v_blur: blur the v channel in some areas to reduce file size
116
  struct DownsampleConfig {
117
    // Default is YUV420.
118
0
    DownsampleConfig() : u_factor_x(2), u_factor_y(2),
119
0
                         v_factor_x(2), v_factor_y(2),
120
0
                         u_sharpen(true), u_blur(true),
121
0
                         v_sharpen(true), v_blur(true),
122
0
                         use_silver_screen(false) {}
123
    int u_factor_x;
124
    int u_factor_y;
125
    int v_factor_x;
126
    int v_factor_y;
127
    bool u_sharpen;
128
    bool u_blur;
129
    bool v_sharpen;
130
    bool v_blur;
131
    bool use_silver_screen;
132
  };
133
134
  void Downsample(const DownsampleConfig& cfg);
135
136
  void SaveToJpegData(JPEGData* jpg) const;
137
138
  std::vector<uint8_t> ToSRGB() const;
139
140
  std::vector<uint8_t> ToSRGB(int xmin, int ymin, int xsize, int ysize) const;
141
142
  void ToLinearRGB(std::vector<std::vector<float> >* rgb) const;
143
144
  void ToLinearRGB(int xmin, int ymin, int xsize, int ysize,
145
                   std::vector<std::vector<float> >* rgb) const;
146
147
  std::string FrameTypeStr() const;
148
149
 private:
150
  const int width_;
151
  const int height_;
152
  std::vector<OutputImageComponent> components_;
153
};
154
155
}  // namespace guetzli
156
157
#endif  // GUETZLI_OUTPUT_IMAGE_H_