libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

enc_squeeze.cc (4905B)


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