tor-browser

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

filters.c (8938B)


      1 // Copyright 2011 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 // Spatial prediction using various filters
     11 //
     12 // Author: Urvang (urvang@google.com)
     13 
     14 #include <assert.h>
     15 #include <stdlib.h>
     16 #include <string.h>
     17 
     18 #include "src/dsp/cpu.h"
     19 #include "src/dsp/dsp.h"
     20 #include "src/webp/types.h"
     21 
     22 //------------------------------------------------------------------------------
     23 // Helpful macro.
     24 
     25 #define DCHECK(in, out)                                                        \
     26  do {                                                                         \
     27    assert((in) != NULL);                                                      \
     28    assert((out) != NULL);                                                     \
     29    assert((in) != (out));                                                     \
     30    assert(width > 0);                                                         \
     31    assert(height > 0);                                                        \
     32    assert(stride >= width);                                                   \
     33  } while (0)
     34 
     35 #if !WEBP_NEON_OMIT_C_CODE
     36 static WEBP_INLINE void PredictLine_C(const uint8_t* WEBP_RESTRICT src,
     37                                      const uint8_t* WEBP_RESTRICT pred,
     38                                      uint8_t* WEBP_RESTRICT dst, int length) {
     39  int i;
     40  for (i = 0; i < length; ++i) dst[i] = (uint8_t)(src[i] - pred[i]);
     41 }
     42 
     43 //------------------------------------------------------------------------------
     44 // Horizontal filter.
     45 
     46 static WEBP_INLINE void DoHorizontalFilter_C(const uint8_t* WEBP_RESTRICT in,
     47                                             int width, int height, int stride,
     48                                             uint8_t* WEBP_RESTRICT out) {
     49  const uint8_t* preds = in;
     50  int row;
     51  DCHECK(in, out);
     52 
     53  // Leftmost pixel is the same as input for topmost scanline.
     54  out[0] = in[0];
     55  PredictLine_C(in + 1, preds, out + 1, width - 1);
     56  preds += stride;
     57  in += stride;
     58  out += stride;
     59 
     60  // Filter line-by-line.
     61  for (row = 1; row < height; ++row) {
     62    // Leftmost pixel is predicted from above.
     63    PredictLine_C(in, preds - stride, out, 1);
     64    PredictLine_C(in + 1, preds, out + 1, width - 1);
     65    preds += stride;
     66    in += stride;
     67    out += stride;
     68  }
     69 }
     70 
     71 //------------------------------------------------------------------------------
     72 // Vertical filter.
     73 
     74 static WEBP_INLINE void DoVerticalFilter_C(const uint8_t* WEBP_RESTRICT in,
     75                                           int width, int height, int stride,
     76                                           uint8_t* WEBP_RESTRICT out) {
     77  const uint8_t* preds = in;
     78  int row;
     79  DCHECK(in, out);
     80 
     81  // Very first top-left pixel is copied.
     82  out[0] = in[0];
     83  // Rest of top scan-line is left-predicted.
     84  PredictLine_C(in + 1, preds, out + 1, width - 1);
     85  in += stride;
     86  out += stride;
     87 
     88  // Filter line-by-line.
     89  for (row = 1; row < height; ++row) {
     90    PredictLine_C(in, preds, out, width);
     91    preds += stride;
     92    in += stride;
     93    out += stride;
     94  }
     95 }
     96 #endif  // !WEBP_NEON_OMIT_C_CODE
     97 
     98 //------------------------------------------------------------------------------
     99 // Gradient filter.
    100 
    101 static WEBP_INLINE int GradientPredictor_C(uint8_t a, uint8_t b, uint8_t c) {
    102  const int g = a + b - c;
    103  return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255;  // clip to 8bit
    104 }
    105 
    106 #if !WEBP_NEON_OMIT_C_CODE
    107 static WEBP_INLINE void DoGradientFilter_C(const uint8_t* WEBP_RESTRICT in,
    108                                           int width, int height, int stride,
    109                                           uint8_t* WEBP_RESTRICT out) {
    110  const uint8_t* preds = in;
    111  int row;
    112  DCHECK(in, out);
    113 
    114  // left prediction for top scan-line
    115  out[0] = in[0];
    116  PredictLine_C(in + 1, preds, out + 1, width - 1);
    117  preds += stride;
    118  in += stride;
    119  out += stride;
    120 
    121  // Filter line-by-line.
    122  for (row = 1; row < height; ++row) {
    123    int w;
    124    // leftmost pixel: predict from above.
    125    PredictLine_C(in, preds - stride, out, 1);
    126    for (w = 1; w < width; ++w) {
    127      const int pred = GradientPredictor_C(preds[w - 1],
    128                                           preds[w - stride],
    129                                           preds[w - stride - 1]);
    130      out[w] = (uint8_t)(in[w] - pred);
    131    }
    132    preds += stride;
    133    in += stride;
    134    out += stride;
    135  }
    136 }
    137 #endif  // !WEBP_NEON_OMIT_C_CODE
    138 
    139 #undef DCHECK
    140 
    141 //------------------------------------------------------------------------------
    142 
    143 #if !WEBP_NEON_OMIT_C_CODE
    144 static void HorizontalFilter_C(const uint8_t* WEBP_RESTRICT data,
    145                               int width, int height, int stride,
    146                               uint8_t* WEBP_RESTRICT filtered_data) {
    147  DoHorizontalFilter_C(data, width, height, stride, filtered_data);
    148 }
    149 
    150 static void VerticalFilter_C(const uint8_t* WEBP_RESTRICT data,
    151                             int width, int height, int stride,
    152                             uint8_t* WEBP_RESTRICT filtered_data) {
    153  DoVerticalFilter_C(data, width, height, stride, filtered_data);
    154 }
    155 
    156 static void GradientFilter_C(const uint8_t* WEBP_RESTRICT data,
    157                             int width, int height, int stride,
    158                             uint8_t* WEBP_RESTRICT filtered_data) {
    159  DoGradientFilter_C(data, width, height, stride, filtered_data);
    160 }
    161 #endif  // !WEBP_NEON_OMIT_C_CODE
    162 
    163 //------------------------------------------------------------------------------
    164 
    165 static void NoneUnfilter_C(const uint8_t* prev, const uint8_t* in,
    166                           uint8_t* out, int width) {
    167  (void)prev;
    168  if (out != in) memcpy(out, in, width * sizeof(*out));
    169 }
    170 
    171 static void HorizontalUnfilter_C(const uint8_t* prev, const uint8_t* in,
    172                                 uint8_t* out, int width) {
    173  uint8_t pred = (prev == NULL) ? 0 : prev[0];
    174  int i;
    175  for (i = 0; i < width; ++i) {
    176    out[i] = (uint8_t)(pred + in[i]);
    177    pred = out[i];
    178  }
    179 }
    180 
    181 #if !WEBP_NEON_OMIT_C_CODE
    182 static void VerticalUnfilter_C(const uint8_t* prev, const uint8_t* in,
    183                               uint8_t* out, int width) {
    184  if (prev == NULL) {
    185    HorizontalUnfilter_C(NULL, in, out, width);
    186  } else {
    187    int i;
    188    for (i = 0; i < width; ++i) out[i] = (uint8_t)(prev[i] + in[i]);
    189  }
    190 }
    191 #endif  // !WEBP_NEON_OMIT_C_CODE
    192 
    193 static void GradientUnfilter_C(const uint8_t* prev, const uint8_t* in,
    194                               uint8_t* out, int width) {
    195  if (prev == NULL) {
    196    HorizontalUnfilter_C(NULL, in, out, width);
    197  } else {
    198    uint8_t top = prev[0], top_left = top, left = top;
    199    int i;
    200    for (i = 0; i < width; ++i) {
    201      top = prev[i];  // need to read this first, in case prev==out
    202      left = (uint8_t)(in[i] + GradientPredictor_C(left, top, top_left));
    203      top_left = top;
    204      out[i] = left;
    205    }
    206  }
    207 }
    208 
    209 //------------------------------------------------------------------------------
    210 // Init function
    211 
    212 WebPFilterFunc WebPFilters[WEBP_FILTER_LAST];
    213 WebPUnfilterFunc WebPUnfilters[WEBP_FILTER_LAST];
    214 
    215 extern VP8CPUInfo VP8GetCPUInfo;
    216 extern void VP8FiltersInitMIPSdspR2(void);
    217 extern void VP8FiltersInitMSA(void);
    218 extern void VP8FiltersInitNEON(void);
    219 extern void VP8FiltersInitSSE2(void);
    220 
    221 WEBP_DSP_INIT_FUNC(VP8FiltersInit) {
    222  WebPUnfilters[WEBP_FILTER_NONE] = NoneUnfilter_C;
    223 #if !WEBP_NEON_OMIT_C_CODE
    224  WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_C;
    225  WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_C;
    226 #endif
    227  WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_C;
    228 
    229  WebPFilters[WEBP_FILTER_NONE] = NULL;
    230 #if !WEBP_NEON_OMIT_C_CODE
    231  WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_C;
    232  WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_C;
    233  WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_C;
    234 #endif
    235 
    236  if (VP8GetCPUInfo != NULL) {
    237 #if defined(WEBP_HAVE_SSE2)
    238    if (VP8GetCPUInfo(kSSE2)) {
    239      VP8FiltersInitSSE2();
    240    }
    241 #endif
    242 #if defined(WEBP_USE_MIPS_DSP_R2)
    243    if (VP8GetCPUInfo(kMIPSdspR2)) {
    244      VP8FiltersInitMIPSdspR2();
    245    }
    246 #endif
    247 #if defined(WEBP_USE_MSA)
    248    if (VP8GetCPUInfo(kMSA)) {
    249      VP8FiltersInitMSA();
    250    }
    251 #endif
    252  }
    253 
    254 #if defined(WEBP_HAVE_NEON)
    255  if (WEBP_NEON_OMIT_C_CODE ||
    256      (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
    257    VP8FiltersInitNEON();
    258  }
    259 #endif
    260 
    261  assert(WebPUnfilters[WEBP_FILTER_NONE] != NULL);
    262  assert(WebPUnfilters[WEBP_FILTER_HORIZONTAL] != NULL);
    263  assert(WebPUnfilters[WEBP_FILTER_VERTICAL] != NULL);
    264  assert(WebPUnfilters[WEBP_FILTER_GRADIENT] != NULL);
    265  assert(WebPFilters[WEBP_FILTER_HORIZONTAL] != NULL);
    266  assert(WebPFilters[WEBP_FILTER_VERTICAL] != NULL);
    267  assert(WebPFilters[WEBP_FILTER_GRADIENT] != NULL);
    268 }