tor-browser

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

decode.cc (4496B)


      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/extras/dec/decode.h"
      7 
      8 #include <locale>
      9 
     10 #include "lib/extras/dec/apng.h"
     11 #include "lib/extras/dec/exr.h"
     12 #include "lib/extras/dec/gif.h"
     13 #include "lib/extras/dec/jpg.h"
     14 #include "lib/extras/dec/jxl.h"
     15 #include "lib/extras/dec/pgx.h"
     16 #include "lib/extras/dec/pnm.h"
     17 
     18 namespace jxl {
     19 namespace extras {
     20 namespace {
     21 
     22 // Any valid encoding is larger (ensures codecs can read the first few bytes)
     23 constexpr size_t kMinBytes = 9;
     24 
     25 std::string GetExtension(const std::string& path) {
     26  // Pattern: "name.png"
     27  size_t pos = path.find_last_of('.');
     28  if (pos != std::string::npos) {
     29    return path.substr(pos);
     30  }
     31 
     32  // Extension not found
     33  return "";
     34 }
     35 
     36 }  // namespace
     37 
     38 Codec CodecFromPath(const std::string& path,
     39                    size_t* JXL_RESTRICT bits_per_sample,
     40                    std::string* extension) {
     41  std::string ext = GetExtension(path);
     42  if (extension) {
     43    if (extension->empty()) {
     44      *extension = ext;
     45    } else {
     46      ext = *extension;
     47    }
     48  }
     49  std::transform(ext.begin(), ext.end(), ext.begin(), [](char c) {
     50    return std::tolower(c, std::locale::classic());
     51  });
     52  if (ext == ".png") return Codec::kPNG;
     53 
     54  if (ext == ".jpg") return Codec::kJPG;
     55  if (ext == ".jpeg") return Codec::kJPG;
     56 
     57  if (ext == ".pgx") return Codec::kPGX;
     58 
     59  if (ext == ".pam") return Codec::kPNM;
     60  if (ext == ".pnm") return Codec::kPNM;
     61  if (ext == ".pgm") return Codec::kPNM;
     62  if (ext == ".ppm") return Codec::kPNM;
     63  if (ext == ".pfm") {
     64    if (bits_per_sample != nullptr) *bits_per_sample = 32;
     65    return Codec::kPNM;
     66  }
     67 
     68  if (ext == ".gif") return Codec::kGIF;
     69 
     70  if (ext == ".exr") return Codec::kEXR;
     71 
     72  return Codec::kUnknown;
     73 }
     74 
     75 bool CanDecode(Codec codec) {
     76  switch (codec) {
     77    case Codec::kEXR:
     78      return CanDecodeEXR();
     79    case Codec::kGIF:
     80      return CanDecodeGIF();
     81    case Codec::kJPG:
     82      return CanDecodeJPG();
     83    case Codec::kPNG:
     84      return CanDecodeAPNG();
     85    case Codec::kPNM:
     86    case Codec::kPGX:
     87    case Codec::kJXL:
     88      return true;
     89    default:
     90      return false;
     91  }
     92 }
     93 
     94 std::string ListOfDecodeCodecs() {
     95  std::string list_of_codecs("JXL, PPM, PNM, PFM, PAM, PGX");
     96  if (CanDecode(Codec::kPNG)) list_of_codecs.append(", PNG, APNG");
     97  if (CanDecode(Codec::kGIF)) list_of_codecs.append(", GIF");
     98  if (CanDecode(Codec::kJPG)) list_of_codecs.append(", JPEG");
     99  if (CanDecode(Codec::kEXR)) list_of_codecs.append(", EXR");
    100  return list_of_codecs;
    101 }
    102 
    103 Status DecodeBytes(const Span<const uint8_t> bytes,
    104                   const ColorHints& color_hints, extras::PackedPixelFile* ppf,
    105                   const SizeConstraints* constraints, Codec* orig_codec) {
    106  if (bytes.size() < kMinBytes) return JXL_FAILURE("Too few bytes");
    107 
    108  *ppf = extras::PackedPixelFile();
    109 
    110  // Default values when not set by decoders.
    111  ppf->info.uses_original_profile = JXL_TRUE;
    112  ppf->info.orientation = JXL_ORIENT_IDENTITY;
    113 
    114  const auto choose_codec = [&]() -> Codec {
    115    if (DecodeImageAPNG(bytes, color_hints, ppf, constraints)) {
    116      return Codec::kPNG;
    117    }
    118    if (DecodeImagePGX(bytes, color_hints, ppf, constraints)) {
    119      return Codec::kPGX;
    120    }
    121    if (DecodeImagePNM(bytes, color_hints, ppf, constraints)) {
    122      return Codec::kPNM;
    123    }
    124    JXLDecompressParams dparams = {};
    125    for (const uint32_t num_channels : {1, 2, 3, 4}) {
    126      dparams.accepted_formats.push_back(
    127          {num_channels, JXL_TYPE_FLOAT, JXL_LITTLE_ENDIAN, /*align=*/0});
    128    }
    129    dparams.output_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM;
    130    size_t decoded_bytes;
    131    if (DecodeImageJXL(bytes.data(), bytes.size(), dparams, &decoded_bytes,
    132                       ppf) &&
    133        ApplyColorHints(color_hints, true, ppf->info.num_color_channels == 1,
    134                        ppf)) {
    135      return Codec::kJXL;
    136    }
    137    if (DecodeImageGIF(bytes, color_hints, ppf, constraints)) {
    138      return Codec::kGIF;
    139    }
    140    if (DecodeImageJPG(bytes, color_hints, ppf, constraints)) {
    141      return Codec::kJPG;
    142    }
    143    if (DecodeImageEXR(bytes, color_hints, ppf, constraints)) {
    144      return Codec::kEXR;
    145    }
    146    return Codec::kUnknown;
    147  };
    148 
    149  Codec codec = choose_codec();
    150  if (codec == Codec::kUnknown) {
    151    return JXL_FAILURE("Codecs failed to decode");
    152  }
    153  if (orig_codec) *orig_codec = codec;
    154 
    155  return true;
    156 }
    157 
    158 }  // namespace extras
    159 }  // namespace jxl