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 #define MFIX 24    // 24bit fixed-point arithmetic
26 #define HALF ((1u << MFIX) >> 1)
27 #define KINV_255 ((1u << MFIX) / 255u)
28 
Mult(uint8_t x,uint32_t mult)29 static uint32_t Mult(uint8_t x, uint32_t mult) {
30   const uint32_t v = (x * mult + HALF) >> MFIX;
31   assert(v <= 255);  // <- 24bit precision is enough to ensure that.
32   return v;
33 }
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 
GetScale(uint32_t a,int inverse)128 static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
129   return kMultTables[!inverse][a];
130 }
131 
132 #else
133 
GetScale(uint32_t a,int inverse)134 static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) {
135   return inverse ? (255u << MFIX) / a : a * KINV_255;
136 }
137 
138 #endif  // USE_TABLES_FOR_ALPHA_MULT
139 
WebPMultARGBRow_C(uint32_t * const ptr,int width,int inverse)140 void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse) {
141   int x;
142   for (x = 0; x < width; ++x) {
143     const uint32_t argb = ptr[x];
144     if (argb < 0xff000000u) {      // alpha < 255
145       if (argb <= 0x00ffffffu) {   // alpha == 0
146         ptr[x] = 0;
147       } else {
148         const uint32_t alpha = (argb >> 24) & 0xff;
149         const uint32_t scale = GetScale(alpha, inverse);
150         uint32_t out = argb & 0xff000000u;
151         out |= Mult(argb >>  0, scale) <<  0;
152         out |= Mult(argb >>  8, scale) <<  8;
153         out |= Mult(argb >> 16, scale) << 16;
154         ptr[x] = out;
155       }
156     }
157   }
158 }
159 
WebPMultRow_C(uint8_t * WEBP_RESTRICT const ptr,const uint8_t * WEBP_RESTRICT const alpha,int width,int inverse)160 void WebPMultRow_C(uint8_t* WEBP_RESTRICT const ptr,
161                    const uint8_t* WEBP_RESTRICT const alpha,
162                    int width, int inverse) {
163   int x;
164   for (x = 0; x < width; ++x) {
165     const uint32_t a = alpha[x];
166     if (a != 255) {
167       if (a == 0) {
168         ptr[x] = 0;
169       } else {
170         const uint32_t scale = GetScale(a, inverse);
171         ptr[x] = Mult(ptr[x], scale);
172       }
173     }
174   }
175 }
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 
WebPMultARGBRows(uint8_t * ptr,int stride,int width,int num_rows,int inverse)189 void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
190                       int inverse) {
191   int n;
192   for (n = 0; n < num_rows; ++n) {
193     WebPMultARGBRow((uint32_t*)ptr, width, inverse);
194     ptr += stride;
195   }
196 }
197 
WebPMultRows(uint8_t * WEBP_RESTRICT ptr,int stride,const uint8_t * WEBP_RESTRICT alpha,int alpha_stride,int width,int num_rows,int inverse)198 void WebPMultRows(uint8_t* WEBP_RESTRICT ptr, int stride,
199                   const uint8_t* WEBP_RESTRICT alpha, int alpha_stride,
200                   int width, int num_rows, int inverse) {
201   int n;
202   for (n = 0; n < num_rows; ++n) {
203     WebPMultRow(ptr, alpha, width, inverse);
204     ptr += stride;
205     alpha += alpha_stride;
206   }
207 }
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 #define MULTIPLIER(a)   ((a) * 32897U)
219 #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
ApplyAlphaMultiply_C(uint8_t * rgba,int alpha_first,int w,int h,int stride)226 static void ApplyAlphaMultiply_C(uint8_t* rgba, int alpha_first,
227                                  int w, int h, int stride) {
228   while (h-- > 0) {
229     uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
230     const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
231     int i;
232     for (i = 0; i < w; ++i) {
233       const uint32_t a = alpha[4 * i];
234       if (a != 0xff) {
235         const uint32_t mult = MULTIPLIER(a);
236         rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
237         rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
238         rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
239       }
240     }
241     rgba += stride;
242   }
243 }
244 #endif  // !WEBP_NEON_OMIT_C_CODE
245 #undef MULTIPLIER
246 #undef PREMULTIPLY
247 
248 // rgbA4444
249 
250 #define MULTIPLIER(a)  ((a) * 0x1111)    // 0x1111 ~= (1 << 16) / 15
251 
dither_hi(uint8_t x)252 static WEBP_INLINE uint8_t dither_hi(uint8_t x) {
253   return (x & 0xf0) | (x >> 4);
254 }
255 
dither_lo(uint8_t x)256 static WEBP_INLINE uint8_t dither_lo(uint8_t x) {
257   return (x & 0x0f) | (x << 4);
258 }
259 
multiply(uint8_t x,uint32_t m)260 static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) {
261   return (x * m) >> 16;
262 }
263 
ApplyAlphaMultiply4444_C(uint8_t * rgba4444,int w,int h,int stride,int rg_byte_pos)264 static WEBP_INLINE void ApplyAlphaMultiply4444_C(uint8_t* rgba4444,
265                                                  int w, int h, int stride,
266                                                  int rg_byte_pos /* 0 or 1 */) {
267   while (h-- > 0) {
268     int i;
269     for (i = 0; i < w; ++i) {
270       const uint32_t rg = rgba4444[2 * i + rg_byte_pos];
271       const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)];
272       const uint8_t a = ba & 0x0f;
273       const uint32_t mult = MULTIPLIER(a);
274       const uint8_t r = multiply(dither_hi(rg), mult);
275       const uint8_t g = multiply(dither_lo(rg), mult);
276       const uint8_t b = multiply(dither_hi(ba), mult);
277       rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f);
278       rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a;
279     }
280     rgba4444 += stride;
281   }
282 }
283 #undef MULTIPLIER
284 
ApplyAlphaMultiply_16b_C(uint8_t * rgba4444,int w,int h,int stride)285 static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444,
286                                      int w, int h, int stride) {
287 #if (WEBP_SWAP_16BIT_CSP == 1)
288   ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 1);
289 #else
290   ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 0);
291 #endif
292 }
293 
294 #if !WEBP_NEON_OMIT_C_CODE
DispatchAlpha_C(const uint8_t * WEBP_RESTRICT alpha,int alpha_stride,int width,int height,uint8_t * WEBP_RESTRICT dst,int dst_stride)295 static int DispatchAlpha_C(const uint8_t* WEBP_RESTRICT alpha, int alpha_stride,
296                            int width, int height,
297                            uint8_t* WEBP_RESTRICT dst, int dst_stride) {
298   uint32_t alpha_mask = 0xff;
299   int i, j;
300 
301   for (j = 0; j < height; ++j) {
302     for (i = 0; i < width; ++i) {
303       const uint32_t alpha_value = alpha[i];
304       dst[4 * i] = alpha_value;
305       alpha_mask &= alpha_value;
306     }
307     alpha += alpha_stride;
308     dst += dst_stride;
309   }
310 
311   return (alpha_mask != 0xff);
312 }
313 
DispatchAlphaToGreen_C(const uint8_t * WEBP_RESTRICT alpha,int alpha_stride,int width,int height,uint32_t * WEBP_RESTRICT dst,int dst_stride)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                                    int dst_stride) {
318   int i, j;
319   for (j = 0; j < height; ++j) {
320     for (i = 0; i < width; ++i) {
321       dst[i] = alpha[i] << 8;  // leave A/R/B channels zero'd.
322     }
323     alpha += alpha_stride;
324     dst += dst_stride;
325   }
326 }
327 
ExtractAlpha_C(const uint8_t * WEBP_RESTRICT argb,int argb_stride,int width,int height,uint8_t * WEBP_RESTRICT alpha,int alpha_stride)328 static int ExtractAlpha_C(const uint8_t* WEBP_RESTRICT argb, int argb_stride,
329                           int width, int height,
330                           uint8_t* WEBP_RESTRICT alpha, int alpha_stride) {
331   uint8_t alpha_mask = 0xff;
332   int i, j;
333 
334   for (j = 0; j < height; ++j) {
335     for (i = 0; i < width; ++i) {
336       const uint8_t alpha_value = argb[4 * i];
337       alpha[i] = alpha_value;
338       alpha_mask &= alpha_value;
339     }
340     argb += argb_stride;
341     alpha += alpha_stride;
342   }
343   return (alpha_mask == 0xff);
344 }
345 
ExtractGreen_C(const uint32_t * WEBP_RESTRICT argb,uint8_t * WEBP_RESTRICT alpha,int size)346 static void ExtractGreen_C(const uint32_t* WEBP_RESTRICT argb,
347                            uint8_t* WEBP_RESTRICT alpha, int size) {
348   int i;
349   for (i = 0; i < size; ++i) alpha[i] = argb[i] >> 8;
350 }
351 #endif  // !WEBP_NEON_OMIT_C_CODE
352 
353 //------------------------------------------------------------------------------
354 
HasAlpha8b_C(const uint8_t * src,int length)355 static int HasAlpha8b_C(const uint8_t* src, int length) {
356   while (length-- > 0) if (*src++ != 0xff) return 1;
357   return 0;
358 }
359 
HasAlpha32b_C(const uint8_t * src,int length)360 static int HasAlpha32b_C(const uint8_t* src, int length) {
361   int x;
362   for (x = 0; length-- > 0; x += 4) if (src[x] != 0xff) return 1;
363   return 0;
364 }
365 
AlphaReplace_C(uint32_t * src,int length,uint32_t color)366 static void AlphaReplace_C(uint32_t* src, int length, uint32_t color) {
367   int x;
368   for (x = 0; x < length; ++x) if ((src[x] >> 24) == 0) src[x] = color;
369 }
370 
371 //------------------------------------------------------------------------------
372 // Simple channel manipulations.
373 
MakeARGB32(int a,int r,int g,int b)374 static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
375   return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b);
376 }
377 
378 #ifdef WORDS_BIGENDIAN
PackARGB_C(const uint8_t * WEBP_RESTRICT a,const uint8_t * WEBP_RESTRICT r,const uint8_t * WEBP_RESTRICT g,const uint8_t * WEBP_RESTRICT b,int len,uint32_t * WEBP_RESTRICT out)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 
PackRGB_C(const uint8_t * WEBP_RESTRICT r,const uint8_t * WEBP_RESTRICT g,const uint8_t * WEBP_RESTRICT b,int len,int step,uint32_t * WEBP_RESTRICT out)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                       int len, int step, uint32_t* WEBP_RESTRICT out) {
395   int i, offset = 0;
396   for (i = 0; i < len; ++i) {
397     out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]);
398     offset += step;
399   }
400 }
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 void WebPInitAlphaProcessingMIPSdspR2(void);
429 extern void WebPInitAlphaProcessingSSE2(void);
430 extern void WebPInitAlphaProcessingSSE41(void);
431 extern void WebPInitAlphaProcessingNEON(void);
432 
WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing)433 WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
434   WebPMultARGBRow = WebPMultARGBRow_C;
435   WebPMultRow = WebPMultRow_C;
436   WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C;
437 
438 #ifdef WORDS_BIGENDIAN
439   WebPPackARGB = PackARGB_C;
440 #endif
441   WebPPackRGB = PackRGB_C;
442 #if !WEBP_NEON_OMIT_C_CODE
443   WebPApplyAlphaMultiply = ApplyAlphaMultiply_C;
444   WebPDispatchAlpha = DispatchAlpha_C;
445   WebPDispatchAlphaToGreen = DispatchAlphaToGreen_C;
446   WebPExtractAlpha = ExtractAlpha_C;
447   WebPExtractGreen = ExtractGreen_C;
448 #endif
449 
450   WebPHasAlpha8b = HasAlpha8b_C;
451   WebPHasAlpha32b = HasAlpha32b_C;
452   WebPAlphaReplace = AlphaReplace_C;
453 
454   // If defined, use CPUInfo() to overwrite some pointers with faster versions.
455   if (VP8GetCPUInfo != NULL) {
456 #if defined(WEBP_HAVE_SSE2)
457     if (VP8GetCPUInfo(kSSE2)) {
458       WebPInitAlphaProcessingSSE2();
459 #if defined(WEBP_HAVE_SSE41)
460       if (VP8GetCPUInfo(kSSE4_1)) {
461         WebPInitAlphaProcessingSSE41();
462       }
463 #endif
464     }
465 #endif
466 #if defined(WEBP_USE_MIPS_DSP_R2)
467     if (VP8GetCPUInfo(kMIPSdspR2)) {
468       WebPInitAlphaProcessingMIPSdspR2();
469     }
470 #endif
471   }
472 
473 #if defined(WEBP_HAVE_NEON)
474   if (WEBP_NEON_OMIT_C_CODE ||
475       (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
476     WebPInitAlphaProcessingNEON();
477   }
478 #endif
479 
480   assert(WebPMultARGBRow != NULL);
481   assert(WebPMultRow != NULL);
482   assert(WebPApplyAlphaMultiply != NULL);
483   assert(WebPApplyAlphaMultiply4444 != NULL);
484   assert(WebPDispatchAlpha != NULL);
485   assert(WebPDispatchAlphaToGreen != NULL);
486   assert(WebPExtractAlpha != NULL);
487   assert(WebPExtractGreen != NULL);
488 #ifdef WORDS_BIGENDIAN
489   assert(WebPPackARGB != NULL);
490 #endif
491   assert(WebPPackRGB != NULL);
492   assert(WebPHasAlpha8b != NULL);
493   assert(WebPHasAlpha32b != NULL);
494   assert(WebPAlphaReplace != NULL);
495 }
496