tor-browser

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

icc_codec_common.cc (5755B)


      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/icc_codec_common.h"
      7 
      8 #include <cstdint>
      9 #include <tuple>
     10 
     11 #include "lib/jxl/base/byte_order.h"
     12 #include "lib/jxl/base/status.h"
     13 #include "lib/jxl/padded_bytes.h"
     14 
     15 namespace jxl {
     16 namespace {
     17 uint8_t ByteKind1(uint8_t b) {
     18  if ('a' <= b && b <= 'z') return 0;
     19  if ('A' <= b && b <= 'Z') return 0;
     20  if ('0' <= b && b <= '9') return 1;
     21  if (b == '.' || b == ',') return 1;
     22  if (b == 0) return 2;
     23  if (b == 1) return 3;
     24  if (b < 16) return 4;
     25  if (b == 255) return 6;
     26  if (b > 240) return 5;
     27  return 7;
     28 }
     29 
     30 uint8_t ByteKind2(uint8_t b) {
     31  if ('a' <= b && b <= 'z') return 0;
     32  if ('A' <= b && b <= 'Z') return 0;
     33  if ('0' <= b && b <= '9') return 1;
     34  if (b == '.' || b == ',') return 1;
     35  if (b < 16) return 2;
     36  if (b > 240) return 3;
     37  return 4;
     38 }
     39 
     40 template <typename T>
     41 T PredictValue(T p1, T p2, T p3, int order) {
     42  if (order == 0) return p1;
     43  if (order == 1) return 2 * p1 - p2;
     44  if (order == 2) return 3 * p1 - 3 * p2 + p3;
     45  return 0;
     46 }
     47 }  // namespace
     48 
     49 uint32_t DecodeUint32(const uint8_t* data, size_t size, size_t pos) {
     50  return pos + 4 > size ? 0 : LoadBE32(data + pos);
     51 }
     52 
     53 Status AppendUint32(uint32_t value, PaddedBytes* data) {
     54  size_t pos = data->size();
     55  JXL_RETURN_IF_ERROR(data->resize(pos + 4));
     56  StoreBE32(value, data->data() + pos);
     57  return true;
     58 }
     59 
     60 typedef std::array<uint8_t, 4> Tag;
     61 
     62 Tag DecodeKeyword(const uint8_t* data, size_t size, size_t pos) {
     63  if (pos + 4 > size) return {{' ', ' ', ' ', ' '}};
     64  return {{data[pos], data[pos + 1], data[pos + 2], data[pos + 3]}};
     65 }
     66 
     67 void EncodeKeyword(const Tag& keyword, uint8_t* data, size_t size, size_t pos) {
     68  if (keyword.size() != 4 || pos + 3 >= size) return;
     69  for (size_t i = 0; i < 4; ++i) data[pos + i] = keyword[i];
     70 }
     71 
     72 Status AppendKeyword(const Tag& keyword, PaddedBytes* data) {
     73  static_assert(std::tuple_size<Tag>{} == 4);
     74  return data->append(keyword);
     75 }
     76 
     77 // Checks if a + b > size, taking possible integer overflow into account.
     78 Status CheckOutOfBounds(uint64_t a, uint64_t b, uint64_t size) {
     79  uint64_t pos = a + b;
     80  if (pos > size) return JXL_FAILURE("Out of bounds");
     81  if (pos < a) return JXL_FAILURE("Out of bounds");  // overflow happened
     82  return true;
     83 }
     84 
     85 Status CheckIs32Bit(uint64_t v) {
     86  static constexpr const uint64_t kUpper32 = ~static_cast<uint64_t>(0xFFFFFFFF);
     87  if ((v & kUpper32) != 0) return JXL_FAILURE("32-bit value expected");
     88  return true;
     89 }
     90 
     91 const std::array<uint8_t, kICCHeaderSize> kIccInitialHeaderPrediction = {
     92    0,   0,   0,   0,   0,   0,   0,   0,   4, 0, 0, 0, 'm', 'n', 't', 'r',
     93    'R', 'G', 'B', ' ', 'X', 'Y', 'Z', ' ', 0, 0, 0, 0, 0,   0,   0,   0,
     94    0,   0,   0,   0,   'a', 'c', 's', 'p', 0, 0, 0, 0, 0,   0,   0,   0,
     95    0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,   0,   0,   0,
     96    0,   0,   0,   0,   0,   0,   246, 214, 0, 1, 0, 0, 0,   0,   211, 45,
     97    0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,   0,   0,   0,
     98    0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,   0,   0,   0,
     99    0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,   0,   0,   0,
    100 };
    101 
    102 std::array<uint8_t, kICCHeaderSize> ICCInitialHeaderPrediction(uint32_t size) {
    103  std::array<uint8_t, kICCHeaderSize> copy(kIccInitialHeaderPrediction);
    104  StoreBE32(size, copy.data());
    105  return copy;
    106 }
    107 
    108 void ICCPredictHeader(const uint8_t* icc, size_t size, uint8_t* header,
    109                      size_t pos) {
    110  if (pos == 8 && size >= 8) {
    111    header[80] = icc[4];
    112    header[81] = icc[5];
    113    header[82] = icc[6];
    114    header[83] = icc[7];
    115  }
    116  if (pos == 41 && size >= 41) {
    117    if (icc[40] == 'A') {
    118      header[41] = 'P';
    119      header[42] = 'P';
    120      header[43] = 'L';
    121    }
    122    if (icc[40] == 'M') {
    123      header[41] = 'S';
    124      header[42] = 'F';
    125      header[43] = 'T';
    126    }
    127  }
    128  if (pos == 42 && size >= 42) {
    129    if (icc[40] == 'S' && icc[41] == 'G') {
    130      header[42] = 'I';
    131      header[43] = ' ';
    132    }
    133    if (icc[40] == 'S' && icc[41] == 'U') {
    134      header[42] = 'N';
    135      header[43] = 'W';
    136    }
    137  }
    138 }
    139 
    140 // Predicts a value with linear prediction of given order (0-2), for integers
    141 // with width bytes and given stride in bytes between values.
    142 // The start position is at start + i, and the relevant modulus of i describes
    143 // which byte of the multi-byte integer is being handled.
    144 // The value start + i must be at least stride * 4.
    145 uint8_t LinearPredictICCValue(const uint8_t* data, size_t start, size_t i,
    146                              size_t stride, size_t width, int order) {
    147  size_t pos = start + i;
    148  if (width == 1) {
    149    uint8_t p1 = data[pos - stride];
    150    uint8_t p2 = data[pos - stride * 2];
    151    uint8_t p3 = data[pos - stride * 3];
    152    return PredictValue(p1, p2, p3, order);
    153  } else if (width == 2) {
    154    size_t p = start + (i & ~1);
    155    uint16_t p1 = (data[p - stride * 1] << 8) + data[p - stride * 1 + 1];
    156    uint16_t p2 = (data[p - stride * 2] << 8) + data[p - stride * 2 + 1];
    157    uint16_t p3 = (data[p - stride * 3] << 8) + data[p - stride * 3 + 1];
    158    uint16_t pred = PredictValue(p1, p2, p3, order);
    159    return (i & 1) ? (pred & 255) : ((pred >> 8) & 255);
    160  } else {
    161    size_t p = start + (i & ~3);
    162    uint32_t p1 = DecodeUint32(data, pos, p - stride);
    163    uint32_t p2 = DecodeUint32(data, pos, p - stride * 2);
    164    uint32_t p3 = DecodeUint32(data, pos, p - stride * 3);
    165    uint32_t pred = PredictValue(p1, p2, p3, order);
    166    unsigned shiftbytes = 3 - (i & 3);
    167    return (pred >> (shiftbytes * 8)) & 255;
    168  }
    169 }
    170 
    171 size_t ICCANSContext(size_t i, size_t b1, size_t b2) {
    172  if (i <= 128) return 0;
    173  return 1 + ByteKind1(b1) + ByteKind2(b2) * 8;
    174 }
    175 
    176 }  // namespace jxl