Blame src/dsp/alpha_processing.c

Packit 9c6abc
// Copyright 2013 Google Inc. All Rights Reserved.
Packit 9c6abc
//
Packit 9c6abc
// Use of this source code is governed by a BSD-style license
Packit 9c6abc
// that can be found in the COPYING file in the root of the source
Packit 9c6abc
// tree. An additional intellectual property rights grant can be found
Packit 9c6abc
// in the file PATENTS. All contributing project authors may
Packit 9c6abc
// be found in the AUTHORS file in the root of the source tree.
Packit 9c6abc
// -----------------------------------------------------------------------------
Packit 9c6abc
//
Packit 9c6abc
// Utilities for processing transparent channel.
Packit 9c6abc
//
Packit 9c6abc
// Author: Skal (pascal.massimino@gmail.com)
Packit 9c6abc
Packit 9c6abc
#include <assert.h>
Packit 9c6abc
#include "src/dsp/dsp.h"
Packit 9c6abc
Packit 9c6abc
// Tables can be faster on some platform but incur some extra binary size (~2k).
Packit 9c6abc
#if !defined(USE_TABLES_FOR_ALPHA_MULT)
Packit 9c6abc
#define USE_TABLES_FOR_ALPHA_MULT 0   // ALTERNATE_CODE
Packit 9c6abc
#endif
Packit 9c6abc
Packit 9c6abc
Packit 9c6abc
// -----------------------------------------------------------------------------
Packit 9c6abc
Packit 9c6abc
#define MFIX 24    // 24bit fixed-point arithmetic
Packit 9c6abc
#define HALF ((1u << MFIX) >> 1)
Packit 9c6abc
#define KINV_255 ((1u << MFIX) / 255u)
Packit 9c6abc
Packit 9c6abc
static uint32_t Mult(uint8_t x, uint32_t mult) {
Packit 9c6abc
  const uint32_t v = (x * mult + HALF) >> MFIX;
Packit 9c6abc
  assert(v <= 255);  // <- 24bit precision is enough to ensure that.
Packit 9c6abc
  return v;
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
#if (USE_TABLES_FOR_ALPHA_MULT == 1)
Packit 9c6abc
Packit 9c6abc
static const uint32_t kMultTables[2][256] = {
Packit 9c6abc
  {    // (255u << MFIX) / alpha
Packit 9c6abc
    0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000,
Packit 9c6abc
    0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2,
Packit 9c6abc
    0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000,
Packit 9c6abc
    0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8,
Packit 9c6abc
    0x0aa00000, 0x0a333333, 0x09cec4ec, 0x0971c71c, 0x091b6db6, 0x08cb08d3,
Packit 9c6abc
    0x08800000, 0x0839ce73, 0x07f80000, 0x07ba2e8b, 0x07800000, 0x07492492,
Packit 9c6abc
    0x07155555, 0x06e45306, 0x06b5e50d, 0x0689d89d, 0x06600000, 0x063831f3,
Packit 9c6abc
    0x06124924, 0x05ee23b8, 0x05cba2e8, 0x05aaaaaa, 0x058b2164, 0x056cefa8,
Packit 9c6abc
    0x05500000, 0x05343eb1, 0x05199999, 0x05000000, 0x04e76276, 0x04cfb2b7,
Packit 9c6abc
    0x04b8e38e, 0x04a2e8ba, 0x048db6db, 0x0479435e, 0x04658469, 0x045270d0,
Packit 9c6abc
    0x04400000, 0x042e29f7, 0x041ce739, 0x040c30c3, 0x03fc0000, 0x03ec4ec4,
Packit 9c6abc
    0x03dd1745, 0x03ce540f, 0x03c00000, 0x03b21642, 0x03a49249, 0x03976fc6,
Packit 9c6abc
    0x038aaaaa, 0x037e3f1f, 0x03722983, 0x03666666, 0x035af286, 0x034fcace,
Packit 9c6abc
    0x0344ec4e, 0x033a5440, 0x03300000, 0x0325ed09, 0x031c18f9, 0x0312818a,
Packit 9c6abc
    0x03092492, 0x03000000, 0x02f711dc, 0x02ee5846, 0x02e5d174, 0x02dd7baf,
Packit 9c6abc
    0x02d55555, 0x02cd5cd5, 0x02c590b2, 0x02bdef7b, 0x02b677d4, 0x02af286b,
Packit 9c6abc
    0x02a80000, 0x02a0fd5c, 0x029a1f58, 0x029364d9, 0x028ccccc, 0x0286562d,
Packit 9c6abc
    0x02800000, 0x0279c952, 0x0273b13b, 0x026db6db, 0x0267d95b, 0x026217ec,
Packit 9c6abc
    0x025c71c7, 0x0256e62a, 0x0251745d, 0x024c1bac, 0x0246db6d, 0x0241b2f9,
Packit 9c6abc
    0x023ca1af, 0x0237a6f4, 0x0232c234, 0x022df2df, 0x02293868, 0x02249249,
Packit 9c6abc
    0x02200000, 0x021b810e, 0x021714fb, 0x0212bb51, 0x020e739c, 0x020a3d70,
Packit 9c6abc
    0x02061861, 0x02020408, 0x01fe0000, 0x01fa0be8, 0x01f62762, 0x01f25213,
Packit 9c6abc
    0x01ee8ba2, 0x01ead3ba, 0x01e72a07, 0x01e38e38, 0x01e00000, 0x01dc7f10,
Packit 9c6abc
    0x01d90b21, 0x01d5a3e9, 0x01d24924, 0x01cefa8d, 0x01cbb7e3, 0x01c880e5,
Packit 9c6abc
    0x01c55555, 0x01c234f7, 0x01bf1f8f, 0x01bc14e5, 0x01b914c1, 0x01b61eed,
Packit 9c6abc
    0x01b33333, 0x01b05160, 0x01ad7943, 0x01aaaaaa, 0x01a7e567, 0x01a5294a,
Packit 9c6abc
    0x01a27627, 0x019fcbd2, 0x019d2a20, 0x019a90e7, 0x01980000, 0x01957741,
Packit 9c6abc
    0x0192f684, 0x01907da4, 0x018e0c7c, 0x018ba2e8, 0x018940c5, 0x0186e5f0,
Packit 9c6abc
    0x01849249, 0x018245ae, 0x01800000, 0x017dc11f, 0x017b88ee, 0x0179574e,
Packit 9c6abc
    0x01772c23, 0x01750750, 0x0172e8ba, 0x0170d045, 0x016ebdd7, 0x016cb157,
Packit 9c6abc
    0x016aaaaa, 0x0168a9b9, 0x0166ae6a, 0x0164b8a7, 0x0162c859, 0x0160dd67,
Packit 9c6abc
    0x015ef7bd, 0x015d1745, 0x015b3bea, 0x01596596, 0x01579435, 0x0155c7b4,
Packit 9c6abc
    0x01540000, 0x01523d03, 0x01507eae, 0x014ec4ec, 0x014d0fac, 0x014b5edc,
Packit 9c6abc
    0x0149b26c, 0x01480a4a, 0x01466666, 0x0144c6af, 0x01432b16, 0x0141938b,
Packit 9c6abc
    0x01400000, 0x013e7063, 0x013ce4a9, 0x013b5cc0, 0x0139d89d, 0x01385830,
Packit 9c6abc
    0x0136db6d, 0x01356246, 0x0133ecad, 0x01327a97, 0x01310bf6, 0x012fa0be,
Packit 9c6abc
    0x012e38e3, 0x012cd459, 0x012b7315, 0x012a150a, 0x0128ba2e, 0x01276276,
Packit 9c6abc
    0x01260dd6, 0x0124bc44, 0x01236db6, 0x01222222, 0x0120d97c, 0x011f93bc,
Packit 9c6abc
    0x011e50d7, 0x011d10c4, 0x011bd37a, 0x011a98ef, 0x0119611a, 0x01182bf2,
Packit 9c6abc
    0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358,
Packit 9c6abc
    0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0,
Packit 9c6abc
    0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465,
Packit 9c6abc
    0x01030c30, 0x01020612, 0x01010204, 0x01000000 },
Packit 9c6abc
  {   // alpha * KINV_255
Packit 9c6abc
    0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505,
Packit 9c6abc
    0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b,
Packit 9c6abc
    0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111,
Packit 9c6abc
    0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717,
Packit 9c6abc
    0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, 0x001c1c1c, 0x001d1d1d,
Packit 9c6abc
    0x001e1e1e, 0x001f1f1f, 0x00202020, 0x00212121, 0x00222222, 0x00232323,
Packit 9c6abc
    0x00242424, 0x00252525, 0x00262626, 0x00272727, 0x00282828, 0x00292929,
Packit 9c6abc
    0x002a2a2a, 0x002b2b2b, 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f,
Packit 9c6abc
    0x00303030, 0x00313131, 0x00323232, 0x00333333, 0x00343434, 0x00353535,
Packit 9c6abc
    0x00363636, 0x00373737, 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b,
Packit 9c6abc
    0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, 0x00404040, 0x00414141,
Packit 9c6abc
    0x00424242, 0x00434343, 0x00444444, 0x00454545, 0x00464646, 0x00474747,
Packit 9c6abc
    0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, 0x004c4c4c, 0x004d4d4d,
Packit 9c6abc
    0x004e4e4e, 0x004f4f4f, 0x00505050, 0x00515151, 0x00525252, 0x00535353,
Packit 9c6abc
    0x00545454, 0x00555555, 0x00565656, 0x00575757, 0x00585858, 0x00595959,
Packit 9c6abc
    0x005a5a5a, 0x005b5b5b, 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f,
Packit 9c6abc
    0x00606060, 0x00616161, 0x00626262, 0x00636363, 0x00646464, 0x00656565,
Packit 9c6abc
    0x00666666, 0x00676767, 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b,
Packit 9c6abc
    0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, 0x00707070, 0x00717171,
Packit 9c6abc
    0x00727272, 0x00737373, 0x00747474, 0x00757575, 0x00767676, 0x00777777,
Packit 9c6abc
    0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, 0x007c7c7c, 0x007d7d7d,
Packit 9c6abc
    0x007e7e7e, 0x007f7f7f, 0x00808080, 0x00818181, 0x00828282, 0x00838383,
Packit 9c6abc
    0x00848484, 0x00858585, 0x00868686, 0x00878787, 0x00888888, 0x00898989,
Packit 9c6abc
    0x008a8a8a, 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f,
Packit 9c6abc
    0x00909090, 0x00919191, 0x00929292, 0x00939393, 0x00949494, 0x00959595,
Packit 9c6abc
    0x00969696, 0x00979797, 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b,
Packit 9c6abc
    0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, 0x00a0a0a0, 0x00a1a1a1,
Packit 9c6abc
    0x00a2a2a2, 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7,
Packit 9c6abc
    0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00acacac, 0x00adadad,
Packit 9c6abc
    0x00aeaeae, 0x00afafaf, 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3,
Packit 9c6abc
    0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9,
Packit 9c6abc
    0x00bababa, 0x00bbbbbb, 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf,
Packit 9c6abc
    0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, 0x00c5c5c5,
Packit 9c6abc
    0x00c6c6c6, 0x00c7c7c7, 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb,
Packit 9c6abc
    0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, 0x00d1d1d1,
Packit 9c6abc
    0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7,
Packit 9c6abc
    0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, 0x00dcdcdc, 0x00dddddd,
Packit 9c6abc
    0x00dedede, 0x00dfdfdf, 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3,
Packit 9c6abc
    0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, 0x00e8e8e8, 0x00e9e9e9,
Packit 9c6abc
    0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef,
Packit 9c6abc
    0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5,
Packit 9c6abc
    0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb,
Packit 9c6abc
    0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff }
Packit 9c6abc
};
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
Packit 9c6abc
  return kMultTables[!inverse][a];
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
#else
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
Packit 9c6abc
  return inverse ? (255u << MFIX) / a : a * KINV_255;
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
#endif  // USE_TABLES_FOR_ALPHA_MULT
Packit 9c6abc
Packit 9c6abc
void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse) {
Packit 9c6abc
  int x;
Packit 9c6abc
  for (x = 0; x < width; ++x) {
Packit 9c6abc
    const uint32_t argb = ptr[x];
Packit 9c6abc
    if (argb < 0xff000000u) {      // alpha < 255
Packit 9c6abc
      if (argb <= 0x00ffffffu) {   // alpha == 0
Packit 9c6abc
        ptr[x] = 0;
Packit 9c6abc
      } else {
Packit 9c6abc
        const uint32_t alpha = (argb >> 24) & 0xff;
Packit 9c6abc
        const uint32_t scale = GetScale(alpha, inverse);
Packit 9c6abc
        uint32_t out = argb & 0xff000000u;
Packit 9c6abc
        out |= Mult(argb >>  0, scale) <<  0;
Packit 9c6abc
        out |= Mult(argb >>  8, scale) <<  8;
Packit 9c6abc
        out |= Mult(argb >> 16, scale) << 16;
Packit 9c6abc
        ptr[x] = out;
Packit 9c6abc
      }
Packit 9c6abc
    }
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
void WebPMultRow_C(uint8_t* const ptr, const uint8_t* const alpha,
Packit 9c6abc
                   int width, int inverse) {
Packit 9c6abc
  int x;
Packit 9c6abc
  for (x = 0; x < width; ++x) {
Packit 9c6abc
    const uint32_t a = alpha[x];
Packit 9c6abc
    if (a != 255) {
Packit 9c6abc
      if (a == 0) {
Packit 9c6abc
        ptr[x] = 0;
Packit 9c6abc
      } else {
Packit 9c6abc
        const uint32_t scale = GetScale(a, inverse);
Packit 9c6abc
        ptr[x] = Mult(ptr[x], scale);
Packit 9c6abc
      }
Packit 9c6abc
    }
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
#undef KINV_255
Packit 9c6abc
#undef HALF
Packit 9c6abc
#undef MFIX
Packit 9c6abc
Packit 9c6abc
void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
Packit 9c6abc
void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha,
Packit 9c6abc
                    int width, int inverse);
Packit 9c6abc
Packit 9c6abc
//------------------------------------------------------------------------------
Packit 9c6abc
// Generic per-plane calls
Packit 9c6abc
Packit 9c6abc
void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
Packit 9c6abc
                      int inverse) {
Packit 9c6abc
  int n;
Packit 9c6abc
  for (n = 0; n < num_rows; ++n) {
Packit 9c6abc
    WebPMultARGBRow((uint32_t*)ptr, width, inverse);
Packit 9c6abc
    ptr += stride;
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
void WebPMultRows(uint8_t* ptr, int stride,
Packit 9c6abc
                  const uint8_t* alpha, int alpha_stride,
Packit 9c6abc
                  int width, int num_rows, int inverse) {
Packit 9c6abc
  int n;
Packit 9c6abc
  for (n = 0; n < num_rows; ++n) {
Packit 9c6abc
    WebPMultRow(ptr, alpha, width, inverse);
Packit 9c6abc
    ptr += stride;
Packit 9c6abc
    alpha += alpha_stride;
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
//------------------------------------------------------------------------------
Packit 9c6abc
// Premultiplied modes
Packit 9c6abc
Packit 9c6abc
// non dithered-modes
Packit 9c6abc
Packit 9c6abc
// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.)
Packit 9c6abc
// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5),
Packit 9c6abc
// one can use instead: (x * a * 65793 + (1 << 23)) >> 24
Packit 9c6abc
#if 1     // (int)(x * a / 255.)
Packit 9c6abc
#define MULTIPLIER(a)   ((a) * 32897U)
Packit 9c6abc
#define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
Packit 9c6abc
#else     // (int)(x * a / 255. + .5)
Packit 9c6abc
#define MULTIPLIER(a) ((a) * 65793U)
Packit 9c6abc
#define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24)
Packit 9c6abc
#endif
Packit 9c6abc
Packit 9c6abc
#if !WEBP_NEON_OMIT_C_CODE
Packit 9c6abc
static void ApplyAlphaMultiply_C(uint8_t* rgba, int alpha_first,
Packit 9c6abc
                                 int w, int h, int stride) {
Packit 9c6abc
  while (h-- > 0) {
Packit 9c6abc
    uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
Packit 9c6abc
    const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
Packit 9c6abc
    int i;
Packit 9c6abc
    for (i = 0; i < w; ++i) {
Packit 9c6abc
      const uint32_t a = alpha[4 * i];
Packit 9c6abc
      if (a != 0xff) {
Packit 9c6abc
        const uint32_t mult = MULTIPLIER(a);
Packit 9c6abc
        rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
Packit 9c6abc
        rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
Packit 9c6abc
        rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
Packit 9c6abc
      }
Packit 9c6abc
    }
Packit 9c6abc
    rgba += stride;
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
#endif  // !WEBP_NEON_OMIT_C_CODE
Packit 9c6abc
#undef MULTIPLIER
Packit 9c6abc
#undef PREMULTIPLY
Packit 9c6abc
Packit 9c6abc
// rgbA4444
Packit 9c6abc
Packit 9c6abc
#define MULTIPLIER(a)  ((a) * 0x1111)    // 0x1111 ~= (1 << 16) / 15
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE uint8_t dither_hi(uint8_t x) {
Packit 9c6abc
  return (x & 0xf0) | (x >> 4);
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE uint8_t dither_lo(uint8_t x) {
Packit 9c6abc
  return (x & 0x0f) | (x << 4);
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) {
Packit 9c6abc
  return (x * m) >> 16;
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE void ApplyAlphaMultiply4444_C(uint8_t* rgba4444,
Packit 9c6abc
                                                 int w, int h, int stride,
Packit 9c6abc
                                                 int rg_byte_pos /* 0 or 1 */) {
Packit 9c6abc
  while (h-- > 0) {
Packit 9c6abc
    int i;
Packit 9c6abc
    for (i = 0; i < w; ++i) {
Packit 9c6abc
      const uint32_t rg = rgba4444[2 * i + rg_byte_pos];
Packit 9c6abc
      const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)];
Packit 9c6abc
      const uint8_t a = ba & 0x0f;
Packit 9c6abc
      const uint32_t mult = MULTIPLIER(a);
Packit 9c6abc
      const uint8_t r = multiply(dither_hi(rg), mult);
Packit 9c6abc
      const uint8_t g = multiply(dither_lo(rg), mult);
Packit 9c6abc
      const uint8_t b = multiply(dither_hi(ba), mult);
Packit 9c6abc
      rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f);
Packit 9c6abc
      rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a;
Packit 9c6abc
    }
Packit 9c6abc
    rgba4444 += stride;
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
#undef MULTIPLIER
Packit 9c6abc
Packit 9c6abc
static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444,
Packit 9c6abc
                                     int w, int h, int stride) {
Packit 9c6abc
#if (WEBP_SWAP_16BIT_CSP == 1)
Packit 9c6abc
  ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 1);
Packit 9c6abc
#else
Packit 9c6abc
  ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 0);
Packit 9c6abc
#endif
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
#if !WEBP_NEON_OMIT_C_CODE
Packit 9c6abc
static int DispatchAlpha_C(const uint8_t* alpha, int alpha_stride,
Packit 9c6abc
                           int width, int height,
Packit 9c6abc
                           uint8_t* dst, int dst_stride) {
Packit 9c6abc
  uint32_t alpha_mask = 0xff;
Packit 9c6abc
  int i, j;
Packit 9c6abc
Packit 9c6abc
  for (j = 0; j < height; ++j) {
Packit 9c6abc
    for (i = 0; i < width; ++i) {
Packit 9c6abc
      const uint32_t alpha_value = alpha[i];
Packit 9c6abc
      dst[4 * i] = alpha_value;
Packit 9c6abc
      alpha_mask &= alpha_value;
Packit 9c6abc
    }
Packit 9c6abc
    alpha += alpha_stride;
Packit 9c6abc
    dst += dst_stride;
Packit 9c6abc
  }
Packit 9c6abc
Packit 9c6abc
  return (alpha_mask != 0xff);
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static void DispatchAlphaToGreen_C(const uint8_t* alpha, int alpha_stride,
Packit 9c6abc
                                   int width, int height,
Packit 9c6abc
                                   uint32_t* dst, int dst_stride) {
Packit 9c6abc
  int i, j;
Packit 9c6abc
  for (j = 0; j < height; ++j) {
Packit 9c6abc
    for (i = 0; i < width; ++i) {
Packit 9c6abc
      dst[i] = alpha[i] << 8;  // leave A/R/B channels zero'd.
Packit 9c6abc
    }
Packit 9c6abc
    alpha += alpha_stride;
Packit 9c6abc
    dst += dst_stride;
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static int ExtractAlpha_C(const uint8_t* argb, int argb_stride,
Packit 9c6abc
                          int width, int height,
Packit 9c6abc
                          uint8_t* alpha, int alpha_stride) {
Packit 9c6abc
  uint8_t alpha_mask = 0xff;
Packit 9c6abc
  int i, j;
Packit 9c6abc
Packit 9c6abc
  for (j = 0; j < height; ++j) {
Packit 9c6abc
    for (i = 0; i < width; ++i) {
Packit 9c6abc
      const uint8_t alpha_value = argb[4 * i];
Packit 9c6abc
      alpha[i] = alpha_value;
Packit 9c6abc
      alpha_mask &= alpha_value;
Packit 9c6abc
    }
Packit 9c6abc
    argb += argb_stride;
Packit 9c6abc
    alpha += alpha_stride;
Packit 9c6abc
  }
Packit 9c6abc
  return (alpha_mask == 0xff);
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static void ExtractGreen_C(const uint32_t* argb, uint8_t* alpha, int size) {
Packit 9c6abc
  int i;
Packit 9c6abc
  for (i = 0; i < size; ++i) alpha[i] = argb[i] >> 8;
Packit 9c6abc
}
Packit 9c6abc
#endif  // !WEBP_NEON_OMIT_C_CODE
Packit 9c6abc
Packit 9c6abc
//------------------------------------------------------------------------------
Packit 9c6abc
Packit 9c6abc
static int HasAlpha8b_C(const uint8_t* src, int length) {
Packit 9c6abc
  while (length-- > 0) if (*src++ != 0xff) return 1;
Packit 9c6abc
  return 0;
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
static int HasAlpha32b_C(const uint8_t* src, int length) {
Packit 9c6abc
  int x;
Packit 9c6abc
  for (x = 0; length-- > 0; x += 4) if (src[x] != 0xff) return 1;
Packit 9c6abc
  return 0;
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
//------------------------------------------------------------------------------
Packit 9c6abc
// Simple channel manipulations.
Packit 9c6abc
Packit 9c6abc
static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
Packit 9c6abc
  return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b);
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
#ifdef WORDS_BIGENDIAN
Packit 9c6abc
static void PackARGB_C(const uint8_t* a, const uint8_t* r, const uint8_t* g,
Packit 9c6abc
                       const uint8_t* b, int len, uint32_t* out) {
Packit 9c6abc
  int i;
Packit 9c6abc
  for (i = 0; i < len; ++i) {
Packit 9c6abc
    out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
#endif
Packit 9c6abc
Packit 9c6abc
static void PackRGB_C(const uint8_t* r, const uint8_t* g, const uint8_t* b,
Packit 9c6abc
                      int len, int step, uint32_t* out) {
Packit 9c6abc
  int i, offset = 0;
Packit 9c6abc
  for (i = 0; i < len; ++i) {
Packit 9c6abc
    out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]);
Packit 9c6abc
    offset += step;
Packit 9c6abc
  }
Packit 9c6abc
}
Packit 9c6abc
Packit 9c6abc
void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int);
Packit 9c6abc
void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int);
Packit 9c6abc
int (*WebPDispatchAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
Packit 9c6abc
void (*WebPDispatchAlphaToGreen)(const uint8_t*, int, int, int, uint32_t*, int);
Packit 9c6abc
int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
Packit 9c6abc
void (*WebPExtractGreen)(const uint32_t* argb, uint8_t* alpha, int size);
Packit 9c6abc
#ifdef WORDS_BIGENDIAN
Packit 9c6abc
void (*WebPPackARGB)(const uint8_t* a, const uint8_t* r, const uint8_t* g,
Packit 9c6abc
                     const uint8_t* b, int, uint32_t*);
Packit 9c6abc
#endif
Packit 9c6abc
void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b,
Packit 9c6abc
                    int len, int step, uint32_t* out);
Packit 9c6abc
Packit 9c6abc
int (*WebPHasAlpha8b)(const uint8_t* src, int length);
Packit 9c6abc
int (*WebPHasAlpha32b)(const uint8_t* src, int length);
Packit 9c6abc
Packit 9c6abc
//------------------------------------------------------------------------------
Packit 9c6abc
// Init function
Packit 9c6abc
Packit 9c6abc
extern void WebPInitAlphaProcessingMIPSdspR2(void);
Packit 9c6abc
extern void WebPInitAlphaProcessingSSE2(void);
Packit 9c6abc
extern void WebPInitAlphaProcessingSSE41(void);
Packit 9c6abc
extern void WebPInitAlphaProcessingNEON(void);
Packit 9c6abc
Packit 9c6abc
WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
Packit 9c6abc
  WebPMultARGBRow = WebPMultARGBRow_C;
Packit 9c6abc
  WebPMultRow = WebPMultRow_C;
Packit 9c6abc
  WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C;
Packit 9c6abc
Packit 9c6abc
#ifdef WORDS_BIGENDIAN
Packit 9c6abc
  WebPPackARGB = PackARGB_C;
Packit 9c6abc
#endif
Packit 9c6abc
  WebPPackRGB = PackRGB_C;
Packit 9c6abc
#if !WEBP_NEON_OMIT_C_CODE
Packit 9c6abc
  WebPApplyAlphaMultiply = ApplyAlphaMultiply_C;
Packit 9c6abc
  WebPDispatchAlpha = DispatchAlpha_C;
Packit 9c6abc
  WebPDispatchAlphaToGreen = DispatchAlphaToGreen_C;
Packit 9c6abc
  WebPExtractAlpha = ExtractAlpha_C;
Packit 9c6abc
  WebPExtractGreen = ExtractGreen_C;
Packit 9c6abc
#endif
Packit 9c6abc
Packit 9c6abc
  WebPHasAlpha8b = HasAlpha8b_C;
Packit 9c6abc
  WebPHasAlpha32b = HasAlpha32b_C;
Packit 9c6abc
Packit 9c6abc
  // If defined, use CPUInfo() to overwrite some pointers with faster versions.
Packit 9c6abc
  if (VP8GetCPUInfo != NULL) {
Packit 9c6abc
#if defined(WEBP_USE_SSE2)
Packit 9c6abc
    if (VP8GetCPUInfo(kSSE2)) {
Packit 9c6abc
      WebPInitAlphaProcessingSSE2();
Packit 9c6abc
#if defined(WEBP_USE_SSE41)
Packit 9c6abc
      if (VP8GetCPUInfo(kSSE4_1)) {
Packit 9c6abc
        WebPInitAlphaProcessingSSE41();
Packit 9c6abc
      }
Packit 9c6abc
#endif
Packit 9c6abc
    }
Packit 9c6abc
#endif
Packit 9c6abc
#if defined(WEBP_USE_MIPS_DSP_R2)
Packit 9c6abc
    if (VP8GetCPUInfo(kMIPSdspR2)) {
Packit 9c6abc
      WebPInitAlphaProcessingMIPSdspR2();
Packit 9c6abc
    }
Packit 9c6abc
#endif
Packit 9c6abc
  }
Packit 9c6abc
Packit 9c6abc
#if defined(WEBP_USE_NEON)
Packit 9c6abc
  if (WEBP_NEON_OMIT_C_CODE ||
Packit 9c6abc
      (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
Packit 9c6abc
    WebPInitAlphaProcessingNEON();
Packit 9c6abc
  }
Packit 9c6abc
#endif
Packit 9c6abc
Packit 9c6abc
  assert(WebPMultARGBRow != NULL);
Packit 9c6abc
  assert(WebPMultRow != NULL);
Packit 9c6abc
  assert(WebPApplyAlphaMultiply != NULL);
Packit 9c6abc
  assert(WebPApplyAlphaMultiply4444 != NULL);
Packit 9c6abc
  assert(WebPDispatchAlpha != NULL);
Packit 9c6abc
  assert(WebPDispatchAlphaToGreen != NULL);
Packit 9c6abc
  assert(WebPExtractAlpha != NULL);
Packit 9c6abc
  assert(WebPExtractGreen != NULL);
Packit 9c6abc
#ifdef WORDS_BIGENDIAN
Packit 9c6abc
  assert(WebPPackARGB != NULL);
Packit 9c6abc
#endif
Packit 9c6abc
  assert(WebPPackRGB != NULL);
Packit 9c6abc
  assert(WebPHasAlpha8b != NULL);
Packit 9c6abc
  assert(WebPHasAlpha32b != NULL);
Packit 9c6abc
}