libjxl

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

headers.cc (6562B)


      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/headers.h"
      7 
      8 #include "lib/jxl/fields.h"
      9 #include "lib/jxl/frame_dimensions.h"
     10 
     11 namespace jxl {
     12 namespace {
     13 
     14 struct Rational {
     15   constexpr explicit Rational(uint32_t num, uint32_t den)
     16       : num(num), den(den) {}
     17 
     18   // Returns floor(multiplicand * rational).
     19   constexpr uint32_t MulTruncate(uint32_t multiplicand) const {
     20     return static_cast<uint64_t>(multiplicand) * num / den;
     21   }
     22 
     23   uint32_t num;
     24   uint32_t den;
     25 };
     26 
     27 Rational FixedAspectRatios(uint32_t ratio) {
     28   JXL_ASSERT(0 != ratio && ratio < 8);
     29   // Other candidates: 5/4, 7/5, 14/9, 16/10, 5/3, 21/9, 12/5
     30   constexpr Rational kRatios[7] = {Rational(1, 1),    // square
     31                                    Rational(12, 10),  //
     32                                    Rational(4, 3),    // camera
     33                                    Rational(3, 2),    // mobile camera
     34                                    Rational(16, 9),   // camera/display
     35                                    Rational(5, 4),    //
     36                                    Rational(2, 1)};   //
     37   return kRatios[ratio - 1];
     38 }
     39 
     40 uint32_t FindAspectRatio(uint32_t xsize, uint32_t ysize) {
     41   for (uint32_t r = 1; r < 8; ++r) {
     42     if (xsize == FixedAspectRatios(r).MulTruncate(ysize)) {
     43       return r;
     44     }
     45   }
     46   return 0;  // Must send xsize instead
     47 }
     48 
     49 }  // namespace
     50 
     51 size_t SizeHeader::xsize() const {
     52   if (ratio_ != 0) {
     53     return FixedAspectRatios(ratio_).MulTruncate(
     54         static_cast<uint32_t>(ysize()));
     55   }
     56   return small_ ? ((xsize_div8_minus_1_ + 1) * 8) : xsize_;
     57 }
     58 
     59 Status SizeHeader::Set(size_t xsize64, size_t ysize64) {
     60   if (xsize64 > 0xFFFFFFFFull || ysize64 > 0xFFFFFFFFull) {
     61     return JXL_FAILURE("Image too large");
     62   }
     63   const uint32_t xsize32 = static_cast<uint32_t>(xsize64);
     64   const uint32_t ysize32 = static_cast<uint32_t>(ysize64);
     65   if (xsize64 == 0 || ysize64 == 0) return JXL_FAILURE("Empty image");
     66   ratio_ = FindAspectRatio(xsize32, ysize32);
     67   small_ = ysize64 <= 256 && (ysize64 % kBlockDim) == 0 &&
     68            (ratio_ != 0 || (xsize64 <= 256 && (xsize64 % kBlockDim) == 0));
     69   if (small_) {
     70     ysize_div8_minus_1_ = ysize32 / 8 - 1;
     71   } else {
     72     ysize_ = ysize32;
     73   }
     74 
     75   if (ratio_ == 0) {
     76     if (small_) {
     77       xsize_div8_minus_1_ = xsize32 / 8 - 1;
     78     } else {
     79       xsize_ = xsize32;
     80     }
     81   }
     82   JXL_ASSERT(xsize() == xsize64);
     83   JXL_ASSERT(ysize() == ysize64);
     84   return true;
     85 }
     86 
     87 Status PreviewHeader::Set(size_t xsize64, size_t ysize64) {
     88   const uint32_t xsize32 = static_cast<uint32_t>(xsize64);
     89   const uint32_t ysize32 = static_cast<uint32_t>(ysize64);
     90   if (xsize64 == 0 || ysize64 == 0) return JXL_FAILURE("Empty preview");
     91   div8_ = (xsize64 % kBlockDim) == 0 && (ysize64 % kBlockDim) == 0;
     92   if (div8_) {
     93     ysize_div8_ = ysize32 / 8;
     94   } else {
     95     ysize_ = ysize32;
     96   }
     97 
     98   ratio_ = FindAspectRatio(xsize32, ysize32);
     99   if (ratio_ == 0) {
    100     if (div8_) {
    101       xsize_div8_ = xsize32 / 8;
    102     } else {
    103       xsize_ = xsize32;
    104     }
    105   }
    106   JXL_ASSERT(xsize() == xsize64);
    107   JXL_ASSERT(ysize() == ysize64);
    108   return true;
    109 }
    110 
    111 size_t PreviewHeader::xsize() const {
    112   if (ratio_ != 0) {
    113     return FixedAspectRatios(ratio_).MulTruncate(
    114         static_cast<uint32_t>(ysize()));
    115   }
    116   return div8_ ? (xsize_div8_ * 8) : xsize_;
    117 }
    118 
    119 SizeHeader::SizeHeader() { Bundle::Init(this); }
    120 Status SizeHeader::VisitFields(Visitor* JXL_RESTRICT visitor) {
    121   JXL_QUIET_RETURN_IF_ERROR(visitor->Bool(false, &small_));
    122 
    123   if (visitor->Conditional(small_)) {
    124     JXL_QUIET_RETURN_IF_ERROR(visitor->Bits(5, 0, &ysize_div8_minus_1_));
    125   }
    126   if (visitor->Conditional(!small_)) {
    127     // (Could still be small, but non-multiple of 8.)
    128     JXL_QUIET_RETURN_IF_ERROR(visitor->U32(BitsOffset(9, 1), BitsOffset(13, 1),
    129                                            BitsOffset(18, 1), BitsOffset(30, 1),
    130                                            1, &ysize_));
    131   }
    132 
    133   JXL_QUIET_RETURN_IF_ERROR(visitor->Bits(3, 0, &ratio_));
    134   if (visitor->Conditional(ratio_ == 0 && small_)) {
    135     JXL_QUIET_RETURN_IF_ERROR(visitor->Bits(5, 0, &xsize_div8_minus_1_));
    136   }
    137   if (visitor->Conditional(ratio_ == 0 && !small_)) {
    138     JXL_QUIET_RETURN_IF_ERROR(visitor->U32(BitsOffset(9, 1), BitsOffset(13, 1),
    139                                            BitsOffset(18, 1), BitsOffset(30, 1),
    140                                            1, &xsize_));
    141   }
    142 
    143   return true;
    144 }
    145 
    146 PreviewHeader::PreviewHeader() { Bundle::Init(this); }
    147 Status PreviewHeader::VisitFields(Visitor* JXL_RESTRICT visitor) {
    148   JXL_QUIET_RETURN_IF_ERROR(visitor->Bool(false, &div8_));
    149 
    150   if (visitor->Conditional(div8_)) {
    151     JXL_QUIET_RETURN_IF_ERROR(visitor->U32(Val(16), Val(32), BitsOffset(5, 1),
    152                                            BitsOffset(9, 33), 1, &ysize_div8_));
    153   }
    154   if (visitor->Conditional(!div8_)) {
    155     JXL_QUIET_RETURN_IF_ERROR(visitor->U32(BitsOffset(6, 1), BitsOffset(8, 65),
    156                                            BitsOffset(10, 321),
    157                                            BitsOffset(12, 1345), 1, &ysize_));
    158   }
    159 
    160   JXL_QUIET_RETURN_IF_ERROR(visitor->Bits(3, 0, &ratio_));
    161   if (visitor->Conditional(ratio_ == 0 && div8_)) {
    162     JXL_QUIET_RETURN_IF_ERROR(visitor->U32(Val(16), Val(32), BitsOffset(5, 1),
    163                                            BitsOffset(9, 33), 1, &xsize_div8_));
    164   }
    165   if (visitor->Conditional(ratio_ == 0 && !div8_)) {
    166     JXL_QUIET_RETURN_IF_ERROR(visitor->U32(BitsOffset(6, 1), BitsOffset(8, 65),
    167                                            BitsOffset(10, 321),
    168                                            BitsOffset(12, 1345), 1, &xsize_));
    169   }
    170 
    171   return true;
    172 }
    173 
    174 AnimationHeader::AnimationHeader() { Bundle::Init(this); }
    175 Status AnimationHeader::VisitFields(Visitor* JXL_RESTRICT visitor) {
    176   JXL_QUIET_RETURN_IF_ERROR(visitor->U32(Val(100), Val(1000), BitsOffset(10, 1),
    177                                          BitsOffset(30, 1), 1, &tps_numerator));
    178   JXL_QUIET_RETURN_IF_ERROR(visitor->U32(Val(1), Val(1001), BitsOffset(8, 1),
    179                                          BitsOffset(10, 1), 1,
    180                                          &tps_denominator));
    181 
    182   JXL_QUIET_RETURN_IF_ERROR(
    183       visitor->U32(Val(0), Bits(3), Bits(16), Bits(32), 0, &num_loops));
    184 
    185   JXL_QUIET_RETURN_IF_ERROR(visitor->Bool(false, &have_timecodes));
    186   return true;
    187 }
    188 
    189 Status ReadSizeHeader(BitReader* JXL_RESTRICT reader,
    190                       SizeHeader* JXL_RESTRICT size) {
    191   return Bundle::Read(reader, size);
    192 }
    193 
    194 }  // namespace jxl