18b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Copyright 2013 Google Inc. All Rights Reserved. 28b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// 38b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Use of this source code is governed by a BSD-style license 48b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// that can be found in the COPYING file in the root of the source 58b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// tree. An additional intellectual property rights grant can be found 68b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// in the file PATENTS. All contributing project authors may 78b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// be found in the AUTHORS file in the root of the source tree. 88b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// ----------------------------------------------------------------------------- 98b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// 108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Utilities for processing transparent channel. 118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// 128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Author: Skal (pascal.massimino@gmail.com) 138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#include <assert.h> 1533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "./dsp.h" 168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// Tables can be faster on some platform but incur some extra binary size (~2k). 188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// #define USE_TABLES_FOR_ALPHA_MULT 198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora// ----------------------------------------------------------------------------- 218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#define MFIX 24 // 24bit fixed-point arithmetic 238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#define HALF ((1u << MFIX) >> 1) 248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#define KINV_255 ((1u << MFIX) / 255u) 258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic uint32_t Mult(uint8_t x, uint32_t mult) { 278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint32_t v = (x * mult + HALF) >> MFIX; 288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora assert(v <= 255); // <- 24bit precision is enough to ensure that. 298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return v; 308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#ifdef USE_TABLES_FOR_ALPHA_MULT 338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic const uint32_t kMultTables[2][256] = { 358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora { // (255u << MFIX) / alpha 368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00000000, 0xff000000, 0x7f800000, 0x55000000, 0x3fc00000, 0x33000000, 378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x2a800000, 0x246db6db, 0x1fe00000, 0x1c555555, 0x19800000, 0x172e8ba2, 388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x15400000, 0x139d89d8, 0x1236db6d, 0x11000000, 0x0ff00000, 0x0f000000, 398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x0e2aaaaa, 0x0d6bca1a, 0x0cc00000, 0x0c249249, 0x0b9745d1, 0x0b1642c8, 408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x0aa00000, 0x0a333333, 0x09cec4ec, 0x0971c71c, 0x091b6db6, 0x08cb08d3, 418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x08800000, 0x0839ce73, 0x07f80000, 0x07ba2e8b, 0x07800000, 0x07492492, 428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x07155555, 0x06e45306, 0x06b5e50d, 0x0689d89d, 0x06600000, 0x063831f3, 438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x06124924, 0x05ee23b8, 0x05cba2e8, 0x05aaaaaa, 0x058b2164, 0x056cefa8, 448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x05500000, 0x05343eb1, 0x05199999, 0x05000000, 0x04e76276, 0x04cfb2b7, 458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x04b8e38e, 0x04a2e8ba, 0x048db6db, 0x0479435e, 0x04658469, 0x045270d0, 468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x04400000, 0x042e29f7, 0x041ce739, 0x040c30c3, 0x03fc0000, 0x03ec4ec4, 478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x03dd1745, 0x03ce540f, 0x03c00000, 0x03b21642, 0x03a49249, 0x03976fc6, 488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x038aaaaa, 0x037e3f1f, 0x03722983, 0x03666666, 0x035af286, 0x034fcace, 498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x0344ec4e, 0x033a5440, 0x03300000, 0x0325ed09, 0x031c18f9, 0x0312818a, 508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x03092492, 0x03000000, 0x02f711dc, 0x02ee5846, 0x02e5d174, 0x02dd7baf, 518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x02d55555, 0x02cd5cd5, 0x02c590b2, 0x02bdef7b, 0x02b677d4, 0x02af286b, 528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x02a80000, 0x02a0fd5c, 0x029a1f58, 0x029364d9, 0x028ccccc, 0x0286562d, 538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x02800000, 0x0279c952, 0x0273b13b, 0x026db6db, 0x0267d95b, 0x026217ec, 548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x025c71c7, 0x0256e62a, 0x0251745d, 0x024c1bac, 0x0246db6d, 0x0241b2f9, 558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x023ca1af, 0x0237a6f4, 0x0232c234, 0x022df2df, 0x02293868, 0x02249249, 568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x02200000, 0x021b810e, 0x021714fb, 0x0212bb51, 0x020e739c, 0x020a3d70, 578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x02061861, 0x02020408, 0x01fe0000, 0x01fa0be8, 0x01f62762, 0x01f25213, 588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01ee8ba2, 0x01ead3ba, 0x01e72a07, 0x01e38e38, 0x01e00000, 0x01dc7f10, 598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01d90b21, 0x01d5a3e9, 0x01d24924, 0x01cefa8d, 0x01cbb7e3, 0x01c880e5, 608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01c55555, 0x01c234f7, 0x01bf1f8f, 0x01bc14e5, 0x01b914c1, 0x01b61eed, 618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01b33333, 0x01b05160, 0x01ad7943, 0x01aaaaaa, 0x01a7e567, 0x01a5294a, 628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01a27627, 0x019fcbd2, 0x019d2a20, 0x019a90e7, 0x01980000, 0x01957741, 638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x0192f684, 0x01907da4, 0x018e0c7c, 0x018ba2e8, 0x018940c5, 0x0186e5f0, 648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01849249, 0x018245ae, 0x01800000, 0x017dc11f, 0x017b88ee, 0x0179574e, 658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01772c23, 0x01750750, 0x0172e8ba, 0x0170d045, 0x016ebdd7, 0x016cb157, 668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x016aaaaa, 0x0168a9b9, 0x0166ae6a, 0x0164b8a7, 0x0162c859, 0x0160dd67, 678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x015ef7bd, 0x015d1745, 0x015b3bea, 0x01596596, 0x01579435, 0x0155c7b4, 688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01540000, 0x01523d03, 0x01507eae, 0x014ec4ec, 0x014d0fac, 0x014b5edc, 698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x0149b26c, 0x01480a4a, 0x01466666, 0x0144c6af, 0x01432b16, 0x0141938b, 708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01400000, 0x013e7063, 0x013ce4a9, 0x013b5cc0, 0x0139d89d, 0x01385830, 718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x0136db6d, 0x01356246, 0x0133ecad, 0x01327a97, 0x01310bf6, 0x012fa0be, 728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x012e38e3, 0x012cd459, 0x012b7315, 0x012a150a, 0x0128ba2e, 0x01276276, 738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01260dd6, 0x0124bc44, 0x01236db6, 0x01222222, 0x0120d97c, 0x011f93bc, 748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x011e50d7, 0x011d10c4, 0x011bd37a, 0x011a98ef, 0x0119611a, 0x01182bf2, 758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x0116f96f, 0x0115c988, 0x01149c34, 0x0113716a, 0x01124924, 0x01112358, 768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01100000, 0x010edf12, 0x010dc087, 0x010ca458, 0x010b8a7d, 0x010a72f0, 778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01095da8, 0x01084a9f, 0x010739ce, 0x01062b2e, 0x01051eb8, 0x01041465, 788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x01030c30, 0x01020612, 0x01010204, 0x01000000 }, 798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora { // alpha * KINV_255 808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505, 818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00060606, 0x00070707, 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b, 828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, 0x00101010, 0x00111111, 838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00121212, 0x00131313, 0x00141414, 0x00151515, 0x00161616, 0x00171717, 848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, 0x001c1c1c, 0x001d1d1d, 858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x001e1e1e, 0x001f1f1f, 0x00202020, 0x00212121, 0x00222222, 0x00232323, 868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00242424, 0x00252525, 0x00262626, 0x00272727, 0x00282828, 0x00292929, 878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x002a2a2a, 0x002b2b2b, 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f, 888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00303030, 0x00313131, 0x00323232, 0x00333333, 0x00343434, 0x00353535, 898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00363636, 0x00373737, 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b, 908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, 0x00404040, 0x00414141, 918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00424242, 0x00434343, 0x00444444, 0x00454545, 0x00464646, 0x00474747, 928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, 0x004c4c4c, 0x004d4d4d, 938b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x004e4e4e, 0x004f4f4f, 0x00505050, 0x00515151, 0x00525252, 0x00535353, 948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00545454, 0x00555555, 0x00565656, 0x00575757, 0x00585858, 0x00595959, 958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x005a5a5a, 0x005b5b5b, 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f, 968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00606060, 0x00616161, 0x00626262, 0x00636363, 0x00646464, 0x00656565, 978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00666666, 0x00676767, 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b, 988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, 0x00707070, 0x00717171, 998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00727272, 0x00737373, 0x00747474, 0x00757575, 0x00767676, 0x00777777, 1008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, 0x007c7c7c, 0x007d7d7d, 1018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x007e7e7e, 0x007f7f7f, 0x00808080, 0x00818181, 0x00828282, 0x00838383, 1028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00848484, 0x00858585, 0x00868686, 0x00878787, 0x00888888, 0x00898989, 1038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x008a8a8a, 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f, 1048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00909090, 0x00919191, 0x00929292, 0x00939393, 0x00949494, 0x00959595, 1058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00969696, 0x00979797, 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b, 1068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, 0x00a0a0a0, 0x00a1a1a1, 1078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00a2a2a2, 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7, 1088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00acacac, 0x00adadad, 1098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00aeaeae, 0x00afafaf, 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3, 1108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9, 1118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00bababa, 0x00bbbbbb, 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf, 1128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, 0x00c5c5c5, 1138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00c6c6c6, 0x00c7c7c7, 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb, 1148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, 0x00d1d1d1, 1158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7, 1168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, 0x00dcdcdc, 0x00dddddd, 1178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00dedede, 0x00dfdfdf, 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3, 1188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, 0x00e8e8e8, 0x00e9e9e9, 1198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00eaeaea, 0x00ebebeb, 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef, 1208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, 0x00f4f4f4, 0x00f5f5f5, 1218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00f6f6f6, 0x00f7f7f7, 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb, 1228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff } 1238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}; 1248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { 1268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return kMultTables[!inverse][a]; 1278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 1288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#else 1308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arorastatic WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { 1328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return inverse ? (255u << MFIX) / a : a * KINV_255; 1338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 1348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 1358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#endif // USE_TABLES_FOR_ALPHA_MULT 1368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 13733f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void MultARGBRow(uint32_t* const ptr, int width, int inverse) { 1388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int x; 1398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora for (x = 0; x < width; ++x) { 1408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint32_t argb = ptr[x]; 1418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (argb < 0xff000000u) { // alpha < 255 1428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (argb <= 0x00ffffffu) { // alpha == 0 1438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ptr[x] = 0; 1448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 1458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint32_t alpha = (argb >> 24) & 0xff; 1468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint32_t scale = GetScale(alpha, inverse); 1478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora uint32_t out = argb & 0xff000000u; 1488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora out |= Mult(argb >> 0, scale) << 0; 1498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora out |= Mult(argb >> 8, scale) << 8; 1508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora out |= Mult(argb >> 16, scale) << 16; 1518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ptr[x] = out; 1528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 1568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 15733f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void MultRow(uint8_t* const ptr, const uint8_t* const alpha, 15833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int width, int inverse) { 1598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int x; 1608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora for (x = 0; x < width; ++x) { 1618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint32_t a = alpha[x]; 1628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (a != 255) { 1638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora if (a == 0) { 1648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ptr[x] = 0; 1658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } else { 1668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint32_t scale = GetScale(a, inverse); 1678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ptr[x] = Mult(ptr[x], scale); 1688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 1718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 1728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 17333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#undef KINV_255 17433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#undef HALF 17533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#undef MFIX 17633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 17733f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid (*WebPMultARGBRow)(uint32_t* const ptr, int width, int inverse); 17833f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid (*WebPMultRow)(uint8_t* const ptr, const uint8_t* const alpha, 17933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int width, int inverse); 18033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 18133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 18233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Generic per-plane calls 18333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 18433f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid WebPMultARGBRows(uint8_t* ptr, int stride, int width, int num_rows, 18533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int inverse) { 18633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int n; 18733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (n = 0; n < num_rows; ++n) { 18833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPMultARGBRow((uint32_t*)ptr, width, inverse); 18933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora ptr += stride; 19033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 19133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 19233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 1938b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroravoid WebPMultRows(uint8_t* ptr, int stride, 1948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const uint8_t* alpha, int alpha_stride, 1958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int width, int num_rows, int inverse) { 1968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora int n; 1978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora for (n = 0; n < num_rows; ++n) { 1988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora WebPMultRow(ptr, alpha, width, inverse); 1998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora ptr += stride; 2008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora alpha += alpha_stride; 2018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora } 2028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 2038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 20433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 20533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Premultiplied modes 20633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 20733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// non dithered-modes 20833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 20933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// (x * a * 32897) >> 23 is bit-wise equivalent to (int)(x * a / 255.) 21033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// for all 8bit x or a. For bit-wise equivalence to (int)(x * a / 255. + .5), 21133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// one can use instead: (x * a * 65793 + (1 << 23)) >> 24 21233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#if 1 // (int)(x * a / 255.) 21333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define MULTIPLIER(a) ((a) * 32897U) 21433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define PREMULTIPLY(x, m) (((x) * (m)) >> 23) 21533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#else // (int)(x * a / 255. + .5) 21633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define MULTIPLIER(a) ((a) * 65793U) 21733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24) 21833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#endif 21933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 22033f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, 22133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int w, int h, int stride) { 22233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora while (h-- > 0) { 22333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); 22433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); 22533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int i; 22633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (i = 0; i < w; ++i) { 22733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint32_t a = alpha[4 * i]; 22833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (a != 0xff) { 22933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint32_t mult = MULTIPLIER(a); 23033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora rgb[4 * i + 0] = PREMULTIPLY(rgb[4 * i + 0], mult); 23133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora rgb[4 * i + 1] = PREMULTIPLY(rgb[4 * i + 1], mult); 23233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora rgb[4 * i + 2] = PREMULTIPLY(rgb[4 * i + 2], mult); 23333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 23433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 23533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora rgba += stride; 23633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 23733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 23833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#undef MULTIPLIER 23933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#undef PREMULTIPLY 24033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 24133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// rgbA4444 24233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 24333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define MULTIPLIER(a) ((a) * 0x1111) // 0x1111 ~= (1 << 16) / 15 24433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 24533f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE uint8_t dither_hi(uint8_t x) { 24633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (x & 0xf0) | (x >> 4); 24733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 24833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 24933f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE uint8_t dither_lo(uint8_t x) { 25033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (x & 0x0f) | (x << 4); 25133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 25233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 25333f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) { 25433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (x * m) >> 16; 25533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 25633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 25733f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE void ApplyAlphaMultiply4444(uint8_t* rgba4444, 25833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int w, int h, int stride, 25933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int rg_byte_pos /* 0 or 1 */) { 26033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora while (h-- > 0) { 26133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int i; 26233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (i = 0; i < w; ++i) { 26333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint32_t rg = rgba4444[2 * i + rg_byte_pos]; 26433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint32_t ba = rgba4444[2 * i + (rg_byte_pos ^ 1)]; 26533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t a = ba & 0x0f; 26633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint32_t mult = MULTIPLIER(a); 26733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t r = multiply(dither_hi(rg), mult); 26833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t g = multiply(dither_lo(rg), mult); 26933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t b = multiply(dither_hi(ba), mult); 27033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora rgba4444[2 * i + rg_byte_pos] = (r & 0xf0) | ((g >> 4) & 0x0f); 27133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora rgba4444[2 * i + (rg_byte_pos ^ 1)] = (b & 0xf0) | a; 27233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 27333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora rgba4444 += stride; 27433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 27533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 27633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#undef MULTIPLIER 2778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 27833f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void ApplyAlphaMultiply_16b(uint8_t* rgba4444, 27933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int w, int h, int stride) { 28033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#ifdef WEBP_SWAP_16BIT_CSP 28133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora ApplyAlphaMultiply4444(rgba4444, w, h, stride, 1); 28233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#else 28333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora ApplyAlphaMultiply4444(rgba4444, w, h, stride, 0); 28433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#endif 28533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 28633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 2878c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic int ExtractAlpha(const uint8_t* argb, int argb_stride, 2888c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int width, int height, 2898c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* alpha, int alpha_stride) { 2908c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t alpha_mask = 0xff; 2918c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int i, j; 2928c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2938c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (j = 0; j < height; ++j) { 2948c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (i = 0; i < width; ++i) { 2958c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t alpha_value = argb[4 * i]; 2968c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora alpha[i] = alpha_value; 2978c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora alpha_mask &= alpha_value; 2988c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 2998c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora argb += argb_stride; 3008c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora alpha += alpha_stride; 3018c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3028c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return (alpha_mask == 0xff); 3038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 3048c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 30533f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int); 30633f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int); 3078c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Aroraint (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int); 30833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 30933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 31033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Init function 31133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 3128c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Aroraextern void WebPInitAlphaProcessingSSE2(void); 3138c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3149e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zernstatic volatile VP8CPUInfo alpha_processing_last_cpuinfo_used = 3159e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zern (VP8CPUInfo)&alpha_processing_last_cpuinfo_used; 3169e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zern 31733f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid WebPInitAlphaProcessing(void) { 3189e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zern if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return; 3199e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zern 32033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPMultARGBRow = MultARGBRow; 32133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPMultRow = MultRow; 32233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPApplyAlphaMultiply = ApplyAlphaMultiply; 32333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b; 3248c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPExtractAlpha = ExtractAlpha; 3258c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // If defined, use CPUInfo() to overwrite some pointers with faster versions. 3278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (VP8GetCPUInfo != NULL) { 3288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#if defined(WEBP_USE_SSE2) 3298c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (VP8GetCPUInfo(kSSE2)) { 3308c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPInitAlphaProcessingSSE2(); 3318c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3328c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#endif 3338c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3349e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zern alpha_processing_last_cpuinfo_used = VP8GetCPUInfo; 33533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 336