15a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Copyright 2012 Google Inc. All Rights Reserved.
25a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//
35a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// This code is licensed under the same terms as WebM:
45a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//  Software License Agreement:  http://www.webmproject.org/license/software/
55a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
65a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// -----------------------------------------------------------------------------
75a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//
85a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Image transforms and color space conversion methods for lossless decoder.
95a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//
105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Authors: Vikas Arora (vikaas.arora@gmail.com)
115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//          Jyrki Alakuijala (jyrki@google.com)
125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//          Urvang Joshi (urvang@google.com)
135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#define ANDROID_WEBP_RGB
155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#if defined(__cplusplus) || defined(c_plusplus)
175a50414796e9a458925c7a13a15055d02406bf43Vikas Aroraextern "C" {
185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#endif
195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include <math.h>
215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include <stdlib.h>
225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "./lossless.h"
235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "../dec/vp8li.h"
245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "../dsp/yuv.h"
255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "../dsp/dsp.h"
265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#include "../enc/histogram.h"
275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#define MAX_DIFF_COST (1e30f)
295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// lookup table for small values of log2(int)
315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#define APPROX_LOG_MAX  4096
325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#define LOG_2_RECIPROCAL 1.44269504088896338700465094007086
335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#define LOG_LOOKUP_IDX_MAX 256
345a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic const float kLog2Table[LOG_LOOKUP_IDX_MAX] = {
355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  0.0000000000000000f, 0.0000000000000000f,
365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  1.0000000000000000f, 1.5849625007211560f,
375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  2.0000000000000000f, 2.3219280948873621f,
385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  2.5849625007211560f, 2.8073549220576041f,
395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  3.0000000000000000f, 3.1699250014423121f,
405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  3.3219280948873621f, 3.4594316186372973f,
415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  3.5849625007211560f, 3.7004397181410921f,
425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  3.8073549220576041f, 3.9068905956085187f,
435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  4.0000000000000000f, 4.0874628412503390f,
445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  4.1699250014423121f, 4.2479275134435852f,
455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  4.3219280948873626f, 4.3923174227787606f,
465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  4.4594316186372973f, 4.5235619560570130f,
475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  4.5849625007211560f, 4.6438561897747243f,
485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  4.7004397181410917f, 4.7548875021634682f,
495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  4.8073549220576037f, 4.8579809951275718f,
505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  4.9068905956085187f, 4.9541963103868749f,
515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.0000000000000000f, 5.0443941193584533f,
525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.0874628412503390f, 5.1292830169449663f,
535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.1699250014423121f, 5.2094533656289501f,
545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.2479275134435852f, 5.2854022188622487f,
555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.3219280948873626f, 5.3575520046180837f,
565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.3923174227787606f, 5.4262647547020979f,
575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.4594316186372973f, 5.4918530963296747f,
585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.5235619560570130f, 5.5545888516776376f,
595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.5849625007211560f, 5.6147098441152083f,
605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.6438561897747243f, 5.6724253419714951f,
615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.7004397181410917f, 5.7279204545631987f,
625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.7548875021634682f, 5.7813597135246599f,
635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.8073549220576037f, 5.8328900141647412f,
645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.8579809951275718f, 5.8826430493618415f,
655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.9068905956085187f, 5.9307373375628866f,
665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  5.9541963103868749f, 5.9772799234999167f,
675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.0000000000000000f, 6.0223678130284543f,
685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.0443941193584533f, 6.0660891904577720f,
695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.0874628412503390f, 6.1085244567781691f,
705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.1292830169449663f, 6.1497471195046822f,
715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.1699250014423121f, 6.1898245588800175f,
725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.2094533656289501f, 6.2288186904958804f,
735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.2479275134435852f, 6.2667865406949010f,
745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.2854022188622487f, 6.3037807481771030f,
755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.3219280948873626f, 6.3398500028846243f,
765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.3575520046180837f, 6.3750394313469245f,
775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.3923174227787606f, 6.4093909361377017f,
785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.4262647547020979f, 6.4429434958487279f,
795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.4594316186372973f, 6.4757334309663976f,
805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.4918530963296747f, 6.5077946401986963f,
815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.5235619560570130f, 6.5391588111080309f,
825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.5545888516776376f, 6.5698556083309478f,
835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.5849625007211560f, 6.5999128421871278f,
845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.6147098441152083f, 6.6293566200796094f,
855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.6438561897747243f, 6.6582114827517946f,
865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.6724253419714951f, 6.6865005271832185f,
875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.7004397181410917f, 6.7142455176661224f,
885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.7279204545631987f, 6.7414669864011464f,
895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.7548875021634682f, 6.7681843247769259f,
905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.7813597135246599f, 6.7944158663501061f,
915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.8073549220576037f, 6.8201789624151878f,
925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.8328900141647412f, 6.8454900509443747f,
935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.8579809951275718f, 6.8703647195834047f,
945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.8826430493618415f, 6.8948177633079437f,
955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.9068905956085187f, 6.9188632372745946f,
965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.9307373375628866f, 6.9425145053392398f,
975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.9541963103868749f, 6.9657842846620869f,
985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  6.9772799234999167f, 6.9886846867721654f,
995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.0000000000000000f, 7.0112272554232539f,
1005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.0223678130284543f, 7.0334230015374501f,
1015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.0443941193584533f, 7.0552824355011898f,
1025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.0660891904577720f, 7.0768155970508308f,
1035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.0874628412503390f, 7.0980320829605263f,
1045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.1085244567781691f, 7.1189410727235076f,
1055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.1292830169449663f, 7.1395513523987936f,
1065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.1497471195046822f, 7.1598713367783890f,
1075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.1699250014423121f, 7.1799090900149344f,
1085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.1898245588800175f, 7.1996723448363644f,
1095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.2094533656289501f, 7.2191685204621611f,
1105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.2288186904958804f, 7.2384047393250785f,
1115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.2479275134435852f, 7.2573878426926521f,
1125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.2667865406949010f, 7.2761244052742375f,
1135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.2854022188622487f, 7.2946207488916270f,
1145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.3037807481771030f, 7.3128829552843557f,
1155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.3219280948873626f, 7.3309168781146167f,
1165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.3398500028846243f, 7.3487281542310771f,
1175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.3575520046180837f, 7.3663222142458160f,
1185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.3750394313469245f, 7.3837042924740519f,
1195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.3923174227787606f, 7.4008794362821843f,
1205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.4093909361377017f, 7.4178525148858982f,
1215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.4262647547020979f, 7.4346282276367245f,
1225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.4429434958487279f, 7.4512111118323289f,
1235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.4594316186372973f, 7.4676055500829976f,
1245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.4757334309663976f, 7.4838157772642563f,
1255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.4918530963296747f, 7.4998458870832056f,
1265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.5077946401986963f, 7.5156998382840427f,
1275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.5235619560570130f, 7.5313814605163118f,
1285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.5391588111080309f, 7.5468944598876364f,
1295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.5545888516776376f, 7.5622424242210728f,
1305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.5698556083309478f, 7.5774288280357486f,
1315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.5849625007211560f, 7.5924570372680806f,
1325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.5999128421871278f, 7.6073303137496104f,
1335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.6147098441152083f, 7.6220518194563764f,
1345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.6293566200796094f, 7.6366246205436487f,
1355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.6438561897747243f, 7.6510516911789281f,
1365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.6582114827517946f, 7.6653359171851764f,
1375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.6724253419714951f, 7.6794800995054464f,
1385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.6865005271832185f, 7.6934869574993252f,
1395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.7004397181410917f, 7.7073591320808825f,
1405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.7142455176661224f, 7.7210991887071855f,
1415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.7279204545631987f, 7.7347096202258383f,
1425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.7414669864011464f, 7.7481928495894605f,
1435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.7548875021634682f, 7.7615512324444795f,
1445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.7681843247769259f, 7.7747870596011736f,
1455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.7813597135246599f, 7.7879025593914317f,
1465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.7944158663501061f, 7.8008998999203047f,
1475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.8073549220576037f, 7.8137811912170374f,
1485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.8201789624151878f, 7.8265484872909150f,
1495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.8328900141647412f, 7.8392037880969436f,
1505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.8454900509443747f, 7.8517490414160571f,
1515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.8579809951275718f, 7.8641861446542797f,
1525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.8703647195834047f, 7.8765169465649993f,
1535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.8826430493618415f, 7.8887432488982591f,
1545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.8948177633079437f, 7.9008668079807486f,
1555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.9068905956085187f, 7.9128893362299619f,
1565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.9188632372745946f, 7.9248125036057812f,
1575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.9307373375628866f, 7.9366379390025709f,
1585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.9425145053392398f, 7.9483672315846778f,
1595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.9541963103868749f, 7.9600019320680805f,
1605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.9657842846620869f, 7.9715435539507719f,
1615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.9772799234999167f, 7.9829935746943103f,
1625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  7.9886846867721654f, 7.9943534368588577f
1635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora};
1645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1655a50414796e9a458925c7a13a15055d02406bf43Vikas Arorafloat VP8LFastLog2(int v) {
1665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (v < LOG_LOOKUP_IDX_MAX) {
1675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    return kLog2Table[v];
1685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } else if (v < APPROX_LOG_MAX) {
1695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int log_cnt = 0;
1705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    while (v >= LOG_LOOKUP_IDX_MAX) {
1715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ++log_cnt;
1725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      v = v >> 1;
1735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
1745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    return kLog2Table[v] + (float)log_cnt;
1755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } else {
1765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    return (float)(LOG_2_RECIPROCAL * log((double)v));
1775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
1785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
1795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
1815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Image transforms.
1825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// In-place sum of each component with mod 256.
1845a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE void AddPixelsEq(uint32_t* a, uint32_t b) {
1855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t alpha_and_green = (*a & 0xff00ff00u) + (b & 0xff00ff00u);
1865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t red_and_blue = (*a & 0x00ff00ffu) + (b & 0x00ff00ffu);
1875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  *a = (alpha_and_green & 0xff00ff00u) | (red_and_blue & 0x00ff00ffu);
1885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
1895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1905a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) {
1915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return (((a0 ^ a1) & 0xfefefefeL) >> 1) + (a0 & a1);
1925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
1935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1945a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) {
1955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return Average2(Average2(a0, a2), a1);
1965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
1975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
1985a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1,
1995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                     uint32_t a2, uint32_t a3) {
2005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return Average2(Average2(a0, a1), Average2(a2, a3));
2015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
2035a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE uint32_t Clip255(uint32_t a) {
2045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (a < 256) {
2055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    return a;
2065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
2075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  // return 0, when a is a negative integer.
2085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  // return 255, when a is positive.
2095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return ~a >> 24;
2105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
2125a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE int AddSubtractComponentFull(int a, int b, int c) {
2135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return Clip255(a + b - c);
2145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
2165a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1,
2175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                                   uint32_t c2) {
2185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24);
2195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int r = AddSubtractComponentFull((c0 >> 16) & 0xff,
2205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                         (c1 >> 16) & 0xff,
2215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                         (c2 >> 16) & 0xff);
2225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int g = AddSubtractComponentFull((c0 >> 8) & 0xff,
2235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                         (c1 >> 8) & 0xff,
2245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                         (c2 >> 8) & 0xff);
2255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff);
2265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return (a << 24) | (r << 16) | (g << 8) | b;
2275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
2295a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE int AddSubtractComponentHalf(int a, int b) {
2305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return Clip255(a + (a - b) / 2);
2315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
2335a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
2345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                                   uint32_t c2) {
2355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t ave = Average2(c0, c1);
2365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24);
2375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff);
2385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff);
2395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff);
2405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return (a << 24) | (r << 16) | (g << 8) | b;
2415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
2435a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE int Sub3(int a, int b, int c) {
2445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int pa = b - c;
2455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int pb = a - c;
2465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return abs(pa) - abs(pb);
2475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
2495a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) {
2505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int pa_minus_pb =
2515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      Sub3((a >> 24)       , (b >> 24)       , (c >> 24)       ) +
2525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) +
2535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      Sub3((a >>  8) & 0xff, (b >>  8) & 0xff, (c >>  8) & 0xff) +
2545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      Sub3((a      ) & 0xff, (b      ) & 0xff, (c      ) & 0xff);
2555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
2565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return (pa_minus_pb <= 0) ? a : b;
2575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
2595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
2605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Predictors
2615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
2625a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor0(uint32_t left, const uint32_t* const top) {
2635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  (void)top;
2645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  (void)left;
2655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return ARGB_BLACK;
2665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2675a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor1(uint32_t left, const uint32_t* const top) {
2685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  (void)top;
2695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return left;
2705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2715a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor2(uint32_t left, const uint32_t* const top) {
2725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  (void)left;
2735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return top[0];
2745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2755a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor3(uint32_t left, const uint32_t* const top) {
2765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  (void)left;
2775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return top[1];
2785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2795a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor4(uint32_t left, const uint32_t* const top) {
2805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  (void)left;
2815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return top[-1];
2825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2835a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor5(uint32_t left, const uint32_t* const top) {
2845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t pred = Average3(left, top[0], top[1]);
2855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return pred;
2865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2875a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor6(uint32_t left, const uint32_t* const top) {
2885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t pred = Average2(left, top[-1]);
2895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return pred;
2905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2915a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor7(uint32_t left, const uint32_t* const top) {
2925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t pred = Average2(left, top[0]);
2935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return pred;
2945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
2955a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor8(uint32_t left, const uint32_t* const top) {
2965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t pred = Average2(top[-1], top[0]);
2975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  (void)left;
2985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return pred;
2995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
3005a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor9(uint32_t left, const uint32_t* const top) {
3015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t pred = Average2(top[0], top[1]);
3025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  (void)left;
3035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return pred;
3045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
3055a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor10(uint32_t left, const uint32_t* const top) {
3065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t pred = Average4(left, top[-1], top[0], top[1]);
3075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return pred;
3085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
3095a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor11(uint32_t left, const uint32_t* const top) {
3105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t pred = Select(top[0], left, top[-1]);
3115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return pred;
3125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
3135a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor12(uint32_t left, const uint32_t* const top) {
3145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]);
3155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return pred;
3165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
3175a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic uint32_t Predictor13(uint32_t left, const uint32_t* const top) {
3185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]);
3195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return pred;
3205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
3215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
3225a50414796e9a458925c7a13a15055d02406bf43Vikas Aroratypedef uint32_t (*PredictorFunc)(uint32_t left, const uint32_t* const top);
3235a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic const PredictorFunc kPredictors[16] = {
3245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  Predictor0, Predictor1, Predictor2, Predictor3,
3255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  Predictor4, Predictor5, Predictor6, Predictor7,
3265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  Predictor8, Predictor9, Predictor10, Predictor11,
3275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  Predictor12, Predictor13,
3285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  Predictor0, Predictor0    // <- padding security sentinels
3295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora};
3305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
3315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// TODO(vikasa): Replace 256 etc with defines.
3325a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic float PredictionCostSpatial(const int* counts,
3335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                   int weight_0, double exp_val) {
3345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int significant_symbols = 16;
3355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const double exp_decay_factor = 0.6;
3365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  double bits = weight_0 * counts[0];
3375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int i;
3385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (i = 1; i < significant_symbols; ++i) {
3395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    bits += exp_val * (counts[i] + counts[256 - i]);
3405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    exp_val *= exp_decay_factor;
3415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
3425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return (float)(-0.1 * bits);
3435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
3445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
3455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Compute the Shanon's entropy: Sum(p*log2(p))
3465a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic float ShannonEntropy(const int* const array, int n) {
3475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int i;
3485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  float retval = 0.f;
3495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int sum = 0;
3505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (i = 0; i < n; ++i) {
3515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (array[i] != 0) {
3525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      sum += array[i];
3535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      retval -= VP8LFastSLog2(array[i]);
3545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
3555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
3565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  retval += VP8LFastSLog2(sum);
3575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return retval;
3585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
3595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
3605a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic float PredictionCostSpatialHistogram(int accumulated[4][256],
3615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                            int tile[4][256]) {
3625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int i;
3635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int k;
3645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int combo[256];
3655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  double retval = 0;
3665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (i = 0; i < 4; ++i) {
3675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const double exp_val = 0.94;
3685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    retval += PredictionCostSpatial(&tile[i][0], 1, exp_val);
3695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    retval += ShannonEntropy(&tile[i][0], 256);
3705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (k = 0; k < 256; ++k) {
3715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      combo[k] = accumulated[i][k] + tile[i][k];
3725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
3735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    retval += ShannonEntropy(&combo[0], 256);
3745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
3755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return (float)retval;
3765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
3775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
3785a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int GetBestPredictorForTile(int width, int height,
3795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                   int tile_x, int tile_y, int bits,
3805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                   int accumulated[4][256],
3815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                   const uint32_t* const argb_scratch) {
3825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int kNumPredModes = 14;
3835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int col_start = tile_x << bits;
3845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int row_start = tile_y << bits;
3855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int tile_size = 1 << bits;
3865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int ymax = (tile_size <= height - row_start) ?
3875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      tile_size : height - row_start;
3885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int xmax = (tile_size <= width - col_start) ?
3895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      tile_size : width - col_start;
3905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int histo[4][256];
3915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  float best_diff = MAX_DIFF_COST;
3925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int best_mode = 0;
3935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
3945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int mode;
3955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (mode = 0; mode < kNumPredModes; ++mode) {
3965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t* current_row = argb_scratch;
3975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const PredictorFunc pred_func = kPredictors[mode];
3985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    float cur_diff;
3995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int y;
4005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    memset(&histo[0][0], 0, sizeof(histo));
4015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (y = 0; y < ymax; ++y) {
4025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int x;
4035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int row = row_start + y;
4045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const uint32_t* const upper_row = current_row;
4055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      current_row = upper_row + width;
4065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      for (x = 0; x < xmax; ++x) {
4075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        const int col = col_start + x;
4085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        uint32_t predict;
4095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        uint32_t predict_diff;
4105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        if (row == 0) {
4115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          predict = (col == 0) ? ARGB_BLACK : current_row[col - 1];  // Left.
4125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        } else if (col == 0) {
4135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          predict = upper_row[col];  // Top.
4145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        } else {
4155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          predict = pred_func(current_row[col - 1], upper_row + col);
4165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
4175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        predict_diff = VP8LSubPixels(current_row[col], predict);
4185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ++histo[0][predict_diff >> 24];
4195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ++histo[1][((predict_diff >> 16) & 0xff)];
4205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ++histo[2][((predict_diff >> 8) & 0xff)];
4215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ++histo[3][(predict_diff & 0xff)];
4225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
4235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
4245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    cur_diff = PredictionCostSpatialHistogram(accumulated, histo);
4255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (cur_diff < best_diff) {
4265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      best_diff = cur_diff;
4275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      best_mode = mode;
4285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
4295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
4305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
4315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return best_mode;
4325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
4335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
4345a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void CopyTileWithPrediction(int width, int height,
4355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                   int tile_x, int tile_y, int bits, int mode,
4365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                   const uint32_t* const argb_scratch,
4375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                   uint32_t* const argb) {
4385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int col_start = tile_x << bits;
4395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int row_start = tile_y << bits;
4405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int tile_size = 1 << bits;
4415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int ymax = (tile_size <= height - row_start) ?
4425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      tile_size : height - row_start;
4435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int xmax = (tile_size <= width - col_start) ?
4445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      tile_size : width - col_start;
4455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const PredictorFunc pred_func = kPredictors[mode];
4465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t* current_row = argb_scratch;
4475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
4485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int y;
4495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (y = 0; y < ymax; ++y) {
4505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int x;
4515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int row = row_start + y;
4525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t* const upper_row = current_row;
4535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    current_row = upper_row + width;
4545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (x = 0; x < xmax; ++x) {
4555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int col = col_start + x;
4565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int pix = row * width + col;
4575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      uint32_t predict;
4585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (row == 0) {
4595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        predict = (col == 0) ? ARGB_BLACK : current_row[col - 1];  // Left.
4605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      } else if (col == 0) {
4615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        predict = upper_row[col];  // Top.
4625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      } else {
4635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        predict = pred_func(current_row[col - 1], upper_row + col);
4645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
4655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      argb[pix] = VP8LSubPixels(current_row[col], predict);
4665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
4675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
4685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
4695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
4705a50414796e9a458925c7a13a15055d02406bf43Vikas Aroravoid VP8LResidualImage(int width, int height, int bits,
4715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                       uint32_t* const argb, uint32_t* const argb_scratch,
4725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                       uint32_t* const image) {
4735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int max_tile_size = 1 << bits;
4745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int tiles_per_row = VP8LSubSampleSize(width, bits);
4755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int tiles_per_col = VP8LSubSampleSize(height, bits);
4765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  uint32_t* const upper_row = argb_scratch;
4775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  uint32_t* const current_tile_rows = argb_scratch + width;
4785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int tile_y;
4795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int histo[4][256];
4805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  memset(histo, 0, sizeof(histo));
4815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (tile_y = 0; tile_y < tiles_per_col; ++tile_y) {
4825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int tile_y_offset = tile_y * max_tile_size;
4835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int this_tile_height =
4845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        (tile_y < tiles_per_col - 1) ? max_tile_size : height - tile_y_offset;
4855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int tile_x;
4865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (tile_y > 0) {
4875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      memcpy(upper_row, current_tile_rows + (max_tile_size - 1) * width,
4885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora             width * sizeof(*upper_row));
4895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
4905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    memcpy(current_tile_rows, &argb[tile_y_offset * width],
4915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora           this_tile_height * width * sizeof(*current_tile_rows));
4925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (tile_x = 0; tile_x < tiles_per_row; ++tile_x) {
4935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int pred;
4945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int y;
4955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int tile_x_offset = tile_x * max_tile_size;
4965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int all_x_max = tile_x_offset + max_tile_size;
4975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (all_x_max > width) {
4985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        all_x_max = width;
4995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
5005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      pred = GetBestPredictorForTile(width, height, tile_x, tile_y, bits, histo,
5015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                     argb_scratch);
5025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      image[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
5035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred,
5045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                             argb_scratch, argb);
5055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      for (y = 0; y < max_tile_size; ++y) {
5065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        int ix;
5075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        int all_x;
5085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        int all_y = tile_y_offset + y;
5095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        if (all_y >= height) {
5105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          break;
5115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
5125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ix = all_y * width + tile_x_offset;
5135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
5145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          const uint32_t a = argb[ix];
5155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          ++histo[0][a >> 24];
5165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          ++histo[1][((a >> 16) & 0xff)];
5175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          ++histo[2][((a >> 8) & 0xff)];
5185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          ++histo[3][(a & 0xff)];
5195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
5205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
5215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
5225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
5235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
5245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Inverse prediction.
5265a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void PredictorInverseTransform(const VP8LTransform* const transform,
5275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                      int y_start, int y_end, uint32_t* data) {
5285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int width = transform->xsize_;
5295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (y_start == 0) {  // First Row follows the L (mode=1) mode.
5305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int x;
5315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t pred0 = Predictor0(data[-1], NULL);
5325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    AddPixelsEq(data, pred0);
5335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (x = 1; x < width; ++x) {
5345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const uint32_t pred1 = Predictor1(data[x - 1], NULL);
5355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      AddPixelsEq(data + x, pred1);
5365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
5375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    data += width;
5385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    ++y_start;
5395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
5405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  {
5425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int y = y_start;
5435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int mask = (1 << transform->bits_) - 1;
5445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
5455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t* pred_mode_base =
5465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        transform->data_ + (y >> transform->bits_) * tiles_per_row;
5475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    while (y < y_end) {
5495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int x;
5505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const uint32_t pred2 = Predictor2(data[-1], data - width);
5515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const uint32_t* pred_mode_src = pred_mode_base;
5525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      PredictorFunc pred_func;
5535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      // First pixel follows the T (mode=2) mode.
5555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      AddPixelsEq(data, pred2);
5565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      // .. the rest:
5585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      pred_func = kPredictors[((*pred_mode_src++) >> 8) & 0xf];
5595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      for (x = 1; x < width; ++x) {
5605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        uint32_t pred;
5615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        if ((x & mask) == 0) {    // start of tile. Read predictor function.
5625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          pred_func = kPredictors[((*pred_mode_src++) >> 8) & 0xf];
5635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
5645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        pred = pred_func(data[x - 1], data + x - width);
5655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        AddPixelsEq(data + x, pred);
5665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
5675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      data += width;
5685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ++y;
5695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if ((y & mask) == 0) {   // Use the same mask, since tiles are squares.
5705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        pred_mode_base += tiles_per_row;
5715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
5725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
5735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
5745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
5755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5765a50414796e9a458925c7a13a15055d02406bf43Vikas Aroravoid VP8LSubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixs) {
5775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int i;
5785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (i = 0; i < num_pixs; ++i) {
5795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t argb = argb_data[i];
5805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t green = (argb >> 8) & 0xff;
5815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff;
5825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t new_b = ((argb & 0xff) - green) & 0xff;
5835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    argb_data[i] = (argb & 0xff00ff00) | (new_r << 16) | new_b;
5845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
5855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
5865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
5875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Add green to blue and red channels (i.e. perform the inverse transform of
5885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// 'subtract green').
5895a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void AddGreenToBlueAndRed(const VP8LTransform* const transform,
5905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                 int y_start, int y_end, uint32_t* data) {
5915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int width = transform->xsize_;
5925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t* const data_end = data + (y_end - y_start) * width;
5935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (data < data_end) {
5945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t argb = *data;
5955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    // "* 0001001u" is equivalent to "(green << 16) + green)"
5965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t green = ((argb >> 8) & 0xff);
5975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    uint32_t red_blue = (argb & 0x00ff00ffu);
5985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    red_blue += (green << 16) | green;
5995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    red_blue &= 0x00ff00ffu;
6005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *data++ = (argb & 0xff00ff00u) | red_blue;
6015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
6025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
6035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6045a50414796e9a458925c7a13a15055d02406bf43Vikas Aroratypedef struct {
6055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  // Note: the members are uint8_t, so that any negative values are
6065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  // automatically converted to "mod 256" values.
6075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  uint8_t green_to_red_;
6085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  uint8_t green_to_blue_;
6095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  uint8_t red_to_blue_;
6105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora} Multipliers;
6115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6125a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE void MultipliersClear(Multipliers* m) {
6135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  m->green_to_red_ = 0;
6145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  m->green_to_blue_ = 0;
6155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  m->red_to_blue_ = 0;
6165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
6175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6185a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred,
6195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                                int8_t color) {
6205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return (uint32_t)((int)(color_pred) * color) >> 5;
6215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
6225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6235a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE void ColorCodeToMultipliers(uint32_t color_code,
6245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                               Multipliers* const m) {
6255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  m->green_to_red_  = (color_code >>  0) & 0xff;
6265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  m->green_to_blue_ = (color_code >>  8) & 0xff;
6275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  m->red_to_blue_   = (color_code >> 16) & 0xff;
6285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
6295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6305a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE uint32_t MultipliersToColorCode(Multipliers* const m) {
6315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return 0xff000000u |
6325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora         ((uint32_t)(m->red_to_blue_) << 16) |
6335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora         ((uint32_t)(m->green_to_blue_) << 8) |
6345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora         m->green_to_red_;
6355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
6365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6375a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE uint32_t TransformColor(const Multipliers* const m,
6385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                           uint32_t argb, int inverse) {
6395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t green = argb >> 8;
6405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t red = argb >> 16;
6415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  uint32_t new_red = red;
6425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  uint32_t new_blue = argb;
6435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (inverse) {
6455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    new_red += ColorTransformDelta(m->green_to_red_, green);
6465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    new_red &= 0xff;
6475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    new_blue += ColorTransformDelta(m->green_to_blue_, green);
6485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    new_blue += ColorTransformDelta(m->red_to_blue_, new_red);
6495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    new_blue &= 0xff;
6505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } else {
6515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    new_red -= ColorTransformDelta(m->green_to_red_, green);
6525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    new_red &= 0xff;
6535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    new_blue -= ColorTransformDelta(m->green_to_blue_, green);
6545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    new_blue -= ColorTransformDelta(m->red_to_blue_, red);
6555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    new_blue &= 0xff;
6565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
6575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);
6585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
6595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6605a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic WEBP_INLINE int SkipRepeatedPixels(const uint32_t* const argb,
6615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                          int ix, int xsize) {
6625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t v = argb[ix];
6635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (ix >= xsize + 3) {
6645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (v == argb[ix - xsize] &&
6655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        argb[ix - 1] == argb[ix - xsize - 1] &&
6665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        argb[ix - 2] == argb[ix - xsize - 2] &&
6675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        argb[ix - 3] == argb[ix - xsize - 3]) {
6685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      return 1;
6695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
6705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    return v == argb[ix - 3] && v == argb[ix - 2] && v == argb[ix - 1];
6715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } else if (ix >= 3) {
6725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    return v == argb[ix - 3] && v == argb[ix - 2] && v == argb[ix - 1];
6735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
6745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return 0;
6755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
6765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6775a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic float PredictionCostCrossColor(const int accumulated[256],
6785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                      const int counts[256]) {
6795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  // Favor low entropy, locally and globally.
6805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int i;
6815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int combo[256];
6825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (i = 0; i < 256; ++i) {
6835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    combo[i] = accumulated[i] + counts[i];
6845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
6855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return ShannonEntropy(combo, 256) +
6865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora         ShannonEntropy(counts, 256) +
6875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora         PredictionCostSpatial(counts, 3, 2.4);  // Favor small absolute values.
6885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
6895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
6905a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic Multipliers GetBestColorTransformForTile(
6915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int tile_x, int tile_y, int bits,
6925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    Multipliers prevX,
6935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    Multipliers prevY,
6945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int step, int xsize, int ysize,
6955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int* accumulated_red_histo,
6965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int* accumulated_blue_histo,
6975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t* const argb) {
6985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  float best_diff = MAX_DIFF_COST;
6995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  float cur_diff;
7005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int halfstep = step / 2;
7015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int max_tile_size = 1 << bits;
7025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int tile_y_offset = tile_y * max_tile_size;
7035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int tile_x_offset = tile_x * max_tile_size;
7045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int green_to_red;
7055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int green_to_blue;
7065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int red_to_blue;
7075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int all_x_max = tile_x_offset + max_tile_size;
7085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int all_y_max = tile_y_offset + max_tile_size;
7095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  Multipliers best_tx;
7105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  MultipliersClear(&best_tx);
7115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (all_x_max > xsize) {
7125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    all_x_max = xsize;
7135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
7145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (all_y_max > ysize) {
7155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    all_y_max = ysize;
7165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
7175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (green_to_red = -64; green_to_red <= 64; green_to_red += halfstep) {
7185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int histo[256] = { 0 };
7195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int all_y;
7205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    Multipliers tx;
7215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    MultipliersClear(&tx);
7225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    tx.green_to_red_ = green_to_red & 0xff;
7235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
7245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) {
7255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      uint32_t predict;
7265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int ix = all_y * xsize + tile_x_offset;
7275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int all_x;
7285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
7295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        if (SkipRepeatedPixels(argb, ix, xsize)) {
7305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          continue;
7315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
7325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        predict = TransformColor(&tx, argb[ix], 0);
7335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ++histo[(predict >> 16) & 0xff];  // red.
7345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
7355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
7365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    cur_diff = PredictionCostCrossColor(&accumulated_red_histo[0], &histo[0]);
7375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (tx.green_to_red_ == prevX.green_to_red_) {
7385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      cur_diff -= 3;  // favor keeping the areas locally similar
7395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
7405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (tx.green_to_red_ == prevY.green_to_red_) {
7415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      cur_diff -= 3;  // favor keeping the areas locally similar
7425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
7435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (tx.green_to_red_ == 0) {
7445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      cur_diff -= 3;
7455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
7465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if (cur_diff < best_diff) {
7475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      best_diff = cur_diff;
7485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      best_tx = tx;
7495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
7505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
7515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  best_diff = MAX_DIFF_COST;
7525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  green_to_red = best_tx.green_to_red_;
7535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (green_to_blue = -32; green_to_blue <= 32; green_to_blue += step) {
7545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (red_to_blue = -32; red_to_blue <= 32; red_to_blue += step) {
7555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int all_y;
7565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int histo[256] = { 0 };
7575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      Multipliers tx;
7585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      tx.green_to_red_ = green_to_red;
7595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      tx.green_to_blue_ = green_to_blue;
7605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      tx.red_to_blue_ = red_to_blue;
7615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      for (all_y = tile_y_offset; all_y < all_y_max; ++all_y) {
7625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        uint32_t predict;
7635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        int all_x;
7645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        int ix = all_y * xsize + tile_x_offset;
7655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
7665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          if (SkipRepeatedPixels(argb, ix, xsize)) {
7675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora            continue;
7685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          }
7695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          predict = TransformColor(&tx, argb[ix], 0);
7705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          ++histo[predict & 0xff];  // blue.
7715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
7725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
7735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      cur_diff =
7745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        PredictionCostCrossColor(&accumulated_blue_histo[0], &histo[0]);
7755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (tx.green_to_blue_ == prevX.green_to_blue_) {
7765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        cur_diff -= 3;  // favor keeping the areas locally similar
7775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
7785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (tx.green_to_blue_ == prevY.green_to_blue_) {
7795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        cur_diff -= 3;  // favor keeping the areas locally similar
7805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
7815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (tx.red_to_blue_ == prevX.red_to_blue_) {
7825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        cur_diff -= 3;  // favor keeping the areas locally similar
7835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
7845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (tx.red_to_blue_ == prevY.red_to_blue_) {
7855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        cur_diff -= 3;  // favor keeping the areas locally similar
7865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
7875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (tx.green_to_blue_ == 0) {
7885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        cur_diff -= 3;
7895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
7905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (tx.red_to_blue_ == 0) {
7915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        cur_diff -= 3;
7925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
7935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (cur_diff < best_diff) {
7945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        best_diff = cur_diff;
7955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        best_tx = tx;
7965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
7975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
7985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
7995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return best_tx;
8005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
8015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
8025a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void CopyTileWithColorTransform(int xsize, int ysize,
8035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                       int tile_x, int tile_y, int bits,
8045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                       Multipliers color_transform,
8055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                       uint32_t* const argb) {
8065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int y;
8075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int xscan = 1 << bits;
8085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int yscan = 1 << bits;
8095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  tile_x <<= bits;
8105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  tile_y <<= bits;
8115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (xscan > xsize - tile_x) {
8125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    xscan = xsize - tile_x;
8135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
8145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (yscan > ysize - tile_y) {
8155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    yscan = ysize - tile_y;
8165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
8175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  yscan += tile_y;
8185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (y = tile_y; y < yscan; ++y) {
8195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int ix = y * xsize + tile_x;
8205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int end_ix = ix + xscan;
8215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (; ix < end_ix; ++ix) {
8225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      argb[ix] = TransformColor(&color_transform, argb[ix], 0);
8235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
8245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
8255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
8265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
8275a50414796e9a458925c7a13a15055d02406bf43Vikas Aroravoid VP8LColorSpaceTransform(int width, int height, int bits, int step,
8285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                             uint32_t* const argb, uint32_t* image) {
8295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int max_tile_size = 1 << bits;
8305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int tile_xsize = VP8LSubSampleSize(width, bits);
8315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int tile_ysize = VP8LSubSampleSize(height, bits);
8325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int accumulated_red_histo[256] = { 0 };
8335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int accumulated_blue_histo[256] = { 0 };
8345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int tile_y;
8355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int tile_x;
8365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  Multipliers prevX;
8375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  Multipliers prevY;
8385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  MultipliersClear(&prevY);
8395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  MultipliersClear(&prevX);
8405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  for (tile_y = 0; tile_y < tile_ysize; ++tile_y) {
8415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (tile_x = 0; tile_x < tile_xsize; ++tile_x) {
8425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      Multipliers color_transform;
8435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int all_x_max;
8445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int y;
8455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int tile_y_offset = tile_y * max_tile_size;
8465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      const int tile_x_offset = tile_x * max_tile_size;
8475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (tile_y != 0) {
8485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ColorCodeToMultipliers(image[tile_y * tile_xsize + tile_x - 1], &prevX);
8495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ColorCodeToMultipliers(image[(tile_y - 1) * tile_xsize + tile_x],
8505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                               &prevY);
8515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      } else if (tile_x != 0) {
8525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ColorCodeToMultipliers(image[tile_y * tile_xsize + tile_x - 1], &prevX);
8535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
8545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      color_transform =
8555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          GetBestColorTransformForTile(tile_x, tile_y, bits,
8565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                       prevX, prevY,
8575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                       step, width, height,
8585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                       &accumulated_red_histo[0],
8595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                       &accumulated_blue_histo[0],
8605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                       argb);
8615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      image[tile_y * tile_xsize + tile_x] =
8625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          MultipliersToColorCode(&color_transform);
8635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      CopyTileWithColorTransform(width, height, tile_x, tile_y, bits,
8645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                 color_transform, argb);
8655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
8665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      // Gather accumulated histogram data.
8675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      all_x_max = tile_x_offset + max_tile_size;
8685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (all_x_max > width) {
8695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        all_x_max = width;
8705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
8715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      for (y = 0; y < max_tile_size; ++y) {
8725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        int ix;
8735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        int all_x;
8745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        int all_y = tile_y_offset + y;
8755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        if (all_y >= height) {
8765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          break;
8775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
8785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ix = all_y * width + tile_x_offset;
8795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        for (all_x = tile_x_offset; all_x < all_x_max; ++all_x, ++ix) {
8805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          if (ix >= 2 &&
8815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora              argb[ix] == argb[ix - 2] &&
8825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora              argb[ix] == argb[ix - 1]) {
8835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora            continue;  // repeated pixels are handled by backward references
8845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          }
8855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          if (ix >= width + 2 &&
8865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora              argb[ix - 2] == argb[ix - width - 2] &&
8875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora              argb[ix - 1] == argb[ix - width - 1] &&
8885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora              argb[ix] == argb[ix - width]) {
8895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora            continue;  // repeated pixels are handled by backward references
8905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          }
8915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          ++accumulated_red_histo[(argb[ix] >> 16) & 0xff];
8925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora          ++accumulated_blue_histo[argb[ix] & 0xff];
8935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        }
8945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
8955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
8965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
8975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
8985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
8995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Color space inverse transform.
9005a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ColorSpaceInverseTransform(const VP8LTransform* const transform,
9015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                       int y_start, int y_end, uint32_t* data) {
9025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int width = transform->xsize_;
9035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int mask = (1 << transform->bits_) - 1;
9045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int tiles_per_row = VP8LSubSampleSize(width, transform->bits_);
9055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int y = y_start;
9065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t* pred_row =
9075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      transform->data_ + (y >> transform->bits_) * tiles_per_row;
9085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
9095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (y < y_end) {
9105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t* pred = pred_row;
9115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    Multipliers m = { 0, 0, 0 };
9125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int x;
9135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
9145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (x = 0; x < width; ++x) {
9155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if ((x & mask) == 0) ColorCodeToMultipliers(*pred++, &m);
9165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      data[x] = TransformColor(&m, data[x], 1);
9175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
9185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    data += width;
9195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    ++y;
9205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    if ((y & mask) == 0) pred_row += tiles_per_row;;
9215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
9225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
9235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
9245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Separate out pixels packed together using pixel-bundling.
9255a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ColorIndexInverseTransform(
9265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const VP8LTransform* const transform,
9275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    int y_start, int y_end, const uint32_t* src, uint32_t* dst) {
9285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  int y;
9295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int bits_per_pixel = 8 >> transform->bits_;
9305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const int width = transform->xsize_;
9315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t* const color_map = transform->data_;
9325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (bits_per_pixel < 8) {
9335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int pixels_per_byte = 1 << transform->bits_;
9345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const int count_mask = pixels_per_byte - 1;
9355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t bit_mask = (1 << bits_per_pixel) - 1;
9365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (y = y_start; y < y_end; ++y) {
9375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      uint32_t packed_pixels = 0;
9385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int x;
9395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      for (x = 0; x < width; ++x) {
9405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        // We need to load fresh 'packed_pixels' once every 'pixels_per_byte'
9415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        // increments of x. Fortunately, pixels_per_byte is a power of 2, so
9425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        // can just use a mask for that, instead of decrementing a counter.
9435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        if ((x & count_mask) == 0) packed_pixels = ((*src++) >> 8) & 0xff;
9445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        *dst++ = color_map[packed_pixels & bit_mask];
9455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        packed_pixels >>= bits_per_pixel;
9465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
9475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
9485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } else {
9495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    for (y = y_start; y < y_end; ++y) {
9505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      int x;
9515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      for (x = 0; x < width; ++x) {
9525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        *dst++ = color_map[((*src++) >> 8) & 0xff];
9535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
9545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
9555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
9565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
9575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
9585a50414796e9a458925c7a13a15055d02406bf43Vikas Aroravoid VP8LInverseTransform(const VP8LTransform* const transform,
9595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                          int row_start, int row_end,
9605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                          const uint32_t* const in, uint32_t* const out) {
9615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  assert(row_start < row_end);
9625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  assert(row_end <= transform->ysize_);
9635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  switch (transform->type_) {
9645a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case SUBTRACT_GREEN:
9655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      AddGreenToBlueAndRed(transform, row_start, row_end, out);
9665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
9675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case PREDICTOR_TRANSFORM:
9685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      PredictorInverseTransform(transform, row_start, row_end, out);
9695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (row_end != transform->ysize_) {
9705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        // The last predicted row in this iteration will be the top-pred row
9715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        // for the first row in next iteration.
9725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        const int width = transform->xsize_;
9735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        memcpy(out - width, out + (row_end - row_start - 1) * width,
9745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora               width * sizeof(*out));
9755a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
9765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
9775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case CROSS_COLOR_TRANSFORM:
9785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ColorSpaceInverseTransform(transform, row_start, row_end, out);
9795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
9805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case COLOR_INDEXING_TRANSFORM:
9815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      if (in == out && transform->bits_ > 0) {
9825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        // Move packed pixels to the end of unpacked region, so that unpacking
9835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        // can occur seamlessly.
9845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        // Also, note that this is the only transform that applies on
9855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        // the effective width of VP8LSubSampleSize(xsize_, bits_). All other
9865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        // transforms work on effective width of xsize_.
9875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        const int out_stride = (row_end - row_start) * transform->xsize_;
9885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        const int in_stride = (row_end - row_start) *
9895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora            VP8LSubSampleSize(transform->xsize_, transform->bits_);
9905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        uint32_t* const src = out + out_stride - in_stride;
9915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        memmove(src, out, in_stride * sizeof(*src));
9925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ColorIndexInverseTransform(transform, row_start, row_end, src, out);
9935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      } else {
9945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora        ColorIndexInverseTransform(transform, row_start, row_end, in, out);
9955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      }
9965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
9975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
9985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
9995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
10005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
10015a50414796e9a458925c7a13a15055d02406bf43Vikas Arora// Color space conversion.
10025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
10035a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic int is_big_endian(void) {
10045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  static const union {
10055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    uint16_t w;
10065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    uint8_t b[2];
10075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } tmp = { 1 };
10085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  return (tmp.b[0] != 1);
10095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
10105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
10115a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ConvertBGRAToRGB(const uint32_t* src,
10125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                             int num_pixels, uint8_t* dst) {
10135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t* const src_end = src + num_pixels;
10145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (src < src_end) {
10155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t argb = *src++;
10165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = (argb >> 16) & 0xff;
10175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = (argb >>  8) & 0xff;
10185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = (argb >>  0) & 0xff;
10195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
10205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
10215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
10225a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ConvertBGRAToRGBA(const uint32_t* src,
10235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                              int num_pixels, uint8_t* dst) {
10245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t* const src_end = src + num_pixels;
10255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (src < src_end) {
10265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t argb = *src++;
10275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = (argb >> 16) & 0xff;
10285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = (argb >>  8) & 0xff;
10295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = (argb >>  0) & 0xff;
10305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = (argb >> 24) & 0xff;
10315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
10325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
10335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
10345a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ConvertBGRAToRGBA4444(const uint32_t* src,
10355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                  int num_pixels, uint8_t* dst) {
10365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t* const src_end = src + num_pixels;
10375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (src < src_end) {
10385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t argb = *src++;
10395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#ifdef ANDROID_WEBP_RGB
10405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = ((argb >>  0) & 0xf0) | ((argb >> 28) & 0xf);
10415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf);
10425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#else
10435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf);
10445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = ((argb >>  0) & 0xf0) | ((argb >> 28) & 0xf);
10455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#endif
10465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
10475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
10485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
10495a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ConvertBGRAToRGB565(const uint32_t* src,
10505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                                int num_pixels, uint8_t* dst) {
10515a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t* const src_end = src + num_pixels;
10525a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (src < src_end) {
10535a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t argb = *src++;
10545a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#ifdef ANDROID_WEBP_RGB
10555a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = ((argb >>  5) & 0xe0) | ((argb >>  3) & 0x1f);
10565a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7);
10575a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#else
10585a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7);
10595a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = ((argb >>  5) & 0xe0) | ((argb >>  3) & 0x1f);
10605a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#endif
10615a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
10625a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
10635a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
10645a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void ConvertBGRAToBGR(const uint32_t* src,
10655a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                             int num_pixels, uint8_t* dst) {
10665a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  const uint32_t* const src_end = src + num_pixels;
10675a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  while (src < src_end) {
10685a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t argb = *src++;
10695a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = (argb >>  0) & 0xff;
10705a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = (argb >>  8) & 0xff;
10715a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    *dst++ = (argb >> 16) & 0xff;
10725a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
10735a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
10745a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
10755a50414796e9a458925c7a13a15055d02406bf43Vikas Arorastatic void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst,
10765a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                       int swap_on_big_endian) {
10775a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  if (is_big_endian() == swap_on_big_endian) {
10785a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    const uint32_t* const src_end = src + num_pixels;
10795a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    while (src < src_end) {
10805a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      uint32_t argb = *src++;
10815a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#if !defined(__BIG_ENDIAN__) && (defined(__i386__) || defined(__x86_64__))
10825a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      __asm__ volatile("bswap %0" : "=r"(argb) : "0"(argb));
10835a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      *(uint32_t*)dst = argb;
10845a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      dst += sizeof(argb);
10855a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#elif !defined(__BIG_ENDIAN__) && defined(_MSC_VER)
10865a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      argb = _byteswap_ulong(argb);
10875a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      *(uint32_t*)dst = argb;
10885a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      dst += sizeof(argb);
10895a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#else
10905a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      *dst++ = (argb >> 24) & 0xff;
10915a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      *dst++ = (argb >> 16) & 0xff;
10925a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      *dst++ = (argb >>  8) & 0xff;
10935a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      *dst++ = (argb >>  0) & 0xff;
10945a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#endif
10955a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    }
10965a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  } else {
10975a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    memcpy(dst, src, num_pixels * sizeof(*src));
10985a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
10995a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
11005a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
11015a50414796e9a458925c7a13a15055d02406bf43Vikas Aroravoid VP8LConvertFromBGRA(const uint32_t* const in_data, int num_pixels,
11025a50414796e9a458925c7a13a15055d02406bf43Vikas Arora                         WEBP_CSP_MODE out_colorspace, uint8_t* const rgba) {
11035a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  switch (out_colorspace) {
11045a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_RGB:
11055a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ConvertBGRAToRGB(in_data, num_pixels, rgba);
11065a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11075a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_RGBA:
11085a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ConvertBGRAToRGBA(in_data, num_pixels, rgba);
11095a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11105a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_rgbA:
11115a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ConvertBGRAToRGBA(in_data, num_pixels, rgba);
11125a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0);
11135a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11145a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_BGR:
11155a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ConvertBGRAToBGR(in_data, num_pixels, rgba);
11165a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11175a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_BGRA:
11185a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      CopyOrSwap(in_data, num_pixels, rgba, 1);
11195a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11205a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_bgrA:
11215a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      CopyOrSwap(in_data, num_pixels, rgba, 1);
11225a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      WebPApplyAlphaMultiply(rgba, 0, num_pixels, 1, 0);
11235a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11245a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_ARGB:
11255a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      CopyOrSwap(in_data, num_pixels, rgba, 0);
11265a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11275a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_Argb:
11285a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      CopyOrSwap(in_data, num_pixels, rgba, 0);
11295a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      WebPApplyAlphaMultiply(rgba, 1, num_pixels, 1, 0);
11305a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11315a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_RGBA_4444:
11325a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
11335a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11345a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_rgbA_4444:
11355a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ConvertBGRAToRGBA4444(in_data, num_pixels, rgba);
11365a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      WebPApplyAlphaMultiply4444(rgba, num_pixels, 1, 0);
11375a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11385a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    case MODE_RGB_565:
11395a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      ConvertBGRAToRGB565(in_data, num_pixels, rgba);
11405a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      break;
11415a50414796e9a458925c7a13a15055d02406bf43Vikas Arora    default:
11425a50414796e9a458925c7a13a15055d02406bf43Vikas Arora      assert(0);          // Code flow should not reach here.
11435a50414796e9a458925c7a13a15055d02406bf43Vikas Arora  }
11445a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}
11455a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
11465a50414796e9a458925c7a13a15055d02406bf43Vikas Arora//------------------------------------------------------------------------------
11475a50414796e9a458925c7a13a15055d02406bf43Vikas Arora
11485a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#if defined(__cplusplus) || defined(c_plusplus)
11495a50414796e9a458925c7a13a15055d02406bf43Vikas Arora}    // extern "C"
11505a50414796e9a458925c7a13a15055d02406bf43Vikas Arora#endif
1151