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