tor-browser

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

enc_squeeze.cc (5283B)


      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/enc_squeeze.h"
      7 
      8 #include <jxl/memory_manager.h>
      9 
     10 #include <cstdlib>
     11 
     12 #include "lib/jxl/base/data_parallel.h"
     13 #include "lib/jxl/modular/modular_image.h"
     14 #include "lib/jxl/modular/transform/squeeze.h"
     15 #include "lib/jxl/modular/transform/transform.h"
     16 
     17 namespace jxl {
     18 
     19 #define AVERAGE(X, Y) (((X) + (Y) + (((X) > (Y)) ? 1 : 0)) >> 1)
     20 
     21 Status FwdHSqueeze(Image &input, int c, int rc) {
     22  const Channel &chin = input.channel[c];
     23  JxlMemoryManager *memory_manager = input.memory_manager();
     24 
     25  JXL_DEBUG_V(4, "Doing horizontal squeeze of channel %i to new channel %i", c,
     26              rc);
     27 
     28  JXL_ASSIGN_OR_RETURN(Channel chout,
     29                       Channel::Create(memory_manager, (chin.w + 1) / 2, chin.h,
     30                                       chin.hshift + 1, chin.vshift));
     31  JXL_ASSIGN_OR_RETURN(Channel chout_residual,
     32                       Channel::Create(memory_manager, chin.w - chout.w,
     33                                       chout.h, chin.hshift + 1, chin.vshift));
     34 
     35  for (size_t y = 0; y < chout.h; y++) {
     36    const pixel_type *JXL_RESTRICT p_in = chin.Row(y);
     37    pixel_type *JXL_RESTRICT p_out = chout.Row(y);
     38    pixel_type *JXL_RESTRICT p_res = chout_residual.Row(y);
     39    for (size_t x = 0; x < chout_residual.w; x++) {
     40      pixel_type A = p_in[x * 2];
     41      pixel_type B = p_in[x * 2 + 1];
     42      pixel_type avg = AVERAGE(A, B);
     43      p_out[x] = avg;
     44 
     45      pixel_type diff = A - B;
     46 
     47      pixel_type next_avg = avg;
     48      if (x + 1 < chout_residual.w) {
     49        pixel_type C = p_in[x * 2 + 2];
     50        pixel_type D = p_in[x * 2 + 3];
     51        next_avg = AVERAGE(C, D);  // which will be chout.value(y,x+1)
     52      } else if (chin.w & 1) {
     53        next_avg = p_in[x * 2 + 2];
     54      }
     55      pixel_type left = (x > 0 ? p_in[x * 2 - 1] : avg);
     56      pixel_type tendency = SmoothTendency(left, avg, next_avg);
     57 
     58      p_res[x] = diff - tendency;
     59    }
     60    if (chin.w & 1) {
     61      int x = chout.w - 1;
     62      p_out[x] = p_in[x * 2];
     63    }
     64  }
     65  input.channel[c] = std::move(chout);
     66  input.channel.insert(input.channel.begin() + rc, std::move(chout_residual));
     67  return true;
     68 }
     69 
     70 Status FwdVSqueeze(Image &input, int c, int rc) {
     71  const Channel &chin = input.channel[c];
     72  JxlMemoryManager *memory_manager = input.memory_manager();
     73 
     74  JXL_DEBUG_V(4, "Doing vertical squeeze of channel %i to new channel %i", c,
     75              rc);
     76 
     77  JXL_ASSIGN_OR_RETURN(Channel chout,
     78                       Channel::Create(memory_manager, chin.w, (chin.h + 1) / 2,
     79                                       chin.hshift, chin.vshift + 1));
     80  JXL_ASSIGN_OR_RETURN(Channel chout_residual,
     81                       Channel::Create(memory_manager, chin.w, chin.h - chout.h,
     82                                       chin.hshift, chin.vshift + 1));
     83  intptr_t onerow_in = chin.plane.PixelsPerRow();
     84  for (size_t y = 0; y < chout_residual.h; y++) {
     85    const pixel_type *JXL_RESTRICT p_in = chin.Row(y * 2);
     86    pixel_type *JXL_RESTRICT p_out = chout.Row(y);
     87    pixel_type *JXL_RESTRICT p_res = chout_residual.Row(y);
     88    for (size_t x = 0; x < chout.w; x++) {
     89      pixel_type A = p_in[x];
     90      pixel_type B = p_in[x + onerow_in];
     91      pixel_type avg = AVERAGE(A, B);
     92      p_out[x] = avg;
     93 
     94      pixel_type diff = A - B;
     95 
     96      pixel_type next_avg = avg;
     97      if (y + 1 < chout_residual.h) {
     98        pixel_type C = p_in[x + 2 * onerow_in];
     99        pixel_type D = p_in[x + 3 * onerow_in];
    100        next_avg = AVERAGE(C, D);  // which will be chout.value(y+1,x)
    101      } else if (chin.h & 1) {
    102        next_avg = p_in[x + 2 * onerow_in];
    103      }
    104      pixel_type top =
    105          (y > 0 ? p_in[static_cast<ssize_t>(x) - onerow_in] : avg);
    106      pixel_type tendency = SmoothTendency(top, avg, next_avg);
    107 
    108      p_res[x] = diff - tendency;
    109    }
    110  }
    111  if (chin.h & 1) {
    112    size_t y = chout.h - 1;
    113    const pixel_type *p_in = chin.Row(y * 2);
    114    pixel_type *p_out = chout.Row(y);
    115    for (size_t x = 0; x < chout.w; x++) {
    116      p_out[x] = p_in[x];
    117    }
    118  }
    119  input.channel[c] = std::move(chout);
    120  input.channel.insert(input.channel.begin() + rc, std::move(chout_residual));
    121  return true;
    122 }
    123 
    124 Status FwdSqueeze(Image &input, std::vector<SqueezeParams> parameters,
    125                  ThreadPool *pool) {
    126  if (parameters.empty()) {
    127    DefaultSqueezeParameters(&parameters, input);
    128  }
    129  // if nothing to do, don't do squeeze
    130  if (parameters.empty()) return false;
    131  for (auto &parameter : parameters) {
    132    JXL_RETURN_IF_ERROR(
    133        CheckMetaSqueezeParams(parameter, input.channel.size()));
    134    bool horizontal = parameter.horizontal;
    135    bool in_place = parameter.in_place;
    136    uint32_t beginc = parameter.begin_c;
    137    uint32_t endc = parameter.begin_c + parameter.num_c - 1;
    138    uint32_t offset;
    139    if (in_place) {
    140      offset = endc + 1;
    141    } else {
    142      offset = input.channel.size();
    143    }
    144    for (uint32_t c = beginc; c <= endc; c++) {
    145      if (horizontal) {
    146        JXL_RETURN_IF_ERROR(FwdHSqueeze(input, c, offset + c - beginc));
    147      } else {
    148        JXL_RETURN_IF_ERROR(FwdVSqueeze(input, c, offset + c - beginc));
    149      }
    150    }
    151  }
    152  return true;
    153 }
    154 
    155 }  // namespace jxl