tor-browser

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

rescaler.c (8304B)


      1 // Copyright 2014 Google Inc. All Rights Reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style license
      4 // that can be found in the COPYING file in the root of the source
      5 // tree. An additional intellectual property rights grant can be found
      6 // in the file PATENTS. All contributing project authors may
      7 // be found in the AUTHORS file in the root of the source tree.
      8 // -----------------------------------------------------------------------------
      9 //
     10 // Rescaling functions
     11 //
     12 // Author: Skal (pascal.massimino@gmail.com)
     13 
     14 #include <assert.h>
     15 #include <stddef.h>
     16 
     17 #include "src/dsp/cpu.h"
     18 #include "src/webp/types.h"
     19 #include "src/dsp/dsp.h"
     20 #include "src/utils/rescaler_utils.h"
     21 
     22 //------------------------------------------------------------------------------
     23 // Implementations of critical functions ImportRow / ExportRow
     24 
     25 #define ROUNDER (WEBP_RESCALER_ONE >> 1)
     26 #define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
     27 #define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)
     28 
     29 //------------------------------------------------------------------------------
     30 // Row import
     31 
     32 void WebPRescalerImportRowExpand_C(WebPRescaler* WEBP_RESTRICT const wrk,
     33                                   const uint8_t* WEBP_RESTRICT src) {
     34  const int x_stride = wrk->num_channels;
     35  const int x_out_max = wrk->dst_width * wrk->num_channels;
     36  int channel;
     37  assert(!WebPRescalerInputDone(wrk));
     38  assert(wrk->x_expand);
     39  for (channel = 0; channel < x_stride; ++channel) {
     40    int x_in = channel;
     41    int x_out = channel;
     42    // simple bilinear interpolation
     43    int accum = wrk->x_add;
     44    rescaler_t left = (rescaler_t)src[x_in];
     45    rescaler_t right =
     46        (wrk->src_width > 1) ? (rescaler_t)src[x_in + x_stride] : left;
     47    x_in += x_stride;
     48    while (1) {
     49      wrk->frow[x_out] = right * wrk->x_add + (left - right) * accum;
     50      x_out += x_stride;
     51      if (x_out >= x_out_max) break;
     52      accum -= wrk->x_sub;
     53      if (accum < 0) {
     54        left = right;
     55        x_in += x_stride;
     56        assert(x_in < wrk->src_width * x_stride);
     57        right = (rescaler_t)src[x_in];
     58        accum += wrk->x_add;
     59      }
     60    }
     61    assert(wrk->x_sub == 0 /* <- special case for src_width=1 */ || accum == 0);
     62  }
     63 }
     64 
     65 void WebPRescalerImportRowShrink_C(WebPRescaler* WEBP_RESTRICT const wrk,
     66                                   const uint8_t* WEBP_RESTRICT src) {
     67  const int x_stride = wrk->num_channels;
     68  const int x_out_max = wrk->dst_width * wrk->num_channels;
     69  int channel;
     70  assert(!WebPRescalerInputDone(wrk));
     71  assert(!wrk->x_expand);
     72  for (channel = 0; channel < x_stride; ++channel) {
     73    int x_in = channel;
     74    int x_out = channel;
     75    uint32_t sum = 0;
     76    int accum = 0;
     77    while (x_out < x_out_max) {
     78      uint32_t base = 0;
     79      accum += wrk->x_add;
     80      while (accum > 0) {
     81        accum -= wrk->x_sub;
     82        assert(x_in < wrk->src_width * x_stride);
     83        base = src[x_in];
     84        sum += base;
     85        x_in += x_stride;
     86      }
     87      {        // Emit next horizontal pixel.
     88        const rescaler_t frac = base * (-accum);
     89        wrk->frow[x_out] = sum * wrk->x_sub - frac;
     90        // fresh fractional start for next pixel
     91        sum = (int)MULT_FIX(frac, wrk->fx_scale);
     92      }
     93      x_out += x_stride;
     94    }
     95    assert(accum == 0);
     96  }
     97 }
     98 
     99 //------------------------------------------------------------------------------
    100 // Row export
    101 
    102 void WebPRescalerExportRowExpand_C(WebPRescaler* const wrk) {
    103  int x_out;
    104  uint8_t* const dst = wrk->dst;
    105  rescaler_t* const irow = wrk->irow;
    106  const int x_out_max = wrk->dst_width * wrk->num_channels;
    107  const rescaler_t* const frow = wrk->frow;
    108  assert(!WebPRescalerOutputDone(wrk));
    109  assert(wrk->y_accum <= 0);
    110  assert(wrk->y_expand);
    111  assert(wrk->y_sub != 0);
    112  if (wrk->y_accum == 0) {
    113    for (x_out = 0; x_out < x_out_max; ++x_out) {
    114      const uint32_t J = frow[x_out];
    115      const int v = (int)MULT_FIX(J, wrk->fy_scale);
    116      dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
    117    }
    118  } else {
    119    const uint32_t B = WEBP_RESCALER_FRAC(-wrk->y_accum, wrk->y_sub);
    120    const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B);
    121    for (x_out = 0; x_out < x_out_max; ++x_out) {
    122      const uint64_t I = (uint64_t)A * frow[x_out]
    123                       + (uint64_t)B * irow[x_out];
    124      const uint32_t J = (uint32_t)((I + ROUNDER) >> WEBP_RESCALER_RFIX);
    125      const int v = (int)MULT_FIX(J, wrk->fy_scale);
    126      dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
    127    }
    128  }
    129 }
    130 
    131 void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
    132  int x_out;
    133  uint8_t* const dst = wrk->dst;
    134  rescaler_t* const irow = wrk->irow;
    135  const int x_out_max = wrk->dst_width * wrk->num_channels;
    136  const rescaler_t* const frow = wrk->frow;
    137  const uint32_t yscale = wrk->fy_scale * (-wrk->y_accum);
    138  assert(!WebPRescalerOutputDone(wrk));
    139  assert(wrk->y_accum <= 0);
    140  assert(!wrk->y_expand);
    141  if (yscale) {
    142    for (x_out = 0; x_out < x_out_max; ++x_out) {
    143      const uint32_t frac = (uint32_t)MULT_FIX_FLOOR(frow[x_out], yscale);
    144      const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
    145      dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
    146      irow[x_out] = frac;   // new fractional start
    147    }
    148  } else {
    149    for (x_out = 0; x_out < x_out_max; ++x_out) {
    150      const int v = (int)MULT_FIX(irow[x_out], wrk->fxy_scale);
    151      dst[x_out] = (v > 255) ? 255u : (uint8_t)v;
    152      irow[x_out] = 0;
    153    }
    154  }
    155 }
    156 
    157 #undef MULT_FIX_FLOOR
    158 #undef MULT_FIX
    159 #undef ROUNDER
    160 
    161 //------------------------------------------------------------------------------
    162 // Main entry calls
    163 
    164 void WebPRescalerImportRow(WebPRescaler* WEBP_RESTRICT const wrk,
    165                           const uint8_t* WEBP_RESTRICT src) {
    166  assert(!WebPRescalerInputDone(wrk));
    167  if (!wrk->x_expand) {
    168    WebPRescalerImportRowShrink(wrk, src);
    169  } else {
    170    WebPRescalerImportRowExpand(wrk, src);
    171  }
    172 }
    173 
    174 void WebPRescalerExportRow(WebPRescaler* const wrk) {
    175  if (wrk->y_accum <= 0) {
    176    assert(!WebPRescalerOutputDone(wrk));
    177    if (wrk->y_expand) {
    178      WebPRescalerExportRowExpand(wrk);
    179    } else if (wrk->fxy_scale) {
    180      WebPRescalerExportRowShrink(wrk);
    181    } else {  // special case
    182      int i;
    183      assert(wrk->src_height == wrk->dst_height && wrk->x_add == 1);
    184      assert(wrk->src_width == 1 && wrk->dst_width <= 2);
    185      for (i = 0; i < wrk->num_channels * wrk->dst_width; ++i) {
    186        wrk->dst[i] = wrk->irow[i];
    187        wrk->irow[i] = 0;
    188      }
    189    }
    190    wrk->y_accum += wrk->y_add;
    191    wrk->dst += wrk->dst_stride;
    192    ++wrk->dst_y;
    193  }
    194 }
    195 
    196 //------------------------------------------------------------------------------
    197 
    198 WebPRescalerImportRowFunc WebPRescalerImportRowExpand;
    199 WebPRescalerImportRowFunc WebPRescalerImportRowShrink;
    200 
    201 WebPRescalerExportRowFunc WebPRescalerExportRowExpand;
    202 WebPRescalerExportRowFunc WebPRescalerExportRowShrink;
    203 
    204 extern VP8CPUInfo VP8GetCPUInfo;
    205 extern void WebPRescalerDspInitSSE2(void);
    206 extern void WebPRescalerDspInitMIPS32(void);
    207 extern void WebPRescalerDspInitMIPSdspR2(void);
    208 extern void WebPRescalerDspInitMSA(void);
    209 extern void WebPRescalerDspInitNEON(void);
    210 
    211 WEBP_DSP_INIT_FUNC(WebPRescalerDspInit) {
    212 #if !defined(WEBP_REDUCE_SIZE)
    213 #if !WEBP_NEON_OMIT_C_CODE
    214  WebPRescalerExportRowExpand = WebPRescalerExportRowExpand_C;
    215  WebPRescalerExportRowShrink = WebPRescalerExportRowShrink_C;
    216 #endif
    217 
    218  WebPRescalerImportRowExpand = WebPRescalerImportRowExpand_C;
    219  WebPRescalerImportRowShrink = WebPRescalerImportRowShrink_C;
    220 
    221  if (VP8GetCPUInfo != NULL) {
    222 #if defined(WEBP_HAVE_SSE2)
    223    if (VP8GetCPUInfo(kSSE2)) {
    224      WebPRescalerDspInitSSE2();
    225    }
    226 #endif
    227 #if defined(WEBP_USE_MIPS32)
    228    if (VP8GetCPUInfo(kMIPS32)) {
    229      WebPRescalerDspInitMIPS32();
    230    }
    231 #endif
    232 #if defined(WEBP_USE_MIPS_DSP_R2)
    233    if (VP8GetCPUInfo(kMIPSdspR2)) {
    234      WebPRescalerDspInitMIPSdspR2();
    235    }
    236 #endif
    237 #if defined(WEBP_USE_MSA)
    238    if (VP8GetCPUInfo(kMSA)) {
    239      WebPRescalerDspInitMSA();
    240    }
    241 #endif
    242  }
    243 
    244 #if defined(WEBP_HAVE_NEON)
    245  if (WEBP_NEON_OMIT_C_CODE ||
    246      (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
    247    WebPRescalerDspInitNEON();
    248  }
    249 #endif
    250 
    251  assert(WebPRescalerExportRowExpand != NULL);
    252  assert(WebPRescalerExportRowShrink != NULL);
    253  assert(WebPRescalerImportRowExpand != NULL);
    254  assert(WebPRescalerImportRowShrink != NULL);
    255 #endif   // WEBP_REDUCE_SIZE
    256 }