Coverage Report

Created: 2022-08-24 06:33

/src/libjxl/lib/jxl/image_bundle.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/image_bundle.h"
7
8
#include <limits>
9
#include <utility>
10
11
#include "lib/jxl/base/byte_order.h"
12
#include "lib/jxl/base/padded_bytes.h"
13
#include "lib/jxl/base/printf_macros.h"
14
#include "lib/jxl/base/profiler.h"
15
#include "lib/jxl/codec_in_out.h"
16
#include "lib/jxl/color_management.h"
17
#include "lib/jxl/fields.h"
18
#include "lib/jxl/luminance.h"
19
20
namespace jxl {
21
22
0
void ImageBundle::ShrinkTo(size_t xsize, size_t ysize) {
23
0
  if (HasColor()) color_.ShrinkTo(xsize, ysize);
24
0
  for (ImageF& ec : extra_channels_) {
25
0
    ec.ShrinkTo(xsize, ysize);
26
0
  }
27
0
}
28
29
// Called by all other SetFrom*.
30
void ImageBundle::SetFromImage(Image3F&& color,
31
26.4k
                               const ColorEncoding& c_current) {
32
26.4k
  JXL_CHECK(color.xsize() != 0 && color.ysize() != 0);
33
26.4k
  JXL_CHECK(metadata_->color_encoding.IsGray() == c_current.IsGray());
34
26.4k
  color_ = std::move(color);
35
26.4k
  c_current_ = c_current;
36
26.4k
  VerifySizes();
37
26.4k
}
38
39
184
void ImageBundle::VerifyMetadata() const {
40
184
  JXL_CHECK(!c_current_.ICC().empty());
41
184
  JXL_CHECK(metadata_->color_encoding.IsGray() == IsGray());
42
43
184
  if (metadata_->HasAlpha() && alpha().xsize() == 0) {
44
0
    JXL_ABORT("MD alpha_bits %u IB alpha %" PRIuS " x %" PRIuS "\n",
45
0
              metadata_->GetAlphaBits(), alpha().xsize(), alpha().ysize());
46
0
  }
47
184
  const uint32_t alpha_bits = metadata_->GetAlphaBits();
48
184
  JXL_CHECK(alpha_bits <= 32);
49
50
  // metadata_->num_extra_channels may temporarily differ from
51
  // extra_channels_.size(), e.g. after SetAlpha. They are synced by the next
52
  // call to VisitFields.
53
184
}
54
55
26.5k
void ImageBundle::VerifySizes() const {
56
26.5k
  const size_t xs = xsize();
57
26.5k
  const size_t ys = ysize();
58
59
26.5k
  if (HasExtraChannels()) {
60
0
    JXL_CHECK(xs != 0 && ys != 0);
61
0
    for (const ImageF& ec : extra_channels_) {
62
0
      JXL_CHECK(ec.xsize() == xs);
63
0
      JXL_CHECK(ec.ysize() == ys);
64
0
    }
65
0
  }
66
26.5k
}
67
68
0
size_t ImageBundle::DetectRealBitdepth() const {
69
0
  return metadata_->bit_depth.bits_per_sample;
70
71
  // TODO(lode): let this function return lower bit depth if possible, e.g.
72
  // return 8 bits in case the original image came from a 16-bit PNG that
73
  // was in fact representable as 8-bit PNG. Ensure that the implementation
74
  // returns 16 if e.g. two consecutive 16-bit values appeared in the original
75
  // image (such as 32768 and 32769), take into account that e.g. the values
76
  // 3-bit can represent is not a superset of the values 2-bit can represent,
77
  // and there may be slight imprecisions in the floating point image.
78
0
}
79
80
0
const ImageF& ImageBundle::black() const {
81
0
  JXL_ASSERT(HasBlack());
82
0
  const size_t ec = metadata_->Find(ExtraChannel::kBlack) -
83
0
                    metadata_->extra_channel_info.data();
84
0
  JXL_ASSERT(ec < extra_channels_.size());
85
0
  return extra_channels_[ec];
86
0
}
87
1.36k
const ImageF& ImageBundle::alpha() const {
88
1.36k
  JXL_ASSERT(HasAlpha());
89
1.36k
  const size_t ec = metadata_->Find(ExtraChannel::kAlpha) -
90
1.36k
                    metadata_->extra_channel_info.data();
91
1.36k
  JXL_ASSERT(ec < extra_channels_.size());
92
1.36k
  return extra_channels_[ec];
93
1.36k
}
94
0
ImageF* ImageBundle::alpha() {
95
0
  JXL_ASSERT(HasAlpha());
96
0
  const size_t ec = metadata_->Find(ExtraChannel::kAlpha) -
97
0
                    metadata_->extra_channel_info.data();
98
0
  JXL_ASSERT(ec < extra_channels_.size());
99
0
  return &extra_channels_[ec];
100
0
}
101
102
0
void ImageBundle::SetAlpha(ImageF&& alpha, bool alpha_is_premultiplied) {
103
0
  const ExtraChannelInfo* eci = metadata_->Find(ExtraChannel::kAlpha);
104
  // Must call SetAlphaBits first, otherwise we don't know which channel index
105
0
  JXL_CHECK(eci != nullptr);
106
0
  JXL_CHECK(alpha.xsize() != 0 && alpha.ysize() != 0);
107
0
  JXL_CHECK(eci->alpha_associated == alpha_is_premultiplied);
108
0
  if (extra_channels_.size() < metadata_->extra_channel_info.size()) {
109
    // TODO(jon): get rid of this case
110
0
    extra_channels_.insert(
111
0
        extra_channels_.begin() + (eci - metadata_->extra_channel_info.data()),
112
0
        std::move(alpha));
113
0
  } else {
114
0
    extra_channels_[eci - metadata_->extra_channel_info.data()] =
115
0
        std::move(alpha);
116
0
  }
117
  // num_extra_channels is automatically set in visitor
118
0
  VerifySizes();
119
0
}
120
121
92
void ImageBundle::SetExtraChannels(std::vector<ImageF>&& extra_channels) {
122
92
  for (const ImageF& plane : extra_channels) {
123
0
    JXL_CHECK(plane.xsize() != 0 && plane.ysize() != 0);
124
0
  }
125
92
  extra_channels_ = std::move(extra_channels);
126
92
  VerifySizes();
127
92
}
128
}  // namespace jxl