• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 * const ptr,const uint8_t * const alpha,int width,int inverse)160 void WebPMultRow_C(uint8_t* const ptr, const uint8_t* const alpha,
161                    int width, int inverse) {
162   int x;
163   for (x = 0; x < width; ++x) {
164     const uint32_t a = alpha[x];
165     if (a != 255) {
166       if (a == 0) {
167         ptr[x] = 0;
168       } else {
169         const uint32_t scale = GetScale(a, inverse);
170         ptr[x] = Mult(ptr[x], scale);
171       }
172     }
173   }
174 }
175 
176 #undef KINV_255
177 #undef HALF
178 #undef MFIX
179 
180 void (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse);
181 void (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha,
182                     int width, int inverse);
183 
184 //------------------------------------------------------------------------------
185 // Generic per-plane calls
186 
WebPMultARGBRows(uint8_t * ptr,int stride,int width,int num_rows,int inverse)187 void WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows,
188                       int inverse) {
189   int n;
190   for (n = 0; n < num_rows; ++n) {
191     WebPMultARGBRow((uint32_t*)ptr, width, inverse);
192     ptr += stride;
193   }
194 }
195 
WebPMultRows(uint8_t * ptr,int stride,const uint8_t * alpha,int alpha_stride,int width,int num_rows,int inverse)196 void WebPMultRows(uint8_t* ptr, int stride,
197                   const uint8_t* alpha, int alpha_stride,
198                   int width, int num_rows, int inverse) {
199   int n;
200   for (n = 0; n < num_rows; ++n) {
201     WebPMultRow(ptr, alpha, width, inverse);
202     ptr += stride;
203     alpha += alpha_stride;
204   }
205 }
206 
207 //------------------------------------------------------------------------------
208 // Premultiplied modes
209 
210 // non dithered-modes
211 
212 // (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.)
213 // for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5),
214 // one can use instead: (x * a * 65793 + (1 << 23)) >> 24
215 #if 1     // (int)(x * a / 255.)
216 #define MULTIPLIER(a)   ((a) * 32897U)
217 #define PREMULTIPLY(x, m) (((x) * (m)) >> 23)
218 #else     // (int)(x * a / 255. + .5)
219 #define MULTIPLIER(a) ((a) * 65793U)
220 #define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24)
221 #endif
222 
223 #if !WEBP_NEON_OMIT_C_CODE
ApplyAlphaMultiply_C(uint8_t * rgba,int alpha_first,int w,int h,int stride)224 static void ApplyAlphaMultiply_C(uint8_t* rgba, int alpha_first,
225                                  int w, int h, int stride) {
226   while (h-- > 0) {
227     uint8_t* const rgb = rgba + (alpha_first ? 1 : 0);
228     const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3);
229     int i;
230     for (i = 0; i < w; ++i) {
231       const uint32_t a = alpha[4 * i];
232       if (a != 0xff) {
233         const uint32_t mult = MULTIPLIER(a);
234         rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult);
235         rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult);
236         rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult);
237       }
238     }
239     rgba += stride;
240   }
241 }
242 #endif  // !WEBP_NEON_OMIT_C_CODE
243 #undef MULTIPLIER
244 #undef PREMULTIPLY
245 
246 // rgbA4444
247 
248 #define MULTIPLIER(a)  ((a) * 0x1111)    // 0x1111 ~= (1 << 16) / 15
249 
dither_hi(uint8_t x)250 static WEBP_INLINE uint8_t dither_hi(uint8_t x) {
251   return (x & 0xf0) | (x >> 4);
252 }
253 
dither_lo(uint8_t x)254 static WEBP_INLINE uint8_t dither_lo(uint8_t x) {
255   return (x & 0x0f) | (x << 4);
256 }
257 
multiply(uint8_t x,uint32_t m)258 static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) {
259   return (x * m) >> 16;
260 }
261 
ApplyAlphaMultiply4444_C(uint8_t * rgba4444,int w,int h,int stride,int rg_byte_pos)262 static WEBP_INLINE void ApplyAlphaMultiply4444_C(uint8_t* rgba4444,
263                                                  int w, int h, int stride,
264                                                  int rg_byte_pos /* 0 or 1 */) {
265   while (h-- > 0) {
266     int i;
267     for (i = 0; i < w; ++i) {
268       const uint32_t rg = rgba4444[2 * i + rg_byte_pos];
269       const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)];
270       const uint8_t a = ba & 0x0f;
271       const uint32_t mult = MULTIPLIER(a);
272       const uint8_t r = multiply(dither_hi(rg), mult);
273       const uint8_t g = multiply(dither_lo(rg), mult);
274       const uint8_t b = multiply(dither_hi(ba), mult);
275       rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f);
276       rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a;
277     }
278     rgba4444 += stride;
279   }
280 }
281 #undef MULTIPLIER
282 
ApplyAlphaMultiply_16b_C(uint8_t * rgba4444,int w,int h,int stride)283 static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444,
284                                      int w, int h, int stride) {
285 #if (WEBP_SWAP_16BIT_CSP == 1)
286   ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 1);
287 #else
288   ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 0);
289 #endif
290 }
291 
292 #if !WEBP_NEON_OMIT_C_CODE
DispatchAlpha_C(const uint8_t * alpha,int alpha_stride,int width,int height,uint8_t * dst,int dst_stride)293 static int DispatchAlpha_C(const uint8_t* alpha, int alpha_stride,
294                            int width, int height,
295                            uint8_t* dst, int dst_stride) {
296   uint32_t alpha_mask = 0xff;
297   int i, j;
298 
299   for (j = 0; j < height; ++j) {
300     for (i = 0; i < width; ++i) {
301       const uint32_t alpha_value = alpha[i];
302       dst[4 * i] = alpha_value;
303       alpha_mask &= alpha_value;
304     }
305     alpha += alpha_stride;
306     dst += dst_stride;
307   }
308 
309   return (alpha_mask != 0xff);
310 }
311 
DispatchAlphaToGreen_C(const uint8_t * alpha,int alpha_stride,int width,int height,uint32_t * dst,int dst_stride)312 static void DispatchAlphaToGreen_C(const uint8_t* alpha, int alpha_stride,
313                                    int width, int height,
314                                    uint32_t* dst, int dst_stride) {
315   int i, j;
316   for (j = 0; j < height; ++j) {
317     for (i = 0; i < width; ++i) {
318       dst[i] = alpha[i] << 8;  // leave A/R/B channels zero'd.
319     }
320     alpha += alpha_stride;
321     dst += dst_stride;
322   }
323 }
324 
ExtractAlpha_C(const uint8_t * argb,int argb_stride,int width,int height,uint8_t * alpha,int alpha_stride)325 static int ExtractAlpha_C(const uint8_t* argb, int argb_stride,
326                           int width, int height,
327                           uint8_t* alpha, int alpha_stride) {
328   uint8_t alpha_mask = 0xff;
329   int i, j;
330 
331   for (j = 0; j < height; ++j) {
332     for (i = 0; i < width; ++i) {
333       const uint8_t alpha_value = argb[4 * i];
334       alpha[i] = alpha_value;
335       alpha_mask &= alpha_value;
336     }
337     argb += argb_stride;
338     alpha += alpha_stride;
339   }
340   return (alpha_mask == 0xff);
341 }
342 
ExtractGreen_C(const uint32_t * argb,uint8_t * alpha,int size)343 static void ExtractGreen_C(const uint32_t* argb, uint8_t* alpha, int size) {
344   int i;
345   for (i = 0; i < size; ++i) alpha[i] = argb[i] >> 8;
346 }
347 #endif  // !WEBP_NEON_OMIT_C_CODE
348 
349 //------------------------------------------------------------------------------
350 
HasAlpha8b_C(const uint8_t * src,int length)351 static int HasAlpha8b_C(const uint8_t* src, int length) {
352   while (length-- > 0) if (*src++ != 0xff) return 1;
353   return 0;
354 }
355 
HasAlpha32b_C(const uint8_t * src,int length)356 static int HasAlpha32b_C(const uint8_t* src, int length) {
357   int x;
358   for (x = 0; length-- > 0; x += 4) if (src[x] != 0xff) return 1;
359   return 0;
360 }
361 
AlphaReplace_C(uint32_t * src,int length,uint32_t color)362 static void AlphaReplace_C(uint32_t* src, int length, uint32_t color) {
363   int x;
364   for (x = 0; x < length; ++x) if ((src[x] >> 24) == 0) src[x] = color;
365 }
366 
367 //------------------------------------------------------------------------------
368 // Simple channel manipulations.
369 
MakeARGB32(int a,int r,int g,int b)370 static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) {
371   return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b);
372 }
373 
374 #ifdef WORDS_BIGENDIAN
PackARGB_C(const uint8_t * a,const uint8_t * r,const uint8_t * g,const uint8_t * b,int len,uint32_t * out)375 static void PackARGB_C(const uint8_t* a, const uint8_t* r, const uint8_t* g,
376                        const uint8_t* b, int len, uint32_t* out) {
377   int i;
378   for (i = 0; i < len; ++i) {
379     out[i] = MakeARGB32(a[4 * i], r[4 * i], g[4 * i], b[4 * i]);
380   }
381 }
382 #endif
383 
PackRGB_C(const uint8_t * r,const uint8_t * g,const uint8_t * b,int len,int step,uint32_t * out)384 static void PackRGB_C(const uint8_t* r, const uint8_t* g, const uint8_t* b,
385                       int len, int step, uint32_t* out) {
386   int i, offset = 0;
387   for (i = 0; i < len; ++i) {
388     out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]);
389     offset += step;
390   }
391 }
392 
393 void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int);
394 void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int);
395 int (*WebPDispatchAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
396 void (*WebPDispatchAlphaToGreen)(const uint8_t*, int, int, int, uint32_t*, int);
397 int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int);
398 void (*WebPExtractGreen)(const uint32_t* argb, uint8_t* alpha, int size);
399 #ifdef WORDS_BIGENDIAN
400 void (*WebPPackARGB)(const uint8_t* a, const uint8_t* r, const uint8_t* g,
401                      const uint8_t* b, int, uint32_t*);
402 #endif
403 void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b,
404                     int len, int step, uint32_t* out);
405 
406 int (*WebPHasAlpha8b)(const uint8_t* src, int length);
407 int (*WebPHasAlpha32b)(const uint8_t* src, int length);
408 void (*WebPAlphaReplace)(uint32_t* src, int length, uint32_t color);
409 
410 //------------------------------------------------------------------------------
411 // Init function
412 
413 extern void WebPInitAlphaProcessingMIPSdspR2(void);
414 extern void WebPInitAlphaProcessingSSE2(void);
415 extern void WebPInitAlphaProcessingSSE41(void);
416 extern void WebPInitAlphaProcessingNEON(void);
417 
WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing)418 WEBP_DSP_INIT_FUNC(WebPInitAlphaProcessing) {
419   WebPMultARGBRow = WebPMultARGBRow_C;
420   WebPMultRow = WebPMultRow_C;
421   WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C;
422 
423 #ifdef WORDS_BIGENDIAN
424   WebPPackARGB = PackARGB_C;
425 #endif
426   WebPPackRGB = PackRGB_C;
427 #if !WEBP_NEON_OMIT_C_CODE
428   WebPApplyAlphaMultiply = ApplyAlphaMultiply_C;
429   WebPDispatchAlpha = DispatchAlpha_C;
430   WebPDispatchAlphaToGreen = DispatchAlphaToGreen_C;
431   WebPExtractAlpha = ExtractAlpha_C;
432   WebPExtractGreen = ExtractGreen_C;
433 #endif
434 
435   WebPHasAlpha8b = HasAlpha8b_C;
436   WebPHasAlpha32b = HasAlpha32b_C;
437   WebPAlphaReplace = AlphaReplace_C;
438 
439   // If defined, use CPUInfo() to overwrite some pointers with faster versions.
440   if (VP8GetCPUInfo != NULL) {
441 #if defined(WEBP_USE_SSE2)
442     if (VP8GetCPUInfo(kSSE2)) {
443       WebPInitAlphaProcessingSSE2();
444 #if defined(WEBP_USE_SSE41)
445       if (VP8GetCPUInfo(kSSE4_1)) {
446         WebPInitAlphaProcessingSSE41();
447       }
448 #endif
449     }
450 #endif
451 #if defined(WEBP_USE_MIPS_DSP_R2)
452     if (VP8GetCPUInfo(kMIPSdspR2)) {
453       WebPInitAlphaProcessingMIPSdspR2();
454     }
455 #endif
456   }
457 
458 #if defined(WEBP_USE_NEON)
459   if (WEBP_NEON_OMIT_C_CODE ||
460       (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {
461     WebPInitAlphaProcessingNEON();
462   }
463 #endif
464 
465   assert(WebPMultARGBRow != NULL);
466   assert(WebPMultRow != NULL);
467   assert(WebPApplyAlphaMultiply != NULL);
468   assert(WebPApplyAlphaMultiply4444 != NULL);
469   assert(WebPDispatchAlpha != NULL);
470   assert(WebPDispatchAlphaToGreen != NULL);
471   assert(WebPExtractAlpha != NULL);
472   assert(WebPExtractGreen != NULL);
473 #ifdef WORDS_BIGENDIAN
474   assert(WebPPackARGB != NULL);
475 #endif
476   assert(WebPPackRGB != NULL);
477   assert(WebPHasAlpha8b != NULL);
478   assert(WebPHasAlpha32b != NULL);
479   assert(WebPAlphaReplace != NULL);
480 }
481