tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

image_bundle.h (9233B)


      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 #ifndef LIB_JXL_IMAGE_BUNDLE_H_
      7 #define LIB_JXL_IMAGE_BUNDLE_H_
      8 
      9 // The main image or frame consists of a bundle of associated images.
     10 
     11 #include <jxl/cms_interface.h>
     12 #include <jxl/memory_manager.h>
     13 
     14 #include <cstddef>
     15 #include <cstdint>
     16 #include <memory>
     17 #include <string>
     18 #include <utility>
     19 #include <vector>
     20 
     21 #include "lib/jxl/base/common.h"
     22 #include "lib/jxl/base/data_parallel.h"
     23 #include "lib/jxl/base/rect.h"
     24 #include "lib/jxl/base/status.h"
     25 #include "lib/jxl/color_encoding_internal.h"
     26 #include "lib/jxl/common.h"  // JPEGXL_ENABLE_TRANSCODE_JPEG
     27 #include "lib/jxl/frame_header.h"
     28 #include "lib/jxl/image.h"
     29 #include "lib/jxl/image_metadata.h"
     30 #include "lib/jxl/image_ops.h"
     31 #include "lib/jxl/jpeg/jpeg_data.h"
     32 
     33 namespace jxl {
     34 
     35 // A bundle of color/alpha/depth/plane images.
     36 class ImageBundle {
     37 public:
     38  // Uninitialized state for use as output parameter.
     39  explicit ImageBundle(JxlMemoryManager* memory_manager)
     40      : memory_manager_(memory_manager), metadata_(nullptr) {}
     41  // Caller is responsible for setting metadata before calling Set*.
     42  ImageBundle(JxlMemoryManager* memory_manager, const ImageMetadata* metadata)
     43      : memory_manager_(memory_manager), metadata_(metadata) {}
     44 
     45  // Move-only (allows storing in std::vector).
     46  ImageBundle(ImageBundle&&) = default;
     47  ImageBundle& operator=(ImageBundle&&) = default;
     48 
     49  StatusOr<ImageBundle> Copy() const {
     50    JxlMemoryManager* memory_manager = this->memory_manager();
     51    ImageBundle copy(memory_manager, metadata_);
     52    JXL_ASSIGN_OR_RETURN(
     53        copy.color_,
     54        Image3F::Create(memory_manager, color_.xsize(), color_.ysize()));
     55    JXL_RETURN_IF_ERROR(CopyImageTo(color_, &copy.color_));
     56    copy.c_current_ = c_current_;
     57    copy.extra_channels_.reserve(extra_channels_.size());
     58    for (const ImageF& plane : extra_channels_) {
     59      JXL_ASSIGN_OR_RETURN(
     60          ImageF ec,
     61          ImageF::Create(memory_manager, plane.xsize(), plane.ysize()));
     62      JXL_RETURN_IF_ERROR(CopyImageTo(plane, &ec));
     63      copy.extra_channels_.emplace_back(std::move(ec));
     64    }
     65 
     66    copy.jpeg_data =
     67        jpeg_data ? make_unique<jpeg::JPEGData>(*jpeg_data) : nullptr;
     68    copy.color_transform = color_transform;
     69    copy.chroma_subsampling = chroma_subsampling;
     70 
     71    return copy;
     72  }
     73 
     74  // -- SIZE
     75 
     76  size_t xsize() const {
     77    if (IsJPEG()) return jpeg_data->width;
     78    if (color_.xsize() != 0) return color_.xsize();
     79    return extra_channels_.empty() ? 0 : extra_channels_[0].xsize();
     80  }
     81  size_t ysize() const {
     82    if (IsJPEG()) return jpeg_data->height;
     83    if (color_.ysize() != 0) return color_.ysize();
     84    return extra_channels_.empty() ? 0 : extra_channels_[0].ysize();
     85  }
     86  Status ShrinkTo(size_t xsize, size_t ysize);
     87 
     88  // sizes taking orientation into account
     89  size_t oriented_xsize() const {
     90    if (static_cast<uint32_t>(metadata_->GetOrientation()) > 4) {
     91      return ysize();
     92    } else {
     93      return xsize();
     94    }
     95  }
     96  size_t oriented_ysize() const {
     97    if (static_cast<uint32_t>(metadata_->GetOrientation()) > 4) {
     98      return xsize();
     99    } else {
    100      return ysize();
    101    }
    102  }
    103 
    104  JxlMemoryManager* memory_manager_;
    105 
    106  // -- COLOR
    107 
    108  JxlMemoryManager* memory_manager() const { return memory_manager_; }
    109 
    110  // Whether color() is valid/usable. Returns true in most cases. Even images
    111  // with spot colors (one example of when !planes().empty()) typically have a
    112  // part that can be converted to RGB.
    113  bool HasColor() const { return color_.xsize() != 0; }
    114 
    115  // For resetting the size when switching from a reference to main frame.
    116  void RemoveColor() { color_ = Image3F(); }
    117 
    118  // Do not use if !HasColor().
    119  const Image3F& color() const {
    120    // If this fails, Set* was not called - perhaps because decoding failed?
    121    JXL_DASSERT(HasColor());
    122    return color_;
    123  }
    124 
    125  // Do not use if !HasColor().
    126  Image3F* color() {
    127    JXL_DASSERT(HasColor());
    128    return &color_;
    129  }
    130 
    131  // If c_current.IsGray(), all planes must be identical. NOTE: c_current is
    132  // independent of metadata()->color_encoding, which is the original, whereas
    133  // a decoder might return pixels in a different c_current.
    134  // This only sets the color channels, you must also make extra channels
    135  // match the amount that is in the metadata.
    136  Status SetFromImage(Image3F&& color, const ColorEncoding& c_current);
    137 
    138  // -- COLOR ENCODING
    139 
    140  const ColorEncoding& c_current() const { return c_current_; }
    141 
    142  // Returns whether the color image has identical planes. Once established by
    143  // Set*, remains unchanged until a subsequent Set* or TransformTo.
    144  bool IsGray() const { return c_current_.IsGray(); }
    145 
    146  bool IsSRGB() const { return c_current_.IsSRGB(); }
    147  bool IsLinearSRGB() const { return c_current_.IsLinearSRGB(); }
    148 
    149  // Set the c_current profile without doing any transformation, e.g. if the
    150  // transformation was already applied.
    151  void OverrideProfile(const ColorEncoding& new_c_current) {
    152    c_current_ = new_c_current;
    153  }
    154 
    155  // TODO(lode): TransformTo and CopyTo are implemented in enc_image_bundle.cc,
    156  // move these functions out of this header file and class, to
    157  // enc_image_bundle.h.
    158 
    159  // Transforms color to c_desired and sets c_current to c_desired. Alpha and
    160  // metadata remains unchanged.
    161  Status TransformTo(const ColorEncoding& c_desired, const JxlCmsInterface& cms,
    162                     ThreadPool* pool = nullptr);
    163  // Copies this:rect, converts to c_desired, and allocates+fills out.
    164  Status CopyTo(const Rect& rect, const ColorEncoding& c_desired,
    165                const JxlCmsInterface& cms, Image3F* out,
    166                ThreadPool* pool = nullptr) const;
    167 
    168  // Detect 'real' bit depth, which can be lower than nominal bit depth
    169  // (this is common in PNG), returns 'real' bit depth
    170  size_t DetectRealBitdepth() const;
    171 
    172  // -- ALPHA
    173 
    174  Status SetAlpha(ImageF&& alpha);
    175  bool HasAlpha() const {
    176    return metadata_->Find(ExtraChannel::kAlpha) != nullptr;
    177  }
    178  bool AlphaIsPremultiplied() const {
    179    const ExtraChannelInfo* eci = metadata_->Find(ExtraChannel::kAlpha);
    180    return (eci == nullptr) ? false : eci->alpha_associated;
    181  }
    182  const ImageF* alpha() const;
    183  ImageF* alpha();
    184 
    185  // -- EXTRA CHANNELS
    186  bool HasBlack() const {
    187    return metadata_->Find(ExtraChannel::kBlack) != nullptr;
    188  }
    189  const ImageF* black() const;
    190 
    191  // Extra channels of unknown interpretation (e.g. spot colors).
    192  Status SetExtraChannels(std::vector<ImageF>&& extra_channels);
    193  void ClearExtraChannels() { extra_channels_.clear(); }
    194  bool HasExtraChannels() const { return !extra_channels_.empty(); }
    195  const std::vector<ImageF>& extra_channels() const { return extra_channels_; }
    196  std::vector<ImageF>& extra_channels() { return extra_channels_; }
    197 
    198  const ImageMetadata* metadata() const { return metadata_; }
    199 
    200  Status VerifyMetadata() const;
    201 
    202  void SetDecodedBytes(size_t decoded_bytes) { decoded_bytes_ = decoded_bytes; }
    203  size_t decoded_bytes() const { return decoded_bytes_; }
    204 
    205  // -- JPEG transcoding:
    206 
    207  // Returns true if image does or will represent quantized DCT-8 coefficients,
    208  // stored in 8x8 pixel regions.
    209  bool IsJPEG() const {
    210 #if JPEGXL_ENABLE_TRANSCODE_JPEG
    211    return jpeg_data != nullptr;
    212 #else   // JPEGXL_ENABLE_TRANSCODE_JPEG
    213    return false;
    214 #endif  // JPEGXL_ENABLE_TRANSCODE_JPEG
    215  }
    216 
    217  std::unique_ptr<jpeg::JPEGData> jpeg_data;
    218  // these fields are used to signal the input JPEG color space
    219  // NOTE: JPEG doesn't actually provide a way to determine whether YCbCr was
    220  // applied or not.
    221  ColorTransform color_transform = ColorTransform::kNone;
    222  YCbCrChromaSubsampling chroma_subsampling;
    223 
    224  FrameOrigin origin{0, 0};
    225 
    226  // Animation-related information, corresponding to the timecode and duration
    227  // fields of the jxl::AnimationFrame of the jxl::FrameHeader.
    228  // TODO(lode): ImageBundle is used here to carry the information from
    229  // jxl::FrameHeader, consider instead passing a jxl::FrameHeader directly to
    230  // EncodeFrame or having a field of that type here.
    231  uint32_t duration = 0;
    232  uint32_t timecode = 0;
    233 
    234  // TODO(lode): these fields do not match the JXL frame header, it should be
    235  // possible to specify up to 4 (3 if nonzero duration) slots to save this
    236  // frame as reference (see save_as_reference).
    237  bool use_for_next_frame = false;
    238  bool blend = false;
    239  BlendMode blendmode = BlendMode::kBlend;
    240 
    241  std::string name;
    242 
    243 private:
    244  // Called after any Set* to ensure their sizes are compatible.
    245  Status VerifySizes() const;
    246 
    247  // Required for TransformTo so that an ImageBundle is self-sufficient. Always
    248  // points to the same thing, but cannot be const-pointer because that prevents
    249  // the compiler from generating a move ctor.
    250  const ImageMetadata* metadata_;
    251 
    252  // Initialized by Set*:
    253  Image3F color_;  // If empty, planes_ is not; all planes equal if IsGray().
    254  ColorEncoding c_current_;  // of color_
    255 
    256  // Initialized by SetPlanes; size = ImageMetadata.num_extra_channels
    257  std::vector<ImageF> extra_channels_;
    258 
    259  // How many bytes of the input were actually read.
    260  size_t decoded_bytes_ = 0;
    261 };
    262 
    263 }  // namespace jxl
    264 
    265 #endif  // LIB_JXL_IMAGE_BUNDLE_H_