1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2012 Google Inc. All Rights Reserved.
2a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//
30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license
40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source
50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found
60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may
70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree.
8a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
9a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//
10a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Image transforms and color space conversion methods for lossless decoder.
11a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//
12a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Authors: Vikas Arora (vikaas.arora@gmail.com)
13a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//          Jyrki Alakuijala (jyrki@google.com)
14a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//          Urvang Joshi (urvang@google.com)
15a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include "./dsp.h"
171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
18a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include <math.h>
19a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include <stdlib.h>
20a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../dec/vp8li.h"
2133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "../utils/endian_inl.h"
2233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "./lossless.h"
231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#include "./yuv.h"
24a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
25a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define MAX_DIFF_COST (1e30f)
26a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
27a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// lookup table for small values of log2(int)
281e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraconst float kLog2Table[LOG_LOOKUP_IDX_MAX] = {
29a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  0.0000000000000000f, 0.0000000000000000f,
30a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  1.0000000000000000f, 1.5849625007211560f,
31a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  2.0000000000000000f, 2.3219280948873621f,
32a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  2.5849625007211560f, 2.8073549220576041f,
33a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  3.0000000000000000f, 3.1699250014423121f,
34a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  3.3219280948873621f, 3.4594316186372973f,
35a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  3.5849625007211560f, 3.7004397181410921f,
36a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  3.8073549220576041f, 3.9068905956085187f,
37a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  4.0000000000000000f, 4.0874628412503390f,
38a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  4.1699250014423121f, 4.2479275134435852f,
39a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  4.3219280948873626f, 4.3923174227787606f,
40a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  4.4594316186372973f, 4.5235619560570130f,
41a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  4.5849625007211560f, 4.6438561897747243f,
42a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  4.7004397181410917f, 4.7548875021634682f,
43a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  4.8073549220576037f, 4.8579809951275718f,
44a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  4.9068905956085187f, 4.9541963103868749f,
45a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.0000000000000000f, 5.0443941193584533f,
46a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.0874628412503390f, 5.1292830169449663f,
47a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.1699250014423121f, 5.2094533656289501f,
48a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.2479275134435852f, 5.2854022188622487f,
49a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.3219280948873626f, 5.3575520046180837f,
50a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.3923174227787606f, 5.4262647547020979f,
51a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.4594316186372973f, 5.4918530963296747f,
52a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.5235619560570130f, 5.5545888516776376f,
53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.5849625007211560f, 5.6147098441152083f,
54a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.6438561897747243f, 5.6724253419714951f,
55a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.7004397181410917f, 5.7279204545631987f,
56a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.7548875021634682f, 5.7813597135246599f,
57a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.8073549220576037f, 5.8328900141647412f,
58a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.8579809951275718f, 5.8826430493618415f,
59a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.9068905956085187f, 5.9307373375628866f,
60a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  5.9541963103868749f, 5.9772799234999167f,
61a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.0000000000000000f, 6.0223678130284543f,
62a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.0443941193584533f, 6.0660891904577720f,
63a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.0874628412503390f, 6.1085244567781691f,
64a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.1292830169449663f, 6.1497471195046822f,
65a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.1699250014423121f, 6.1898245588800175f,
66a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.2094533656289501f, 6.2288186904958804f,
67a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.2479275134435852f, 6.2667865406949010f,
68a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.2854022188622487f, 6.3037807481771030f,
69a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.3219280948873626f, 6.3398500028846243f,
70a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.3575520046180837f, 6.3750394313469245f,
71a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.3923174227787606f, 6.4093909361377017f,
72a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.4262647547020979f, 6.4429434958487279f,
73a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.4594316186372973f, 6.4757334309663976f,
74a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.4918530963296747f, 6.5077946401986963f,
75a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.5235619560570130f, 6.5391588111080309f,
76a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.5545888516776376f, 6.5698556083309478f,
77a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.5849625007211560f, 6.5999128421871278f,
78a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.6147098441152083f, 6.6293566200796094f,
79a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.6438561897747243f, 6.6582114827517946f,
80a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.6724253419714951f, 6.6865005271832185f,
81a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.7004397181410917f, 6.7142455176661224f,
82a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.7279204545631987f, 6.7414669864011464f,
83a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.7548875021634682f, 6.7681843247769259f,
84a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.7813597135246599f, 6.7944158663501061f,
85a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.8073549220576037f, 6.8201789624151878f,
86a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.8328900141647412f, 6.8454900509443747f,
87a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.8579809951275718f, 6.8703647195834047f,
88a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.8826430493618415f, 6.8948177633079437f,
89a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.9068905956085187f, 6.9188632372745946f,
90a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.9307373375628866f, 6.9425145053392398f,
91a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.9541963103868749f, 6.9657842846620869f,
92a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  6.9772799234999167f, 6.9886846867721654f,
93a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.0000000000000000f, 7.0112272554232539f,
94a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.0223678130284543f, 7.0334230015374501f,
95a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.0443941193584533f, 7.0552824355011898f,
96a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.0660891904577720f, 7.0768155970508308f,
97a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.0874628412503390f, 7.0980320829605263f,
98a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.1085244567781691f, 7.1189410727235076f,
99a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.1292830169449663f, 7.1395513523987936f,
100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.1497471195046822f, 7.1598713367783890f,
101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.1699250014423121f, 7.1799090900149344f,
102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.1898245588800175f, 7.1996723448363644f,
103a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.2094533656289501f, 7.2191685204621611f,
104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.2288186904958804f, 7.2384047393250785f,
105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.2479275134435852f, 7.2573878426926521f,
106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.2667865406949010f, 7.2761244052742375f,
107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.2854022188622487f, 7.2946207488916270f,
108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.3037807481771030f, 7.3128829552843557f,
109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.3219280948873626f, 7.3309168781146167f,
110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.3398500028846243f, 7.3487281542310771f,
111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.3575520046180837f, 7.3663222142458160f,
112a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.3750394313469245f, 7.3837042924740519f,
113a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.3923174227787606f, 7.4008794362821843f,
114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.4093909361377017f, 7.4178525148858982f,
115a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.4262647547020979f, 7.4346282276367245f,
116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.4429434958487279f, 7.4512111118323289f,
117a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.4594316186372973f, 7.4676055500829976f,
118a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.4757334309663976f, 7.4838157772642563f,
119a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.4918530963296747f, 7.4998458870832056f,
120a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.5077946401986963f, 7.5156998382840427f,
121a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.5235619560570130f, 7.5313814605163118f,
122a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.5391588111080309f, 7.5468944598876364f,
123a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.5545888516776376f, 7.5622424242210728f,
124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.5698556083309478f, 7.5774288280357486f,
125a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.5849625007211560f, 7.5924570372680806f,
126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.5999128421871278f, 7.6073303137496104f,
127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.6147098441152083f, 7.6220518194563764f,
128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.6293566200796094f, 7.6366246205436487f,
129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.6438561897747243f, 7.6510516911789281f,
130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.6582114827517946f, 7.6653359171851764f,
131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.6724253419714951f, 7.6794800995054464f,
132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.6865005271832185f, 7.6934869574993252f,
133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.7004397181410917f, 7.7073591320808825f,
134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.7142455176661224f, 7.7210991887071855f,
135a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.7279204545631987f, 7.7347096202258383f,
136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.7414669864011464f, 7.7481928495894605f,
137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.7548875021634682f, 7.7615512324444795f,
138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.7681843247769259f, 7.7747870596011736f,
139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.7813597135246599f, 7.7879025593914317f,
140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.7944158663501061f, 7.8008998999203047f,
141a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.8073549220576037f, 7.8137811912170374f,
142a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.8201789624151878f, 7.8265484872909150f,
143a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.8328900141647412f, 7.8392037880969436f,
144a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.8454900509443747f, 7.8517490414160571f,
145a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.8579809951275718f, 7.8641861446542797f,
146a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.8703647195834047f, 7.8765169465649993f,
147a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.8826430493618415f, 7.8887432488982591f,
148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.8948177633079437f, 7.9008668079807486f,
149a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.9068905956085187f, 7.9128893362299619f,
150a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.9188632372745946f, 7.9248125036057812f,
151a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.9307373375628866f, 7.9366379390025709f,
152a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.9425145053392398f, 7.9483672315846778f,
153a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.9541963103868749f, 7.9600019320680805f,
154a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.9657842846620869f, 7.9715435539507719f,
155a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.9772799234999167f, 7.9829935746943103f,
156a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  7.9886846867721654f, 7.9943534368588577f
157a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora};
158a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1591e7bf8805bd030c19924a5306837ecd72c295751Vikas Aroraconst float kSLog2Table[LOG_LOOKUP_IDX_MAX] = {
1601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  0.00000000f,    0.00000000f,  2.00000000f,   4.75488750f,
1611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  8.00000000f,   11.60964047f,  15.50977500f,  19.65148445f,
1621e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  24.00000000f,  28.52932501f,  33.21928095f,  38.05374781f,
1631e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  43.01955001f,  48.10571634f,  53.30296891f,  58.60335893f,
1641e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  64.00000000f,  69.48686830f,  75.05865003f,  80.71062276f,
1651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  86.43856190f,  92.23866588f,  98.10749561f,  104.04192499f,
1661e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  110.03910002f, 116.09640474f, 122.21143267f, 128.38196256f,
1671e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  134.60593782f, 140.88144886f, 147.20671787f, 153.58008562f,
1681e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  160.00000000f, 166.46500594f, 172.97373660f, 179.52490559f,
1691e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  186.11730005f, 192.74977453f, 199.42124551f, 206.13068654f,
1701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  212.87712380f, 219.65963219f, 226.47733176f, 233.32938445f,
1711e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  240.21499122f, 247.13338933f, 254.08384998f, 261.06567603f,
1721e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  268.07820003f, 275.12078236f, 282.19280949f, 289.29369244f,
1731e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  296.42286534f, 303.57978409f, 310.76392512f, 317.97478424f,
1741e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  325.21187564f, 332.47473081f, 339.76289772f, 347.07593991f,
1751e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  354.41343574f, 361.77497759f, 369.16017124f, 376.56863518f,
1761e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  384.00000000f, 391.45390785f, 398.93001188f, 406.42797576f,
1771e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  413.94747321f, 421.48818752f, 429.04981119f, 436.63204548f,
1781e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  444.23460010f, 451.85719280f, 459.49954906f, 467.16140179f,
1791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  474.84249102f, 482.54256363f, 490.26137307f, 497.99867911f,
1801e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  505.75424759f, 513.52785023f, 521.31926438f, 529.12827280f,
1811e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  536.95466351f, 544.79822957f, 552.65876890f, 560.53608414f,
1821e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  568.42998244f, 576.34027536f, 584.26677867f, 592.20931226f,
1831e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  600.16769996f, 608.14176943f, 616.13135206f, 624.13628279f,
1841e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  632.15640007f, 640.19154569f, 648.24156472f, 656.30630539f,
1851e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  664.38561898f, 672.47935976f, 680.58738488f, 688.70955430f,
1861e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  696.84573069f, 704.99577935f, 713.15956818f, 721.33696754f,
1871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  729.52785023f, 737.73209140f, 745.94956849f, 754.18016116f,
1881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  762.42375127f, 770.68022275f, 778.94946161f, 787.23135586f,
1891e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  795.52579543f, 803.83267219f, 812.15187982f, 820.48331383f,
1901e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  828.82687147f, 837.18245171f, 845.54995518f, 853.92928416f,
1911e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  862.32034249f, 870.72303558f, 879.13727036f, 887.56295522f,
1921e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  896.00000000f, 904.44831595f, 912.90781569f, 921.37841320f,
1931e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  929.86002376f, 938.35256392f, 946.85595152f, 955.37010560f,
1941e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  963.89494641f, 972.43039537f, 980.97637504f, 989.53280911f,
1951e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  998.09962237f, 1006.67674069f, 1015.26409097f, 1023.86160116f,
1961e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1032.46920021f, 1041.08681805f, 1049.71438560f, 1058.35183469f,
1971e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1066.99909811f, 1075.65610955f, 1084.32280357f, 1092.99911564f,
1981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1101.68498204f, 1110.38033993f, 1119.08512727f, 1127.79928282f,
1991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1136.52274614f, 1145.25545758f, 1153.99735821f, 1162.74838989f,
2001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1171.50849518f, 1180.27761738f, 1189.05570047f, 1197.84268914f,
2011e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1206.63852876f, 1215.44316535f, 1224.25654560f, 1233.07861684f,
2021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1241.90932703f, 1250.74862473f, 1259.59645914f, 1268.45278005f,
2031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1277.31753781f, 1286.19068338f, 1295.07216828f, 1303.96194457f,
2041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1312.85996488f, 1321.76618236f, 1330.68055071f, 1339.60302413f,
2051e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1348.53355734f, 1357.47210556f, 1366.41862452f, 1375.37307041f,
2061e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1384.33539991f, 1393.30557020f, 1402.28353887f, 1411.26926400f,
2071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1420.26270412f, 1429.26381818f, 1438.27256558f, 1447.28890615f,
2081e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1456.31280014f, 1465.34420819f, 1474.38309138f, 1483.42941118f,
2091e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1492.48312945f, 1501.54420843f, 1510.61261078f, 1519.68829949f,
2101e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1528.77123795f, 1537.86138993f, 1546.95871952f, 1556.06319119f,
2111e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1565.17476976f, 1574.29342040f, 1583.41910860f, 1592.55180020f,
2121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1601.69146137f, 1610.83805860f, 1619.99155871f, 1629.15192882f,
2131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1638.31913637f, 1647.49314911f, 1656.67393509f, 1665.86146266f,
2141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1675.05570047f, 1684.25661744f, 1693.46418280f, 1702.67836605f,
2151e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1711.89913698f, 1721.12646563f, 1730.36032233f, 1739.60067768f,
2161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1748.84750254f, 1758.10076802f, 1767.36044551f, 1776.62650662f,
2171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1785.89892323f, 1795.17766747f, 1804.46271172f, 1813.75402857f,
2181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1823.05159087f, 1832.35537170f, 1841.66534438f, 1850.98148244f,
2191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1860.30375965f, 1869.63214999f, 1878.96662767f, 1888.30716711f,
2201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1897.65374295f, 1907.00633003f, 1916.36490342f, 1925.72943838f,
2211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1935.09991037f, 1944.47629506f, 1953.85856831f, 1963.24670620f,
2221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  1972.64068498f, 1982.04048108f, 1991.44607117f, 2000.85743204f,
2231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  2010.27454072f, 2019.69737440f, 2029.12591044f, 2038.56012640f
2241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora};
2251e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
2268b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraconst VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = {
2278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  { 0, 0}, { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 1}, { 4, 1}, { 5, 1},
2288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  { 5, 1}, { 6, 2}, { 6, 2}, { 6, 2}, { 6, 2}, { 7, 2}, { 7, 2}, { 7, 2},
2298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  { 7, 2}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3},
2308b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  { 8, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3},
2318b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  { 9, 3}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4},
2328b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4},
2338b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {10, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
2348b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
2358b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {11, 4}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
2368b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
2378b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
2388b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},
2398b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {12, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
2408b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
2418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
2428b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},
2438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {13, 5}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
2448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
2458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
2468b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
2478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
2488b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
2498b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
2508b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},
2518b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {14, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
2528b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
2538b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
2548b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
2558b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
2568b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
2578b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
2588b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},
2598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {15, 6}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2608b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2628b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2668b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2708b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2718b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2728b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2748b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},
2758b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {16, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2768b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2788b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2798b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2808b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2818b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2828b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2838b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2848b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2858b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2868b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2878b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2888b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2898b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2908b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},
2918b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora};
2928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
2938b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraconst uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = {
2948b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora   0,  0,  0,  0,  0,  0,  1,  0,  1,  0,  1,  2,  3,  0,  1,  2,  3,
2958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora   0,  1,  2,  3,  4,  5,  6,  7,  0,  1,  2,  3,  4,  5,  6,  7,
2968b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
2978b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
2988b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
2998b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
3008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
3018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
3028b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
3038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
3048b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
3058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
3068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
3078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
3088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
3098b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
3108b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
3118b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
3128b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
3138b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
3148b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
3158b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
3168b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
3178b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
3188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  127,
3198b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
3208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
3218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
3228b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
3238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
3248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
3258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
3268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126
3278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora};
3288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
32933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// The threshold till approximate version of log_2 can be used.
33033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Practically, we can get rid of the call to log() as the two values match to
33133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// very high degree (the ratio of these two is 0.99999x).
33233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Keeping a high threshold for now.
33333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define APPROX_LOG_WITH_CORRECTION_MAX  65536
33433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define APPROX_LOG_MAX                   4096
33533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086
33633f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic float FastSLog2Slow(uint32_t v) {
3371e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  assert(v >= LOG_LOOKUP_IDX_MAX);
33833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
339a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int log_cnt = 0;
34033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    uint32_t y = 1;
34133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int correction = 0;
3421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    const float v_f = (float)v;
34333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t orig_v = v;
34433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    do {
345a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ++log_cnt;
346a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      v = v >> 1;
34733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      y = y << 1;
34833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    } while (v >= LOG_LOOKUP_IDX_MAX);
34933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256
35033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // Xf = floor(Xf) * (1 + (v % y) / v)
35133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v)
35233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // The correction factor: log(1 + d) ~ d; for very small d values, so
35333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v
35433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // LOG_2_RECIPROCAL ~ 23/16
35533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    correction = (23 * (orig_v & (y - 1))) >> 4;
35633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    return v_f * (kLog2Table[v] + log_cnt) + correction;
3571e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  } else {
3581e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    return (float)(LOG_2_RECIPROCAL * v * log((double)v));
3591e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  }
3601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora}
3611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
36233f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic float FastLog2Slow(uint32_t v) {
3631e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  assert(v >= LOG_LOOKUP_IDX_MAX);
36433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (v < APPROX_LOG_WITH_CORRECTION_MAX) {
3651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    int log_cnt = 0;
36633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    uint32_t y = 1;
36733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t orig_v = v;
36833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    double log_2;
36933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    do {
3701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      ++log_cnt;
3711e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      v = v >> 1;
37233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      y = y << 1;
37333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    } while (v >= LOG_LOOKUP_IDX_MAX);
37433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    log_2 = kLog2Table[v] + log_cnt;
37533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (orig_v >= APPROX_LOG_MAX) {
37633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      // Since the division is still expensive, add this correction factor only
37733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      // for large values of 'v'.
37833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      const int correction = (23 * (orig_v & (y - 1))) >> 4;
37933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      log_2 += (double)correction / orig_v;
3801e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    }
38133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    return (float)log_2;
382a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
383a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return (float)(LOG_2_RECIPROCAL * log((double)v));
384a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
385a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
386a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
387a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
388a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Image transforms.
389a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
39033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Mostly used to reduce code size + readability
39133f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; }
39233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// In-place sum of each component with mod 256.
394a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
395a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u);
396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu);
397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
398a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
399a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
400a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
401a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (((a0 ^ a1) & 0xfefefefeL) >> 1) + (a0 & a1);
402a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
403a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
404a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
405a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return Average2(Average2(a0, a2), a1);
406a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
407a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
408a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
409a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                     uint32_t a2, uint32_t a3) {
410a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return Average2(Average2(a0, a1), Average2(a2, a3));
411a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
412a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
413a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t Clip255(uint32_t a) {
414a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (a < 256) {
415a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    return a;
416a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
417a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // return 0, when a is a negative integer.
418a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // return 255, when a is positive.
419a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return ~a >> 24;
420a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
421a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
422a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) {
423a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return Clip255(a + b - c);
424a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
425a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
426a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
427a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                                   uint32_t c2) {
428a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24);
429a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int r = AddSubtractComponentFull((c0 >> 16) & 0xff,
430a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                         (c1 >> 16) & 0xff,
431a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                         (c2 >> 16) & 0xff);
432a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int g = AddSubtractComponentFull((c0 >> 8) & 0xff,
433a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                         (c1 >> 8) & 0xff,
434a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                         (c2 >> 8) & 0xff);
435a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);
43633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
437a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
438a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
439a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int AddSubtractComponentHalf(int a, int b) {
440a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return Clip255(a + (a - b) / 2);
441a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
442a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
443a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
444a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                                   uint32_t c2) {
445a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t ave = Average2(c0, c1);
446a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24);
447a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff);
448a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff);
449a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff);
45033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b;
451a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
452a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
4538c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// gcc-4.9 on ARM generates incorrect code in Select() when Sub3() is inlined.
4548c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#if defined(__arm__) && LOCAL_GCC_VERSION == 0x409
4558c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora# define LOCAL_INLINE __attribute__ ((noinline))
4568c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#else
4578c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora# define LOCAL_INLINE WEBP_INLINE
4588c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#endif
4598c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora
4608c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic LOCAL_INLINE int Sub3(int a, int b, int c) {
4611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const int pb = b - c;
4621e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const int pa = a - c;
4631e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  return abs(pb) - abs(pa);
464a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
465a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
4668c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#undef LOCAL_INLINE
4678c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora
468a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
469a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int pa_minus_pb =
470a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      Sub3((a >> 24)       , (b >> 24)       , (c >> 24)       ) +
471a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +
472a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      Sub3((a >>  8) & 0xff, (b >>  8) & 0xff, (c >>  8) & 0xff) +
473a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      Sub3((a      ) & 0xff, (b      ) & 0xff, (c      ) & 0xff);
474a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (pa_minus_pb <= 0) ? a : b;
475a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
476a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
477a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
478a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Predictors
479a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
480a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor0(uint32_t left, const uint32_t* const top) {
481a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  (void)top;
482a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  (void)left;
483a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return ARGB_BLACK;
484a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
485a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor1(uint32_t left, const uint32_t* const top) {
486a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  (void)top;
487a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return left;
488a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
489a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor2(uint32_t left, const uint32_t* const top) {
490a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  (void)left;
491a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return top[0];
492a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
493a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor3(uint32_t left, const uint32_t* const top) {
494a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  (void)left;
495a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return top[1];
496a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
497a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor4(uint32_t left, const uint32_t* const top) {
498a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  (void)left;
499a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return top[-1];
500a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
501a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
502a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t pred = Average3(left, top[0], top[1]);
503a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return pred;
504a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
505a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
506a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t pred = Average2(left, top[-1]);
507a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return pred;
508a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
509a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
510a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t pred = Average2(left, top[0]);
511a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return pred;
512a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
513a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
514a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t pred = Average2(top[-1], top[0]);
515a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  (void)left;
516a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return pred;
517a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
518a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
519a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t pred = Average2(top[0], top[1]);
520a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  (void)left;
521a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return pred;
522a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
523a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
524a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
525a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return pred;
526a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
527a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
52833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const uint32_t pred = Select(top[0], left, top[-1]);
529a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return pred;
530a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
531a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
53233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
533a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return pred;
534a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
535a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
53633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
537a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return pred;
538a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
539a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
54033f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic const VP8LPredictorFunc kPredictorsC[16] = {
541a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  Predictor0, Predictor1, Predictor2, Predictor3,
542a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  Predictor4, Predictor5, Predictor6, Predictor7,
543a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  Predictor8, Predictor9, Predictor10, Predictor11,
544a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  Predictor12, Predictor13,
545a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  Predictor0, Predictor0    // <- padding security sentinels
546a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora};
547a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
54833f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic float PredictionCostSpatial(const int counts[256], int weight_0,
54933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                   double exp_val) {
55033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int significant_symbols = 256 >> 4;
551a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const double exp_decay_factor = 0.6;
552a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  double bits = weight_0 * counts[0];
553a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int i;
554a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  for (i = 1; i < significant_symbols; ++i) {
555a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    bits += exp_val * (counts[i] + counts[256 - i]);
556a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    exp_val *= exp_decay_factor;
557a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
558a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (float)(-0.1 * bits);
559a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
560a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
5611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Compute the combined Shanon's entropy for distribution {X} and {X+Y}
56233f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic float CombinedShannonEntropy(const int X[256], const int Y[256]) {
563a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int i;
5641e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  double retval = 0.;
5651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  int sumX = 0, sumXY = 0;
56633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (i = 0; i < 256; ++i) {
5671e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    const int x = X[i];
56833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int xy = x + Y[i];
5691e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    if (x != 0) {
5701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      sumX += x;
5711e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      retval -= VP8LFastSLog2(x);
57233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      sumXY += xy;
57333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      retval -= VP8LFastSLog2(xy);
57433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    } else if (xy != 0) {
5751e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      sumXY += xy;
5761e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      retval -= VP8LFastSLog2(xy);
577a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
578a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
5791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  retval += VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY);
5801e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  return (float)retval;
581a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
582a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
58333f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic float PredictionCostSpatialHistogram(const int accumulated[4][256],
58433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                            const int tile[4][256]) {
585a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int i;
586a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  double retval = 0;
587a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  for (i = 0; i < 4; ++i) {
5881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    const double kExpValue = 0.94;
5891e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    retval += PredictionCostSpatial(tile[i], 1, kExpValue);
59033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    retval += CombinedShannonEntropy(tile[i], accumulated[i]);
591a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
592a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (float)retval;
593a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
594a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
59533f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE void UpdateHisto(int histo_argb[4][256], uint32_t argb) {
59633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  ++histo_argb[0][argb >> 24];
59733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  ++histo_argb[1][(argb >> 16) & 0xff];
59833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  ++histo_argb[2][(argb >> 8) & 0xff];
59933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  ++histo_argb[3][argb & 0xff];
60033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
60133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
602a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int GetBestPredictorForTile(int width, int height,
603a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                   int tile_x, int tile_y, int bits,
60433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                   const int accumulated[4][256],
605a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                   const uint32_t* const argb_scratch) {
606a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int kNumPredModes = 14;
607a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int col_start = tile_x << bits;
608a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int row_start = tile_y << bits;
609a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int tile_size = 1 << bits;
61033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int max_y = GetMin(tile_size, height - row_start);
61133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int max_x = GetMin(tile_size, width - col_start);
612a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  float best_diff = MAX_DIFF_COST;
613a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int best_mode = 0;
614a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int mode;
615a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  for (mode = 0; mode < kNumPredModes; ++mode) {
616a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t* current_row = argb_scratch;
61733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const VP8LPredictorFunc pred_func = VP8LPredictors[mode];
618a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    float cur_diff;
619a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int y;
62033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int histo_argb[4][256];
62133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    memset(histo_argb, 0, sizeof(histo_argb));
62233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (y = 0; y < max_y; ++y) {
623a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      int x;
624a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int row = row_start + y;
625a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t* const upper_row = current_row;
626a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      current_row = upper_row + width;
62733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      for (x = 0; x < max_x; ++x) {
628a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        const int col = col_start + x;
629a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        uint32_t predict;
630a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        if (row == 0) {
631a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora          predict = (col == 0) ? ARGB_BLACK : current_row[col - 1];  // Left.
632a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        } else if (col == 0) {
633a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora          predict = upper_row[col];  // Top.
634a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        } else {
635a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora          predict = pred_func(current_row[col - 1], upper_row + col);
636a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        }
63733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        UpdateHisto(histo_argb, VP8LSubPixels(current_row[col], predict));
638a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
639a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
64033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cur_diff = PredictionCostSpatialHistogram(
64133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        accumulated, (const int (*)[256])histo_argb);
642a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (cur_diff < best_diff) {
643a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      best_diff = cur_diff;
644a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      best_mode = mode;
645a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
646a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
647a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
648a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return best_mode;
649a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
650a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
651a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void CopyTileWithPrediction(int width, int height,
652a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                   int tile_x, int tile_y, int bits, int mode,
653a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                   const uint32_t* const argb_scratch,
654a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                   uint32_t* const argb) {
655a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int col_start = tile_x << bits;
656a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int row_start = tile_y << bits;
657a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int tile_size = 1 << bits;
65833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int max_y = GetMin(tile_size, height - row_start);
65933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int max_x = GetMin(tile_size, width - col_start);
66033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const VP8LPredictorFunc pred_func = VP8LPredictors[mode];
661a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t* current_row = argb_scratch;
662a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
663a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int y;
66433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (y = 0; y < max_y; ++y) {
665a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int x;
666a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int row = row_start + y;
667a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t* const upper_row = current_row;
668a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    current_row = upper_row + width;
66933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (x = 0; x < max_x; ++x) {
670a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int col = col_start + x;
671a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int pix = row * width + col;
672a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      uint32_t predict;
673a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (row == 0) {
674a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        predict = (col == 0) ? ARGB_BLACK : current_row[col - 1];  // Left.
675a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      } else if (col == 0) {
676a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        predict = upper_row[col];  // Top.
677a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      } else {
678a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        predict = pred_func(current_row[col - 1], upper_row + col);
679a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
680a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      argb[pix] = VP8LSubPixels(current_row[col], predict);
681a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
682a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
683a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
684a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
685a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LResidualImage(int width, int height, int bits,
686a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                       uint32_t* const argb, uint32_t* const argb_scratch,
687a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                       uint32_t* const image) {
688a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int max_tile_size = 1 << bits;
689a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int tiles_per_row = VP8LSubSampleSize(width, bits);
690a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int tiles_per_col = VP8LSubSampleSize(height, bits);
691a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* const upper_row = argb_scratch;
692a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t* const current_tile_rows = argb_scratch + width;
693a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int tile_y;
694a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int histo[4][256];
695a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  memset(histo, 0, sizeof(histo));
696a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
697a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int tile_y_offset = tile_y * max_tile_size;
698a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int this_tile_height =
699a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        (tile_y < tiles_per_col - 1) ? max_tile_size : height - tile_y_offset;
700a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int tile_x;
701a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (tile_y > 0) {
702a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      memcpy(upper_row, current_tile_rows + (max_tile_size - 1) * width,
703a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora             width * sizeof(*upper_row));
704a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
705a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    memcpy(current_tile_rows, &argb[tile_y_offset * width],
706a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora           this_tile_height * width * sizeof(*current_tile_rows));
707a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
708a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      int pred;
709a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      int y;
710a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int tile_x_offset = tile_x * max_tile_size;
711a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      int all_x_max = tile_x_offset + max_tile_size;
712a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (all_x_max > width) {
713a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        all_x_max = width;
714a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
71533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      pred = GetBestPredictorForTile(width, height, tile_x, tile_y, bits,
71633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                     (const int (*)[256])histo,
717a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                     argb_scratch);
718a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      image[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
719a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred,
720a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             argb_scratch, argb);
721a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      for (y = 0; y < max_tile_size; ++y) {
722a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        int ix;
723a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        int all_x;
724a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        int all_y = tile_y_offset + y;
725a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        if (all_y >= height) {
726a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora          break;
727a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        }
728a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        ix = all_y * width + tile_x_offset;
729a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
73033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          UpdateHisto(histo, argb[ix]);
731a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        }
732a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
733a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
734a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
735a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
736a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
737a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Inverse prediction.
738a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void PredictorInverseTransform(const VP8LTransform* const transform,
739a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                      int y_start, int y_end, uint32_t* data) {
740a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int width = transform->xsize_;
741a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (y_start == 0) {  // First Row follows the L (mode=1) mode.
742a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int x;
743a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t pred0 = Predictor0(data[-1], NULL);
744a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    AddPixelsEq(data, pred0);
745a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (x = 1; x < width; ++x) {
746a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t pred1 = Predictor1(data[x - 1], NULL);
747a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      AddPixelsEq(data + x, pred1);
748a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
749a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    data += width;
750a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ++y_start;
751a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
752a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
753a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  {
754a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    int y = y_start;
75533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int tile_width = 1 << transform->bits_;
75633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int mask = tile_width - 1;
75733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int safe_width = width & ~mask;
758a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
759a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t* pred_mode_base =
760a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        transform->data_ + (y >> transform->bits_) * tiles_per_row;
761a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
762a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    while (y < y_end) {
763a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t pred2 = Predictor2(data[-1], data - width);
764a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const uint32_t* pred_mode_src = pred_mode_base;
76533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LPredictorFunc pred_func;
76633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      int x = 1;
76733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      int t = 1;
768a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // First pixel follows the T (mode=2) mode.
769a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      AddPixelsEq(data, pred2);
770a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // .. the rest:
77133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      while (x < safe_width) {
77233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf];
77333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        for (; t < tile_width; ++t, ++x) {
77433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          const uint32_t pred = pred_func(data[x - 1], data + x - width);
77533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          AddPixelsEq(data + x, pred);
77633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        }
77733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        t = 0;
77833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      }
77933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      if (x < width) {
78033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        pred_func = VP8LPredictors[((*pred_mode_src++) >> 8) & 0xf];
78133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        for (; x < width; ++x) {
78233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          const uint32_t pred = pred_func(data[x - 1], data + x - width);
78333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          AddPixelsEq(data + x, pred);
784a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        }
785a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
786a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      data += width;
787a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ++y;
788a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if ((y & mask) == 0) {   // Use the same mask, since tiles are squares.
789a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        pred_mode_base += tiles_per_row;
790a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
791a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
792a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
793a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
794a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
79533f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) {
79633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int i;
79733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (i = 0; i < num_pixels; ++i) {
798a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t argb = argb_data[i];
799a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t green = (argb >> 8) & 0xff;
800a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff;
801a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t new_b = ((argb & 0xff) - green) & 0xff;
802a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    argb_data[i] = (argb & 0xff00ff00) | (new_r << 16) | new_b;
803a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
804a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
805a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
806a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Add green to blue and red channels (i.e. perform the inverse transform of
807a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 'subtract green').
80833f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LAddGreenToBlueAndRed_C(uint32_t* data, int num_pixels) {
80933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int i;
81033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (i = 0; i < num_pixels; ++i) {
81133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t argb = data[i];
812a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t green = ((argb >> 8) & 0xff);
813a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint32_t red_blue = (argb & 0x00ff00ffu);
814a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    red_blue += (green << 16) | green;
815a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    red_blue &= 0x00ff00ffu;
81633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    data[i] = (argb & 0xff00ff00u) | red_blue;
817a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
818a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
819a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
82033f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE void MultipliersClear(VP8LMultipliers* const m) {
821a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  m->green_to_red_ = 0;
822a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  m->green_to_blue_ = 0;
823a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  m->red_to_blue_ = 0;
824a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
825a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
826a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
827a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                                int8_t color) {
828a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (uint32_t)((int)(color_pred) * color) >> 5;
829a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
830a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
831a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
83233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                               VP8LMultipliers* const m) {
833a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  m->green_to_red_  = (color_code >>  0) & 0xff;
834a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  m->green_to_blue_ = (color_code >>  8) & 0xff;
835a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  m->red_to_blue_   = (color_code >> 16) & 0xff;
836a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
837a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
83833f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE uint32_t MultipliersToColorCode(
83933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const VP8LMultipliers* const m) {
840a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 0xff000000u |
841a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora         ((uint32_t)(m->red_to_blue_) << 16) |
842a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora         ((uint32_t)(m->green_to_blue_) << 8) |
843a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora         m->green_to_red_;
844a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
845a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
84633f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data,
84733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                          int num_pixels) {
84833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int i;
84933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (i = 0; i < num_pixels; ++i) {
85033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t argb = data[i];
85133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t green = argb >> 8;
85233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t red = argb >> 16;
85333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    uint32_t new_red = red;
85433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    uint32_t new_blue = argb;
85533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    new_red -= ColorTransformDelta(m->green_to_red_, green);
85633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    new_red &= 0xff;
85733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    new_blue -= ColorTransformDelta(m->green_to_blue_, green);
85833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    new_blue -= ColorTransformDelta(m->red_to_blue_, red);
85933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    new_blue &= 0xff;
86033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
86133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
86233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
863a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
86433f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LTransformColorInverse_C(const VP8LMultipliers* const m, uint32_t* data,
86533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                 int num_pixels) {
86633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int i;
86733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (i = 0; i < num_pixels; ++i) {
86833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t argb = data[i];
86933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t green = argb >> 8;
87033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t red = argb >> 16;
87133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    uint32_t new_red = red;
87233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    uint32_t new_blue = argb;
873a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    new_red += ColorTransformDelta(m->green_to_red_, green);
874a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    new_red &= 0xff;
875a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    new_blue += ColorTransformDelta(m->green_to_blue_, green);
876a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    new_blue += ColorTransformDelta(m->red_to_blue_, new_red);
877a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    new_blue &= 0xff;
87833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
879a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
880a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
881a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
8821e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,
8831e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora                                             uint32_t argb) {
8841e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const uint32_t green = argb >> 8;
8851e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  uint32_t new_red = argb >> 16;
8861e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  new_red -= ColorTransformDelta(green_to_red, green);
8871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  return (new_red & 0xff);
8881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora}
8891e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
8901e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,
8911e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora                                              uint8_t red_to_blue,
8921e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora                                              uint32_t argb) {
8931e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const uint32_t green = argb >> 8;
8941e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const uint32_t red = argb >> 16;
8951e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  uint8_t new_blue = argb;
8961e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  new_blue -= ColorTransformDelta(green_to_blue, green);
8971e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  new_blue -= ColorTransformDelta(red_to_blue, red);
8981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  return (new_blue & 0xff);
8991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora}
9001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
901a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic float PredictionCostCrossColor(const int accumulated[256],
902a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                      const int counts[256]) {
903a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // Favor low entropy, locally and globally.
9041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  // Favor small absolute values for PredictionCostSpatial
9051e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  static const double kExpValue = 2.4;
90633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return CombinedShannonEntropy(counts, accumulated) +
9071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora         PredictionCostSpatial(counts, 3, kExpValue);
908a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
909a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
91033f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic float GetPredictionCostCrossColorRed(
91133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max,
91233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, int green_to_red,
91333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int accumulated_red_histo[256], const uint32_t* const argb) {
91433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int all_y;
91533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int histo[256] = { 0 };
916a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  float cur_diff;
91733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) {
91833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int ix = all_y * xsize + tile_x_offset;
91933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int all_x;
92033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
92133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      ++histo[TransformColorRed(green_to_red, argb[ix])];  // red.
92233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
923a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
92433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  cur_diff = PredictionCostCrossColor(accumulated_red_histo, histo);
92533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if ((uint8_t)green_to_red == prev_x.green_to_red_) {
92633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cur_diff -= 3;  // favor keeping the areas locally similar
927a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
92833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if ((uint8_t)green_to_red == prev_y.green_to_red_) {
92933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cur_diff -= 3;  // favor keeping the areas locally similar
93033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
93133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (green_to_red == 0) {
93233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cur_diff -= 3;
93333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
93433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return cur_diff;
93533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
93633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
93733f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void GetBestGreenToRed(
93833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max,
93933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y,
94033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int accumulated_red_histo[256], const uint32_t* const argb,
94133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    VP8LMultipliers* const best_tx) {
94233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int min_green_to_red = -64;
94333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int max_green_to_red = 64;
94433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int green_to_red = 0;
94533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int eval_min = 1;
94633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int eval_max = 1;
94733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  float cur_diff_min = MAX_DIFF_COST;
94833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  float cur_diff_max = MAX_DIFF_COST;
94933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // Do a binary search to find the optimal green_to_red color transform.
95033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  while (max_green_to_red - min_green_to_red > 2) {
95133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (eval_min) {
95233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      cur_diff_min = GetPredictionCostCrossColorRed(
95333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize,
95433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          prev_x, prev_y, min_green_to_red, accumulated_red_histo, argb);
95533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      eval_min = 0;
956a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
95733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (eval_max) {
95833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      cur_diff_max = GetPredictionCostCrossColorRed(
95933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize,
96033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          prev_x, prev_y, max_green_to_red, accumulated_red_histo, argb);
96133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      eval_max = 0;
962a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
96333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (cur_diff_min < cur_diff_max) {
96433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      green_to_red = min_green_to_red;
96533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      max_green_to_red = (max_green_to_red + min_green_to_red) / 2;
96633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      eval_max = 1;
96733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    } else {
96833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      green_to_red = max_green_to_red;
96933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      min_green_to_red = (max_green_to_red + min_green_to_red) / 2;
97033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      eval_min = 1;
971a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
97233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
97333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  best_tx->green_to_red_ = green_to_red;
97433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
97533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
97633f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic float GetPredictionCostCrossColorBlue(
97733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max,
97833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y,
97933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int green_to_blue, int red_to_blue, const int accumulated_blue_histo[256],
98033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t* const argb) {
98133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int all_y;
98233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int histo[256] = { 0 };
98333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  float cur_diff;
98433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) {
98533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int all_x;
98633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int ix = all_y * xsize + tile_x_offset;
98733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
98833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      ++histo[TransformColorBlue(green_to_blue, red_to_blue, argb[ix])];
989a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
990a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
99133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  cur_diff = PredictionCostCrossColor(accumulated_blue_histo, histo);
99233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if ((uint8_t)green_to_blue == prev_x.green_to_blue_) {
99333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cur_diff -= 3;  // favor keeping the areas locally similar
99433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
99533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if ((uint8_t)green_to_blue == prev_y.green_to_blue_) {
99633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cur_diff -= 3;  // favor keeping the areas locally similar
99733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
99833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if ((uint8_t)red_to_blue == prev_x.red_to_blue_) {
99933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cur_diff -= 3;  // favor keeping the areas locally similar
100033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
100133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if ((uint8_t)red_to_blue == prev_y.red_to_blue_) {
100233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cur_diff -= 3;  // favor keeping the areas locally similar
100333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
100433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (green_to_blue == 0) {
100533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cur_diff -= 3;
100633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
100733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (red_to_blue == 0) {
100833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cur_diff -= 3;
100933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
101033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return cur_diff;
101133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
101233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
101333f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void GetBestGreenRedToBlue(
101433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int tile_x_offset, int tile_y_offset, int all_x_max, int all_y_max,
101533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int xsize, VP8LMultipliers prev_x, VP8LMultipliers prev_y, int quality,
101633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int accumulated_blue_histo[256], const uint32_t* const argb,
101733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    VP8LMultipliers* const best_tx) {
101833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  float best_diff = MAX_DIFF_COST;
101933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  float cur_diff;
102033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int step = (quality < 25) ? 32 : (quality > 50) ? 8 : 16;
102133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int min_green_to_blue = -32;
102233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int max_green_to_blue = 32;
102333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int min_red_to_blue = -32;
102433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int max_red_to_blue = 32;
102533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int num_iters =
102633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      (1 + (max_green_to_blue - min_green_to_blue) / step) *
102733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      (1 + (max_red_to_blue - min_red_to_blue) / step);
102833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // Number of tries to get optimal green_to_blue & red_to_blue color transforms
102933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // after finding a local minima.
103033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int max_tries_after_min = 4 + (num_iters >> 2);
103133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int num_tries_after_min = 0;
103233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int green_to_blue;
103333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (green_to_blue = min_green_to_blue;
103433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora       green_to_blue <= max_green_to_blue &&
103533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora       num_tries_after_min < max_tries_after_min;
103633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora       green_to_blue += step) {
103733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int red_to_blue;
103833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (red_to_blue = min_red_to_blue;
103933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora         red_to_blue <= max_red_to_blue &&
104033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora         num_tries_after_min < max_tries_after_min;
104133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora         red_to_blue += step) {
104233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      cur_diff = GetPredictionCostCrossColorBlue(
104333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize, prev_x,
104433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          prev_y, green_to_blue, red_to_blue, accumulated_blue_histo, argb);
1045a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (cur_diff < best_diff) {
1046a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        best_diff = cur_diff;
104733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        best_tx->green_to_blue_ = green_to_blue;
104833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        best_tx->red_to_blue_ = red_to_blue;
104933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        num_tries_after_min = 0;
105033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      } else {
105133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        ++num_tries_after_min;
1052a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
1053a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1054a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
105533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
105633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
105733f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic VP8LMultipliers GetBestColorTransformForTile(
105833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int tile_x, int tile_y, int bits,
105933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    VP8LMultipliers prev_x,
106033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    VP8LMultipliers prev_y,
106133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int quality, int xsize, int ysize,
106233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int accumulated_red_histo[256],
106333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int accumulated_blue_histo[256],
106433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t* const argb) {
106533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int max_tile_size = 1 << bits;
106633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int tile_y_offset = tile_y * max_tile_size;
106733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int tile_x_offset = tile_x * max_tile_size;
106833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int all_x_max = GetMin(tile_x_offset + max_tile_size, xsize);
106933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int all_y_max = GetMin(tile_y_offset + max_tile_size, ysize);
107033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LMultipliers best_tx;
107133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  MultipliersClear(&best_tx);
107233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
107333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  GetBestGreenToRed(tile_x_offset, tile_y_offset, all_x_max, all_y_max, xsize,
107433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                    prev_x, prev_y, accumulated_red_histo, argb, &best_tx);
107533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  GetBestGreenRedToBlue(tile_x_offset, tile_y_offset, all_x_max, all_y_max,
107633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                        xsize, prev_x, prev_y, quality, accumulated_blue_histo,
107733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                        argb, &best_tx);
1078a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return best_tx;
1079a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1080a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1081a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void CopyTileWithColorTransform(int xsize, int ysize,
108233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                       int tile_x, int tile_y,
108333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                       int max_tile_size,
108433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                       VP8LMultipliers color_transform,
108533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                       uint32_t* argb) {
108633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int xscan = GetMin(max_tile_size, xsize - tile_x);
108733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int yscan = GetMin(max_tile_size, ysize - tile_y);
108833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  argb += tile_y * xsize + tile_x;
108933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  while (yscan-- > 0) {
109033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    VP8LTransformColor(&color_transform, argb, xscan);
109133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    argb += xsize;
1092a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1093a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1094a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
109533f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LColorSpaceTransform(int width, int height, int bits, int quality,
1096a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                             uint32_t* const argb, uint32_t* image) {
1097a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int max_tile_size = 1 << bits;
109833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int tile_xsize = VP8LSubSampleSize(width, bits);
109933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int tile_ysize = VP8LSubSampleSize(height, bits);
1100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int accumulated_red_histo[256] = { 0 };
1101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int accumulated_blue_histo[256] = { 0 };
110233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int tile_x, tile_y;
110333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LMultipliers prev_x, prev_y;
110433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  MultipliersClear(&prev_y);
110533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  MultipliersClear(&prev_x);
1106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  for (tile_y = 0; tile_y < tile_ysize; ++tile_y) {
1107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    for (tile_x = 0; tile_x < tile_xsize; ++tile_x) {
1108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      int y;
1109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      const int tile_x_offset = tile_x * max_tile_size;
111033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      const int tile_y_offset = tile_y * max_tile_size;
111133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      const int all_x_max = GetMin(tile_x_offset + max_tile_size, width);
111233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      const int all_y_max = GetMin(tile_y_offset + max_tile_size, height);
111333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      const int offset = tile_y * tile_xsize + tile_x;
1114a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (tile_y != 0) {
111533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        ColorCodeToMultipliers(image[offset - tile_xsize], &prev_y);
1116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
111733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      prev_x = GetBestColorTransformForTile(tile_x, tile_y, bits,
111833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                            prev_x, prev_y,
111933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                            quality, width, height,
112033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                            accumulated_red_histo,
112133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                            accumulated_blue_histo,
112233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                            argb);
112333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      image[offset] = MultipliersToColorCode(&prev_x);
112433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      CopyTileWithColorTransform(width, height, tile_x_offset, tile_y_offset,
112533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                 max_tile_size, prev_x, argb);
1126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      // Gather accumulated histogram data.
112833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      for (y = tile_y_offset; y < all_y_max; ++y) {
112933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        int ix = y * width + tile_x_offset;
113033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        const int ix_end = ix + all_x_max - tile_x_offset;
113133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        for (; ix < ix_end; ++ix) {
113233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          const uint32_t pix = argb[ix];
1133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora          if (ix >= 2 &&
113433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora              pix == argb[ix - 2] &&
113533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora              pix == argb[ix - 1]) {
1136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora            continue;  // repeated pixels are handled by backward references
1137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora          }
1138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora          if (ix >= width + 2 &&
1139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora              argb[ix - 2] == argb[ix - width - 2] &&
1140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora              argb[ix - 1] == argb[ix - width - 1] &&
114133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora              pix == argb[ix - width]) {
1142a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora            continue;  // repeated pixels are handled by backward references
1143a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora          }
114433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          ++accumulated_red_histo[(pix >> 16) & 0xff];
114533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora          ++accumulated_blue_histo[(pix >> 0) & 0xff];
1146a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        }
1147a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
1148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1149a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1150a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1151a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1152a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Color space inverse transform.
1153a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void ColorSpaceInverseTransform(const VP8LTransform* const transform,
1154a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                       int y_start, int y_end, uint32_t* data) {
1155a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int width = transform->xsize_;
115633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int tile_width = 1 << transform->bits_;
115733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int mask = tile_width - 1;
115833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int safe_width = width & ~mask;
115933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int remaining_width = width - safe_width;
1160a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
1161a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  int y = y_start;
1162a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t* pred_row =
1163a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      transform->data_ + (y >> transform->bits_) * tiles_per_row;
1164a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1165a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (y < y_end) {
1166a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t* pred = pred_row;
116733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    VP8LMultipliers m = { 0, 0, 0 };
116833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t* const data_safe_end = data + safe_width;
116933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint32_t* const data_end = data + width;
117033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    while (data < data_safe_end) {
117133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      ColorCodeToMultipliers(*pred++, &m);
117233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LTransformColorInverse(&m, data, tile_width);
117333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      data += tile_width;
117433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
117533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (data < data_end) {  // Left-overs using C-version.
117633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      ColorCodeToMultipliers(*pred++, &m);
117733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LTransformColorInverse(&m, data, remaining_width);
117833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      data += remaining_width;
1179a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1180a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    ++y;
11818c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora    if ((y & mask) == 0) pred_row += tiles_per_row;
1182a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1183a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1184a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1185a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Separate out pixels packed together using pixel-bundling.
11860406ce1417f76f2034833414dcecc9f56253640cVikas Arora// We define two methods for ARGB data (uint32_t) and alpha-only data (uint8_t).
11870406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define COLOR_INDEX_INVERSE(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE)             \
11880406ce1417f76f2034833414dcecc9f56253640cVikas Aroravoid FUNC_NAME(const VP8LTransform* const transform,                           \
11890406ce1417f76f2034833414dcecc9f56253640cVikas Arora               int y_start, int y_end, const TYPE* src, TYPE* dst) {           \
11900406ce1417f76f2034833414dcecc9f56253640cVikas Arora  int y;                                                                       \
11910406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int bits_per_pixel = 8 >> transform->bits_;                            \
11920406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int width = transform->xsize_;                                         \
11930406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint32_t* const color_map = transform->data_;                          \
11940406ce1417f76f2034833414dcecc9f56253640cVikas Arora  if (bits_per_pixel < 8) {                                                    \
11950406ce1417f76f2034833414dcecc9f56253640cVikas Arora    const int pixels_per_byte = 1 << transform->bits_;                         \
11960406ce1417f76f2034833414dcecc9f56253640cVikas Arora    const int count_mask = pixels_per_byte - 1;                                \
11970406ce1417f76f2034833414dcecc9f56253640cVikas Arora    const uint32_t bit_mask = (1 << bits_per_pixel) - 1;                       \
11980406ce1417f76f2034833414dcecc9f56253640cVikas Arora    for (y = y_start; y < y_end; ++y) {                                        \
11990406ce1417f76f2034833414dcecc9f56253640cVikas Arora      uint32_t packed_pixels = 0;                                              \
12000406ce1417f76f2034833414dcecc9f56253640cVikas Arora      int x;                                                                   \
12010406ce1417f76f2034833414dcecc9f56253640cVikas Arora      for (x = 0; x < width; ++x) {                                            \
12020406ce1417f76f2034833414dcecc9f56253640cVikas Arora        /* We need to load fresh 'packed_pixels' once every                */  \
12030406ce1417f76f2034833414dcecc9f56253640cVikas Arora        /* 'pixels_per_byte' increments of x. Fortunately, pixels_per_byte */  \
12040406ce1417f76f2034833414dcecc9f56253640cVikas Arora        /* is a power of 2, so can just use a mask for that, instead of    */  \
12050406ce1417f76f2034833414dcecc9f56253640cVikas Arora        /* decrementing a counter.                                         */  \
12060406ce1417f76f2034833414dcecc9f56253640cVikas Arora        if ((x & count_mask) == 0) packed_pixels = GET_INDEX(*src++);          \
12070406ce1417f76f2034833414dcecc9f56253640cVikas Arora        *dst++ = GET_VALUE(color_map[packed_pixels & bit_mask]);               \
12080406ce1417f76f2034833414dcecc9f56253640cVikas Arora        packed_pixels >>= bits_per_pixel;                                      \
12090406ce1417f76f2034833414dcecc9f56253640cVikas Arora      }                                                                        \
12100406ce1417f76f2034833414dcecc9f56253640cVikas Arora    }                                                                          \
12110406ce1417f76f2034833414dcecc9f56253640cVikas Arora  } else {                                                                     \
12120406ce1417f76f2034833414dcecc9f56253640cVikas Arora    for (y = y_start; y < y_end; ++y) {                                        \
12130406ce1417f76f2034833414dcecc9f56253640cVikas Arora      int x;                                                                   \
12140406ce1417f76f2034833414dcecc9f56253640cVikas Arora      for (x = 0; x < width; ++x) {                                            \
12150406ce1417f76f2034833414dcecc9f56253640cVikas Arora        *dst++ = GET_VALUE(color_map[GET_INDEX(*src++)]);                      \
12160406ce1417f76f2034833414dcecc9f56253640cVikas Arora      }                                                                        \
12170406ce1417f76f2034833414dcecc9f56253640cVikas Arora    }                                                                          \
12180406ce1417f76f2034833414dcecc9f56253640cVikas Arora  }                                                                            \
12190406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
12200406ce1417f76f2034833414dcecc9f56253640cVikas Arora
12210406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE uint32_t GetARGBIndex(uint32_t idx) {
12220406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return (idx >> 8) & 0xff;
12230406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
12240406ce1417f76f2034833414dcecc9f56253640cVikas Arora
12250406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE uint8_t GetAlphaIndex(uint8_t idx) {
12260406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return idx;
1227a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1228a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
12290406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE uint32_t GetARGBValue(uint32_t val) {
12300406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return val;
12310406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
12320406ce1417f76f2034833414dcecc9f56253640cVikas Arora
12330406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE uint8_t GetAlphaValue(uint32_t val) {
12340406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return (val >> 8) & 0xff;
12350406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
12360406ce1417f76f2034833414dcecc9f56253640cVikas Arora
12370406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic COLOR_INDEX_INVERSE(ColorIndexInverseTransform, uint32_t, GetARGBIndex,
12380406ce1417f76f2034833414dcecc9f56253640cVikas Arora                           GetARGBValue)
12390406ce1417f76f2034833414dcecc9f56253640cVikas AroraCOLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, uint8_t, GetAlphaIndex,
12400406ce1417f76f2034833414dcecc9f56253640cVikas Arora                    GetAlphaValue)
12410406ce1417f76f2034833414dcecc9f56253640cVikas Arora
12420406ce1417f76f2034833414dcecc9f56253640cVikas Arora#undef COLOR_INDEX_INVERSE
12430406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1244a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LInverseTransform(const VP8LTransform* const transform,
1245a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                          int row_start, int row_end,
1246a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                          const uint32_t* const in, uint32_t* const out) {
12478b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  const int width = transform->xsize_;
1248a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(row_start < row_end);
1249a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(row_end <= transform->ysize_);
1250a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  switch (transform->type_) {
1251a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case SUBTRACT_GREEN:
125233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LAddGreenToBlueAndRed(out, (row_end - row_start) * width);
1253a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1254a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case PREDICTOR_TRANSFORM:
1255a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      PredictorInverseTransform(transform, row_start, row_end, out);
1256a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (row_end != transform->ysize_) {
1257a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // The last predicted row in this iteration will be the top-pred row
1258a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // for the first row in next iteration.
1259a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        memcpy(out - width, out + (row_end - row_start - 1) * width,
1260a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora               width * sizeof(*out));
1261a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
1262a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1263a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case CROSS_COLOR_TRANSFORM:
1264a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      ColorSpaceInverseTransform(transform, row_start, row_end, out);
1265a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1266a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case COLOR_INDEXING_TRANSFORM:
1267a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      if (in == out && transform->bits_ > 0) {
1268a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // Move packed pixels to the end of unpacked region, so that unpacking
1269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // can occur seamlessly.
1270a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // Also, note that this is the only transform that applies on
1271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // the effective width of VP8LSubSampleSize(xsize_, bits_). All other
1272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        // transforms work on effective width of xsize_.
12738b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora        const int out_stride = (row_end - row_start) * width;
1274a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        const int in_stride = (row_end - row_start) *
1275a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora            VP8LSubSampleSize(transform->xsize_, transform->bits_);
1276a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        uint32_t* const src = out + out_stride - in_stride;
1277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        memmove(src, out, in_stride * sizeof(*src));
1278a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        ColorIndexInverseTransform(transform, row_start, row_end, src, out);
1279a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      } else {
1280a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora        ColorIndexInverseTransform(transform, row_start, row_end, in, out);
1281a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      }
1282a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1283a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1284a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1285a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1286a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
1287a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Color space conversion.
1288a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1289a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic int is_big_endian(void) {
1290a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  static const union {
1291a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint16_t w;
1292a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint8_t b[2];
1293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } tmp = { 1 };
1294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (tmp.b[0] != 1);
1295a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1296a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
129733f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LConvertBGRAToRGB_C(const uint32_t* src,
129833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                            int num_pixels, uint8_t* dst) {
1299a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t* const src_end = src + num_pixels;
1300a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (src < src_end) {
1301a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t argb = *src++;
1302a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    *dst++ = (argb >> 16) & 0xff;
1303a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    *dst++ = (argb >>  8) & 0xff;
1304a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    *dst++ = (argb >>  0) & 0xff;
1305a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1306a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1307a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
130833f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LConvertBGRAToRGBA_C(const uint32_t* src,
130933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                             int num_pixels, uint8_t* dst) {
1310a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t* const src_end = src + num_pixels;
1311a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (src < src_end) {
1312a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t argb = *src++;
1313a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    *dst++ = (argb >> 16) & 0xff;
1314a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    *dst++ = (argb >>  8) & 0xff;
1315a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    *dst++ = (argb >>  0) & 0xff;
1316a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    *dst++ = (argb >> 24) & 0xff;
1317a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1318a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1319a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
132033f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LConvertBGRAToRGBA4444_C(const uint32_t* src,
132133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                 int num_pixels, uint8_t* dst) {
1322a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t* const src_end = src + num_pixels;
1323a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (src < src_end) {
1324a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t argb = *src++;
13251e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    const uint8_t rg = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf);
13261e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    const uint8_t ba = ((argb >>  0) & 0xf0) | ((argb >> 28) & 0xf);
13271e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef WEBP_SWAP_16BIT_CSP
13281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    *dst++ = ba;
13291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    *dst++ = rg;
1330a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#else
13311e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    *dst++ = rg;
13321e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    *dst++ = ba;
1333a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif
1334a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1335a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1336a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
133733f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LConvertBGRAToRGB565_C(const uint32_t* src,
133833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                               int num_pixels, uint8_t* dst) {
1339a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t* const src_end = src + num_pixels;
1340a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (src < src_end) {
1341a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t argb = *src++;
13421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    const uint8_t rg = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7);
13431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    const uint8_t gb = ((argb >>  5) & 0xe0) | ((argb >>  3) & 0x1f);
13441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef WEBP_SWAP_16BIT_CSP
13451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    *dst++ = gb;
13461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    *dst++ = rg;
1347a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#else
13481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    *dst++ = rg;
13491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora    *dst++ = gb;
1350a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif
1351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
135433f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LConvertBGRAToBGR_C(const uint32_t* src,
135533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                            int num_pixels, uint8_t* dst) {
1356a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const uint32_t* const src_end = src + num_pixels;
1357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  while (src < src_end) {
1358a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t argb = *src++;
1359a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    *dst++ = (argb >>  0) & 0xff;
1360a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    *dst++ = (argb >>  8) & 0xff;
1361a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    *dst++ = (argb >> 16) & 0xff;
1362a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1363a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1364a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1365a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst,
1366a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                       int swap_on_big_endian) {
1367a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (is_big_endian() == swap_on_big_endian) {
1368a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    const uint32_t* const src_end = src + num_pixels;
1369a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    while (src < src_end) {
137033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      const uint32_t argb = *src++;
13711e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
137233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#if !defined(WORDS_BIGENDIAN)
13731e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#if !defined(WEBP_REFERENCE_IMPLEMENTATION)
137433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      *(uint32_t*)dst = BSwap32(argb);
13750406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else  // WEBP_REFERENCE_IMPLEMENTATION
13761e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      dst[0] = (argb >> 24) & 0xff;
13771e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      dst[1] = (argb >> 16) & 0xff;
13781e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      dst[2] = (argb >>  8) & 0xff;
13791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      dst[3] = (argb >>  0) & 0xff;
1380a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif
138133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#else  // WORDS_BIGENDIAN
13820406ce1417f76f2034833414dcecc9f56253640cVikas Arora      dst[0] = (argb >>  0) & 0xff;
13830406ce1417f76f2034833414dcecc9f56253640cVikas Arora      dst[1] = (argb >>  8) & 0xff;
13840406ce1417f76f2034833414dcecc9f56253640cVikas Arora      dst[2] = (argb >> 16) & 0xff;
13850406ce1417f76f2034833414dcecc9f56253640cVikas Arora      dst[3] = (argb >> 24) & 0xff;
13860406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif
13871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora      dst += sizeof(argb);
1388a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    }
1389a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  } else {
1390a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    memcpy(dst, src, num_pixels * sizeof(*src));
1391a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1392a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1393a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
1394a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
1395a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                         WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) {
1396a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  switch (out_colorspace) {
1397a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_RGB:
139833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LConvertBGRAToRGB(in_data, num_pixels, rgba);
1399a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1400a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_RGBA:
140133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba);
1402a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1403a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_rgbA:
140433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LConvertBGRAToRGBA(in_data, num_pixels, rgba);
1405a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0);
1406a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1407a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_BGR:
140833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LConvertBGRAToBGR(in_data, num_pixels, rgba);
1409a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1410a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_BGRA:
1411a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      CopyOrSwap(in_data, num_pixels, rgba, 1);
1412a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1413a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_bgrA:
1414a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      CopyOrSwap(in_data, num_pixels, rgba, 1);
1415a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0);
1416a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1417a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_ARGB:
1418a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      CopyOrSwap(in_data, num_pixels, rgba, 0);
1419a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1420a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_Argb:
1421a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      CopyOrSwap(in_data, num_pixels, rgba, 0);
1422a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      WebPApplyAlphaMultiply(rgba, 1, num_pixels, 1, 0);
1423a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1424a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_RGBA_4444:
142533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
1426a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1427a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_rgbA_4444:
142833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
1429a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0);
1430a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1431a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    case MODE_RGB_565:
143233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LConvertBGRAToRGB565(in_data, num_pixels, rgba);
1433a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      break;
1434a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    default:
1435a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      assert(0);          // Code flow should not reach here.
1436a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1437a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
1438a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
143933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------
14400406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel.
14410406ce1417f76f2034833414dcecc9f56253640cVikas Aroravoid VP8LBundleColorMap(const uint8_t* const row, int width,
14420406ce1417f76f2034833414dcecc9f56253640cVikas Arora                        int xbits, uint32_t* const dst) {
14430406ce1417f76f2034833414dcecc9f56253640cVikas Arora  int x;
14440406ce1417f76f2034833414dcecc9f56253640cVikas Arora  if (xbits > 0) {
14450406ce1417f76f2034833414dcecc9f56253640cVikas Arora    const int bit_depth = 1 << (3 - xbits);
14460406ce1417f76f2034833414dcecc9f56253640cVikas Arora    const int mask = (1 << xbits) - 1;
14470406ce1417f76f2034833414dcecc9f56253640cVikas Arora    uint32_t code = 0xff000000;
14480406ce1417f76f2034833414dcecc9f56253640cVikas Arora    for (x = 0; x < width; ++x) {
14490406ce1417f76f2034833414dcecc9f56253640cVikas Arora      const int xsub = x & mask;
14500406ce1417f76f2034833414dcecc9f56253640cVikas Arora      if (xsub == 0) {
14510406ce1417f76f2034833414dcecc9f56253640cVikas Arora        code = 0xff000000;
14520406ce1417f76f2034833414dcecc9f56253640cVikas Arora      }
14530406ce1417f76f2034833414dcecc9f56253640cVikas Arora      code |= row[x] << (8 + bit_depth * xsub);
14540406ce1417f76f2034833414dcecc9f56253640cVikas Arora      dst[x >> xbits] = code;
14550406ce1417f76f2034833414dcecc9f56253640cVikas Arora    }
14560406ce1417f76f2034833414dcecc9f56253640cVikas Arora  } else {
14570406ce1417f76f2034833414dcecc9f56253640cVikas Arora    for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8);
14580406ce1417f76f2034833414dcecc9f56253640cVikas Arora  }
14590406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
14600406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1461a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
1462a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
146333f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic double ExtraCost(const uint32_t* population, int length) {
146433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int i;
146533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  double cost = 0.;
146633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2];
146733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return cost;
14688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
14698b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
147033f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic double ExtraCostCombined(const uint32_t* X, const uint32_t* Y,
147133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                int length) {
147233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int i;
147333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  double cost = 0.;
147433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (i = 2; i < length - 2; ++i) {
147533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int xy = X[i + 2] + Y[i + 2];
147633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    cost += (i >> 1) * xy;
14778b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
147833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return cost;
147933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
148033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
148133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Returns the various RLE counts
148233f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic VP8LStreaks HuffmanCostCount(const uint32_t* population, int length) {
148333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int i;
148433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int streak = 0;
148533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LStreaks stats;
148633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  memset(&stats, 0, sizeof(stats));
148733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (i = 0; i < length - 1; ++i) {
148833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    ++streak;
148933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (population[i] == population[i + 1]) {
149033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      continue;
149133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
149233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    stats.counts[population[i] != 0] += (streak > 3);
149333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    stats.streaks[population[i] != 0][(streak > 3)] += streak;
149433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    streak = 0;
14958b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
149633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  ++streak;
149733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  stats.counts[population[i] != 0] += (streak > 3);
149833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  stats.streaks[population[i] != 0][(streak > 3)] += streak;
149933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return stats;
15008b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
15018b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
150233f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic VP8LStreaks HuffmanCostCombinedCount(const uint32_t* X,
150333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                            const uint32_t* Y, int length) {
150433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int i;
150533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int streak = 0;
150633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LStreaks stats;
150733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  memset(&stats, 0, sizeof(stats));
150833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  for (i = 0; i < length - 1; ++i) {
150933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int xy = X[i] + Y[i];
151033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int xy_next = X[i + 1] + Y[i + 1];
151133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    ++streak;
151233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (xy == xy_next) {
151333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      continue;
151433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
151533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    stats.counts[xy != 0] += (streak > 3);
151633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    stats.streaks[xy != 0][(streak > 3)] += streak;
151733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    streak = 0;
15188b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
151933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  {
152033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int xy = X[i] + Y[i];
152133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    ++streak;
152233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    stats.counts[xy != 0] += (streak > 3);
152333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    stats.streaks[xy != 0][(streak > 3)] += streak;
15248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
152533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return stats;
15268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
15278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
152833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------
15298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
153033f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void HistogramAdd(const VP8LHistogram* const a,
153133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                         const VP8LHistogram* const b,
153233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                         VP8LHistogram* const out) {
153333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int i;
153433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
153533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  assert(a->palette_code_bits_ == b->palette_code_bits_);
153633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (b != out) {
153733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (i = 0; i < literal_size; ++i) {
153833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      out->literal_[i] = a->literal_[i] + b->literal_[i];
153933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
154033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
154133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      out->distance_[i] = a->distance_[i] + b->distance_[i];
154233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
154333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (i = 0; i < NUM_LITERAL_CODES; ++i) {
154433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      out->red_[i] = a->red_[i] + b->red_[i];
154533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      out->blue_[i] = a->blue_[i] + b->blue_[i];
154633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      out->alpha_[i] = a->alpha_[i] + b->alpha_[i];
154733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
154833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  } else {
154933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (i = 0; i < literal_size; ++i) {
155033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      out->literal_[i] += a->literal_[i];
155133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
155233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
155333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      out->distance_[i] += a->distance_[i];
155433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
155533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    for (i = 0; i < NUM_LITERAL_CODES; ++i) {
155633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      out->red_[i] += a->red_[i];
155733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      out->blue_[i] += a->blue_[i];
155833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      out->alpha_[i] += a->alpha_[i];
155933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
156033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
15618b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
156233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
15638b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora//------------------------------------------------------------------------------
15648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
156533f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LProcessBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;
156633f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LProcessBlueAndRedFunc VP8LAddGreenToBlueAndRed;
156733f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LPredictorFunc VP8LPredictors[16];
156833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
156933f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LTransformColorFunc VP8LTransformColor;
157033f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LTransformColorFunc VP8LTransformColorInverse;
157133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
157233f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LConvertFunc VP8LConvertBGRAToRGB;
157333f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LConvertFunc VP8LConvertBGRAToRGBA;
157433f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LConvertFunc VP8LConvertBGRAToRGBA4444;
157533f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LConvertFunc VP8LConvertBGRAToRGB565;
157633f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LConvertFunc VP8LConvertBGRAToBGR;
157733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
157833f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LFastLog2SlowFunc VP8LFastLog2Slow;
157933f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LFastLog2SlowFunc VP8LFastSLog2Slow;
158033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
158133f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LCostFunc VP8LExtraCost;
158233f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LCostCombinedFunc VP8LExtraCostCombined;
158333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
158433f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LCostCountFunc VP8LHuffmanCostCount;
158533f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LCostCombinedCountFunc VP8LHuffmanCostCombinedCount;
158633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
158733f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LHistogramAddFunc VP8LHistogramAdd;
158833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
158933f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraextern void VP8LDspInitSSE2(void);
159033f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraextern void VP8LDspInitNEON(void);
159133f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraextern void VP8LDspInitMIPS32(void);
15928b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
15939e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zernstatic volatile VP8CPUInfo lossless_last_cpuinfo_used =
15949e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zern    (VP8CPUInfo)&lossless_last_cpuinfo_used;
15959e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zern
15968b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroravoid VP8LDspInit(void) {
15979e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zern  if (lossless_last_cpuinfo_used == VP8GetCPUInfo) return;
15989e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zern
159933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  memcpy(VP8LPredictors, kPredictorsC, sizeof(VP8LPredictors));
160033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
160133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C;
160233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C;
160333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
160433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LTransformColor = VP8LTransformColor_C;
160533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LTransformColorInverse = VP8LTransformColorInverse_C;
160633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
160733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C;
160833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C;
160933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C;
161033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C;
161133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C;
161233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
161333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LFastLog2Slow = FastLog2Slow;
161433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LFastSLog2Slow = FastSLog2Slow;
161533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
161633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LExtraCost = ExtraCost;
161733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LExtraCostCombined = ExtraCostCombined;
161833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
161933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LHuffmanCostCount = HuffmanCostCount;
162033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LHuffmanCostCombinedCount = HuffmanCostCombinedCount;
162133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
162233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  VP8LHistogramAdd = HistogramAdd;
16238b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
16248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  // If defined, use CPUInfo() to overwrite some pointers with faster versions.
16258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  if (VP8GetCPUInfo != NULL) {
16268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#if defined(WEBP_USE_SSE2)
16278b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    if (VP8GetCPUInfo(kSSE2)) {
16288b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora      VP8LDspInitSSE2();
16298b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
1630a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif
163133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#if defined(WEBP_USE_NEON)
163233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (VP8GetCPUInfo(kNEON)) {
163333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LDspInitNEON();
163433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
163533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#endif
163633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#if defined(WEBP_USE_MIPS32)
163733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (VP8GetCPUInfo(kMIPS32)) {
163833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      VP8LDspInitMIPS32();
163933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
164033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#endif
16418b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
16429e80ee991168a0a6c2a906dd2c17c5e17df4566eJames Zern  lossless_last_cpuinfo_used = VP8GetCPUInfo;
16438b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
16448b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
16458b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora//------------------------------------------------------------------------------
1646