Coverage Report

Created: 2026-01-13 06:40

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