Path: blob/master/thirdparty/libwebp/src/dsp/lossless_enc.c
21437 views
// Copyright 2015 Google Inc. All Rights Reserved.1//2// Use of this source code is governed by a BSD-style license3// that can be found in the COPYING file in the root of the source4// tree. An additional intellectual property rights grant can be found5// in the file PATENTS. All contributing project authors may6// be found in the AUTHORS file in the root of the source tree.7// -----------------------------------------------------------------------------8//9// Image transform methods for lossless encoder.10//11// Authors: Vikas Arora ([email protected])12// Jyrki Alakuijala ([email protected])13// Urvang Joshi ([email protected])1415#include <assert.h>16#include <math.h>17#include <stdlib.h>18#include <string.h>1920#include "src/dsp/cpu.h"21#include "src/dsp/dsp.h"22#include "src/dsp/lossless.h"23#include "src/dsp/lossless_common.h"24#include "src/enc/histogram_enc.h"25#include "src/utils/utils.h"26#include "src/webp/format_constants.h"27#include "src/webp/types.h"2829// lookup table for small values of log2(int) * (1 << LOG_2_PRECISION_BITS).30// Obtained in Python with:31// a = [ str(round((1<<23)*math.log2(i))) if i else "0" for i in range(256)]32// print(',\n'.join([' '+','.join(v)33// for v in batched([i.rjust(9) for i in a],7)]))34const uint32_t kLog2Table[LOG_LOOKUP_IDX_MAX] = {350, 0, 8388608, 13295629, 16777216, 19477745, 21684237,3623549800, 25165824, 26591258, 27866353, 29019816, 30072845, 31041538,3731938408, 32773374, 33554432, 34288123, 34979866, 35634199, 36254961,3836845429, 37408424, 37946388, 38461453, 38955489, 39430146, 39886887,3940327016, 40751698, 41161982, 41558811, 41943040, 42315445, 42676731,4043027545, 43368474, 43700062, 44022807, 44337167, 44643569, 44942404,4145234037, 45518808, 45797032, 46069003, 46334996, 46595268, 46850061,4247099600, 47344097, 47583753, 47818754, 48049279, 48275495, 48497560,4348715624, 48929828, 49140306, 49347187, 49550590, 49750631, 49947419,4450141058, 50331648, 50519283, 50704053, 50886044, 51065339, 51242017,4551416153, 51587818, 51757082, 51924012, 52088670, 52251118, 52411415,4652569616, 52725775, 52879946, 53032177, 53182516, 53331012, 53477707,4753622645, 53765868, 53907416, 54047327, 54185640, 54322389, 54457611,4854591338, 54723604, 54854440, 54983876, 55111943, 55238669, 55364082,4955488208, 55611074, 55732705, 55853126, 55972361, 56090432, 56207362,5056323174, 56437887, 56551524, 56664103, 56775645, 56886168, 56995691,5157104232, 57211808, 57318436, 57424133, 57528914, 57632796, 57735795,5257837923, 57939198, 58039632, 58139239, 58238033, 58336027, 58433234,5358529666, 58625336, 58720256, 58814437, 58907891, 59000628, 59092661,5459183999, 59274652, 59364632, 59453947, 59542609, 59630625, 59718006,5559804761, 59890898, 59976426, 60061354, 60145690, 60229443, 60312620,5660395229, 60477278, 60558775, 60639726, 60720140, 60800023, 60879382,5760958224, 61036555, 61114383, 61191714, 61268554, 61344908, 61420785,5861496188, 61571124, 61645600, 61719620, 61793189, 61866315, 61939001,5962011253, 62083076, 62154476, 62225457, 62296024, 62366182, 62435935,6062505289, 62574248, 62642816, 62710997, 62778797, 62846219, 62913267,6162979946, 63046260, 63112212, 63177807, 63243048, 63307939, 63372484,6263436687, 63500551, 63564080, 63627277, 63690146, 63752690, 63814912,6363876816, 63938405, 63999682, 64060650, 64121313, 64181673, 64241734,6464301498, 64360969, 64420148, 64479040, 64537646, 64595970, 64654014,6564711782, 64769274, 64826495, 64883447, 64940132, 64996553, 65052711,6665108611, 65164253, 65219641, 65274776, 65329662, 65384299, 65438691,6765492840, 65546747, 65600416, 65653847, 65707044, 65760008, 65812741,6865865245, 65917522, 65969575, 66021404, 66073013, 66124403, 66175575,6966226531, 66277275, 66327806, 66378127, 66428240, 66478146, 66527847,7066577345, 66626641, 66675737, 66724635, 66773336, 66821842, 66870154,7166918274, 66966204, 67013944, 6706149772};7374// lookup table for small values of int*log2(int) * (1 << LOG_2_PRECISION_BITS).75// Obtained in Python with:76// a=[ "%d"%i if i<(1<<32) else "%dull"%i77// for i in [ round((1<<LOG_2_PRECISION_BITS)*math.log2(i)*i) if i78// else 0 for i in range(256)]]79// print(',\n '.join([','.join(v) for v in batched([i.rjust(15)80// for i in a],4)]))81const uint64_t kSLog2Table[LOG_LOOKUP_IDX_MAX] = {820, 0, 16777216, 39886887,8367108864, 97388723, 130105423, 164848600,84201326592, 239321324, 278663526, 319217973,85360874141, 403539997, 447137711, 491600606,86536870912, 582898099, 629637592, 677049776,87725099212, 773754010, 822985323, 872766924,88923074875, 973887230, 1025183802, 1076945958,891129156447, 1181799249, 1234859451, 1288323135,901342177280, 1396409681, 1451008871, 1505964059,911561265072, 1616902301, 1672866655, 1729149526,921785742744, 1842638548, 1899829557, 1957308741,932015069397, 2073105127, 2131409817, 2189977618ull,942248802933ull, 2307880396ull, 2367204859ull, 2426771383ull,952486575220ull, 2546611805ull, 2606876748ull, 2667365819ull,962728074942ull, 2789000187ull, 2850137762ull, 2911484006ull,972973035382ull, 3034788471ull, 3096739966ull, 3158886666ull,983221225472ull, 3283753383ull, 3346467489ull, 3409364969ull,993472443085ull, 3535699182ull, 3599130679ull, 3662735070ull,1003726509920ull, 3790452862ull, 3854561593ull, 3918833872ull,1013983267519ull, 4047860410ull, 4112610476ull, 4177515704ull,1024242574127ull, 4307783833ull, 4373142952ull, 4438649662ull,1034504302186ull, 4570098787ull, 4636037770ull, 4702117480ull,1044768336298ull, 4834692645ull, 4901184974ull, 4967811774ull,1055034571569ull, 5101462912ull, 5168484389ull, 5235634615ull,1065302912235ull, 5370315922ull, 5437844376ull, 5505496324ull,1075573270518ull, 5641165737ull, 5709180782ull, 5777314477ull,1085845565671ull, 5913933235ull, 5982416059ull, 6051013057ull,1096119723161ull, 6188545324ull, 6257478518ull, 6326521733ull,1106395673979ull, 6464934282ull, 6534301685ull, 6603775250ull,1116673354052ull, 6743037185ull, 6812823756ull, 6882712890ull,1126952703725ull, 7022795412ull, 7092987118ull, 7163278025ull,1137233667324ull, 7304154222ull, 7374737939ull, 7445417707ull,1147516192768ull, 7587062379ull, 7658025806ull, 7729082328ull,1157800231234ull, 7871471825ull, 7942803410ull, 8014225311ull,1168085736859ull, 8157337394ull, 8229026267ull, 8300802839ull,1178372666477ull, 8444616560ull, 8516652476ull, 8588773618ull,1188660979393ull, 8733269211ull, 8805642493ull, 8878098667ull,1198950637170ull, 9023257446ull, 9095958945ull, 9168741125ull,1209241603454ull, 9314545403ull, 9387566451ull, 9460666086ull,1219533843800ull, 9607099093ull, 9680431471ull, 9753840445ull,1229827325535ull, 9900886263ull, 9974522161ull, 10048232765ull,12310122017615ull, 10195876260ull, 10269808253ull, 10343813150ull,12410417890516ull, 10492039919ull, 10566260934ull, 10640553138ull,12510714916116ull, 10789349456ull, 10863852751ull, 10938425600ull,12611013067604ull, 11087778372ull, 11162557513ull, 11237404645ull,12711312319387ull, 11387301364ull, 11462350205ull, 11537465541ull,12811612647010ull, 11687894253ull, 11763206912ull, 11838584638ull,12911914027082ull, 11989533899ull, 12065104750ull, 12140739296ull,13012216437206ull, 12292198148ull, 12368021795ull, 12443907826ull,13112519855920ull, 12595865759ull, 12671937032ull, 12748069427ull,13212824262637ull, 12900516358ull, 12976830290ull, 13053204134ull,13313129637595ull, 13206130381ull, 13282682202ull, 13359292772ull,13413435961806ull, 13512689025ull, 13589474149ull, 13666316903ull,13513743217014ull, 13820174211ull, 13897188225ull, 13974258793ull,13614051385649ull, 14128568535ull, 14205807192ull, 14283101363ull,13714360450796ull, 14437855239ull, 14515314443ull, 14592828162ull,13814670396151ull, 14748018167ull, 14825693972ull, 14903423326ull,13914981205995ull, 15059041743ull, 15136930339ull, 15214871554ull,14015292865160ull, 15370910930ull, 15449008641ull, 15527158071ull,14115605359001ull, 15683611210ull, 15761914485ull, 15840268608ull,14215918673369ull, 15997128556ull, 16075633960ull, 16154189373ull,14316232794589ull, 16311449405ull, 16390153617ull, 16468907026ull,14416547709431ull, 16626560636ull, 16705460444ull, 16784408661ull,14516863405094ull, 16942449552ull, 17021541845ull, 17100681785ull146};147148const VP8LPrefixCode kPrefixEncodeCode[PREFIX_LOOKUP_IDX_MAX] = {149{ 0, 0}, { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 1}, { 4, 1}, { 5, 1},150{ 5, 1}, { 6, 2}, { 6, 2}, { 6, 2}, { 6, 2}, { 7, 2}, { 7, 2}, { 7, 2},151{ 7, 2}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3}, { 8, 3},152{ 8, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3}, { 9, 3},153{ 9, 3}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4},154{10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4},155{10, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},156{11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},157{11, 4}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},158{12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},159{12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},160{12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5}, {12, 5},161{12, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},162{13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},163{13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},164{13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5}, {13, 5},165{13, 5}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},166{14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},167{14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},168{14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},169{14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},170{14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},171{14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},172{14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6}, {14, 6},173{14, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},174{15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},175{15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},176{15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},177{15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},178{15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},179{15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},180{15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6}, {15, 6},181{15, 6}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},182{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},183{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},184{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},185{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},186{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},187{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},188{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},189{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},190{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},191{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},192{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},193{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},194{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},195{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},196{16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7}, {16, 7},197{16, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},198{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},199{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},200{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},201{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},202{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},203{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},204{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},205{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},206{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},207{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},208{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},209{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},210{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},211{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},212{17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7}, {17, 7},213};214215const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = {2160, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3,2170, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,2180, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,2190, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,2200, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,22116, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,2220, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,22316, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,2240, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,22516, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,22632, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,22748, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,2280, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,22916, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,23032, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,23148, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,2320, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,23316, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,23432, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,23548, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,23664, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,23780, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,23896, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,239112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,240127,2410, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,24216, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,24332, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,24448, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,24564, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,24680, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,24796, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,248112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126249};250251static uint64_t FastSLog2Slow_C(uint32_t v) {252assert(v >= LOG_LOOKUP_IDX_MAX);253if (v < APPROX_LOG_WITH_CORRECTION_MAX) {254const uint64_t orig_v = v;255uint64_t correction;256#if !defined(WEBP_HAVE_SLOW_CLZ_CTZ)257// use clz if available258const uint64_t log_cnt = BitsLog2Floor(v) - 7;259const uint32_t y = 1 << log_cnt;260v >>= log_cnt;261#else262uint64_t log_cnt = 0;263uint32_t y = 1;264do {265++log_cnt;266v = v >> 1;267y = y << 1;268} while (v >= LOG_LOOKUP_IDX_MAX);269#endif270// vf = (2^log_cnt) * Xf; where y = 2^log_cnt and Xf < 256271// Xf = floor(Xf) * (1 + (v % y) / v)272// log2(Xf) = log2(floor(Xf)) + log2(1 + (v % y) / v)273// The correction factor: log(1 + d) ~ d; for very small d values, so274// log2(1 + (v % y) / v) ~ LOG_2_RECIPROCAL * (v % y)/v275correction = LOG_2_RECIPROCAL_FIXED * (orig_v & (y - 1));276return orig_v * (kLog2Table[v] + (log_cnt << LOG_2_PRECISION_BITS)) +277correction;278} else {279return (uint64_t)(LOG_2_RECIPROCAL_FIXED_DOUBLE * v * log((double)v) + .5);280}281}282283static uint32_t FastLog2Slow_C(uint32_t v) {284assert(v >= LOG_LOOKUP_IDX_MAX);285if (v < APPROX_LOG_WITH_CORRECTION_MAX) {286const uint32_t orig_v = v;287uint32_t log_2;288#if !defined(WEBP_HAVE_SLOW_CLZ_CTZ)289// use clz if available290const uint32_t log_cnt = BitsLog2Floor(v) - 7;291const uint32_t y = 1 << log_cnt;292v >>= log_cnt;293#else294uint32_t log_cnt = 0;295uint32_t y = 1;296do {297++log_cnt;298v = v >> 1;299y = y << 1;300} while (v >= LOG_LOOKUP_IDX_MAX);301#endif302log_2 = kLog2Table[v] + (log_cnt << LOG_2_PRECISION_BITS);303if (orig_v >= APPROX_LOG_MAX) {304// Since the division is still expensive, add this correction factor only305// for large values of 'v'.306const uint64_t correction = LOG_2_RECIPROCAL_FIXED * (orig_v & (y - 1));307log_2 += (uint32_t)DivRound(correction, orig_v);308}309return log_2;310} else {311return (uint32_t)(LOG_2_RECIPROCAL_FIXED_DOUBLE * log((double)v) + .5);312}313}314315//------------------------------------------------------------------------------316// Methods to calculate Entropy (Shannon).317318// Compute the combined Shanon's entropy for distribution {X} and {X+Y}319static uint64_t CombinedShannonEntropy_C(const uint32_t X[256],320const uint32_t Y[256]) {321int i;322uint64_t retval = 0;323uint32_t sumX = 0, sumXY = 0;324for (i = 0; i < 256; ++i) {325const uint32_t x = X[i];326if (x != 0) {327const uint32_t xy = x + Y[i];328sumX += x;329retval += VP8LFastSLog2(x);330sumXY += xy;331retval += VP8LFastSLog2(xy);332} else if (Y[i] != 0) {333sumXY += Y[i];334retval += VP8LFastSLog2(Y[i]);335}336}337retval = VP8LFastSLog2(sumX) + VP8LFastSLog2(sumXY) - retval;338return retval;339}340341static uint64_t ShannonEntropy_C(const uint32_t* X, int n) {342int i;343uint64_t retval = 0;344uint32_t sumX = 0;345for (i = 0; i < n; ++i) {346const int x = X[i];347if (x != 0) {348sumX += x;349retval += VP8LFastSLog2(x);350}351}352retval = VP8LFastSLog2(sumX) - retval;353return retval;354}355356void VP8LBitEntropyInit(VP8LBitEntropy* const entropy) {357entropy->entropy = 0;358entropy->sum = 0;359entropy->nonzeros = 0;360entropy->max_val = 0;361entropy->nonzero_code = VP8L_NON_TRIVIAL_SYM;362}363364void VP8LBitsEntropyUnrefined(const uint32_t* WEBP_RESTRICT const array, int n,365VP8LBitEntropy* WEBP_RESTRICT const entropy) {366int i;367368VP8LBitEntropyInit(entropy);369370for (i = 0; i < n; ++i) {371if (array[i] != 0) {372entropy->sum += array[i];373entropy->nonzero_code = i;374++entropy->nonzeros;375entropy->entropy += VP8LFastSLog2(array[i]);376if (entropy->max_val < array[i]) {377entropy->max_val = array[i];378}379}380}381entropy->entropy = VP8LFastSLog2(entropy->sum) - entropy->entropy;382}383384static WEBP_INLINE void GetEntropyUnrefinedHelper(385uint32_t val, int i, uint32_t* WEBP_RESTRICT const val_prev,386int* WEBP_RESTRICT const i_prev,387VP8LBitEntropy* WEBP_RESTRICT const bit_entropy,388VP8LStreaks* WEBP_RESTRICT const stats) {389const int streak = i - *i_prev;390391// Gather info for the bit entropy.392if (*val_prev != 0) {393bit_entropy->sum += (*val_prev) * streak;394bit_entropy->nonzeros += streak;395bit_entropy->nonzero_code = *i_prev;396bit_entropy->entropy += VP8LFastSLog2(*val_prev) * streak;397if (bit_entropy->max_val < *val_prev) {398bit_entropy->max_val = *val_prev;399}400}401402// Gather info for the Huffman cost.403stats->counts[*val_prev != 0] += (streak > 3);404stats->streaks[*val_prev != 0][(streak > 3)] += streak;405406*val_prev = val;407*i_prev = i;408}409410static void GetEntropyUnrefined_C(411const uint32_t X[], int length,412VP8LBitEntropy* WEBP_RESTRICT const bit_entropy,413VP8LStreaks* WEBP_RESTRICT const stats) {414int i;415int i_prev = 0;416uint32_t x_prev = X[0];417418memset(stats, 0, sizeof(*stats));419VP8LBitEntropyInit(bit_entropy);420421for (i = 1; i < length; ++i) {422const uint32_t x = X[i];423if (x != x_prev) {424GetEntropyUnrefinedHelper(x, i, &x_prev, &i_prev, bit_entropy, stats);425}426}427GetEntropyUnrefinedHelper(0, i, &x_prev, &i_prev, bit_entropy, stats);428429bit_entropy->entropy = VP8LFastSLog2(bit_entropy->sum) - bit_entropy->entropy;430}431432static void GetCombinedEntropyUnrefined_C(433const uint32_t X[], const uint32_t Y[], int length,434VP8LBitEntropy* WEBP_RESTRICT const bit_entropy,435VP8LStreaks* WEBP_RESTRICT const stats) {436int i = 1;437int i_prev = 0;438uint32_t xy_prev = X[0] + Y[0];439440memset(stats, 0, sizeof(*stats));441VP8LBitEntropyInit(bit_entropy);442443for (i = 1; i < length; ++i) {444const uint32_t xy = X[i] + Y[i];445if (xy != xy_prev) {446GetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, bit_entropy, stats);447}448}449GetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, bit_entropy, stats);450451bit_entropy->entropy = VP8LFastSLog2(bit_entropy->sum) - bit_entropy->entropy;452}453454//------------------------------------------------------------------------------455456void VP8LSubtractGreenFromBlueAndRed_C(uint32_t* argb_data, int num_pixels) {457int i;458for (i = 0; i < num_pixels; ++i) {459const int argb = (int)argb_data[i];460const int green = (argb >> 8) & 0xff;461const uint32_t new_r = (((argb >> 16) & 0xff) - green) & 0xff;462const uint32_t new_b = (((argb >> 0) & 0xff) - green) & 0xff;463argb_data[i] = ((uint32_t)argb & 0xff00ff00u) | (new_r << 16) | new_b;464}465}466467static WEBP_INLINE int ColorTransformDelta(int8_t color_pred, int8_t color) {468return ((int)color_pred * color) >> 5;469}470471static WEBP_INLINE int8_t U32ToS8(uint32_t v) {472return (int8_t)(v & 0xff);473}474475void VP8LTransformColor_C(const VP8LMultipliers* WEBP_RESTRICT const m,476uint32_t* WEBP_RESTRICT data, int num_pixels) {477int i;478for (i = 0; i < num_pixels; ++i) {479const uint32_t argb = data[i];480const int8_t green = U32ToS8(argb >> 8);481const int8_t red = U32ToS8(argb >> 16);482int new_red = red & 0xff;483int new_blue = argb & 0xff;484new_red -= ColorTransformDelta((int8_t)m->green_to_red, green);485new_red &= 0xff;486new_blue -= ColorTransformDelta((int8_t)m->green_to_blue, green);487new_blue -= ColorTransformDelta((int8_t)m->red_to_blue, red);488new_blue &= 0xff;489data[i] = (argb & 0xff00ff00u) | (new_red << 16) | (new_blue);490}491}492493static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red,494uint32_t argb) {495const int8_t green = U32ToS8(argb >> 8);496int new_red = argb >> 16;497new_red -= ColorTransformDelta((int8_t)green_to_red, green);498return (new_red & 0xff);499}500501static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue,502uint8_t red_to_blue,503uint32_t argb) {504const int8_t green = U32ToS8(argb >> 8);505const int8_t red = U32ToS8(argb >> 16);506int new_blue = argb & 0xff;507new_blue -= ColorTransformDelta((int8_t)green_to_blue, green);508new_blue -= ColorTransformDelta((int8_t)red_to_blue, red);509return (new_blue & 0xff);510}511512void VP8LCollectColorRedTransforms_C(const uint32_t* WEBP_RESTRICT argb,513int stride,514int tile_width, int tile_height,515int green_to_red, uint32_t histo[]) {516while (tile_height-- > 0) {517int x;518for (x = 0; x < tile_width; ++x) {519++histo[TransformColorRed((uint8_t)green_to_red, argb[x])];520}521argb += stride;522}523}524525void VP8LCollectColorBlueTransforms_C(const uint32_t* WEBP_RESTRICT argb,526int stride,527int tile_width, int tile_height,528int green_to_blue, int red_to_blue,529uint32_t histo[]) {530while (tile_height-- > 0) {531int x;532for (x = 0; x < tile_width; ++x) {533++histo[TransformColorBlue((uint8_t)green_to_blue, (uint8_t)red_to_blue,534argb[x])];535}536argb += stride;537}538}539540//------------------------------------------------------------------------------541542static int VectorMismatch_C(const uint32_t* const array1,543const uint32_t* const array2, int length) {544int match_len = 0;545546while (match_len < length && array1[match_len] == array2[match_len]) {547++match_len;548}549return match_len;550}551552// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel.553void VP8LBundleColorMap_C(const uint8_t* WEBP_RESTRICT const row,554int width, int xbits, uint32_t* WEBP_RESTRICT dst) {555int x;556if (xbits > 0) {557const int bit_depth = 1 << (3 - xbits);558const int mask = (1 << xbits) - 1;559uint32_t code = 0xff000000;560for (x = 0; x < width; ++x) {561const int xsub = x & mask;562if (xsub == 0) {563code = 0xff000000;564}565code |= row[x] << (8 + bit_depth * xsub);566dst[x >> xbits] = code;567}568} else {569for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8);570}571}572573//------------------------------------------------------------------------------574575static uint32_t ExtraCost_C(const uint32_t* population, int length) {576int i;577uint32_t cost = population[4] + population[5];578assert(length % 2 == 0);579for (i = 2; i < length / 2 - 1; ++i) {580cost += i * (population[2 * i + 2] + population[2 * i + 3]);581}582return cost;583}584585//------------------------------------------------------------------------------586587static void AddVector_C(const uint32_t* WEBP_RESTRICT a,588const uint32_t* WEBP_RESTRICT b,589uint32_t* WEBP_RESTRICT out, int size) {590int i;591for (i = 0; i < size; ++i) out[i] = a[i] + b[i];592}593594static void AddVectorEq_C(const uint32_t* WEBP_RESTRICT a,595uint32_t* WEBP_RESTRICT out, int size) {596int i;597for (i = 0; i < size; ++i) out[i] += a[i];598}599600//------------------------------------------------------------------------------601// Image transforms.602603static void PredictorSub0_C(const uint32_t* in, const uint32_t* upper,604int num_pixels, uint32_t* WEBP_RESTRICT out) {605int i;606for (i = 0; i < num_pixels; ++i) out[i] = VP8LSubPixels(in[i], ARGB_BLACK);607(void)upper;608}609610static void PredictorSub1_C(const uint32_t* in, const uint32_t* upper,611int num_pixels, uint32_t* WEBP_RESTRICT out) {612int i;613for (i = 0; i < num_pixels; ++i) out[i] = VP8LSubPixels(in[i], in[i - 1]);614(void)upper;615}616617// It subtracts the prediction from the input pixel and stores the residual618// in the output pixel.619#define GENERATE_PREDICTOR_SUB(PREDICTOR_I) \620static void PredictorSub##PREDICTOR_I##_C(const uint32_t* in, \621const uint32_t* upper, \622int num_pixels, \623uint32_t* WEBP_RESTRICT out) { \624int x; \625assert(upper != NULL); \626for (x = 0; x < num_pixels; ++x) { \627const uint32_t pred = \628VP8LPredictor##PREDICTOR_I##_C(&in[x - 1], upper + x); \629out[x] = VP8LSubPixels(in[x], pred); \630} \631}632633GENERATE_PREDICTOR_SUB(2)634GENERATE_PREDICTOR_SUB(3)635GENERATE_PREDICTOR_SUB(4)636GENERATE_PREDICTOR_SUB(5)637GENERATE_PREDICTOR_SUB(6)638GENERATE_PREDICTOR_SUB(7)639GENERATE_PREDICTOR_SUB(8)640GENERATE_PREDICTOR_SUB(9)641GENERATE_PREDICTOR_SUB(10)642GENERATE_PREDICTOR_SUB(11)643GENERATE_PREDICTOR_SUB(12)644GENERATE_PREDICTOR_SUB(13)645646//------------------------------------------------------------------------------647648VP8LProcessEncBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed;649VP8LProcessEncBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed_SSE;650651VP8LTransformColorFunc VP8LTransformColor;652VP8LTransformColorFunc VP8LTransformColor_SSE;653654VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms;655VP8LCollectColorBlueTransformsFunc VP8LCollectColorBlueTransforms_SSE;656VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms;657VP8LCollectColorRedTransformsFunc VP8LCollectColorRedTransforms_SSE;658659VP8LFastLog2SlowFunc VP8LFastLog2Slow;660VP8LFastSLog2SlowFunc VP8LFastSLog2Slow;661662VP8LCostFunc VP8LExtraCost;663VP8LCombinedShannonEntropyFunc VP8LCombinedShannonEntropy;664VP8LShannonEntropyFunc VP8LShannonEntropy;665666VP8LGetEntropyUnrefinedFunc VP8LGetEntropyUnrefined;667VP8LGetCombinedEntropyUnrefinedFunc VP8LGetCombinedEntropyUnrefined;668669VP8LAddVectorFunc VP8LAddVector;670VP8LAddVectorEqFunc VP8LAddVectorEq;671672VP8LVectorMismatchFunc VP8LVectorMismatch;673VP8LBundleColorMapFunc VP8LBundleColorMap;674VP8LBundleColorMapFunc VP8LBundleColorMap_SSE;675676VP8LPredictorAddSubFunc VP8LPredictorsSub[16];677VP8LPredictorAddSubFunc VP8LPredictorsSub_C[16];678VP8LPredictorAddSubFunc VP8LPredictorsSub_SSE[16];679680extern VP8CPUInfo VP8GetCPUInfo;681extern void VP8LEncDspInitSSE2(void);682extern void VP8LEncDspInitSSE41(void);683extern void VP8LEncDspInitAVX2(void);684extern void VP8LEncDspInitNEON(void);685extern void VP8LEncDspInitMIPS32(void);686extern void VP8LEncDspInitMIPSdspR2(void);687extern void VP8LEncDspInitMSA(void);688689WEBP_DSP_INIT_FUNC(VP8LEncDspInit) {690VP8LDspInit();691692#if !WEBP_NEON_OMIT_C_CODE693VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C;694695VP8LTransformColor = VP8LTransformColor_C;696#endif697698VP8LCollectColorBlueTransforms = VP8LCollectColorBlueTransforms_C;699VP8LCollectColorRedTransforms = VP8LCollectColorRedTransforms_C;700701VP8LFastLog2Slow = FastLog2Slow_C;702VP8LFastSLog2Slow = FastSLog2Slow_C;703704VP8LExtraCost = ExtraCost_C;705VP8LCombinedShannonEntropy = CombinedShannonEntropy_C;706VP8LShannonEntropy = ShannonEntropy_C;707708VP8LGetEntropyUnrefined = GetEntropyUnrefined_C;709VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_C;710711VP8LAddVector = AddVector_C;712VP8LAddVectorEq = AddVectorEq_C;713714VP8LVectorMismatch = VectorMismatch_C;715VP8LBundleColorMap = VP8LBundleColorMap_C;716717VP8LPredictorsSub[0] = PredictorSub0_C;718VP8LPredictorsSub[1] = PredictorSub1_C;719VP8LPredictorsSub[2] = PredictorSub2_C;720VP8LPredictorsSub[3] = PredictorSub3_C;721VP8LPredictorsSub[4] = PredictorSub4_C;722VP8LPredictorsSub[5] = PredictorSub5_C;723VP8LPredictorsSub[6] = PredictorSub6_C;724VP8LPredictorsSub[7] = PredictorSub7_C;725VP8LPredictorsSub[8] = PredictorSub8_C;726VP8LPredictorsSub[9] = PredictorSub9_C;727VP8LPredictorsSub[10] = PredictorSub10_C;728VP8LPredictorsSub[11] = PredictorSub11_C;729VP8LPredictorsSub[12] = PredictorSub12_C;730VP8LPredictorsSub[13] = PredictorSub13_C;731VP8LPredictorsSub[14] = PredictorSub0_C; // <- padding security sentinels732VP8LPredictorsSub[15] = PredictorSub0_C;733734VP8LPredictorsSub_C[0] = PredictorSub0_C;735VP8LPredictorsSub_C[1] = PredictorSub1_C;736VP8LPredictorsSub_C[2] = PredictorSub2_C;737VP8LPredictorsSub_C[3] = PredictorSub3_C;738VP8LPredictorsSub_C[4] = PredictorSub4_C;739VP8LPredictorsSub_C[5] = PredictorSub5_C;740VP8LPredictorsSub_C[6] = PredictorSub6_C;741VP8LPredictorsSub_C[7] = PredictorSub7_C;742VP8LPredictorsSub_C[8] = PredictorSub8_C;743VP8LPredictorsSub_C[9] = PredictorSub9_C;744VP8LPredictorsSub_C[10] = PredictorSub10_C;745VP8LPredictorsSub_C[11] = PredictorSub11_C;746VP8LPredictorsSub_C[12] = PredictorSub12_C;747VP8LPredictorsSub_C[13] = PredictorSub13_C;748VP8LPredictorsSub_C[14] = PredictorSub0_C; // <- padding security sentinels749VP8LPredictorsSub_C[15] = PredictorSub0_C;750751// If defined, use CPUInfo() to overwrite some pointers with faster versions.752if (VP8GetCPUInfo != NULL) {753#if defined(WEBP_HAVE_SSE2)754if (VP8GetCPUInfo(kSSE2)) {755VP8LEncDspInitSSE2();756#if defined(WEBP_HAVE_SSE41)757if (VP8GetCPUInfo(kSSE4_1)) {758VP8LEncDspInitSSE41();759#if defined(WEBP_HAVE_AVX2)760if (VP8GetCPUInfo(kAVX2)) {761VP8LEncDspInitAVX2();762}763#endif764}765#endif766}767#endif768#if defined(WEBP_USE_MIPS32)769if (VP8GetCPUInfo(kMIPS32)) {770VP8LEncDspInitMIPS32();771}772#endif773#if defined(WEBP_USE_MIPS_DSP_R2)774if (VP8GetCPUInfo(kMIPSdspR2)) {775VP8LEncDspInitMIPSdspR2();776}777#endif778#if defined(WEBP_USE_MSA)779if (VP8GetCPUInfo(kMSA)) {780VP8LEncDspInitMSA();781}782#endif783}784785#if defined(WEBP_HAVE_NEON)786if (WEBP_NEON_OMIT_C_CODE ||787(VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) {788VP8LEncDspInitNEON();789}790#endif791792assert(VP8LSubtractGreenFromBlueAndRed != NULL);793assert(VP8LTransformColor != NULL);794assert(VP8LCollectColorBlueTransforms != NULL);795assert(VP8LCollectColorRedTransforms != NULL);796assert(VP8LFastLog2Slow != NULL);797assert(VP8LFastSLog2Slow != NULL);798assert(VP8LExtraCost != NULL);799assert(VP8LCombinedShannonEntropy != NULL);800assert(VP8LShannonEntropy != NULL);801assert(VP8LGetEntropyUnrefined != NULL);802assert(VP8LGetCombinedEntropyUnrefined != NULL);803assert(VP8LAddVector != NULL);804assert(VP8LAddVectorEq != NULL);805assert(VP8LVectorMismatch != NULL);806assert(VP8LBundleColorMap != NULL);807assert(VP8LPredictorsSub[0] != NULL);808assert(VP8LPredictorsSub[1] != NULL);809assert(VP8LPredictorsSub[2] != NULL);810assert(VP8LPredictorsSub[3] != NULL);811assert(VP8LPredictorsSub[4] != NULL);812assert(VP8LPredictorsSub[5] != NULL);813assert(VP8LPredictorsSub[6] != NULL);814assert(VP8LPredictorsSub[7] != NULL);815assert(VP8LPredictorsSub[8] != NULL);816assert(VP8LPredictorsSub[9] != NULL);817assert(VP8LPredictorsSub[10] != NULL);818assert(VP8LPredictorsSub[11] != NULL);819assert(VP8LPredictorsSub[12] != NULL);820assert(VP8LPredictorsSub[13] != NULL);821assert(VP8LPredictorsSub[14] != NULL);822assert(VP8LPredictorsSub[15] != NULL);823assert(VP8LPredictorsSub_C[0] != NULL);824assert(VP8LPredictorsSub_C[1] != NULL);825assert(VP8LPredictorsSub_C[2] != NULL);826assert(VP8LPredictorsSub_C[3] != NULL);827assert(VP8LPredictorsSub_C[4] != NULL);828assert(VP8LPredictorsSub_C[5] != NULL);829assert(VP8LPredictorsSub_C[6] != NULL);830assert(VP8LPredictorsSub_C[7] != NULL);831assert(VP8LPredictorsSub_C[8] != NULL);832assert(VP8LPredictorsSub_C[9] != NULL);833assert(VP8LPredictorsSub_C[10] != NULL);834assert(VP8LPredictorsSub_C[11] != NULL);835assert(VP8LPredictorsSub_C[12] != NULL);836assert(VP8LPredictorsSub_C[13] != NULL);837assert(VP8LPredictorsSub_C[14] != NULL);838assert(VP8LPredictorsSub_C[15] != NULL);839}840841//------------------------------------------------------------------------------842843844