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