tor-browser

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

rct.cc (5075B)


      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/modular/transform/rct.h"
      7 #undef HWY_TARGET_INCLUDE
      8 #define HWY_TARGET_INCLUDE "lib/jxl/modular/transform/rct.cc"
      9 #include <hwy/foreach_target.h>
     10 #include <hwy/highway.h>
     11 HWY_BEFORE_NAMESPACE();
     12 namespace jxl {
     13 namespace HWY_NAMESPACE {
     14 
     15 // These templates are not found via ADL.
     16 using hwy::HWY_NAMESPACE::Add;
     17 using hwy::HWY_NAMESPACE::ShiftRight;
     18 using hwy::HWY_NAMESPACE::Sub;
     19 
     20 template <int transform_type>
     21 void InvRCTRow(const pixel_type* in0, const pixel_type* in1,
     22               const pixel_type* in2, pixel_type* out0, pixel_type* out1,
     23               pixel_type* out2, size_t w) {
     24  static_assert(transform_type >= 0 && transform_type < 7,
     25                "Invalid transform type");
     26  int second = transform_type >> 1;
     27  int third = transform_type & 1;
     28 
     29  size_t x = 0;
     30  const HWY_FULL(pixel_type) d;
     31  const size_t N = Lanes(d);
     32  for (; x + N - 1 < w; x += N) {
     33    if (transform_type == 6) {
     34      auto Y = Load(d, in0 + x);
     35      auto Co = Load(d, in1 + x);
     36      auto Cg = Load(d, in2 + x);
     37      Y = Sub(Y, ShiftRight<1>(Cg));
     38      auto G = Add(Cg, Y);
     39      Y = Sub(Y, ShiftRight<1>(Co));
     40      auto R = Add(Y, Co);
     41      Store(R, d, out0 + x);
     42      Store(G, d, out1 + x);
     43      Store(Y, d, out2 + x);
     44    } else {
     45      auto First = Load(d, in0 + x);
     46      auto Second = Load(d, in1 + x);
     47      auto Third = Load(d, in2 + x);
     48      if (third) Third = Add(Third, First);
     49      if (second == 1) {
     50        Second = Add(Second, First);
     51      } else if (second == 2) {
     52        Second = Add(Second, ShiftRight<1>(Add(First, Third)));
     53      }
     54      Store(First, d, out0 + x);
     55      Store(Second, d, out1 + x);
     56      Store(Third, d, out2 + x);
     57    }
     58  }
     59  for (; x < w; x++) {
     60    if (transform_type == 6) {
     61      pixel_type Y = in0[x];
     62      pixel_type Co = in1[x];
     63      pixel_type Cg = in2[x];
     64      pixel_type tmp = PixelAdd(Y, -(Cg >> 1));
     65      pixel_type G = PixelAdd(Cg, tmp);
     66      pixel_type B = PixelAdd(tmp, -(Co >> 1));
     67      pixel_type R = PixelAdd(B, Co);
     68      out0[x] = R;
     69      out1[x] = G;
     70      out2[x] = B;
     71    } else {
     72      pixel_type First = in0[x];
     73      pixel_type Second = in1[x];
     74      pixel_type Third = in2[x];
     75      if (third) Third = PixelAdd(Third, First);
     76      if (second == 1) {
     77        Second = PixelAdd(Second, First);
     78      } else if (second == 2) {
     79        Second = PixelAdd(Second, (PixelAdd(First, Third) >> 1));
     80      }
     81      out0[x] = First;
     82      out1[x] = Second;
     83      out2[x] = Third;
     84    }
     85  }
     86 }
     87 
     88 Status InvRCT(Image& input, size_t begin_c, size_t rct_type, ThreadPool* pool) {
     89  JXL_RETURN_IF_ERROR(CheckEqualChannels(input, begin_c, begin_c + 2));
     90  size_t m = begin_c;
     91  Channel& c0 = input.channel[m + 0];
     92  size_t w = c0.w;
     93  size_t h = c0.h;
     94  if (rct_type == 0) {  // noop
     95    return true;
     96  }
     97  // Permutation: 0=RGB, 1=GBR, 2=BRG, 3=RBG, 4=GRB, 5=BGR
     98  int permutation = rct_type / 7;
     99  JXL_ENSURE(permutation < 6);
    100  // 0-5 values have the low bit corresponding to Third and the high bits
    101  // corresponding to Second. 6 corresponds to YCoCg.
    102  //
    103  // Second: 0=nop, 1=SubtractFirst, 2=SubtractAvgFirstThird
    104  //
    105  // Third: 0=nop, 1=SubtractFirst
    106  int custom = rct_type % 7;
    107  // Special case: permute-only. Swap channels around.
    108  if (custom == 0) {
    109    Channel ch0 = std::move(input.channel[m]);
    110    Channel ch1 = std::move(input.channel[m + 1]);
    111    Channel ch2 = std::move(input.channel[m + 2]);
    112    input.channel[m + (permutation % 3)] = std::move(ch0);
    113    input.channel[m + ((permutation + 1 + permutation / 3) % 3)] =
    114        std::move(ch1);
    115    input.channel[m + ((permutation + 2 - permutation / 3) % 3)] =
    116        std::move(ch2);
    117    return true;
    118  }
    119  constexpr decltype(&InvRCTRow<0>) inv_rct_row[] = {
    120      InvRCTRow<0>, InvRCTRow<1>, InvRCTRow<2>, InvRCTRow<3>,
    121      InvRCTRow<4>, InvRCTRow<5>, InvRCTRow<6>};
    122  const auto process_row = [&](const uint32_t task,
    123                               size_t /* thread */) -> Status {
    124    const size_t y = task;
    125    const pixel_type* in0 = input.channel[m].Row(y);
    126    const pixel_type* in1 = input.channel[m + 1].Row(y);
    127    const pixel_type* in2 = input.channel[m + 2].Row(y);
    128    pixel_type* out0 = input.channel[m + (permutation % 3)].Row(y);
    129    pixel_type* out1 =
    130        input.channel[m + ((permutation + 1 + permutation / 3) % 3)].Row(y);
    131    pixel_type* out2 =
    132        input.channel[m + ((permutation + 2 - permutation / 3) % 3)].Row(y);
    133    inv_rct_row[custom](in0, in1, in2, out0, out1, out2, w);
    134    return true;
    135  };
    136  JXL_RETURN_IF_ERROR(
    137      RunOnPool(pool, 0, h, ThreadPool::NoInit, process_row, "InvRCT"));
    138  return true;
    139 }
    140 
    141 }  // namespace HWY_NAMESPACE
    142 }  // namespace jxl
    143 HWY_AFTER_NAMESPACE();
    144 
    145 #if HWY_ONCE
    146 namespace jxl {
    147 
    148 HWY_EXPORT(InvRCT);
    149 Status InvRCT(Image& input, size_t begin_c, size_t rct_type, ThreadPool* pool) {
    150  return HWY_DYNAMIC_DISPATCH(InvRCT)(input, begin_c, rct_type, pool);
    151 }
    152 
    153 }  // namespace jxl
    154 #endif