libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

image_bundle.h (8767B)


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