libjxl

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

image_bundle.cc (4216B)


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