Coverage Report

Created: 2024-07-27 06:27

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