tor-browser

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

alpha_processing.c (19532B)


      1 // Copyright 2013 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 // Utilities for processing transparent channel.
     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/dsp/dsp.h"
     19 #include "src/webp/types.h"
     20 
     21 // Tables can be faster on some platform but incur some extra binary size (~2k).
     22 #if !defined(USE_TABLES_FOR_ALPHA_MULT)
     23 #define USE_TABLES_FOR_ALPHA_MULT 0   // ALTERNATE_CODE
     24 #endif
     25 
     26 
     27 // -----------------------------------------------------------------------------
     28 
     29 #define MFIX 24    // 24bit fixed-point arithmetic
     30 #define HALF ((1u << MFIX) >> 1)
     31 #define KINV_255 ((1u << MFIX) / 255u)
     32 
     33 static uint32_t Mult(uint8_t x, uint32_t mult) {
     34  const uint32_t v = (x * mult + HALF) >> MFIX;
     35  assert(v <= 255);  // <- 24bit precision is enough to ensure that.
     36  return v;
     37 }
     38 
     39 #if (USE_TABLES_FOR_ALPHA_MULT == 1)
     40 
     41 static const uint32_t kMultTables[2][256] = {
     42  {    // (255u << MFIX) / alpha
     43    0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000,
     44    0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2,
     45    0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000,
     46    0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8,
     47    0x0aa00000, 0x0a333333, 0x09cec4ec, 0x0971c71c, 0x091b6db6, 0x08cb08d3,
     48    0x08800000, 0x0839ce73, 0x07f80000, 0x07ba2e8b, 0x07800000, 0x07492492,
     49    0x07155555, 0x06e45306, 0x06b5e50d, 0x0689d89d, 0x06600000, 0x063831f3,
     50    0x06124924, 0x05ee23b8, 0x05cba2e8, 0x05aaaaaa, 0x058b2164, 0x056cefa8,
     51    0x05500000, 0x05343eb1, 0x05199999, 0x05000000, 0x04e76276, 0x04cfb2b7,
     52    0x04b8e38e, 0x04a2e8ba, 0x048db6db, 0x0479435e, 0x04658469, 0x045270d0,
     53    0x04400000, 0x042e29f7, 0x041ce739, 0x040c30c3, 0x03fc0000, 0x03ec4ec4,
     54    0x03dd1745, 0x03ce540f, 0x03c00000, 0x03b21642, 0x03a49249, 0x03976fc6,
     55    0x038aaaaa, 0x037e3f1f, 0x03722983, 0x03666666, 0x035af286, 0x034fcace,
     56    0x0344ec4e, 0x033a5440, 0x03300000, 0x0325ed09, 0x031c18f9, 0x0312818a,
     57    0x03092492, 0x03000000, 0x02f711dc, 0x02ee5846, 0x02e5d174, 0x02dd7baf,
     58    0x02d55555, 0x02cd5cd5, 0x02c590b2, 0x02bdef7b, 0x02b677d4, 0x02af286b,
     59    0x02a80000, 0x02a0fd5c, 0x029a1f58, 0x029364d9, 0x028ccccc, 0x0286562d,
     60    0x02800000, 0x0279c952, 0x0273b13b, 0x026db6db, 0x0267d95b, 0x026217ec,
     61    0x025c71c7, 0x0256e62a, 0x0251745d, 0x024c1bac, 0x0246db6d, 0x0241b2f9,
     62    0x023ca1af, 0x0237a6f4, 0x0232c234, 0x022df2df, 0x02293868, 0x02249249,
     63    0x02200000, 0x021b810e, 0x021714fb, 0x0212bb51, 0x020e739c, 0x020a3d70,
     64    0x02061861, 0x02020408, 0x01fe0000, 0x01fa0be8, 0x01f62762, 0x01f25213,
     65    0x01ee8ba2, 0x01ead3ba, 0x01e72a07, 0x01e38e38, 0x01e00000, 0x01dc7f10,
     66    0x01d90b21, 0x01d5a3e9, 0x01d24924, 0x01cefa8d, 0x01cbb7e3, 0x01c880e5,
     67    0x01c55555, 0x01c234f7, 0x01bf1f8f, 0x01bc14e5, 0x01b914c1, 0x01b61eed,
     68    0x01b33333, 0x01b05160, 0x01ad7943, 0x01aaaaaa, 0x01a7e567, 0x01a5294a,
     69    0x01a27627, 0x019fcbd2, 0x019d2a20, 0x019a90e7, 0x01980000, 0x01957741,
     70    0x0192f684, 0x01907da4, 0x018e0c7c, 0x018ba2e8, 0x018940c5, 0x0186e5f0,
     71    0x01849249, 0x018245ae, 0x01800000, 0x017dc11f, 0x017b88ee, 0x0179574e,
     72    0x01772c23, 0x01750750, 0x0172e8ba, 0x0170d045, 0x016ebdd7, 0x016cb157,
     73    0x016aaaaa, 0x0168a9b9, 0x0166ae6a, 0x0164b8a7, 0x0162c859, 0x0160dd67,
     74    0x015ef7bd, 0x015d1745, 0x015b3bea, 0x01596596, 0x01579435, 0x0155c7b4,
     75    0x01540000, 0x01523d03, 0x01507eae, 0x014ec4ec, 0x014d0fac, 0x014b5edc,
     76    0x0149b26c, 0x01480a4a, 0x01466666, 0x0144c6af, 0x01432b16, 0x0141938b,
     77    0x01400000, 0x013e7063, 0x013ce4a9, 0x013b5cc0, 0x0139d89d, 0x01385830,
     78    0x0136db6d, 0x01356246, 0x0133ecad, 0x01327a97, 0x01310bf6, 0x012fa0be,
     79    0x012e38e3, 0x012cd459, 0x012b7315, 0x012a150a, 0x0128ba2e, 0x01276276,
     80    0x01260dd6, 0x0124bc44, 0x01236db6, 0x01222222, 0x0120d97c, 0x011f93bc,
     81    0x011e50d7, 0x011d10c4, 0x011bd37a, 0x011a98ef, 0x0119611a, 0x01182bf2,
     82    0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358,
     83    0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0,
     84    0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465,
     85    0x01030c30, 0x01020612, 0x01010204, 0x01000000 },
     86  {   // alpha * KINV_255
     87    0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505,
     88    0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b,
     89    0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111,
     90    0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717,
     91    0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, 0x001c1c1c, 0x001d1d1d,
     92    0x001e1e1e, 0x001f1f1f, 0x00202020, 0x00212121, 0x00222222, 0x00232323,
     93    0x00242424, 0x00252525, 0x00262626, 0x00272727, 0x00282828, 0x00292929,
     94    0x002a2a2a, 0x002b2b2b, 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f,
     95    0x00303030, 0x00313131, 0x00323232, 0x00333333, 0x00343434, 0x00353535,
     96    0x00363636, 0x00373737, 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b,
     97    0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, 0x00404040, 0x00414141,
     98    0x00424242, 0x00434343, 0x00444444, 0x00454545, 0x00464646, 0x00474747,
     99    0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, 0x004c4c4c, 0x004d4d4d,
    100    0x004e4e4e, 0x004f4f4f, 0x00505050, 0x00515151, 0x00525252, 0x00535353,
    101    0x00545454, 0x00555555, 0x00565656, 0x00575757, 0x00585858, 0x00595959,
    102    0x005a5a5a, 0x005b5b5b, 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f,
    103    0x00606060, 0x00616161, 0x00626262, 0x00636363, 0x00646464, 0x00656565,
    104    0x00666666, 0x00676767, 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b,
    105    0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, 0x00707070, 0x00717171,
    106    0x00727272, 0x00737373, 0x00747474, 0x00757575, 0x00767676, 0x00777777,
    107    0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, 0x007c7c7c, 0x007d7d7d,
    108    0x007e7e7e, 0x007f7f7f, 0x00808080, 0x00818181, 0x00828282, 0x00838383,
    109    0x00848484, 0x00858585, 0x00868686, 0x00878787, 0x00888888, 0x00898989,
    110    0x008a8a8a, 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f,
    111    0x00909090, 0x00919191, 0x00929292, 0x00939393, 0x00949494, 0x00959595,
    112    0x00969696, 0x00979797, 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b,
    113    0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, 0x00a0a0a0, 0x00a1a1a1,
    114    0x00a2a2a2, 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7,
    115    0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00acacac, 0x00adadad,
    116    0x00aeaeae, 0x00afafaf, 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3,
    117    0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9,
    118    0x00bababa, 0x00bbbbbb, 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf,
    119    0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, 0x00c5c5c5,
    120    0x00c6c6c6, 0x00c7c7c7, 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb,
    121    0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, 0x00d1d1d1,
    122    0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7,
    123    0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, 0x00dcdcdc, 0x00dddddd,
    124    0x00dedede, 0x00dfdfdf, 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3,
    125    0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, 0x00e8e8e8, 0x00e9e9e9,
    126    0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef,
    127    0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5,
    128    0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb,
    129    0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff }
    130 };
    131 
    132 static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
    133  return kMultTables[!inverse][a];
    134 }
    135 
    136 #else
    137 
    138 static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
    139  return inverse ? (255u << MFIX) / a : a * KINV_255;
    140 }
    141 
    142 #endif  // USE_TABLES_FOR_ALPHA_MULT
    143 
    144 void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse) {
    145  int x;
    146  for (x = 0; x < width; ++x) {
    147    const uint32_t argb = ptr[x];
    148    if (argb < 0xff000000u) {      // alpha < 255
    149      if (argb <= 0x00ffffffu) {   // alpha == 0
    150        ptr[x] = 0;
    151      } else {
    152        const uint32_t alpha = (argb >> 24) & 0xff;
    153        const uint32_t scale = GetScale(alpha, inverse);
    154        uint32_t out = argb & 0xff000000u;
    155        out |= Mult(argb >>  0, scale) <<  0;
    156        out |= Mult(argb >>  8, scale) <<  8;
    157        out |= Mult(argb >> 16, scale) << 16;
    158        ptr[x] = out;
    159      }
    160    }
    161  }
    162 }
    163 
    164 void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr,
    165                   const uint8_t* WEBP_RESTRICT const alpha,
    166                   int width, int inverse) {
    167  int x;
    168  for (x = 0; x < width; ++x) {
    169    const uint32_t a = alpha[x];
    170    if (a != 255) {
    171      if (a == 0) {
    172        ptr[x] = 0;
    173      } else {
    174        const uint32_t scale = GetScale(a, inverse);
    175        ptr[x] = Mult(ptr[x], scale);
    176      }
    177    }
    178  }
    179 }
    180 
    181 #undef KINV_255
    182 #undef HALF
    183 #undef MFIX
    184 
    185 void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
    186 void (*WebPMultRow)(uint8_t* WEBP_RESTRICT const ptr,
    187                    const uint8_t* WEBP_RESTRICT const alpha,
    188                    int width, int inverse);
    189 
    190 //------------------------------------------------------------------------------
    191 // Generic per-plane calls
    192 
    193 void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
    194                      int inverse) {
    195  int n;
    196  for (n = 0; n < num_rows; ++n) {
    197    WebPMultARGBRow((uint32_t*)ptr, width, inverse);
    198    ptr += stride;
    199  }
    200 }
    201 
    202 void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride,
    203                  const uint8_t* WEBP_RESTRICT alpha, int alpha_stride,
    204                  int width, int num_rows, int inverse) {
    205  int n;
    206  for (n = 0; n < num_rows; ++n) {
    207    WebPMultRow(ptr, alpha, width, inverse);
    208    ptr += stride;
    209    alpha += alpha_stride;
    210  }
    211 }
    212 
    213 //------------------------------------------------------------------------------
    214 // Premultiplied modes
    215 
    216 // non dithered-modes
    217 
    218 // (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.)
    219 // for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5),
    220 // one can use instead: (x * a * 65793 + (1 << 23)) >> 24
    221 #if 1     // (int)(x * a / 255.)
    222 #define MULTIPLIER(a)   ((a) * 32897U)
    223 #define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
    224 #else     // (int)(x * a / 255. + .5)
    225 #define MULTIPLIER(a) ((a) * 65793U)
    226 #define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24)
    227 #endif
    228 
    229 #if !WEBP_NEON_OMIT_C_CODE
    230 static void ApplyAlphaMultiply_C(uint8_t* rgba, int alpha_first,
    231                                 int w, int h, int stride) {
    232  while (h-- > 0) {
    233    uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
    234    const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
    235    int i;
    236    for (i = 0; i < w; ++i) {
    237      const uint32_t a = alpha[4 * i];
    238      if (a != 0xff) {
    239        const uint32_t mult = MULTIPLIER(a);
    240        rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
    241        rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
    242        rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
    243      }
    244    }
    245    rgba += stride;
    246  }
    247 }
    248 #endif  // !WEBP_NEON_OMIT_C_CODE
    249 #undef MULTIPLIER
    250 #undef PREMULTIPLY
    251 
    252 // rgbA4444
    253 
    254 #define MULTIPLIER(a)  ((a) * 0x1111)    // 0x1111 ~= (1 << 16) / 15
    255 
    256 static WEBP_INLINE uint8_t dither_hi(uint8_t x) {
    257  return (x & 0xf0) | (x >> 4);
    258 }
    259 
    260 static WEBP_INLINE uint8_t dither_lo(uint8_t x) {
    261  return (x & 0x0f) | (x << 4);
    262 }
    263 
    264 static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) {
    265  return (x * m) >> 16;
    266 }
    267 
    268 static WEBP_INLINE void ApplyAlphaMultiply4444_C(uint8_t* rgba4444,
    269                                                 int w, int h, int stride,
    270                                                 int rg_byte_pos /* 0 or 1 */) {
    271  while (h-- > 0) {
    272    int i;
    273    for (i = 0; i < w; ++i) {
    274      const uint32_t rg = rgba4444[2 * i + rg_byte_pos];
    275      const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)];
    276      const uint8_t a = ba & 0x0f;
    277      const uint32_t mult = MULTIPLIER(a);
    278      const uint8_t r = multiply(dither_hi(rg), mult);
    279      const uint8_t g = multiply(dither_lo(rg), mult);
    280      const uint8_t b = multiply(dither_hi(ba), mult);
    281      rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f);
    282      rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a;
    283    }
    284    rgba4444 += stride;
    285  }
    286 }
    287 #undef MULTIPLIER
    288 
    289 static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444,
    290                                     int w, int h, int stride) {
    291 #if (WEBP_SWAP_16BIT_CSP == 1)
    292  ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 1);
    293 #else
    294  ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 0);
    295 #endif
    296 }
    297 
    298 #if !WEBP_NEON_OMIT_C_CODE
    299 static int DispatchAlpha_C(const uint8_t* WEBP_RESTRICT alpha, int alpha_stride,
    300                           int width, int height,
    301                           uint8_t* WEBP_RESTRICT dst, int dst_stride) {
    302  uint32_t alpha_mask = 0xff;
    303  int i, j;
    304 
    305  for (j = 0; j < height; ++j) {
    306    for (i = 0; i < width; ++i) {
    307      const uint32_t alpha_value = alpha[i];
    308      dst[4 * i] = alpha_value;
    309      alpha_mask &= alpha_value;
    310    }
    311    alpha += alpha_stride;
    312    dst += dst_stride;
    313  }
    314 
    315  return (alpha_mask != 0xff);
    316 }
    317 
    318 static void DispatchAlphaToGreen_C(const uint8_t* WEBP_RESTRICT alpha,
    319                                   int alpha_stride, int width, int height,
    320                                   uint32_t* WEBP_RESTRICT dst,
    321                                   int dst_stride) {
    322  int i, j;
    323  for (j = 0; j < height; ++j) {
    324    for (i = 0; i < width; ++i) {
    325      dst[i] = alpha[i] << 8;  // leave A/R/B channels zero'd.
    326    }
    327    alpha += alpha_stride;
    328    dst += dst_stride;
    329  }
    330 }
    331 
    332 static int ExtractAlpha_C(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
    333                          int width, int height,
    334                          uint8_t* WEBP_RESTRICT alpha, int alpha_stride) {
    335  uint8_t alpha_mask = 0xff;
    336  int i, j;
    337 
    338  for (j = 0; j < height; ++j) {
    339    for (i = 0; i < width; ++i) {
    340      const uint8_t alpha_value = argb[4 * i];
    341      alpha[i] = alpha_value;
    342      alpha_mask &= alpha_value;
    343    }
    344    argb += argb_stride;
    345    alpha += alpha_stride;
    346  }
    347  return (alpha_mask == 0xff);
    348 }
    349 
    350 static void ExtractGreen_C(const uint32_t* WEBP_RESTRICT argb,
    351                           uint8_t* WEBP_RESTRICT alpha, int size) {
    352  int i;
    353  for (i = 0; i < size; ++i) alpha[i] = argb[i] >> 8;
    354 }
    355 #endif  // !WEBP_NEON_OMIT_C_CODE
    356 
    357 //------------------------------------------------------------------------------
    358 
    359 static int HasAlpha8b_C(const uint8_t* src, int length) {
    360  while (length-- > 0) if (*src++ != 0xff) return 1;
    361  return 0;
    362 }
    363 
    364 static int HasAlpha32b_C(const uint8_t* src, int length) {
    365  int x;
    366  for (x = 0; length-- > 0; x += 4) if (src[x] != 0xff) return 1;
    367  return 0;
    368 }
    369 
    370 static void AlphaReplace_C(uint32_t* src, int length, uint32_t color) {
    371  int x;
    372  for (x = 0; x < length; ++x) if ((src[x] >> 24) == 0) src[x] = color;
    373 }
    374 
    375 //------------------------------------------------------------------------------
    376 // Simple channel manipulations.
    377 
    378 static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
    379  return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b);
    380 }
    381 
    382 #ifdef WORDS_BIGENDIAN
    383 static void PackARGB_C(const uint8_t* WEBP_RESTRICT a,
    384                       const uint8_t* WEBP_RESTRICT r,
    385                       const uint8_t* WEBP_RESTRICT g,
    386                       const uint8_t* WEBP_RESTRICT b,
    387                       int len, uint32_t* WEBP_RESTRICT out) {
    388  int i;
    389  for (i = 0; i < len; ++i) {
    390    out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
    391  }
    392 }
    393 #endif
    394 
    395 static void PackRGB_C(const uint8_t* WEBP_RESTRICT r,
    396                      const uint8_t* WEBP_RESTRICT g,
    397                      const uint8_t* WEBP_RESTRICT b,
    398                      int len, int step, uint32_t* WEBP_RESTRICT out) {
    399  int i, offset = 0;
    400  for (i = 0; i < len; ++i) {
    401    out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]);
    402    offset += step;
    403  }
    404 }
    405 
    406 void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int);
    407 void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int);
    408 int (*WebPDispatchAlpha)(const uint8_t* WEBP_RESTRICT, int, int, int,
    409                         uint8_t* WEBP_RESTRICT, int);
    410 void (*WebPDispatchAlphaToGreen)(const uint8_t* WEBP_RESTRICT, int, int, int,
    411                                 uint32_t* WEBP_RESTRICT, int);
    412 int (*WebPExtractAlpha)(const uint8_t* WEBP_RESTRICT, int, int, int,
    413                        uint8_t* WEBP_RESTRICT, int);
    414 void (*WebPExtractGreen)(const uint32_t* WEBP_RESTRICT argb,
    415                         uint8_t* WEBP_RESTRICT alpha, int size);
    416 #ifdef WORDS_BIGENDIAN
    417 void (*WebPPackARGB)(const uint8_t* a, const uint8_t* r, const uint8_t* g,
    418                     const uint8_t* b, int, uint32_t*);
    419 #endif
    420 void (*WebPPackRGB)(const uint8_t* WEBP_RESTRICT r,
    421                    const uint8_t* WEBP_RESTRICT g,
    422                    const uint8_t* WEBP_RESTRICT b,
    423                    int len, int step, uint32_t* WEBP_RESTRICT out);
    424 
    425 int (*WebPHasAlpha8b)(const uint8_t* src, int length);
    426 int (*WebPHasAlpha32b)(const uint8_t* src, int length);
    427 void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color);
    428 
    429 //------------------------------------------------------------------------------
    430 // Init function
    431 
    432 extern VP8CPUInfo VP8GetCPUInfo;
    433 extern void WebPInitAlphaProcessingMIPSdspR2(void);
    434 extern void WebPInitAlphaProcessingSSE2(void);
    435 extern void WebPInitAlphaProcessingSSE41(void);
    436 extern void WebPInitAlphaProcessingNEON(void);
    437 
    438 WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
    439  WebPMultARGBRow = WebPMultARGBRow_C;
    440  WebPMultRow = WebPMultRow_C;
    441  WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C;
    442 
    443 #ifdef WORDS_BIGENDIAN
    444  WebPPackARGB = PackARGB_C;
    445 #endif
    446  WebPPackRGB = PackRGB_C;
    447 #if !WEBP_NEON_OMIT_C_CODE
    448  WebPApplyAlphaMultiply = ApplyAlphaMultiply_C;
    449  WebPDispatchAlpha = DispatchAlpha_C;
    450  WebPDispatchAlphaToGreen = DispatchAlphaToGreen_C;
    451  WebPExtractAlpha = ExtractAlpha_C;
    452  WebPExtractGreen = ExtractGreen_C;
    453 #endif
    454 
    455  WebPHasAlpha8b = HasAlpha8b_C;
    456  WebPHasAlpha32b = HasAlpha32b_C;
    457  WebPAlphaReplace = AlphaReplace_C;
    458 
    459  // If defined, use CPUInfo() to overwrite some pointers with faster versions.
    460  if (VP8GetCPUInfo != NULL) {
    461 #if defined(WEBP_HAVE_SSE2)
    462    if (VP8GetCPUInfo(kSSE2)) {
    463      WebPInitAlphaProcessingSSE2();
    464 #if defined(WEBP_HAVE_SSE41)
    465      if (VP8GetCPUInfo(kSSE4_1)) {
    466        WebPInitAlphaProcessingSSE41();
    467      }
    468 #endif
    469    }
    470 #endif
    471 #if defined(WEBP_USE_MIPS_DSP_R2)
    472    if (VP8GetCPUInfo(kMIPSdspR2)) {
    473      WebPInitAlphaProcessingMIPSdspR2();
    474    }
    475 #endif
    476  }
    477 
    478 #if defined(WEBP_HAVE_NEON)
    479  if (WEBP_NEON_OMIT_C_CODE ||
    480      (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
    481    WebPInitAlphaProcessingNEON();
    482  }
    483 #endif
    484 
    485  assert(WebPMultARGBRow != NULL);
    486  assert(WebPMultRow != NULL);
    487  assert(WebPApplyAlphaMultiply != NULL);
    488  assert(WebPApplyAlphaMultiply4444 != NULL);
    489  assert(WebPDispatchAlpha != NULL);
    490  assert(WebPDispatchAlphaToGreen != NULL);
    491  assert(WebPExtractAlpha != NULL);
    492  assert(WebPExtractGreen != NULL);
    493 #ifdef WORDS_BIGENDIAN
    494  assert(WebPPackARGB != NULL);
    495 #endif
    496  assert(WebPPackRGB != NULL);
    497  assert(WebPHasAlpha8b != NULL);
    498  assert(WebPHasAlpha32b != NULL);
    499  assert(WebPAlphaReplace != NULL);
    500 }