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