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