tor-browser

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

encode.cc (5505B)


      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/enc/encode.h"
      7 
      8 #include <locale>
      9 
     10 #include "lib/extras/enc/apng.h"
     11 #include "lib/extras/enc/exr.h"
     12 #include "lib/extras/enc/jpg.h"
     13 #include "lib/extras/enc/npy.h"
     14 #include "lib/extras/enc/pgx.h"
     15 #include "lib/extras/enc/pnm.h"
     16 
     17 namespace jxl {
     18 namespace extras {
     19 
     20 Status Encoder::VerifyBasicInfo(const JxlBasicInfo& info) {
     21  if (info.xsize == 0 || info.ysize == 0) {
     22    return JXL_FAILURE("Empty image");
     23  }
     24  if (info.num_color_channels != 1 && info.num_color_channels != 3) {
     25    return JXL_FAILURE("Invalid number of color channels");
     26  }
     27  if (info.alpha_bits > 0 && info.alpha_bits != info.bits_per_sample) {
     28    return JXL_FAILURE("Alpha bit depth does not match image bit depth");
     29  }
     30  if (info.orientation != JXL_ORIENT_IDENTITY) {
     31    return JXL_FAILURE("Orientation must be identity");
     32  }
     33  return true;
     34 }
     35 
     36 Status Encoder::VerifyFormat(const JxlPixelFormat& format) const {
     37  for (auto f : AcceptedFormats()) {
     38    if (f.num_channels != format.num_channels) continue;
     39    if (f.data_type != format.data_type) continue;
     40    if (f.data_type == JXL_TYPE_UINT8 || f.endianness == format.endianness) {
     41      return true;
     42    }
     43  }
     44  return JXL_FAILURE("Format is not in the list of accepted formats.");
     45 }
     46 
     47 Status Encoder::VerifyBitDepth(JxlDataType data_type, uint32_t bits_per_sample,
     48                               uint32_t exponent_bits) {
     49  if ((data_type == JXL_TYPE_UINT8 &&
     50       (bits_per_sample == 0 || bits_per_sample > 8 || exponent_bits != 0)) ||
     51      (data_type == JXL_TYPE_UINT16 &&
     52       (bits_per_sample <= 8 || bits_per_sample > 16 || exponent_bits != 0)) ||
     53      (data_type == JXL_TYPE_FLOAT16 &&
     54       (bits_per_sample > 16 || exponent_bits > 5))) {
     55    return JXL_FAILURE(
     56        "Incompatible data_type %d and bit depth %u with exponent bits %u",
     57        static_cast<int>(data_type), bits_per_sample, exponent_bits);
     58  }
     59  return true;
     60 }
     61 
     62 Status Encoder::VerifyImageSize(const PackedImage& image,
     63                                const JxlBasicInfo& info) {
     64  if (image.pixels() == nullptr) {
     65    return JXL_FAILURE("Invalid image.");
     66  }
     67  if (image.stride != image.xsize * image.pixel_stride()) {
     68    return JXL_FAILURE("Invalid image stride.");
     69  }
     70  if (image.pixels_size != image.ysize * image.stride) {
     71    return JXL_FAILURE("Invalid image size.");
     72  }
     73  size_t info_num_channels =
     74      (info.num_color_channels + (info.alpha_bits > 0 ? 1 : 0));
     75  if (image.xsize != info.xsize || image.ysize != info.ysize ||
     76      image.format.num_channels != info_num_channels) {
     77    return JXL_FAILURE("Frame size does not match image size");
     78  }
     79  return true;
     80 }
     81 
     82 Status Encoder::VerifyPackedImage(const PackedImage& image,
     83                                  const JxlBasicInfo& info) const {
     84  JXL_RETURN_IF_ERROR(VerifyImageSize(image, info));
     85  JXL_RETURN_IF_ERROR(VerifyFormat(image.format));
     86  JXL_RETURN_IF_ERROR(VerifyBitDepth(image.format.data_type,
     87                                     info.bits_per_sample,
     88                                     info.exponent_bits_per_sample));
     89  return true;
     90 }
     91 
     92 template <int metadata>
     93 class MetadataEncoder : public Encoder {
     94 public:
     95  std::vector<JxlPixelFormat> AcceptedFormats() const override {
     96    std::vector<JxlPixelFormat> formats;
     97    // empty, i.e. no need for actual pixel data
     98    return formats;
     99  }
    100 
    101  Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded,
    102                ThreadPool* pool) const override {
    103    JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
    104    encoded->icc.clear();
    105    encoded->bitstreams.resize(1);
    106    if (metadata == 0) encoded->bitstreams.front() = ppf.metadata.exif;
    107    if (metadata == 1) encoded->bitstreams.front() = ppf.metadata.xmp;
    108    if (metadata == 2) encoded->bitstreams.front() = ppf.metadata.jumbf;
    109    return true;
    110  }
    111 };
    112 
    113 std::unique_ptr<Encoder> Encoder::FromExtension(std::string extension) {
    114  std::transform(
    115      extension.begin(), extension.end(), extension.begin(),
    116      [](char c) { return std::tolower(c, std::locale::classic()); });
    117  if (extension == ".png" || extension == ".apng") return GetAPNGEncoder();
    118  if (extension == ".jpg") return GetJPEGEncoder();
    119  if (extension == ".jpeg") return GetJPEGEncoder();
    120  if (extension == ".npy") return GetNumPyEncoder();
    121  if (extension == ".pgx") return GetPGXEncoder();
    122  if (extension == ".pam") return GetPAMEncoder();
    123  if (extension == ".pgm") return GetPGMEncoder();
    124  if (extension == ".ppm") return GetPPMEncoder();
    125  if (extension == ".pnm") return GetPNMEncoder();
    126  if (extension == ".pfm") return GetPFMEncoder();
    127  if (extension == ".exr") return GetEXREncoder();
    128  if (extension == ".exif") return jxl::make_unique<MetadataEncoder<0>>();
    129  if (extension == ".xmp") return jxl::make_unique<MetadataEncoder<1>>();
    130  if (extension == ".xml") return jxl::make_unique<MetadataEncoder<1>>();
    131  if (extension == ".jumbf") return jxl::make_unique<MetadataEncoder<2>>();
    132  if (extension == ".jumb") return jxl::make_unique<MetadataEncoder<2>>();
    133 
    134  return nullptr;
    135 }
    136 
    137 std::string ListOfEncodeCodecs() {
    138  std::string list_of_codecs("PPM, PNM, PFM, PAM, PGX");
    139  if (GetAPNGEncoder()) list_of_codecs.append(", PNG, APNG");
    140  if (GetJPEGEncoder()) list_of_codecs.append(", JPEG");
    141  if (GetEXREncoder()) list_of_codecs.append(", EXR");
    142  return list_of_codecs;
    143 }
    144 
    145 }  // namespace extras
    146 }  // namespace jxl