1// Copyright 2012 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// Image transforms and color space conversion methods for lossless decoder. 11// 12// Authors: Vikas Arora (vikaas.arora@gmail.com) 13// Jyrki Alakuijala (jyrki@google.com) 14// Urvang Joshi (urvang@google.com) 15 16#include "./dsp.h" 17 18#include <math.h> 19#include <stdlib.h> 20#include "../dec/vp8li.h" 21#include "../utils/endian_inl.h" 22#include "./lossless.h" 23#include "./yuv.h" 24 25#define MAX_DIFF_COST (1e30f) 26 27// lookup table for small values of log2(int) 28const float kLog2Table[LOG_LOOKUP_IDX_MAX] = { 29 0.0000000000000000f, 0.0000000000000000f, 30 1.0000000000000000f, 1.5849625007211560f, 31 2.0000000000000000f, 2.3219280948873621f, 32 2.5849625007211560f, 2.8073549220576041f, 33 3.0000000000000000f, 3.1699250014423121f, 34 3.3219280948873621f, 3.4594316186372973f, 35 3.5849625007211560f, 3.7004397181410921f, 36 3.8073549220576041f, 3.9068905956085187f, 37 4.0000000000000000f, 4.0874628412503390f, 38 4.1699250014423121f, 4.2479275134435852f, 39 4.3219280948873626f, 4.3923174227787606f, 40 4.4594316186372973f, 4.5235619560570130f, 41 4.5849625007211560f, 4.6438561897747243f, 42 4.7004397181410917f, 4.7548875021634682f, 43 4.8073549220576037f, 4.8579809951275718f, 44 4.9068905956085187f, 4.9541963103868749f, 45 5.0000000000000000f, 5.0443941193584533f, 46 5.0874628412503390f, 5.1292830169449663f, 47 5.1699250014423121f, 5.2094533656289501f, 48 5.2479275134435852f, 5.2854022188622487f, 49 5.3219280948873626f, 5.3575520046180837f, 50 5.3923174227787606f, 5.4262647547020979f, 51 5.4594316186372973f, 5.4918530963296747f, 52 5.5235619560570130f, 5.5545888516776376f, 53 5.5849625007211560f, 5.6147098441152083f, 54 5.6438561897747243f, 5.6724253419714951f, 55 5.7004397181410917f, 5.7279204545631987f, 56 5.7548875021634682f, 5.7813597135246599f, 57 5.8073549220576037f, 5.8328900141647412f, 58 5.8579809951275718f, 5.8826430493618415f, 59 5.9068905956085187f, 5.9307373375628866f, 60 5.9541963103868749f, 5.9772799234999167f, 61 6.0000000000000000f, 6.0223678130284543f, 62 6.0443941193584533f, 6.0660891904577720f, 63 6.0874628412503390f, 6.1085244567781691f, 64 6.1292830169449663f, 6.1497471195046822f, 65 6.1699250014423121f, 6.1898245588800175f, 66 6.2094533656289501f, 6.2288186904958804f, 67 6.2479275134435852f, 6.2667865406949010f, 68 6.2854022188622487f, 6.3037807481771030f, 69 6.3219280948873626f, 6.3398500028846243f, 70 6.3575520046180837f, 6.3750394313469245f, 71 6.3923174227787606f, 6.4093909361377017f, 72 6.4262647547020979f, 6.4429434958487279f, 73 6.4594316186372973f, 6.4757334309663976f, 74 6.4918530963296747f, 6.5077946401986963f, 75 6.5235619560570130f, 6.5391588111080309f, 76 6.5545888516776376f, 6.5698556083309478f, 77 6.5849625007211560f, 6.5999128421871278f, 78 6.6147098441152083f, 6.6293566200796094f, 79 6.6438561897747243f, 6.6582114827517946f, 80 6.6724253419714951f, 6.6865005271832185f, 81 6.7004397181410917f, 6.7142455176661224f, 82 6.7279204545631987f, 6.7414669864011464f, 83 6.7548875021634682f, 6.7681843247769259f, 84 6.7813597135246599f, 6.7944158663501061f, 85 6.8073549220576037f, 6.8201789624151878f, 86 6.8328900141647412f, 6.8454900509443747f, 87 6.8579809951275718f, 6.8703647195834047f, 88 6.8826430493618415f, 6.8948177633079437f, 89 6.9068905956085187f, 6.9188632372745946f, 90 6.9307373375628866f, 6.9425145053392398f, 91 6.9541963103868749f, 6.9657842846620869f, 92 6.9772799234999167f, 6.9886846867721654f, 93 7.0000000000000000f, 7.0112272554232539f, 94 7.0223678130284543f, 7.0334230015374501f, 95 7.0443941193584533f, 7.0552824355011898f, 96 7.0660891904577720f, 7.0768155970508308f, 97 7.0874628412503390f, 7.0980320829605263f, 98 7.1085244567781691f, 7.1189410727235076f, 99 7.1292830169449663f, 7.1395513523987936f, 100 7.1497471195046822f, 7.1598713367783890f, 101 7.1699250014423121f, 7.1799090900149344f, 102 7.1898245588800175f, 7.1996723448363644f, 103 7.2094533656289501f, 7.2191685204621611f, 104 7.2288186904958804f, 7.2384047393250785f, 105 7.2479275134435852f, 7.2573878426926521f, 106 7.2667865406949010f, 7.2761244052742375f, 107 7.2854022188622487f, 7.2946207488916270f, 108 7.3037807481771030f, 7.3128829552843557f, 109 7.3219280948873626f, 7.3309168781146167f, 110 7.3398500028846243f, 7.3487281542310771f, 111 7.3575520046180837f, 7.3663222142458160f, 112 7.3750394313469245f, 7.3837042924740519f, 113 7.3923174227787606f, 7.4008794362821843f, 114 7.4093909361377017f, 7.4178525148858982f, 115 7.4262647547020979f, 7.4346282276367245f, 116 7.4429434958487279f, 7.4512111118323289f, 117 7.4594316186372973f, 7.4676055500829976f, 118 7.4757334309663976f, 7.4838157772642563f, 119 7.4918530963296747f, 7.4998458870832056f, 120 7.5077946401986963f, 7.5156998382840427f, 121 7.5235619560570130f, 7.5313814605163118f, 122 7.5391588111080309f, 7.5468944598876364f, 123 7.5545888516776376f, 7.5622424242210728f, 124 7.5698556083309478f, 7.5774288280357486f, 125 7.5849625007211560f, 7.5924570372680806f, 126 7.5999128421871278f, 7.6073303137496104f, 127 7.6147098441152083f, 7.6220518194563764f, 128 7.6293566200796094f, 7.6366246205436487f, 129 7.6438561897747243f, 7.6510516911789281f, 130 7.6582114827517946f, 7.6653359171851764f, 131 7.6724253419714951f, 7.6794800995054464f, 132 7.6865005271832185f, 7.6934869574993252f, 133 7.7004397181410917f, 7.7073591320808825f, 134 7.7142455176661224f, 7.7210991887071855f, 135 7.7279204545631987f, 7.7347096202258383f, 136 7.7414669864011464f, 7.7481928495894605f, 137 7.7548875021634682f, 7.7615512324444795f, 138 7.7681843247769259f, 7.7747870596011736f, 139 7.7813597135246599f, 7.7879025593914317f, 140 7.7944158663501061f, 7.8008998999203047f, 141 7.8073549220576037f, 7.8137811912170374f, 142 7.8201789624151878f, 7.8265484872909150f, 143 7.8328900141647412f, 7.8392037880969436f, 144 7.8454900509443747f, 7.8517490414160571f, 145 7.8579809951275718f, 7.8641861446542797f, 146 7.8703647195834047f, 7.8765169465649993f, 147 7.8826430493618415f, 7.8887432488982591f, 148 7.8948177633079437f, 7.9008668079807486f, 149 7.9068905956085187f, 7.9128893362299619f, 150 7.9188632372745946f, 7.9248125036057812f, 151 7.9307373375628866f, 7.9366379390025709f, 152 7.9425145053392398f, 7.9483672315846778f, 153 7.9541963103868749f, 7.9600019320680805f, 154 7.9657842846620869f, 7.9715435539507719f, 155 7.9772799234999167f, 7.9829935746943103f, 156 7.9886846867721654f, 7.9943534368588577f 157}; 158 159const float kSLog2Table[LOG_LOOKUP_IDX_MAX] = { 160 0.00000000f, 0.00000000f, 2.00000000f, 4.75488750f, 161 8.00000000f, 11.60964047f, 15.50977500f, 19.65148445f, 162 24.00000000f, 28.52932501f, 33.21928095f, 38.05374781f, 163 43.01955001f, 48.10571634f, 53.30296891f, 58.60335893f, 164 64.00000000f, 69.48686830f, 75.05865003f, 80.71062276f, 165 86.43856190f, 92.23866588f, 98.10749561f, 104.04192499f, 166 110.03910002f, 116.09640474f, 122.21143267f, 128.38196256f, 167 134.60593782f, 140.88144886f, 147.20671787f, 153.58008562f, 168 160.00000000f, 166.46500594f, 172.97373660f, 179.52490559f, 169 186.11730005f, 192.74977453f, 199.42124551f, 206.13068654f, 170 212.87712380f, 219.65963219f, 226.47733176f, 233.32938445f, 171 240.21499122f, 247.13338933f, 254.08384998f, 261.06567603f, 172 268.07820003f, 275.12078236f, 282.19280949f, 289.29369244f, 173 296.42286534f, 303.57978409f, 310.76392512f, 317.97478424f, 174 325.21187564f, 332.47473081f, 339.76289772f, 347.07593991f, 175 354.41343574f, 361.77497759f, 369.16017124f, 376.56863518f, 176 384.00000000f, 391.45390785f, 398.93001188f, 406.42797576f, 177 413.94747321f, 421.48818752f, 429.04981119f, 436.63204548f, 178 444.23460010f, 451.85719280f, 459.49954906f, 467.16140179f, 179 474.84249102f, 482.54256363f, 490.26137307f, 497.99867911f, 180 505.75424759f, 513.52785023f, 521.31926438f, 529.12827280f, 181 536.95466351f, 544.79822957f, 552.65876890f, 560.53608414f, 182 568.42998244f, 576.34027536f, 584.26677867f, 592.20931226f, 183 600.16769996f, 608.14176943f, 616.13135206f, 624.13628279f, 184 632.15640007f, 640.19154569f, 648.24156472f, 656.30630539f, 185 664.38561898f, 672.47935976f, 680.58738488f, 688.70955430f, 186 696.84573069f, 704.99577935f, 713.15956818f, 721.33696754f, 187 729.52785023f, 737.73209140f, 745.94956849f, 754.18016116f, 188 762.42375127f, 770.68022275f, 778.94946161f, 787.23135586f, 189 795.52579543f, 803.83267219f, 812.15187982f, 820.48331383f, 190 828.82687147f, 837.18245171f, 845.54995518f, 853.92928416f, 191 862.32034249f, 870.72303558f, 879.13727036f, 887.56295522f, 192 896.00000000f, 904.44831595f, 912.90781569f, 921.37841320f, 193 929.86002376f, 938.35256392f, 946.85595152f, 955.37010560f, 194 963.89494641f, 972.43039537f, 980.97637504f, 989.53280911f, 195 998.09962237f, 1006.67674069f, 1015.26409097f, 1023.86160116f, 196 1032.46920021f, 1041.08681805f, 1049.71438560f, 1058.35183469f, 197 1066.99909811f, 1075.65610955f, 1084.32280357f, 1092.99911564f, 198 1101.68498204f, 1110.38033993f, 1119.08512727f, 1127.79928282f, 199 1136.52274614f, 1145.25545758f, 1153.99735821f, 1162.74838989f, 200 1171.50849518f, 1180.27761738f, 1189.05570047f, 1197.84268914f, 201 1206.63852876f, 1215.44316535f, 1224.25654560f, 1233.07861684f, 202 1241.90932703f, 1250.74862473f, 1259.59645914f, 1268.45278005f, 203 1277.31753781f, 1286.19068338f, 1295.07216828f, 1303.96194457f, 204 1312.85996488f, 1321.76618236f, 1330.68055071f, 1339.60302413f, 205 1348.53355734f, 1357.47210556f, 1366.41862452f, 1375.37307041f, 206 1384.33539991f, 1393.30557020f, 1402.28353887f, 1411.26926400f, 207 1420.26270412f, 1429.26381818f, 1438.27256558f, 1447.28890615f, 208 1456.31280014f, 1465.34420819f, 1474.38309138f, 1483.42941118f, 209 1492.48312945f, 1501.54420843f, 1510.61261078f, 1519.68829949f, 210 1528.77123795f, 1537.86138993f, 1546.95871952f, 1556.06319119f, 211 1565.17476976f, 1574.29342040f, 1583.41910860f, 1592.55180020f, 212 1601.69146137f, 1610.83805860f, 1619.99155871f, 1629.15192882f, 213 1638.31913637f, 1647.49314911f, 1656.67393509f, 1665.86146266f, 214 1675.05570047f, 1684.25661744f, 1693.46418280f, 1702.67836605f, 215 1711.89913698f, 1721.12646563f, 1730.36032233f, 1739.60067768f, 216 1748.84750254f, 1758.10076802f, 1767.36044551f, 1776.62650662f, 217 1785.89892323f, 1795.17766747f, 1804.46271172f, 1813.75402857f, 218 1823.05159087f, 1832.35537170f, 1841.66534438f, 1850.98148244f, 219 1860.30375965f, 1869.63214999f, 1878.96662767f, 1888.30716711f, 220 1897.65374295f, 1907.00633003f, 1916.36490342f, 1925.72943838f, 221 1935.09991037f, 1944.47629506f, 1953.85856831f, 1963.24670620f, 222 1972.64068498f, 1982.04048108f, 1991.44607117f, 2000.85743204f, 223 2010.27454072f, 2019.69737440f, 2029.12591044f, 2038.56012640f 224}; 225 226const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = { 227 { 0, 0}, { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 1}, { 4, 1}, { 5, 1}, 228 { 5, 1}, { 6, 2}, { 6, 2}, { 6, 2}, { 6, 2}, { 7, 2}, { 7, 2}, { 7, 2}, 229 { 7, 2}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, 230 { 8, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, 231 { 9, 3}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, 232 {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, 233 {10, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, 234 {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, 235 {11, 4}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, 236 {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, 237 {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, 238 {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, 239 {12, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, 240 {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, 241 {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, 242 {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, 243 {13, 5}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, 244 {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, 245 {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, 246 {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, 247 {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, 248 {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, 249 {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, 250 {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, 251 {14, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, 252 {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, 253 {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, 254 {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, 255 {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, 256 {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, 257 {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, 258 {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, 259 {15, 6}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 260 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 261 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 262 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 263 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 264 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 265 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 266 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 267 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 268 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 269 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 270 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 271 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 272 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 273 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 274 {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, 275 {16, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 276 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 277 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 278 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 279 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 280 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 281 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 282 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 283 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 284 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 285 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 286 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 287 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 288 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 289 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 290 {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, 291}; 292 293const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = { 294 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 295 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 296 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 297 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 298 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 299 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 300 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 301 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 302 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 303 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 304 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 305 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 306 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 307 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 308 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 309 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 310 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 311 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 312 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 313 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 314 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 315 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 316 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 317 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 318 127, 319 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 320 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 321 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 322 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 323 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 324 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 325 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 326 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126 327}; 328 329// The threshold till approximate version of log_2 can be used. 330// Practically, we can get rid of the call to log() as the two values match to 331// very high degree (the ratio of these two is 0.99999x). 332// Keeping a high threshold for now. 333#define APPROX_LOG_WITH_CORRECTION_MAX 65536 334#define APPROX_LOG_MAX 4096 335#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086 336static float FastSLog2Slow(uint32_t v) { 337 assert(v >= LOG_LOOKUP_IDX_MAX); 338 if (v < APPROX_LOG_WITH_CORRECTION_MAX) { 339 int log_cnt = 0; 340 uint32_t y = 1; 341 int correction = 0; 342 const float v_f = (float)v; 343 const uint32_t orig_v = v; 344 do { 345 ++log_cnt; 346 v = v >> 1; 347 y = y << 1; 348 } while (v >= LOG_LOOKUP_IDX_MAX); 349 // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256 350 // Xf = floor(Xf) * (1 + (v % y) / v) 351 // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v) 352 // The correction factor: log(1 + d) ~ d; for very small d values, so 353 // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v 354 // LOG_2_RECIPROCAL ~ 23/16 355 correction = (23 * (orig_v & (y - 1))) >> 4; 356 return v_f * (kLog2Table[v] + log_cnt) + correction; 357 } else { 358 return (float)(LOG_2_RECIPROCAL * v * log((double)v)); 359 } 360} 361 362static float FastLog2Slow(uint32_t v) { 363 assert(v >= LOG_LOOKUP_IDX_MAX); 364 if (v < APPROX_LOG_WITH_CORRECTION_MAX) { 365 int log_cnt = 0; 366 uint32_t y = 1; 367 const uint32_t orig_v = v; 368 double log_2; 369 do { 370 ++log_cnt; 371 v = v >> 1; 372 y = y << 1; 373 } while (v >= LOG_LOOKUP_IDX_MAX); 374 log_2 = kLog2Table[v] + log_cnt; 375 if (orig_v >= APPROX_LOG_MAX) { 376 // Since the division is still expensive, add this correction factor only 377 // for large values of 'v'. 378 const int correction = (23 * (orig_v & (y - 1))) >> 4; 379 log_2 += (double)correction / orig_v; 380 } 381 return (float)log_2; 382 } else { 383 return (float)(LOG_2_RECIPROCAL * log((double)v)); 384 } 385} 386 387//------------------------------------------------------------------------------ 388// Image transforms. 389 390// Mostly used to reduce code size + readability 391static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; } 392 393// In-place sum of each component with mod 256. 394static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) { 395 const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u); 396 const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu); 397 *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); 398} 399 400static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { 401 return (((a0 ^ a1) & 0xfefefefeL) >> 1) + (a0 & a1); 402} 403 404static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { 405 return Average2(Average2(a0, a2), a1); 406} 407 408static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, 409 uint32_t a2, uint32_t a3) { 410 return Average2(Average2(a0, a1), Average2(a2, a3)); 411} 412 413static WEBP_INLINE uint32_t Clip255(uint32_t a) { 414 if (a < 256) { 415 return a; 416 } 417 // return 0, when a is a negative integer. 418 // return 255, when a is positive. 419 return ~a >> 24; 420} 421 422static WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) { 423 return Clip255(a + b - c); 424} 425 426static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, 427 uint32_t c2) { 428 const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24); 429 const int r = AddSubtractComponentFull((c0 >> 16) & 0xff, 430 (c1 >> 16) & 0xff, 431 (c2 >> 16) & 0xff); 432 const int g = AddSubtractComponentFull((c0 >> 8) & 0xff, 433 (c1 >> 8) & 0xff, 434 (c2 >> 8) & 0xff); 435 const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff); 436 return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; 437} 438 439static WEBP_INLINE int AddSubtractComponentHalf(int a, int b) { 440 return Clip255(a + (a - b) / 2); 441} 442 443static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, 444 uint32_t c2) { 445 const uint32_t ave = Average2(c0, c1); 446 const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24); 447 const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff); 448 const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff); 449 const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff); 450 return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; 451} 452 453static WEBP_INLINE int Sub3(int a, int b, int c) { 454 const int pb = b - c; 455 const int pa = a - c; 456 return abs(pb) - abs(pa); 457} 458 459static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { 460 const int pa_minus_pb = 461 Sub3((a >> 24) , (b >> 24) , (c >> 24) ) + 462 Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) + 463 Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) + 464 Sub3((a ) & 0xff, (b ) & 0xff, (c ) & 0xff); 465 return (pa_minus_pb <= 0) ? a : b; 466} 467 468//------------------------------------------------------------------------------ 469// Predictors 470 471static uint32_t Predictor0(uint32_t left, const uint32_t* const top) { 472 (void)top; 473 (void)left; 474 return ARGB_BLACK; 475} 476static uint32_t Predictor1(uint32_t left, const uint32_t* const top) { 477 (void)top; 478 return left; 479} 480static uint32_t Predictor2(uint32_t left, const uint32_t* const top) { 481 (void)left; 482 return top[0]; 483} 484static uint32_t Predictor3(uint32_t left, const uint32_t* const top) { 485 (void)left; 486 return top[1]; 487} 488static uint32_t Predictor4(uint32_t left, const uint32_t* const top) { 489 (void)left; 490 return top[-1]; 491} 492static uint32_t Predictor5(uint32_t left, const uint32_t* const top) { 493 const uint32_t pred = Average3(left, top[0], top[1]); 494 return pred; 495} 496static uint32_t Predictor6(uint32_t left, const uint32_t* const top) { 497 const uint32_t pred = Average2(left, top[-1]); 498 return pred; 499} 500static uint32_t Predictor7(uint32_t left, const uint32_t* const top) { 501 const uint32_t pred = Average2(left, top[0]); 502 return pred; 503} 504static uint32_t Predictor8(uint32_t left, const uint32_t* const top) { 505 const uint32_t pred = Average2(top[-1], top[0]); 506 (void)left; 507 return pred; 508} 509static uint32_t Predictor9(uint32_t left, const uint32_t* const top) { 510 const uint32_t pred = Average2(top[0], top[1]); 511 (void)left; 512 return pred; 513} 514static uint32_t Predictor10(uint32_t left, const uint32_t* const top) { 515 const uint32_t pred = Average4(left, top[-1], top[0], top[1]); 516 return pred; 517} 518static uint32_t Predictor11(uint32_t left, const uint32_t* const top) { 519 const uint32_t pred = Select(top[0], left, top[-1]); 520 return pred; 521} 522static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { 523 const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); 524 return pred; 525} 526static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { 527 const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); 528 return pred; 529} 530 531static const VP8LPredictorFunc kPredictorsC[16] = { 532 Predictor0, Predictor1, Predictor2, Predictor3, 533 Predictor4, Predictor5, Predictor6, Predictor7, 534 Predictor8, Predictor9, Predictor10, Predictor11, 535 Predictor12, Predictor13, 536 Predictor0, Predictor0 // <- padding security sentinels 537}; 538 539static float PredictionCostSpatial(const int counts[256], int weight_0, 540 double exp_val) { 541 const int significant_symbols = 256 >> 4; 542 const double exp_decay_factor = 0.6; 543 double bits = weight_0 * counts[0]; 544 int i; 545 for (i = 1; i < significant_symbols; ++i) { 546 bits += exp_val * (counts[i] + counts[256 - i]); 547 exp_val *= exp_decay_factor; 548 } 549 return (float)(-0.1 * bits); 550} 551 552// Compute the combined Shanon's entropy for distribution {X} and {X+Y} 553static float CombinedShannonEntropy(const int X[256], const int Y[256]) { 554 int i; 555 double retval = 0.; 556 int sumX = 0, sumXY = 0; 557 for (i = 0; i < 256; ++i) { 558 const int x = X[i]; 559 const int xy = x + Y[i]; 560 if (x != 0) { 561 sumX += x; 562 retval -= VP8LFastSLog2(x); 563 sumXY += xy; 564 retval -= VP8LFastSLog2(xy); 565 } else if (xy != 0) { 566 sumXY += xy; 567 retval -= VP8LFastSLog2(xy); 568 } 569 } 570 retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY); 571 return (float)retval; 572} 573 574static float PredictionCostSpatialHistogram(const int accumulated[4][256], 575 const int tile[4][256]) { 576 int i; 577 double retval = 0; 578 for (i = 0; i < 4; ++i) { 579 const double kExpValue = 0.94; 580 retval += PredictionCostSpatial(tile[i], 1, kExpValue); 581 retval += CombinedShannonEntropy(tile[i], accumulated[i]); 582 } 583 return (float)retval; 584} 585 586static WEBP_INLINE void UpdateHisto(int histo_argb[4][256], uint32_t argb) { 587 ++histo_argb[0][argb >> 24]; 588 ++histo_argb[1][(argb >> 16) & 0xff]; 589 ++histo_argb[2][(argb >> 8) & 0xff]; 590 ++histo_argb[3][argb & 0xff]; 591} 592 593static int GetBestPredictorForTile(int width, int height, 594 int tile_x, int tile_y, int bits, 595 const int accumulated[4][256], 596 const uint32_t* const argb_scratch) { 597 const int kNumPredModes = 14; 598 const int col_start = tile_x << bits; 599 const int row_start = tile_y << bits; 600 const int tile_size = 1 << bits; 601 const int max_y = GetMin(tile_size, height - row_start); 602 const int max_x = GetMin(tile_size, width - col_start); 603 float best_diff = MAX_DIFF_COST; 604 int best_mode = 0; 605 int mode; 606 for (mode = 0; mode < kNumPredModes; ++mode) { 607 const uint32_t* current_row = argb_scratch; 608 const VP8LPredictorFunc pred_func = VP8LPredictors[mode]; 609 float cur_diff; 610 int y; 611 int histo_argb[4][256]; 612 memset(histo_argb, 0, sizeof(histo_argb)); 613 for (y = 0; y < max_y; ++y) { 614 int x; 615 const int row = row_start + y; 616 const uint32_t* const upper_row = current_row; 617 current_row = upper_row + width; 618 for (x = 0; x < max_x; ++x) { 619 const int col = col_start + x; 620 uint32_t predict; 621 if (row == 0) { 622 predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left. 623 } else if (col == 0) { 624 predict = upper_row[col]; // Top. 625 } else { 626 predict = pred_func(current_row[col - 1], upper_row + col); 627 } 628 UpdateHisto(histo_argb, VP8LSubPixels(current_row[col], predict)); 629 } 630 } 631 cur_diff = PredictionCostSpatialHistogram( 632 accumulated, (const int (*)[256])histo_argb); 633 if (cur_diff < best_diff) { 634 best_diff = cur_diff; 635 best_mode = mode; 636 } 637 } 638 639 return best_mode; 640} 641 642static void CopyTileWithPrediction(int width, int height, 643 int tile_x, int tile_y, int bits, int mode, 644 const uint32_t* const argb_scratch, 645 uint32_t* const argb) { 646 const int col_start = tile_x << bits; 647 const int row_start = tile_y << bits; 648 const int tile_size = 1 << bits; 649 const int max_y = GetMin(tile_size, height - row_start); 650 const int max_x = GetMin(tile_size, width - col_start); 651 const VP8LPredictorFunc pred_func = VP8LPredictors[mode]; 652 const uint32_t* current_row = argb_scratch; 653 654 int y; 655 for (y = 0; y < max_y; ++y) { 656 int x; 657 const int row = row_start + y; 658 const uint32_t* const upper_row = current_row; 659 current_row = upper_row + width; 660 for (x = 0; x < max_x; ++x) { 661 const int col = col_start + x; 662 const int pix = row * width + col; 663 uint32_t predict; 664 if (row == 0) { 665 predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left. 666 } else if (col == 0) { 667 predict = upper_row[col]; // Top. 668 } else { 669 predict = pred_func(current_row[col - 1], upper_row + col); 670 } 671 argb[pix] = VP8LSubPixels(current_row[col], predict); 672 } 673 } 674} 675 676void VP8LResidualImage(int width, int height, int bits, 677 uint32_t* const argb, uint32_t* const argb_scratch, 678 uint32_t* const image) { 679 const int max_tile_size = 1 << bits; 680 const int tiles_per_row = VP8LSubSampleSize(width, bits); 681 const int tiles_per_col = VP8LSubSampleSize(height, bits); 682 uint32_t* const upper_row = argb_scratch; 683 uint32_t* const current_tile_rows = argb_scratch + width; 684 int tile_y; 685 int histo[4][256]; 686 memset(histo, 0, sizeof(histo)); 687 for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) { 688 const int tile_y_offset = tile_y * max_tile_size; 689 const int this_tile_height = 690 (tile_y < tiles_per_col - 1) ? max_tile_size : height - tile_y_offset; 691 int tile_x; 692 if (tile_y > 0) { 693 memcpy(upper_row, current_tile_rows + (max_tile_size - 1) * width, 694 width * sizeof(*upper_row)); 695 } 696 memcpy(current_tile_rows, &argb[tile_y_offset * width], 697 this_tile_height * width * sizeof(*current_tile_rows)); 698 for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) { 699 int pred; 700 int y; 701 const int tile_x_offset = tile_x * max_tile_size; 702 int all_x_max = tile_x_offset + max_tile_size; 703 if (all_x_max > width) { 704 all_x_max = width; 705 } 706 pred = GetBestPredictorForTile(width, height, tile_x, tile_y, bits, 707 (const int (*)[256])histo, 708 argb_scratch); 709 image[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8); 710 CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred, 711 argb_scratch, argb); 712 for (y = 0; y < max_tile_size; ++y) { 713 int ix; 714 int all_x; 715 int all_y = tile_y_offset + y; 716 if (all_y >= height) { 717 break; 718 } 719 ix = all_y * width + tile_x_offset; 720 for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) { 721 UpdateHisto(histo, argb[ix]); 722 } 723 } 724 } 725 } 726} 727 728// Inverse prediction. 729static void PredictorInverseTransform(const VP8LTransform* const transform, 730 int y_start, int y_end, uint32_t* data) { 731 const int width = transform->xsize_; 732 if (y_start == 0) { // First Row follows the L (mode=1) mode. 733 int x; 734 const uint32_t pred0 = Predictor0(data[-1], NULL); 735 AddPixelsEq(data, pred0); 736 for (x = 1; x < width; ++x) { 737 const uint32_t pred1 = Predictor1(data[x - 1], NULL); 738 AddPixelsEq(data + x, pred1); 739 } 740 data += width; 741 ++y_start; 742 } 743 744 { 745 int y = y_start; 746 const int tile_width = 1 << transform->bits_; 747 const int mask = tile_width - 1; 748 const int safe_width = width & ~mask; 749 const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); 750 const uint32_t* pred_mode_base = 751 transform->data_ + (y >> transform->bits_) * tiles_per_row; 752 753 while (y < y_end) { 754 const uint32_t pred2 = Predictor2(data[-1], data - width); 755 const uint32_t* pred_mode_src = pred_mode_base; 756 VP8LPredictorFunc pred_func; 757 int x = 1; 758 int t = 1; 759 // First pixel follows the T (mode=2) mode. 760 AddPixelsEq(data, pred2); 761 // .. the rest: 762 while (x < safe_width) { 763 pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf]; 764 for (; t < tile_width; ++t, ++x) { 765 const uint32_t pred = pred_func(data[x - 1], data + x - width); 766 AddPixelsEq(data + x, pred); 767 } 768 t = 0; 769 } 770 if (x < width) { 771 pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf]; 772 for (; x < width; ++x) { 773 const uint32_t pred = pred_func(data[x - 1], data + x - width); 774 AddPixelsEq(data + x, pred); 775 } 776 } 777 data += width; 778 ++y; 779 if ((y & mask) == 0) { // Use the same mask, since tiles are squares. 780 pred_mode_base += tiles_per_row; 781 } 782 } 783 } 784} 785 786void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) { 787 int i; 788 for (i = 0; i < num_pixels; ++i) { 789 const uint32_t argb = argb_data[i]; 790 const uint32_t green = (argb >> 8) & 0xff; 791 const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff; 792 const uint32_t new_b = ((argb & 0xff) - green) & 0xff; 793 argb_data[i] = (argb & 0xff00ff00) | (new_r << 16) | new_b; 794 } 795} 796 797// Add green to blue and red channels (i.e. perform the inverse transform of 798// 'subtract green'). 799void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels) { 800 int i; 801 for (i = 0; i < num_pixels; ++i) { 802 const uint32_t argb = data[i]; 803 const uint32_t green = ((argb >> 8) & 0xff); 804 uint32_t red_blue = (argb & 0x00ff00ffu); 805 red_blue += (green << 16) | green; 806 red_blue &= 0x00ff00ffu; 807 data[i] = (argb & 0xff00ff00u) | red_blue; 808 } 809} 810 811static WEBP_INLINE void MultipliersClear(VP8LMultipliers* const m) { 812 m->green_to_red_ = 0; 813 m->green_to_blue_ = 0; 814 m->red_to_blue_ = 0; 815} 816 817static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, 818 int8_t color) { 819 return (uint32_t)((int)(color_pred) * color) >> 5; 820} 821 822static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, 823 VP8LMultipliers* const m) { 824 m->green_to_red_ = (color_code >> 0) & 0xff; 825 m->green_to_blue_ = (color_code >> 8) & 0xff; 826 m->red_to_blue_ = (color_code >> 16) & 0xff; 827} 828 829static WEBP_INLINE uint32_t MultipliersToColorCode( 830 const VP8LMultipliers* const m) { 831 return 0xff000000u | 832 ((uint32_t)(m->red_to_blue_) << 16) | 833 ((uint32_t)(m->green_to_blue_) << 8) | 834 m->green_to_red_; 835} 836 837void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data, 838 int num_pixels) { 839 int i; 840 for (i = 0; i < num_pixels; ++i) { 841 const uint32_t argb = data[i]; 842 const uint32_t green = argb >> 8; 843 const uint32_t red = argb >> 16; 844 uint32_t new_red = red; 845 uint32_t new_blue = argb; 846 new_red -= ColorTransformDelta(m->green_to_red_, green); 847 new_red &= 0xff; 848 new_blue -= ColorTransformDelta(m->green_to_blue_, green); 849 new_blue -= ColorTransformDelta(m->red_to_blue_, red); 850 new_blue &= 0xff; 851 data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); 852 } 853} 854 855void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, uint32_t* data, 856 int num_pixels) { 857 int i; 858 for (i = 0; i < num_pixels; ++i) { 859 const uint32_t argb = data[i]; 860 const uint32_t green = argb >> 8; 861 const uint32_t red = argb >> 16; 862 uint32_t new_red = red; 863 uint32_t new_blue = argb; 864 new_red += ColorTransformDelta(m->green_to_red_, green); 865 new_red &= 0xff; 866 new_blue += ColorTransformDelta(m->green_to_blue_, green); 867 new_blue += ColorTransformDelta(m->red_to_blue_, new_red); 868 new_blue &= 0xff; 869 data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); 870 } 871} 872 873static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, 874 uint32_t argb) { 875 const uint32_t green = argb >> 8; 876 uint32_t new_red = argb >> 16; 877 new_red -= ColorTransformDelta(green_to_red, green); 878 return (new_red & 0xff); 879} 880 881static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, 882 uint8_t red_to_blue, 883 uint32_t argb) { 884 const uint32_t green = argb >> 8; 885 const uint32_t red = argb >> 16; 886 uint8_t new_blue = argb; 887 new_blue -= ColorTransformDelta(green_to_blue, green); 888 new_blue -= ColorTransformDelta(red_to_blue, red); 889 return (new_blue & 0xff); 890} 891 892static float PredictionCostCrossColor(const int accumulated[256], 893 const int counts[256]) { 894 // Favor low entropy, locally and globally. 895 // Favor small absolute values for PredictionCostSpatial 896 static const double kExpValue = 2.4; 897 return CombinedShannonEntropy(counts, accumulated) + 898 PredictionCostSpatial(counts, 3, kExpValue); 899} 900 901static float GetPredictionCostCrossColorRed( 902 int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max, 903 int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, int green_to_red, 904 const int accumulated_red_histo[256], const uint32_t* const argb) { 905 int all_y; 906 int histo[256] = { 0 }; 907 float cur_diff; 908 for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) { 909 int ix = all_y * xsize + tile_x_offset; 910 int all_x; 911 for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) { 912 ++histo[TransformColorRed(green_to_red, argb[ix])]; // red. 913 } 914 } 915 cur_diff = PredictionCostCrossColor(accumulated_red_histo, histo); 916 if ((uint8_t)green_to_red == prev_x.green_to_red_) { 917 cur_diff -= 3; // favor keeping the areas locally similar 918 } 919 if ((uint8_t)green_to_red == prev_y.green_to_red_) { 920 cur_diff -= 3; // favor keeping the areas locally similar 921 } 922 if (green_to_red == 0) { 923 cur_diff -= 3; 924 } 925 return cur_diff; 926} 927 928static void GetBestGreenToRed( 929 int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max, 930 int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, 931 const int accumulated_red_histo[256], const uint32_t* const argb, 932 VP8LMultipliers* const best_tx) { 933 int min_green_to_red = -64; 934 int max_green_to_red = 64; 935 int green_to_red = 0; 936 int eval_min = 1; 937 int eval_max = 1; 938 float cur_diff_min = MAX_DIFF_COST; 939 float cur_diff_max = MAX_DIFF_COST; 940 // Do a binary search to find the optimal green_to_red color transform. 941 while (max_green_to_red - min_green_to_red > 2) { 942 if (eval_min) { 943 cur_diff_min = GetPredictionCostCrossColorRed( 944 tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize, 945 prev_x, prev_y, min_green_to_red, accumulated_red_histo, argb); 946 eval_min = 0; 947 } 948 if (eval_max) { 949 cur_diff_max = GetPredictionCostCrossColorRed( 950 tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize, 951 prev_x, prev_y, max_green_to_red, accumulated_red_histo, argb); 952 eval_max = 0; 953 } 954 if (cur_diff_min < cur_diff_max) { 955 green_to_red = min_green_to_red; 956 max_green_to_red = (max_green_to_red + min_green_to_red) / 2; 957 eval_max = 1; 958 } else { 959 green_to_red = max_green_to_red; 960 min_green_to_red = (max_green_to_red + min_green_to_red) / 2; 961 eval_min = 1; 962 } 963 } 964 best_tx->green_to_red_ = green_to_red; 965} 966 967static float GetPredictionCostCrossColorBlue( 968 int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max, 969 int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, 970 int green_to_blue, int red_to_blue, const int accumulated_blue_histo[256], 971 const uint32_t* const argb) { 972 int all_y; 973 int histo[256] = { 0 }; 974 float cur_diff; 975 for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) { 976 int all_x; 977 int ix = all_y * xsize + tile_x_offset; 978 for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) { 979 ++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[ix])]; 980 } 981 } 982 cur_diff = PredictionCostCrossColor(accumulated_blue_histo, histo); 983 if ((uint8_t)green_to_blue == prev_x.green_to_blue_) { 984 cur_diff -= 3; // favor keeping the areas locally similar 985 } 986 if ((uint8_t)green_to_blue == prev_y.green_to_blue_) { 987 cur_diff -= 3; // favor keeping the areas locally similar 988 } 989 if ((uint8_t)red_to_blue == prev_x.red_to_blue_) { 990 cur_diff -= 3; // favor keeping the areas locally similar 991 } 992 if ((uint8_t)red_to_blue == prev_y.red_to_blue_) { 993 cur_diff -= 3; // favor keeping the areas locally similar 994 } 995 if (green_to_blue == 0) { 996 cur_diff -= 3; 997 } 998 if (red_to_blue == 0) { 999 cur_diff -= 3; 1000 } 1001 return cur_diff; 1002} 1003 1004static void GetBestGreenRedToBlue( 1005 int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max, 1006 int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality, 1007 const int accumulated_blue_histo[256], const uint32_t* const argb, 1008 VP8LMultipliers* const best_tx) { 1009 float best_diff = MAX_DIFF_COST; 1010 float cur_diff; 1011 const int step = (quality < 25) ? 32 : (quality > 50) ? 8 : 16; 1012 const int min_green_to_blue = -32; 1013 const int max_green_to_blue = 32; 1014 const int min_red_to_blue = -32; 1015 const int max_red_to_blue = 32; 1016 const int num_iters = 1017 (1 + (max_green_to_blue - min_green_to_blue) / step) * 1018 (1 + (max_red_to_blue - min_red_to_blue) / step); 1019 // Number of tries to get optimal green_to_blue & red_to_blue color transforms 1020 // after finding a local minima. 1021 const int max_tries_after_min = 4 + (num_iters >> 2); 1022 int num_tries_after_min = 0; 1023 int green_to_blue; 1024 for (green_to_blue = min_green_to_blue; 1025 green_to_blue <= max_green_to_blue && 1026 num_tries_after_min < max_tries_after_min; 1027 green_to_blue += step) { 1028 int red_to_blue; 1029 for (red_to_blue = min_red_to_blue; 1030 red_to_blue <= max_red_to_blue && 1031 num_tries_after_min < max_tries_after_min; 1032 red_to_blue += step) { 1033 cur_diff = GetPredictionCostCrossColorBlue( 1034 tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize, prev_x, 1035 prev_y, green_to_blue, red_to_blue, accumulated_blue_histo, argb); 1036 if (cur_diff < best_diff) { 1037 best_diff = cur_diff; 1038 best_tx->green_to_blue_ = green_to_blue; 1039 best_tx->red_to_blue_ = red_to_blue; 1040 num_tries_after_min = 0; 1041 } else { 1042 ++num_tries_after_min; 1043 } 1044 } 1045 } 1046} 1047 1048static VP8LMultipliers GetBestColorTransformForTile( 1049 int tile_x, int tile_y, int bits, 1050 VP8LMultipliers prev_x, 1051 VP8LMultipliers prev_y, 1052 int quality, int xsize, int ysize, 1053 const int accumulated_red_histo[256], 1054 const int accumulated_blue_histo[256], 1055 const uint32_t* const argb) { 1056 const int max_tile_size = 1 << bits; 1057 const int tile_y_offset = tile_y * max_tile_size; 1058 const int tile_x_offset = tile_x * max_tile_size; 1059 const int all_x_max = GetMin(tile_x_offset + max_tile_size, xsize); 1060 const int all_y_max = GetMin(tile_y_offset + max_tile_size, ysize); 1061 VP8LMultipliers best_tx; 1062 MultipliersClear(&best_tx); 1063 1064 GetBestGreenToRed(tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize, 1065 prev_x, prev_y, accumulated_red_histo, argb, &best_tx); 1066 GetBestGreenRedToBlue(tile_x_offset, tile_y_offset, all_x_max, all_y_max, 1067 xsize, prev_x, prev_y, quality, accumulated_blue_histo, 1068 argb, &best_tx); 1069 return best_tx; 1070} 1071 1072static void CopyTileWithColorTransform(int xsize, int ysize, 1073 int tile_x, int tile_y, 1074 int max_tile_size, 1075 VP8LMultipliers color_transform, 1076 uint32_t* argb) { 1077 const int xscan = GetMin(max_tile_size, xsize - tile_x); 1078 int yscan = GetMin(max_tile_size, ysize - tile_y); 1079 argb += tile_y * xsize + tile_x; 1080 while (yscan-- > 0) { 1081 VP8LTransformColor(&color_transform, argb, xscan); 1082 argb += xsize; 1083 } 1084} 1085 1086void VP8LColorSpaceTransform(int width, int height, int bits, int quality, 1087 uint32_t* const argb, uint32_t* image) { 1088 const int max_tile_size = 1 << bits; 1089 const int tile_xsize = VP8LSubSampleSize(width, bits); 1090 const int tile_ysize = VP8LSubSampleSize(height, bits); 1091 int accumulated_red_histo[256] = { 0 }; 1092 int accumulated_blue_histo[256] = { 0 }; 1093 int tile_x, tile_y; 1094 VP8LMultipliers prev_x, prev_y; 1095 MultipliersClear(&prev_y); 1096 MultipliersClear(&prev_x); 1097 for (tile_y = 0; tile_y < tile_ysize; ++tile_y) { 1098 for (tile_x = 0; tile_x < tile_xsize; ++tile_x) { 1099 int y; 1100 const int tile_x_offset = tile_x * max_tile_size; 1101 const int tile_y_offset = tile_y * max_tile_size; 1102 const int all_x_max = GetMin(tile_x_offset + max_tile_size, width); 1103 const int all_y_max = GetMin(tile_y_offset + max_tile_size, height); 1104 const int offset = tile_y * tile_xsize + tile_x; 1105 if (tile_y != 0) { 1106 ColorCodeToMultipliers(image[offset - tile_xsize], &prev_y); 1107 } 1108 prev_x = GetBestColorTransformForTile(tile_x, tile_y, bits, 1109 prev_x, prev_y, 1110 quality, width, height, 1111 accumulated_red_histo, 1112 accumulated_blue_histo, 1113 argb); 1114 image[offset] = MultipliersToColorCode(&prev_x); 1115 CopyTileWithColorTransform(width, height, tile_x_offset, tile_y_offset, 1116 max_tile_size, prev_x, argb); 1117 1118 // Gather accumulated histogram data. 1119 for (y = tile_y_offset; y < all_y_max; ++y) { 1120 int ix = y * width + tile_x_offset; 1121 const int ix_end = ix + all_x_max - tile_x_offset; 1122 for (; ix < ix_end; ++ix) { 1123 const uint32_t pix = argb[ix]; 1124 if (ix >= 2 && 1125 pix == argb[ix - 2] && 1126 pix == argb[ix - 1]) { 1127 continue; // repeated pixels are handled by backward references 1128 } 1129 if (ix >= width + 2 && 1130 argb[ix - 2] == argb[ix - width - 2] && 1131 argb[ix - 1] == argb[ix - width - 1] && 1132 pix == argb[ix - width]) { 1133 continue; // repeated pixels are handled by backward references 1134 } 1135 ++accumulated_red_histo[(pix >> 16) & 0xff]; 1136 ++accumulated_blue_histo[(pix >> 0) & 0xff]; 1137 } 1138 } 1139 } 1140 } 1141} 1142 1143// Color space inverse transform. 1144static void ColorSpaceInverseTransform(const VP8LTransform* const transform, 1145 int y_start, int y_end, uint32_t* data) { 1146 const int width = transform->xsize_; 1147 const int tile_width = 1 << transform->bits_; 1148 const int mask = tile_width - 1; 1149 const int safe_width = width & ~mask; 1150 const int remaining_width = width - safe_width; 1151 const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); 1152 int y = y_start; 1153 const uint32_t* pred_row = 1154 transform->data_ + (y >> transform->bits_) * tiles_per_row; 1155 1156 while (y < y_end) { 1157 const uint32_t* pred = pred_row; 1158 VP8LMultipliers m = { 0, 0, 0 }; 1159 const uint32_t* const data_safe_end = data + safe_width; 1160 const uint32_t* const data_end = data + width; 1161 while (data < data_safe_end) { 1162 ColorCodeToMultipliers(*pred++, &m); 1163 VP8LTransformColorInverse(&m, data, tile_width); 1164 data += tile_width; 1165 } 1166 if (data < data_end) { // Left-overs using C-version. 1167 ColorCodeToMultipliers(*pred++, &m); 1168 VP8LTransformColorInverse(&m, data, remaining_width); 1169 data += remaining_width; 1170 } 1171 ++y; 1172 if ((y & mask) == 0) pred_row += tiles_per_row;; 1173 } 1174} 1175 1176// Separate out pixels packed together using pixel-bundling. 1177// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). 1178#define COLOR_INDEX_INVERSE(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \ 1179void FUNC_NAME(const VP8LTransform* const transform, \ 1180 int y_start, int y_end, const TYPE* src, TYPE* dst) { \ 1181 int y; \ 1182 const int bits_per_pixel = 8 >> transform->bits_; \ 1183 const int width = transform->xsize_; \ 1184 const uint32_t* const color_map = transform->data_; \ 1185 if (bits_per_pixel < 8) { \ 1186 const int pixels_per_byte = 1 << transform->bits_; \ 1187 const int count_mask = pixels_per_byte - 1; \ 1188 const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \ 1189 for (y = y_start; y < y_end; ++y) { \ 1190 uint32_t packed_pixels = 0; \ 1191 int x; \ 1192 for (x = 0; x < width; ++x) { \ 1193 /* We need to load fresh 'packed_pixels' once every */ \ 1194 /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \ 1195 /* is a power of 2, so can just use a mask for that, instead of */ \ 1196 /* decrementing a counter. */ \ 1197 if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \ 1198 *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \ 1199 packed_pixels >>= bits_per_pixel; \ 1200 } \ 1201 } \ 1202 } else { \ 1203 for (y = y_start; y < y_end; ++y) { \ 1204 int x; \ 1205 for (x = 0; x < width; ++x) { \ 1206 *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \ 1207 } \ 1208 } \ 1209 } \ 1210} 1211 1212static WEBP_INLINE uint32_t GetARGBIndex(uint32_t idx) { 1213 return (idx >> 8) & 0xff; 1214} 1215 1216static WEBP_INLINE uint8_t GetAlphaIndex(uint8_t idx) { 1217 return idx; 1218} 1219 1220static WEBP_INLINE uint32_t GetARGBValue(uint32_t val) { 1221 return val; 1222} 1223 1224static WEBP_INLINE uint8_t GetAlphaValue(uint32_t val) { 1225 return (val >> 8) & 0xff; 1226} 1227 1228static COLOR_INDEX_INVERSE(ColorIndexInverseTransform, uint32_t, GetARGBIndex, 1229 GetARGBValue) 1230COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, uint8_t, GetAlphaIndex, 1231 GetAlphaValue) 1232 1233#undef COLOR_INDEX_INVERSE 1234 1235void VP8LInverseTransform(const VP8LTransform* const transform, 1236 int row_start, int row_end, 1237 const uint32_t* const in, uint32_t* const out) { 1238 const int width = transform->xsize_; 1239 assert(row_start < row_end); 1240 assert(row_end <= transform->ysize_); 1241 switch (transform->type_) { 1242 case SUBTRACT_GREEN: 1243 VP8LAddGreenToBlueAndRed(out, (row_end - row_start) * width); 1244 break; 1245 case PREDICTOR_TRANSFORM: 1246 PredictorInverseTransform(transform, row_start, row_end, out); 1247 if (row_end != transform->ysize_) { 1248 // The last predicted row in this iteration will be the top-pred row 1249 // for the first row in next iteration. 1250 memcpy(out - width, out + (row_end - row_start - 1) * width, 1251 width * sizeof(*out)); 1252 } 1253 break; 1254 case CROSS_COLOR_TRANSFORM: 1255 ColorSpaceInverseTransform(transform, row_start, row_end, out); 1256 break; 1257 case COLOR_INDEXING_TRANSFORM: 1258 if (in == out && transform->bits_ > 0) { 1259 // Move packed pixels to the end of unpacked region, so that unpacking 1260 // can occur seamlessly. 1261 // Also, note that this is the only transform that applies on 1262 // the effective width of VP8LSubSampleSize(xsize_, bits_). All other 1263 // transforms work on effective width of xsize_. 1264 const int out_stride = (row_end - row_start) * width; 1265 const int in_stride = (row_end - row_start) * 1266 VP8LSubSampleSize(transform->xsize_, transform->bits_); 1267 uint32_t* const src = out + out_stride - in_stride; 1268 memmove(src, out, in_stride * sizeof(*src)); 1269 ColorIndexInverseTransform(transform, row_start, row_end, src, out); 1270 } else { 1271 ColorIndexInverseTransform(transform, row_start, row_end, in, out); 1272 } 1273 break; 1274 } 1275} 1276 1277//------------------------------------------------------------------------------ 1278// Color space conversion. 1279 1280static int is_big_endian(void) { 1281 static const union { 1282 uint16_t w; 1283 uint8_t b[2]; 1284 } tmp = { 1 }; 1285 return (tmp.b[0] != 1); 1286} 1287 1288void VP8LConvertBGRAToRGB_C(const uint32_t* src, 1289 int num_pixels, uint8_t* dst) { 1290 const uint32_t* const src_end = src + num_pixels; 1291 while (src < src_end) { 1292 const uint32_t argb = *src++; 1293 *dst++ = (argb >> 16) & 0xff; 1294 *dst++ = (argb >> 8) & 0xff; 1295 *dst++ = (argb >> 0) & 0xff; 1296 } 1297} 1298 1299void VP8LConvertBGRAToRGBA_C(const uint32_t* src, 1300 int num_pixels, uint8_t* dst) { 1301 const uint32_t* const src_end = src + num_pixels; 1302 while (src < src_end) { 1303 const uint32_t argb = *src++; 1304 *dst++ = (argb >> 16) & 0xff; 1305 *dst++ = (argb >> 8) & 0xff; 1306 *dst++ = (argb >> 0) & 0xff; 1307 *dst++ = (argb >> 24) & 0xff; 1308 } 1309} 1310 1311void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, 1312 int num_pixels, uint8_t* dst) { 1313 const uint32_t* const src_end = src + num_pixels; 1314 while (src < src_end) { 1315 const uint32_t argb = *src++; 1316 const uint8_t rg = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf); 1317 const uint8_t ba = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf); 1318#ifdef WEBP_SWAP_16BIT_CSP 1319 *dst++ = ba; 1320 *dst++ = rg; 1321#else 1322 *dst++ = rg; 1323 *dst++ = ba; 1324#endif 1325 } 1326} 1327 1328void VP8LConvertBGRAToRGB565_C(const uint32_t* src, 1329 int num_pixels, uint8_t* dst) { 1330 const uint32_t* const src_end = src + num_pixels; 1331 while (src < src_end) { 1332 const uint32_t argb = *src++; 1333 const uint8_t rg = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7); 1334 const uint8_t gb = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f); 1335#ifdef WEBP_SWAP_16BIT_CSP 1336 *dst++ = gb; 1337 *dst++ = rg; 1338#else 1339 *dst++ = rg; 1340 *dst++ = gb; 1341#endif 1342 } 1343} 1344 1345void VP8LConvertBGRAToBGR_C(const uint32_t* src, 1346 int num_pixels, uint8_t* dst) { 1347 const uint32_t* const src_end = src + num_pixels; 1348 while (src < src_end) { 1349 const uint32_t argb = *src++; 1350 *dst++ = (argb >> 0) & 0xff; 1351 *dst++ = (argb >> 8) & 0xff; 1352 *dst++ = (argb >> 16) & 0xff; 1353 } 1354} 1355 1356static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, 1357 int swap_on_big_endian) { 1358 if (is_big_endian() == swap_on_big_endian) { 1359 const uint32_t* const src_end = src + num_pixels; 1360 while (src < src_end) { 1361 const uint32_t argb = *src++; 1362 1363#if !defined(WORDS_BIGENDIAN) 1364#if !defined(WEBP_REFERENCE_IMPLEMENTATION) 1365 *(uint32_t*)dst = BSwap32(argb); 1366#else // WEBP_REFERENCE_IMPLEMENTATION 1367 dst[0] = (argb >> 24) & 0xff; 1368 dst[1] = (argb >> 16) & 0xff; 1369 dst[2] = (argb >> 8) & 0xff; 1370 dst[3] = (argb >> 0) & 0xff; 1371#endif 1372#else // WORDS_BIGENDIAN 1373 dst[0] = (argb >> 0) & 0xff; 1374 dst[1] = (argb >> 8) & 0xff; 1375 dst[2] = (argb >> 16) & 0xff; 1376 dst[3] = (argb >> 24) & 0xff; 1377#endif 1378 dst += sizeof(argb); 1379 } 1380 } else { 1381 memcpy(dst, src, num_pixels * sizeof(*src)); 1382 } 1383} 1384 1385void VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels, 1386 WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) { 1387 switch (out_colorspace) { 1388 case MODE_RGB: 1389 VP8LConvertBGRAToRGB(in_data, num_pixels, rgba); 1390 break; 1391 case MODE_RGBA: 1392 VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba); 1393 break; 1394 case MODE_rgbA: 1395 VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba); 1396 WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0); 1397 break; 1398 case MODE_BGR: 1399 VP8LConvertBGRAToBGR(in_data, num_pixels, rgba); 1400 break; 1401 case MODE_BGRA: 1402 CopyOrSwap(in_data, num_pixels, rgba, 1); 1403 break; 1404 case MODE_bgrA: 1405 CopyOrSwap(in_data, num_pixels, rgba, 1); 1406 WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0); 1407 break; 1408 case MODE_ARGB: 1409 CopyOrSwap(in_data, num_pixels, rgba, 0); 1410 break; 1411 case MODE_Argb: 1412 CopyOrSwap(in_data, num_pixels, rgba, 0); 1413 WebPApplyAlphaMultiply(rgba, 1, num_pixels, 1, 0); 1414 break; 1415 case MODE_RGBA_4444: 1416 VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba); 1417 break; 1418 case MODE_rgbA_4444: 1419 VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba); 1420 WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0); 1421 break; 1422 case MODE_RGB_565: 1423 VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba); 1424 break; 1425 default: 1426 assert(0); // Code flow should not reach here. 1427 } 1428} 1429 1430//------------------------------------------------------------------------------ 1431// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel. 1432void VP8LBundleColorMap(const uint8_t* const row, int width, 1433 int xbits, uint32_t* const dst) { 1434 int x; 1435 if (xbits > 0) { 1436 const int bit_depth = 1 << (3 - xbits); 1437 const int mask = (1 << xbits) - 1; 1438 uint32_t code = 0xff000000; 1439 for (x = 0; x < width; ++x) { 1440 const int xsub = x & mask; 1441 if (xsub == 0) { 1442 code = 0xff000000; 1443 } 1444 code |= row[x] << (8 + bit_depth * xsub); 1445 dst[x >> xbits] = code; 1446 } 1447 } else { 1448 for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8); 1449 } 1450} 1451 1452//------------------------------------------------------------------------------ 1453 1454static double ExtraCost(const uint32_t* population, int length) { 1455 int i; 1456 double cost = 0.; 1457 for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2]; 1458 return cost; 1459} 1460 1461static double ExtraCostCombined(const uint32_t* X, const uint32_t* Y, 1462 int length) { 1463 int i; 1464 double cost = 0.; 1465 for (i = 2; i < length - 2; ++i) { 1466 const int xy = X[i + 2] + Y[i + 2]; 1467 cost += (i >> 1) * xy; 1468 } 1469 return cost; 1470} 1471 1472// Returns the various RLE counts 1473static VP8LStreaks HuffmanCostCount(const uint32_t* population, int length) { 1474 int i; 1475 int streak = 0; 1476 VP8LStreaks stats; 1477 memset(&stats, 0, sizeof(stats)); 1478 for (i = 0; i < length - 1; ++i) { 1479 ++streak; 1480 if (population[i] == population[i + 1]) { 1481 continue; 1482 } 1483 stats.counts[population[i] != 0] += (streak > 3); 1484 stats.streaks[population[i] != 0][(streak > 3)] += streak; 1485 streak = 0; 1486 } 1487 ++streak; 1488 stats.counts[population[i] != 0] += (streak > 3); 1489 stats.streaks[population[i] != 0][(streak > 3)] += streak; 1490 return stats; 1491} 1492 1493static VP8LStreaks HuffmanCostCombinedCount(const uint32_t* X, 1494 const uint32_t* Y, int length) { 1495 int i; 1496 int streak = 0; 1497 VP8LStreaks stats; 1498 memset(&stats, 0, sizeof(stats)); 1499 for (i = 0; i < length - 1; ++i) { 1500 const int xy = X[i] + Y[i]; 1501 const int xy_next = X[i + 1] + Y[i + 1]; 1502 ++streak; 1503 if (xy == xy_next) { 1504 continue; 1505 } 1506 stats.counts[xy != 0] += (streak > 3); 1507 stats.streaks[xy != 0][(streak > 3)] += streak; 1508 streak = 0; 1509 } 1510 { 1511 const int xy = X[i] + Y[i]; 1512 ++streak; 1513 stats.counts[xy != 0] += (streak > 3); 1514 stats.streaks[xy != 0][(streak > 3)] += streak; 1515 } 1516 return stats; 1517} 1518 1519//------------------------------------------------------------------------------ 1520 1521static void HistogramAdd(const VP8LHistogram* const a, 1522 const VP8LHistogram* const b, 1523 VP8LHistogram* const out) { 1524 int i; 1525 const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_); 1526 assert(a->palette_code_bits_ == b->palette_code_bits_); 1527 if (b != out) { 1528 for (i = 0; i < literal_size; ++i) { 1529 out->literal_[i] = a->literal_[i] + b->literal_[i]; 1530 } 1531 for (i = 0; i < NUM_DISTANCE_CODES; ++i) { 1532 out->distance_[i] = a->distance_[i] + b->distance_[i]; 1533 } 1534 for (i = 0; i < NUM_LITERAL_CODES; ++i) { 1535 out->red_[i] = a->red_[i] + b->red_[i]; 1536 out->blue_[i] = a->blue_[i] + b->blue_[i]; 1537 out->alpha_[i] = a->alpha_[i] + b->alpha_[i]; 1538 } 1539 } else { 1540 for (i = 0; i < literal_size; ++i) { 1541 out->literal_[i] += a->literal_[i]; 1542 } 1543 for (i = 0; i < NUM_DISTANCE_CODES; ++i) { 1544 out->distance_[i] += a->distance_[i]; 1545 } 1546 for (i = 0; i < NUM_LITERAL_CODES; ++i) { 1547 out->red_[i] += a->red_[i]; 1548 out->blue_[i] += a->blue_[i]; 1549 out->alpha_[i] += a->alpha_[i]; 1550 } 1551 } 1552} 1553 1554//------------------------------------------------------------------------------ 1555 1556VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; 1557VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed; 1558VP8LPredictorFunc VP8LPredictors[16]; 1559 1560VP8LTransformColorFunc VP8LTransformColor; 1561VP8LTransformColorFunc VP8LTransformColorInverse; 1562 1563VP8LConvertFunc VP8LConvertBGRAToRGB; 1564VP8LConvertFunc VP8LConvertBGRAToRGBA; 1565VP8LConvertFunc VP8LConvertBGRAToRGBA4444; 1566VP8LConvertFunc VP8LConvertBGRAToRGB565; 1567VP8LConvertFunc VP8LConvertBGRAToBGR; 1568 1569VP8LFastLog2SlowFunc VP8LFastLog2Slow; 1570VP8LFastLog2SlowFunc VP8LFastSLog2Slow; 1571 1572VP8LCostFunc VP8LExtraCost; 1573VP8LCostCombinedFunc VP8LExtraCostCombined; 1574 1575VP8LCostCountFunc VP8LHuffmanCostCount; 1576VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount; 1577 1578VP8LHistogramAddFunc VP8LHistogramAdd; 1579 1580extern void VP8LDspInitSSE2(void); 1581extern void VP8LDspInitNEON(void); 1582extern void VP8LDspInitMIPS32(void); 1583 1584void VP8LDspInit(void) { 1585 memcpy(VP8LPredictors, kPredictorsC, sizeof(VP8LPredictors)); 1586 1587 VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C; 1588 VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C; 1589 1590 VP8LTransformColor = VP8LTransformColor_C; 1591 VP8LTransformColorInverse = VP8LTransformColorInverse_C; 1592 1593 VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; 1594 VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C; 1595 VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C; 1596 VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C; 1597 VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; 1598 1599 VP8LFastLog2Slow = FastLog2Slow; 1600 VP8LFastSLog2Slow = FastSLog2Slow; 1601 1602 VP8LExtraCost = ExtraCost; 1603 VP8LExtraCostCombined = ExtraCostCombined; 1604 1605 VP8LHuffmanCostCount = HuffmanCostCount; 1606 VP8LHuffmanCostCombinedCount = HuffmanCostCombinedCount; 1607 1608 VP8LHistogramAdd = HistogramAdd; 1609 1610 // If defined, use CPUInfo() to overwrite some pointers with faster versions. 1611 if (VP8GetCPUInfo != NULL) { 1612#if defined(WEBP_USE_SSE2) 1613 if (VP8GetCPUInfo(kSSE2)) { 1614 VP8LDspInitSSE2(); 1615 } 1616#endif 1617#if defined(WEBP_USE_NEON) 1618 if (VP8GetCPUInfo(kNEON)) { 1619 VP8LDspInitNEON(); 1620 } 1621#endif 1622#if defined(WEBP_USE_MIPS32) 1623 if (VP8GetCPUInfo(kMIPS32)) { 1624 VP8LDspInitMIPS32(); 1625 } 1626#endif 1627 } 1628} 1629 1630//------------------------------------------------------------------------------ 1631