Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(516)

Side by Side Diff: third_party/libwebp/dsp/lossless.c

Issue 1546003002: libwebp: update to 0.5.0 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/libwebp/dsp/lossless.h ('k') | third_party/libwebp/dsp/lossless_enc.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 Google Inc. All Rights Reserved. 1 // Copyright 2012 Google Inc. All Rights Reserved.
2 // 2 //
3 // Use of this source code is governed by a BSD-style license 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 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 5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may 6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree. 7 // be found in the AUTHORS file in the root of the source tree.
8 // ----------------------------------------------------------------------------- 8 // -----------------------------------------------------------------------------
9 // 9 //
10 // Image transforms and color space conversion methods for lossless decoder. 10 // Image transforms and color space conversion methods for lossless decoder.
11 // 11 //
12 // Authors: Vikas Arora (vikaas.arora@gmail.com) 12 // Authors: Vikas Arora (vikaas.arora@gmail.com)
13 // Jyrki Alakuijala (jyrki@google.com) 13 // Jyrki Alakuijala (jyrki@google.com)
14 // Urvang Joshi (urvang@google.com) 14 // Urvang Joshi (urvang@google.com)
15 15
16 #include "./dsp.h" 16 #include "./dsp.h"
17 17
18 #include <math.h> 18 #include <math.h>
19 #include <stdlib.h> 19 #include <stdlib.h>
20 #include "../dec/vp8li.h" 20 #include "../dec/vp8li.h"
21 #include "../utils/endian_inl.h" 21 #include "../utils/endian_inl.h"
22 #include "./lossless.h" 22 #include "./lossless.h"
23 #include "./yuv.h"
24 23
25 #define MAX_DIFF_COST (1e30f) 24 #define MAX_DIFF_COST (1e30f)
26 25
27 // lookup table for small values of log2(int)
28 const 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
159 const 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
226 const 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
293 const 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
336 static 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
362 static 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 //------------------------------------------------------------------------------ 26 //------------------------------------------------------------------------------
388 // Image transforms. 27 // Image transforms.
389 28
390 // Mostly used to reduce code size + readability
391 static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; }
392
393 // In-place sum of each component with mod 256. 29 // In-place sum of each component with mod 256.
394 static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) { 30 static WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
395 const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u); 31 const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u);
396 const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu); 32 const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu);
397 *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu); 33 *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
398 } 34 }
399 35
400 static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { 36 static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
401 return (((a0 ^ a1) & 0xfefefefeL) >> 1) + (a0 & a1); 37 return (((a0 ^ a1) & 0xfefefefeu) >> 1) + (a0 & a1);
402 } 38 }
403 39
404 static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { 40 static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
405 return Average2(Average2(a0, a2), a1); 41 return Average2(Average2(a0, a2), a1);
406 } 42 }
407 43
408 static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, 44 static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
409 uint32_t a2, uint32_t a3) { 45 uint32_t a2, uint32_t a3) {
410 return Average2(Average2(a0, a1), Average2(a2, a3)); 46 return Average2(Average2(a0, a1), Average2(a2, a3));
411 } 47 }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 } 166 }
531 static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { 167 static uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
532 const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); 168 const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
533 return pred; 169 return pred;
534 } 170 }
535 static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { 171 static uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
536 const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); 172 const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
537 return pred; 173 return pred;
538 } 174 }
539 175
540 static const VP8LPredictorFunc kPredictorsC[16] = { 176 //------------------------------------------------------------------------------
541 Predictor0, Predictor1, Predictor2, Predictor3,
542 Predictor4, Predictor5, Predictor6, Predictor7,
543 Predictor8, Predictor9, Predictor10, Predictor11,
544 Predictor12, Predictor13,
545 Predictor0, Predictor0 // <- padding security sentinels
546 };
547
548 static float PredictionCostSpatial(const int counts[256], int weight_0,
549 double exp_val) {
550 const int significant_symbols = 256 >> 4;
551 const double exp_decay_factor = 0.6;
552 double bits = weight_0 * counts[0];
553 int i;
554 for (i = 1; i < significant_symbols; ++i) {
555 bits += exp_val * (counts[i] + counts[256 - i]);
556 exp_val *= exp_decay_factor;
557 }
558 return (float)(-0.1 * bits);
559 }
560
561 // Compute the combined Shanon's entropy for distribution {X} and {X+Y}
562 static float CombinedShannonEntropy(const int X[256], const int Y[256]) {
563 int i;
564 double retval = 0.;
565 int sumX = 0, sumXY = 0;
566 for (i = 0; i < 256; ++i) {
567 const int x = X[i];
568 const int xy = x + Y[i];
569 if (x != 0) {
570 sumX += x;
571 retval -= VP8LFastSLog2(x);
572 sumXY += xy;
573 retval -= VP8LFastSLog2(xy);
574 } else if (xy != 0) {
575 sumXY += xy;
576 retval -= VP8LFastSLog2(xy);
577 }
578 }
579 retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY);
580 return (float)retval;
581 }
582
583 static float PredictionCostSpatialHistogram(const int accumulated[4][256],
584 const int tile[4][256]) {
585 int i;
586 double retval = 0;
587 for (i = 0; i < 4; ++i) {
588 const double kExpValue = 0.94;
589 retval += PredictionCostSpatial(tile[i], 1, kExpValue);
590 retval += CombinedShannonEntropy(tile[i], accumulated[i]);
591 }
592 return (float)retval;
593 }
594
595 static WEBP_INLINE void UpdateHisto(int histo_argb[4][256], uint32_t argb) {
596 ++histo_argb[0][argb >> 24];
597 ++histo_argb[1][(argb >> 16) & 0xff];
598 ++histo_argb[2][(argb >> 8) & 0xff];
599 ++histo_argb[3][argb & 0xff];
600 }
601
602 static int GetBestPredictorForTile(int width, int height,
603 int tile_x, int tile_y, int bits,
604 const int accumulated[4][256],
605 const uint32_t* const argb_scratch) {
606 const int kNumPredModes = 14;
607 const int col_start = tile_x << bits;
608 const int row_start = tile_y << bits;
609 const int tile_size = 1 << bits;
610 const int max_y = GetMin(tile_size, height - row_start);
611 const int max_x = GetMin(tile_size, width - col_start);
612 float best_diff = MAX_DIFF_COST;
613 int best_mode = 0;
614 int mode;
615 for (mode = 0; mode < kNumPredModes; ++mode) {
616 const uint32_t* current_row = argb_scratch;
617 const VP8LPredictorFunc pred_func = VP8LPredictors[mode];
618 float cur_diff;
619 int y;
620 int histo_argb[4][256];
621 memset(histo_argb, 0, sizeof(histo_argb));
622 for (y = 0; y < max_y; ++y) {
623 int x;
624 const int row = row_start + y;
625 const uint32_t* const upper_row = current_row;
626 current_row = upper_row + width;
627 for (x = 0; x < max_x; ++x) {
628 const int col = col_start + x;
629 uint32_t predict;
630 if (row == 0) {
631 predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left.
632 } else if (col == 0) {
633 predict = upper_row[col]; // Top.
634 } else {
635 predict = pred_func(current_row[col - 1], upper_row + col);
636 }
637 UpdateHisto(histo_argb, VP8LSubPixels(current_row[col], predict));
638 }
639 }
640 cur_diff = PredictionCostSpatialHistogram(
641 accumulated, (const int (*)[256])histo_argb);
642 if (cur_diff < best_diff) {
643 best_diff = cur_diff;
644 best_mode = mode;
645 }
646 }
647
648 return best_mode;
649 }
650
651 static void CopyTileWithPrediction(int width, int height,
652 int tile_x, int tile_y, int bits, int mode,
653 const uint32_t* const argb_scratch,
654 uint32_t* const argb) {
655 const int col_start = tile_x << bits;
656 const int row_start = tile_y << bits;
657 const int tile_size = 1 << bits;
658 const int max_y = GetMin(tile_size, height - row_start);
659 const int max_x = GetMin(tile_size, width - col_start);
660 const VP8LPredictorFunc pred_func = VP8LPredictors[mode];
661 const uint32_t* current_row = argb_scratch;
662
663 int y;
664 for (y = 0; y < max_y; ++y) {
665 int x;
666 const int row = row_start + y;
667 const uint32_t* const upper_row = current_row;
668 current_row = upper_row + width;
669 for (x = 0; x < max_x; ++x) {
670 const int col = col_start + x;
671 const int pix = row * width + col;
672 uint32_t predict;
673 if (row == 0) {
674 predict = (col == 0) ? ARGB_BLACK : current_row[col - 1]; // Left.
675 } else if (col == 0) {
676 predict = upper_row[col]; // Top.
677 } else {
678 predict = pred_func(current_row[col - 1], upper_row + col);
679 }
680 argb[pix] = VP8LSubPixels(current_row[col], predict);
681 }
682 }
683 }
684
685 void VP8LResidualImage(int width, int height, int bits,
686 uint32_t* const argb, uint32_t* const argb_scratch,
687 uint32_t* const image) {
688 const int max_tile_size = 1 << bits;
689 const int tiles_per_row = VP8LSubSampleSize(width, bits);
690 const int tiles_per_col = VP8LSubSampleSize(height, bits);
691 uint32_t* const upper_row = argb_scratch;
692 uint32_t* const current_tile_rows = argb_scratch + width;
693 int tile_y;
694 int histo[4][256];
695 memset(histo, 0, sizeof(histo));
696 for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
697 const int tile_y_offset = tile_y * max_tile_size;
698 const int this_tile_height =
699 (tile_y < tiles_per_col - 1) ? max_tile_size : height - tile_y_offset;
700 int tile_x;
701 if (tile_y > 0) {
702 memcpy(upper_row, current_tile_rows + (max_tile_size - 1) * width,
703 width * sizeof(*upper_row));
704 }
705 memcpy(current_tile_rows, &argb[tile_y_offset * width],
706 this_tile_height * width * sizeof(*current_tile_rows));
707 for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
708 int pred;
709 int y;
710 const int tile_x_offset = tile_x * max_tile_size;
711 int all_x_max = tile_x_offset + max_tile_size;
712 if (all_x_max > width) {
713 all_x_max = width;
714 }
715 pred = GetBestPredictorForTile(width, height, tile_x, tile_y, bits,
716 (const int (*)[256])histo,
717 argb_scratch);
718 image[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
719 CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred,
720 argb_scratch, argb);
721 for (y = 0; y < max_tile_size; ++y) {
722 int ix;
723 int all_x;
724 int all_y = tile_y_offset + y;
725 if (all_y >= height) {
726 break;
727 }
728 ix = all_y * width + tile_x_offset;
729 for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
730 UpdateHisto(histo, argb[ix]);
731 }
732 }
733 }
734 }
735 }
736 177
737 // Inverse prediction. 178 // Inverse prediction.
738 static void PredictorInverseTransform(const VP8LTransform* const transform, 179 static void PredictorInverseTransform(const VP8LTransform* const transform,
739 int y_start, int y_end, uint32_t* data) { 180 int y_start, int y_end, uint32_t* data) {
740 const int width = transform->xsize_; 181 const int width = transform->xsize_;
741 if (y_start == 0) { // First Row follows the L (mode=1) mode. 182 if (y_start == 0) { // First Row follows the L (mode=1) mode.
742 int x; 183 int x;
743 const uint32_t pred0 = Predictor0(data[-1], NULL); 184 const uint32_t pred0 = Predictor0(data[-1], NULL);
744 AddPixelsEq(data, pred0); 185 AddPixelsEq(data, pred0);
745 for (x = 1; x < width; ++x) { 186 for (x = 1; x < width; ++x) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 } 226 }
786 data += width; 227 data += width;
787 ++y; 228 ++y;
788 if ((y & mask) == 0) { // Use the same mask, since tiles are squares. 229 if ((y & mask) == 0) { // Use the same mask, since tiles are squares.
789 pred_mode_base += tiles_per_row; 230 pred_mode_base += tiles_per_row;
790 } 231 }
791 } 232 }
792 } 233 }
793 } 234 }
794 235
795 void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) {
796 int i;
797 for (i = 0; i < num_pixels; ++i) {
798 const uint32_t argb = argb_data[i];
799 const uint32_t green = (argb >> 8) & 0xff;
800 const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff;
801 const uint32_t new_b = ((argb & 0xff) - green) & 0xff;
802 argb_data[i] = (argb & 0xff00ff00) | (new_r << 16) | new_b;
803 }
804 }
805
806 // Add green to blue and red channels (i.e. perform the inverse transform of 236 // Add green to blue and red channels (i.e. perform the inverse transform of
807 // 'subtract green'). 237 // 'subtract green').
808 void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels) { 238 void VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels) {
809 int i; 239 int i;
810 for (i = 0; i < num_pixels; ++i) { 240 for (i = 0; i < num_pixels; ++i) {
811 const uint32_t argb = data[i]; 241 const uint32_t argb = data[i];
812 const uint32_t green = ((argb >> 8) & 0xff); 242 const uint32_t green = ((argb >> 8) & 0xff);
813 uint32_t red_blue = (argb & 0x00ff00ffu); 243 uint32_t red_blue = (argb & 0x00ff00ffu);
814 red_blue += (green << 16) | green; 244 red_blue += (green << 16) | green;
815 red_blue &= 0x00ff00ffu; 245 red_blue &= 0x00ff00ffu;
816 data[i] = (argb & 0xff00ff00u) | red_blue; 246 data[i] = (argb & 0xff00ff00u) | red_blue;
817 } 247 }
818 } 248 }
819 249
820 static WEBP_INLINE void MultipliersClear(VP8LMultipliers* const m) {
821 m->green_to_red_ = 0;
822 m->green_to_blue_ = 0;
823 m->red_to_blue_ = 0;
824 }
825
826 static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, 250 static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
827 int8_t color) { 251 int8_t color) {
828 return (uint32_t)((int)(color_pred) * color) >> 5; 252 return (uint32_t)((int)(color_pred) * color) >> 5;
829 } 253 }
830 254
831 static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code, 255 static WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
832 VP8LMultipliers* const m) { 256 VP8LMultipliers* const m) {
833 m->green_to_red_ = (color_code >> 0) & 0xff; 257 m->green_to_red_ = (color_code >> 0) & 0xff;
834 m->green_to_blue_ = (color_code >> 8) & 0xff; 258 m->green_to_blue_ = (color_code >> 8) & 0xff;
835 m->red_to_blue_ = (color_code >> 16) & 0xff; 259 m->red_to_blue_ = (color_code >> 16) & 0xff;
836 } 260 }
837 261
838 static WEBP_INLINE uint32_t MultipliersToColorCode(
839 const VP8LMultipliers* const m) {
840 return 0xff000000u |
841 ((uint32_t)(m->red_to_blue_) << 16) |
842 ((uint32_t)(m->green_to_blue_) << 8) |
843 m->green_to_red_;
844 }
845
846 void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
847 int num_pixels) {
848 int i;
849 for (i = 0; i < num_pixels; ++i) {
850 const uint32_t argb = data[i];
851 const uint32_t green = argb >> 8;
852 const uint32_t red = argb >> 16;
853 uint32_t new_red = red;
854 uint32_t new_blue = argb;
855 new_red -= ColorTransformDelta(m->green_to_red_, green);
856 new_red &= 0xff;
857 new_blue -= ColorTransformDelta(m->green_to_blue_, green);
858 new_blue -= ColorTransformDelta(m->red_to_blue_, red);
859 new_blue &= 0xff;
860 data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
861 }
862 }
863
864 void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, uint32_t* data, 262 void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, uint32_t* data,
865 int num_pixels) { 263 int num_pixels) {
866 int i; 264 int i;
867 for (i = 0; i < num_pixels; ++i) { 265 for (i = 0; i < num_pixels; ++i) {
868 const uint32_t argb = data[i]; 266 const uint32_t argb = data[i];
869 const uint32_t green = argb >> 8; 267 const uint32_t green = argb >> 8;
870 const uint32_t red = argb >> 16; 268 const uint32_t red = argb >> 16;
871 uint32_t new_red = red; 269 uint32_t new_red = red;
872 uint32_t new_blue = argb; 270 uint32_t new_blue = argb;
873 new_red += ColorTransformDelta(m->green_to_red_, green); 271 new_red += ColorTransformDelta(m->green_to_red_, green);
874 new_red &= 0xff; 272 new_red &= 0xff;
875 new_blue += ColorTransformDelta(m->green_to_blue_, green); 273 new_blue += ColorTransformDelta(m->green_to_blue_, green);
876 new_blue += ColorTransformDelta(m->red_to_blue_, new_red); 274 new_blue += ColorTransformDelta(m->red_to_blue_, new_red);
877 new_blue &= 0xff; 275 new_blue &= 0xff;
878 data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue); 276 data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
879 } 277 }
880 } 278 }
881 279
882 static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
883 uint32_t argb) {
884 const uint32_t green = argb >> 8;
885 uint32_t new_red = argb >> 16;
886 new_red -= ColorTransformDelta(green_to_red, green);
887 return (new_red & 0xff);
888 }
889
890 static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
891 uint8_t red_to_blue,
892 uint32_t argb) {
893 const uint32_t green = argb >> 8;
894 const uint32_t red = argb >> 16;
895 uint8_t new_blue = argb;
896 new_blue -= ColorTransformDelta(green_to_blue, green);
897 new_blue -= ColorTransformDelta(red_to_blue, red);
898 return (new_blue & 0xff);
899 }
900
901 static float PredictionCostCrossColor(const int accumulated[256],
902 const int counts[256]) {
903 // Favor low entropy, locally and globally.
904 // Favor small absolute values for PredictionCostSpatial
905 static const double kExpValue = 2.4;
906 return CombinedShannonEntropy(counts, accumulated) +
907 PredictionCostSpatial(counts, 3, kExpValue);
908 }
909
910 static float GetPredictionCostCrossColorRed(
911 int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max,
912 int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, int green_to_red,
913 const int accumulated_red_histo[256], const uint32_t* const argb) {
914 int all_y;
915 int histo[256] = { 0 };
916 float cur_diff;
917 for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) {
918 int ix = all_y * xsize + tile_x_offset;
919 int all_x;
920 for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
921 ++histo[TransformColorRed(green_to_red, argb[ix])]; // red.
922 }
923 }
924 cur_diff = PredictionCostCrossColor(accumulated_red_histo, histo);
925 if ((uint8_t)green_to_red == prev_x.green_to_red_) {
926 cur_diff -= 3; // favor keeping the areas locally similar
927 }
928 if ((uint8_t)green_to_red == prev_y.green_to_red_) {
929 cur_diff -= 3; // favor keeping the areas locally similar
930 }
931 if (green_to_red == 0) {
932 cur_diff -= 3;
933 }
934 return cur_diff;
935 }
936
937 static void GetBestGreenToRed(
938 int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max,
939 int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y,
940 const int accumulated_red_histo[256], const uint32_t* const argb,
941 VP8LMultipliers* const best_tx) {
942 int min_green_to_red = -64;
943 int max_green_to_red = 64;
944 int green_to_red = 0;
945 int eval_min = 1;
946 int eval_max = 1;
947 float cur_diff_min = MAX_DIFF_COST;
948 float cur_diff_max = MAX_DIFF_COST;
949 // Do a binary search to find the optimal green_to_red color transform.
950 while (max_green_to_red - min_green_to_red > 2) {
951 if (eval_min) {
952 cur_diff_min = GetPredictionCostCrossColorRed(
953 tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize,
954 prev_x, prev_y, min_green_to_red, accumulated_red_histo, argb);
955 eval_min = 0;
956 }
957 if (eval_max) {
958 cur_diff_max = GetPredictionCostCrossColorRed(
959 tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize,
960 prev_x, prev_y, max_green_to_red, accumulated_red_histo, argb);
961 eval_max = 0;
962 }
963 if (cur_diff_min < cur_diff_max) {
964 green_to_red = min_green_to_red;
965 max_green_to_red = (max_green_to_red + min_green_to_red) / 2;
966 eval_max = 1;
967 } else {
968 green_to_red = max_green_to_red;
969 min_green_to_red = (max_green_to_red + min_green_to_red) / 2;
970 eval_min = 1;
971 }
972 }
973 best_tx->green_to_red_ = green_to_red;
974 }
975
976 static float GetPredictionCostCrossColorBlue(
977 int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max,
978 int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y,
979 int green_to_blue, int red_to_blue, const int accumulated_blue_histo[256],
980 const uint32_t* const argb) {
981 int all_y;
982 int histo[256] = { 0 };
983 float cur_diff;
984 for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) {
985 int all_x;
986 int ix = all_y * xsize + tile_x_offset;
987 for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
988 ++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[ix])];
989 }
990 }
991 cur_diff = PredictionCostCrossColor(accumulated_blue_histo, histo);
992 if ((uint8_t)green_to_blue == prev_x.green_to_blue_) {
993 cur_diff -= 3; // favor keeping the areas locally similar
994 }
995 if ((uint8_t)green_to_blue == prev_y.green_to_blue_) {
996 cur_diff -= 3; // favor keeping the areas locally similar
997 }
998 if ((uint8_t)red_to_blue == prev_x.red_to_blue_) {
999 cur_diff -= 3; // favor keeping the areas locally similar
1000 }
1001 if ((uint8_t)red_to_blue == prev_y.red_to_blue_) {
1002 cur_diff -= 3; // favor keeping the areas locally similar
1003 }
1004 if (green_to_blue == 0) {
1005 cur_diff -= 3;
1006 }
1007 if (red_to_blue == 0) {
1008 cur_diff -= 3;
1009 }
1010 return cur_diff;
1011 }
1012
1013 static void GetBestGreenRedToBlue(
1014 int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max,
1015 int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality,
1016 const int accumulated_blue_histo[256], const uint32_t* const argb,
1017 VP8LMultipliers* const best_tx) {
1018 float best_diff = MAX_DIFF_COST;
1019 float cur_diff;
1020 const int step = (quality < 25) ? 32 : (quality > 50) ? 8 : 16;
1021 const int min_green_to_blue = -32;
1022 const int max_green_to_blue = 32;
1023 const int min_red_to_blue = -32;
1024 const int max_red_to_blue = 32;
1025 const int num_iters =
1026 (1 + (max_green_to_blue - min_green_to_blue) / step) *
1027 (1 + (max_red_to_blue - min_red_to_blue) / step);
1028 // Number of tries to get optimal green_to_blue & red_to_blue color transforms
1029 // after finding a local minima.
1030 const int max_tries_after_min = 4 + (num_iters >> 2);
1031 int num_tries_after_min = 0;
1032 int green_to_blue;
1033 for (green_to_blue = min_green_to_blue;
1034 green_to_blue <= max_green_to_blue &&
1035 num_tries_after_min < max_tries_after_min;
1036 green_to_blue += step) {
1037 int red_to_blue;
1038 for (red_to_blue = min_red_to_blue;
1039 red_to_blue <= max_red_to_blue &&
1040 num_tries_after_min < max_tries_after_min;
1041 red_to_blue += step) {
1042 cur_diff = GetPredictionCostCrossColorBlue(
1043 tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize, prev_x,
1044 prev_y, green_to_blue, red_to_blue, accumulated_blue_histo, argb);
1045 if (cur_diff < best_diff) {
1046 best_diff = cur_diff;
1047 best_tx->green_to_blue_ = green_to_blue;
1048 best_tx->red_to_blue_ = red_to_blue;
1049 num_tries_after_min = 0;
1050 } else {
1051 ++num_tries_after_min;
1052 }
1053 }
1054 }
1055 }
1056
1057 static VP8LMultipliers GetBestColorTransformForTile(
1058 int tile_x, int tile_y, int bits,
1059 VP8LMultipliers prev_x,
1060 VP8LMultipliers prev_y,
1061 int quality, int xsize, int ysize,
1062 const int accumulated_red_histo[256],
1063 const int accumulated_blue_histo[256],
1064 const uint32_t* const argb) {
1065 const int max_tile_size = 1 << bits;
1066 const int tile_y_offset = tile_y * max_tile_size;
1067 const int tile_x_offset = tile_x * max_tile_size;
1068 const int all_x_max = GetMin(tile_x_offset + max_tile_size, xsize);
1069 const int all_y_max = GetMin(tile_y_offset + max_tile_size, ysize);
1070 VP8LMultipliers best_tx;
1071 MultipliersClear(&best_tx);
1072
1073 GetBestGreenToRed(tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize,
1074 prev_x, prev_y, accumulated_red_histo, argb, &best_tx);
1075 GetBestGreenRedToBlue(tile_x_offset, tile_y_offset, all_x_max, all_y_max,
1076 xsize, prev_x, prev_y, quality, accumulated_blue_histo,
1077 argb, &best_tx);
1078 return best_tx;
1079 }
1080
1081 static void CopyTileWithColorTransform(int xsize, int ysize,
1082 int tile_x, int tile_y,
1083 int max_tile_size,
1084 VP8LMultipliers color_transform,
1085 uint32_t* argb) {
1086 const int xscan = GetMin(max_tile_size, xsize - tile_x);
1087 int yscan = GetMin(max_tile_size, ysize - tile_y);
1088 argb += tile_y * xsize + tile_x;
1089 while (yscan-- > 0) {
1090 VP8LTransformColor(&color_transform, argb, xscan);
1091 argb += xsize;
1092 }
1093 }
1094
1095 void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
1096 uint32_t* const argb, uint32_t* image) {
1097 const int max_tile_size = 1 << bits;
1098 const int tile_xsize = VP8LSubSampleSize(width, bits);
1099 const int tile_ysize = VP8LSubSampleSize(height, bits);
1100 int accumulated_red_histo[256] = { 0 };
1101 int accumulated_blue_histo[256] = { 0 };
1102 int tile_x, tile_y;
1103 VP8LMultipliers prev_x, prev_y;
1104 MultipliersClear(&prev_y);
1105 MultipliersClear(&prev_x);
1106 for (tile_y = 0; tile_y < tile_ysize; ++tile_y) {
1107 for (tile_x = 0; tile_x < tile_xsize; ++tile_x) {
1108 int y;
1109 const int tile_x_offset = tile_x * max_tile_size;
1110 const int tile_y_offset = tile_y * max_tile_size;
1111 const int all_x_max = GetMin(tile_x_offset + max_tile_size, width);
1112 const int all_y_max = GetMin(tile_y_offset + max_tile_size, height);
1113 const int offset = tile_y * tile_xsize + tile_x;
1114 if (tile_y != 0) {
1115 ColorCodeToMultipliers(image[offset - tile_xsize], &prev_y);
1116 }
1117 prev_x = GetBestColorTransformForTile(tile_x, tile_y, bits,
1118 prev_x, prev_y,
1119 quality, width, height,
1120 accumulated_red_histo,
1121 accumulated_blue_histo,
1122 argb);
1123 image[offset] = MultipliersToColorCode(&prev_x);
1124 CopyTileWithColorTransform(width, height, tile_x_offset, tile_y_offset,
1125 max_tile_size, prev_x, argb);
1126
1127 // Gather accumulated histogram data.
1128 for (y = tile_y_offset; y < all_y_max; ++y) {
1129 int ix = y * width + tile_x_offset;
1130 const int ix_end = ix + all_x_max - tile_x_offset;
1131 for (; ix < ix_end; ++ix) {
1132 const uint32_t pix = argb[ix];
1133 if (ix >= 2 &&
1134 pix == argb[ix - 2] &&
1135 pix == argb[ix - 1]) {
1136 continue; // repeated pixels are handled by backward references
1137 }
1138 if (ix >= width + 2 &&
1139 argb[ix - 2] == argb[ix - width - 2] &&
1140 argb[ix - 1] == argb[ix - width - 1] &&
1141 pix == argb[ix - width]) {
1142 continue; // repeated pixels are handled by backward references
1143 }
1144 ++accumulated_red_histo[(pix >> 16) & 0xff];
1145 ++accumulated_blue_histo[(pix >> 0) & 0xff];
1146 }
1147 }
1148 }
1149 }
1150 }
1151
1152 // Color space inverse transform. 280 // Color space inverse transform.
1153 static void ColorSpaceInverseTransform(const VP8LTransform* const transform, 281 static void ColorSpaceInverseTransform(const VP8LTransform* const transform,
1154 int y_start, int y_end, uint32_t* data) { 282 int y_start, int y_end, uint32_t* data) {
1155 const int width = transform->xsize_; 283 const int width = transform->xsize_;
1156 const int tile_width = 1 << transform->bits_; 284 const int tile_width = 1 << transform->bits_;
1157 const int mask = tile_width - 1; 285 const int mask = tile_width - 1;
1158 const int safe_width = width & ~mask; 286 const int safe_width = width & ~mask;
1159 const int remaining_width = width - safe_width; 287 const int remaining_width = width - safe_width;
1160 const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_); 288 const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
1161 int y = y_start; 289 int y = y_start;
(...skipping 15 matching lines...) Expand all
1177 VP8LTransformColorInverse(&m, data, remaining_width); 305 VP8LTransformColorInverse(&m, data, remaining_width);
1178 data += remaining_width; 306 data += remaining_width;
1179 } 307 }
1180 ++y; 308 ++y;
1181 if ((y & mask) == 0) pred_row += tiles_per_row; 309 if ((y & mask) == 0) pred_row += tiles_per_row;
1182 } 310 }
1183 } 311 }
1184 312
1185 // Separate out pixels packed together using pixel-bundling. 313 // Separate out pixels packed together using pixel-bundling.
1186 // We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t). 314 // We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t).
1187 #define COLOR_INDEX_INVERSE(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \ 315 #define COLOR_INDEX_INVERSE(FUNC_NAME, F_NAME, STATIC_DECL, TYPE, BIT_SUFFIX, \
1188 void FUNC_NAME(const VP8LTransform* const transform, \ 316 GET_INDEX, GET_VALUE) \
1189 int y_start, int y_end, const TYPE* src, TYPE* dst) { \ 317 static void F_NAME(const TYPE* src, const uint32_t* const color_map, \
318 TYPE* dst, int y_start, int y_end, int width) { \
319 int y; \
320 for (y = y_start; y < y_end; ++y) { \
321 int x; \
322 for (x = 0; x < width; ++x) { \
323 *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \
324 } \
325 } \
326 } \
327 STATIC_DECL void FUNC_NAME(const VP8LTransform* const transform, \
328 int y_start, int y_end, const TYPE* src, \
329 TYPE* dst) { \
1190 int y; \ 330 int y; \
1191 const int bits_per_pixel = 8 >> transform->bits_; \ 331 const int bits_per_pixel = 8 >> transform->bits_; \
1192 const int width = transform->xsize_; \ 332 const int width = transform->xsize_; \
1193 const uint32_t* const color_map = transform->data_; \ 333 const uint32_t* const color_map = transform->data_; \
1194 if (bits_per_pixel < 8) { \ 334 if (bits_per_pixel < 8) { \
1195 const int pixels_per_byte = 1 << transform->bits_; \ 335 const int pixels_per_byte = 1 << transform->bits_; \
1196 const int count_mask = pixels_per_byte - 1; \ 336 const int count_mask = pixels_per_byte - 1; \
1197 const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \ 337 const uint32_t bit_mask = (1 << bits_per_pixel) - 1; \
1198 for (y = y_start; y < y_end; ++y) { \ 338 for (y = y_start; y < y_end; ++y) { \
1199 uint32_t packed_pixels = 0; \ 339 uint32_t packed_pixels = 0; \
1200 int x; \ 340 int x; \
1201 for (x = 0; x < width; ++x) { \ 341 for (x = 0; x < width; ++x) { \
1202 /* We need to load fresh 'packed_pixels' once every */ \ 342 /* We need to load fresh 'packed_pixels' once every */ \
1203 /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \ 343 /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */ \
1204 /* is a power of 2, so can just use a mask for that, instead of */ \ 344 /* is a power of 2, so can just use a mask for that, instead of */ \
1205 /* decrementing a counter. */ \ 345 /* decrementing a counter. */ \
1206 if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \ 346 if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++); \
1207 *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \ 347 *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]); \
1208 packed_pixels >>= bits_per_pixel; \ 348 packed_pixels >>= bits_per_pixel; \
1209 } \ 349 } \
1210 } \ 350 } \
1211 } else { \ 351 } else { \
1212 for (y = y_start; y < y_end; ++y) { \ 352 VP8LMapColor##BIT_SUFFIX(src, color_map, dst, y_start, y_end, width); \
1213 int x; \
1214 for (x = 0; x < width; ++x) { \
1215 *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]); \
1216 } \
1217 } \
1218 } \ 353 } \
1219 } 354 }
1220 355
1221 static WEBP_INLINE uint32_t GetARGBIndex(uint32_t idx) { 356 COLOR_INDEX_INVERSE(ColorIndexInverseTransform, MapARGB, static, uint32_t, 32b,
1222 return (idx >> 8) & 0xff; 357 VP8GetARGBIndex, VP8GetARGBValue)
1223 } 358 COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha, , uint8_t,
1224 359 8b, VP8GetAlphaIndex, VP8GetAlphaValue)
1225 static WEBP_INLINE uint8_t GetAlphaIndex(uint8_t idx) {
1226 return idx;
1227 }
1228
1229 static WEBP_INLINE uint32_t GetARGBValue(uint32_t val) {
1230 return val;
1231 }
1232
1233 static WEBP_INLINE uint8_t GetAlphaValue(uint32_t val) {
1234 return (val >> 8) & 0xff;
1235 }
1236
1237 static COLOR_INDEX_INVERSE(ColorIndexInverseTransform, uint32_t, GetARGBIndex,
1238 GetARGBValue)
1239 COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, uint8_t, GetAlphaIndex,
1240 GetAlphaValue)
1241 360
1242 #undef COLOR_INDEX_INVERSE 361 #undef COLOR_INDEX_INVERSE
1243 362
1244 void VP8LInverseTransform(const VP8LTransform* const transform, 363 void VP8LInverseTransform(const VP8LTransform* const transform,
1245 int row_start, int row_end, 364 int row_start, int row_end,
1246 const uint32_t* const in, uint32_t* const out) { 365 const uint32_t* const in, uint32_t* const out) {
1247 const int width = transform->xsize_; 366 const int width = transform->xsize_;
1248 assert(row_start < row_end); 367 assert(row_start < row_end);
1249 assert(row_end <= transform->ysize_); 368 assert(row_end <= transform->ysize_);
1250 switch (transform->type_) { 369 switch (transform->type_) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 483
1365 static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, 484 static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst,
1366 int swap_on_big_endian) { 485 int swap_on_big_endian) {
1367 if (is_big_endian() == swap_on_big_endian) { 486 if (is_big_endian() == swap_on_big_endian) {
1368 const uint32_t* const src_end = src + num_pixels; 487 const uint32_t* const src_end = src + num_pixels;
1369 while (src < src_end) { 488 while (src < src_end) {
1370 const uint32_t argb = *src++; 489 const uint32_t argb = *src++;
1371 490
1372 #if !defined(WORDS_BIGENDIAN) 491 #if !defined(WORDS_BIGENDIAN)
1373 #if !defined(WEBP_REFERENCE_IMPLEMENTATION) 492 #if !defined(WEBP_REFERENCE_IMPLEMENTATION)
1374 *(uint32_t*)dst = BSwap32(argb); 493 WebPUint32ToMem(dst, BSwap32(argb));
1375 #else // WEBP_REFERENCE_IMPLEMENTATION 494 #else // WEBP_REFERENCE_IMPLEMENTATION
1376 dst[0] = (argb >> 24) & 0xff; 495 dst[0] = (argb >> 24) & 0xff;
1377 dst[1] = (argb >> 16) & 0xff; 496 dst[1] = (argb >> 16) & 0xff;
1378 dst[2] = (argb >> 8) & 0xff; 497 dst[2] = (argb >> 8) & 0xff;
1379 dst[3] = (argb >> 0) & 0xff; 498 dst[3] = (argb >> 0) & 0xff;
1380 #endif 499 #endif
1381 #else // WORDS_BIGENDIAN 500 #else // WORDS_BIGENDIAN
1382 dst[0] = (argb >> 0) & 0xff; 501 dst[0] = (argb >> 0) & 0xff;
1383 dst[1] = (argb >> 8) & 0xff; 502 dst[1] = (argb >> 8) & 0xff;
1384 dst[2] = (argb >> 16) & 0xff; 503 dst[2] = (argb >> 16) & 0xff;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 break; 549 break;
1431 case MODE_RGB_565: 550 case MODE_RGB_565:
1432 VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba); 551 VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba);
1433 break; 552 break;
1434 default: 553 default:
1435 assert(0); // Code flow should not reach here. 554 assert(0); // Code flow should not reach here.
1436 } 555 }
1437 } 556 }
1438 557
1439 //------------------------------------------------------------------------------ 558 //------------------------------------------------------------------------------
1440 // Bundles multiple (1, 2, 4 or 8) pixels into a single pixel.
1441 void VP8LBundleColorMap(const uint8_t* const row, int width,
1442 int xbits, uint32_t* const dst) {
1443 int x;
1444 if (xbits > 0) {
1445 const int bit_depth = 1 << (3 - xbits);
1446 const int mask = (1 << xbits) - 1;
1447 uint32_t code = 0xff000000;
1448 for (x = 0; x < width; ++x) {
1449 const int xsub = x & mask;
1450 if (xsub == 0) {
1451 code = 0xff000000;
1452 }
1453 code |= row[x] << (8 + bit_depth * xsub);
1454 dst[x >> xbits] = code;
1455 }
1456 } else {
1457 for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8);
1458 }
1459 }
1460
1461 //------------------------------------------------------------------------------
1462 559
1463 static double ExtraCost(const uint32_t* population, int length) {
1464 int i;
1465 double cost = 0.;
1466 for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2];
1467 return cost;
1468 }
1469
1470 static double ExtraCostCombined(const uint32_t* X, const uint32_t* Y,
1471 int length) {
1472 int i;
1473 double cost = 0.;
1474 for (i = 2; i < length - 2; ++i) {
1475 const int xy = X[i + 2] + Y[i + 2];
1476 cost += (i >> 1) * xy;
1477 }
1478 return cost;
1479 }
1480
1481 // Returns the various RLE counts
1482 static VP8LStreaks HuffmanCostCount(const uint32_t* population, int length) {
1483 int i;
1484 int streak = 0;
1485 VP8LStreaks stats;
1486 memset(&stats, 0, sizeof(stats));
1487 for (i = 0; i < length - 1; ++i) {
1488 ++streak;
1489 if (population[i] == population[i + 1]) {
1490 continue;
1491 }
1492 stats.counts[population[i] != 0] += (streak > 3);
1493 stats.streaks[population[i] != 0][(streak > 3)] += streak;
1494 streak = 0;
1495 }
1496 ++streak;
1497 stats.counts[population[i] != 0] += (streak > 3);
1498 stats.streaks[population[i] != 0][(streak > 3)] += streak;
1499 return stats;
1500 }
1501
1502 static VP8LStreaks HuffmanCostCombinedCount(const uint32_t* X,
1503 const uint32_t* Y, int length) {
1504 int i;
1505 int streak = 0;
1506 VP8LStreaks stats;
1507 memset(&stats, 0, sizeof(stats));
1508 for (i = 0; i < length - 1; ++i) {
1509 const int xy = X[i] + Y[i];
1510 const int xy_next = X[i + 1] + Y[i + 1];
1511 ++streak;
1512 if (xy == xy_next) {
1513 continue;
1514 }
1515 stats.counts[xy != 0] += (streak > 3);
1516 stats.streaks[xy != 0][(streak > 3)] += streak;
1517 streak = 0;
1518 }
1519 {
1520 const int xy = X[i] + Y[i];
1521 ++streak;
1522 stats.counts[xy != 0] += (streak > 3);
1523 stats.streaks[xy != 0][(streak > 3)] += streak;
1524 }
1525 return stats;
1526 }
1527
1528 //------------------------------------------------------------------------------
1529
1530 static void HistogramAdd(const VP8LHistogram* const a,
1531 const VP8LHistogram* const b,
1532 VP8LHistogram* const out) {
1533 int i;
1534 const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
1535 assert(a->palette_code_bits_ == b->palette_code_bits_);
1536 if (b != out) {
1537 for (i = 0; i < literal_size; ++i) {
1538 out->literal_[i] = a->literal_[i] + b->literal_[i];
1539 }
1540 for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
1541 out->distance_[i] = a->distance_[i] + b->distance_[i];
1542 }
1543 for (i = 0; i < NUM_LITERAL_CODES; ++i) {
1544 out->red_[i] = a->red_[i] + b->red_[i];
1545 out->blue_[i] = a->blue_[i] + b->blue_[i];
1546 out->alpha_[i] = a->alpha_[i] + b->alpha_[i];
1547 }
1548 } else {
1549 for (i = 0; i < literal_size; ++i) {
1550 out->literal_[i] += a->literal_[i];
1551 }
1552 for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
1553 out->distance_[i] += a->distance_[i];
1554 }
1555 for (i = 0; i < NUM_LITERAL_CODES; ++i) {
1556 out->red_[i] += a->red_[i];
1557 out->blue_[i] += a->blue_[i];
1558 out->alpha_[i] += a->alpha_[i];
1559 }
1560 }
1561 }
1562
1563 //------------------------------------------------------------------------------
1564
1565 VP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
1566 VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed; 560 VP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed;
1567 VP8LPredictorFunc VP8LPredictors[16]; 561 VP8LPredictorFunc VP8LPredictors[16];
1568 562
1569 VP8LTransformColorFunc VP8LTransformColor;
1570 VP8LTransformColorFunc VP8LTransformColorInverse; 563 VP8LTransformColorFunc VP8LTransformColorInverse;
1571 564
1572 VP8LConvertFunc VP8LConvertBGRAToRGB; 565 VP8LConvertFunc VP8LConvertBGRAToRGB;
1573 VP8LConvertFunc VP8LConvertBGRAToRGBA; 566 VP8LConvertFunc VP8LConvertBGRAToRGBA;
1574 VP8LConvertFunc VP8LConvertBGRAToRGBA4444; 567 VP8LConvertFunc VP8LConvertBGRAToRGBA4444;
1575 VP8LConvertFunc VP8LConvertBGRAToRGB565; 568 VP8LConvertFunc VP8LConvertBGRAToRGB565;
1576 VP8LConvertFunc VP8LConvertBGRAToBGR; 569 VP8LConvertFunc VP8LConvertBGRAToBGR;
1577 570
1578 VP8LFastLog2SlowFunc VP8LFastLog2Slow; 571 VP8LMapARGBFunc VP8LMapColor32b;
1579 VP8LFastLog2SlowFunc VP8LFastSLog2Slow; 572 VP8LMapAlphaFunc VP8LMapColor8b;
1580
1581 VP8LCostFunc VP8LExtraCost;
1582 VP8LCostCombinedFunc VP8LExtraCostCombined;
1583
1584 VP8LCostCountFunc VP8LHuffmanCostCount;
1585 VP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount;
1586
1587 VP8LHistogramAddFunc VP8LHistogramAdd;
1588 573
1589 extern void VP8LDspInitSSE2(void); 574 extern void VP8LDspInitSSE2(void);
1590 extern void VP8LDspInitNEON(void); 575 extern void VP8LDspInitNEON(void);
1591 extern void VP8LDspInitMIPS32(void); 576 extern void VP8LDspInitMIPSdspR2(void);
1592 577
1593 static volatile VP8CPUInfo lossless_last_cpuinfo_used = 578 static volatile VP8CPUInfo lossless_last_cpuinfo_used =
1594 (VP8CPUInfo)&lossless_last_cpuinfo_used; 579 (VP8CPUInfo)&lossless_last_cpuinfo_used;
1595 580
1596 void VP8LDspInit(void) { 581 WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) {
1597 if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return; 582 if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return;
1598 583
1599 memcpy(VP8LPredictors, kPredictorsC, sizeof(VP8LPredictors)); 584 VP8LPredictors[0] = Predictor0;
585 VP8LPredictors[1] = Predictor1;
586 VP8LPredictors[2] = Predictor2;
587 VP8LPredictors[3] = Predictor3;
588 VP8LPredictors[4] = Predictor4;
589 VP8LPredictors[5] = Predictor5;
590 VP8LPredictors[6] = Predictor6;
591 VP8LPredictors[7] = Predictor7;
592 VP8LPredictors[8] = Predictor8;
593 VP8LPredictors[9] = Predictor9;
594 VP8LPredictors[10] = Predictor10;
595 VP8LPredictors[11] = Predictor11;
596 VP8LPredictors[12] = Predictor12;
597 VP8LPredictors[13] = Predictor13;
598 VP8LPredictors[14] = Predictor0; // <- padding security sentinels
599 VP8LPredictors[15] = Predictor0;
1600 600
1601 VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C;
1602 VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C; 601 VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C;
1603 602
1604 VP8LTransformColor = VP8LTransformColor_C;
1605 VP8LTransformColorInverse = VP8LTransformColorInverse_C; 603 VP8LTransformColorInverse = VP8LTransformColorInverse_C;
1606 604
1607 VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; 605 VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C;
1608 VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C; 606 VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C;
1609 VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C; 607 VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C;
1610 VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C; 608 VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C;
1611 VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; 609 VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C;
1612 610
1613 VP8LFastLog2Slow = FastLog2Slow; 611 VP8LMapColor32b = MapARGB;
1614 VP8LFastSLog2Slow = FastSLog2Slow; 612 VP8LMapColor8b = MapAlpha;
1615
1616 VP8LExtraCost = ExtraCost;
1617 VP8LExtraCostCombined = ExtraCostCombined;
1618
1619 VP8LHuffmanCostCount = HuffmanCostCount;
1620 VP8LHuffmanCostCombinedCount = HuffmanCostCombinedCount;
1621
1622 VP8LHistogramAdd = HistogramAdd;
1623 613
1624 // If defined, use CPUInfo() to overwrite some pointers with faster versions. 614 // If defined, use CPUInfo() to overwrite some pointers with faster versions.
1625 if (VP8GetCPUInfo != NULL) { 615 if (VP8GetCPUInfo != NULL) {
1626 #if defined(WEBP_USE_SSE2) 616 #if defined(WEBP_USE_SSE2)
1627 if (VP8GetCPUInfo(kSSE2)) { 617 if (VP8GetCPUInfo(kSSE2)) {
1628 VP8LDspInitSSE2(); 618 VP8LDspInitSSE2();
1629 } 619 }
1630 #endif 620 #endif
1631 #if defined(WEBP_USE_NEON) 621 #if defined(WEBP_USE_NEON)
1632 if (VP8GetCPUInfo(kNEON)) { 622 if (VP8GetCPUInfo(kNEON)) {
1633 VP8LDspInitNEON(); 623 VP8LDspInitNEON();
1634 } 624 }
1635 #endif 625 #endif
1636 #if defined(WEBP_USE_MIPS32) 626 #if defined(WEBP_USE_MIPS_DSP_R2)
1637 if (VP8GetCPUInfo(kMIPS32)) { 627 if (VP8GetCPUInfo(kMIPSdspR2)) {
1638 VP8LDspInitMIPS32(); 628 VP8LDspInitMIPSdspR2();
1639 } 629 }
1640 #endif 630 #endif
1641 } 631 }
1642 lossless_last_cpuinfo_used = VP8GetCPUInfo; 632 lossless_last_cpuinfo_used = VP8GetCPUInfo;
1643 } 633 }
1644 634
1645 //------------------------------------------------------------------------------ 635 //------------------------------------------------------------------------------
OLDNEW
« no previous file with comments | « third_party/libwebp/dsp/lossless.h ('k') | third_party/libwebp/dsp/lossless_enc.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698