backward_references_enc.c 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801
  1. // Copyright 2012 Google Inc. All Rights Reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license
  4. // that can be found in the COPYING file in the root of the source
  5. // tree. An additional intellectual property rights grant can be found
  6. // in the file PATENTS. All contributing project authors may
  7. // be found in the AUTHORS file in the root of the source tree.
  8. // -----------------------------------------------------------------------------
  9. //
  10. // Author: Jyrki Alakuijala (jyrki@google.com)
  11. //
  12. #include <assert.h>
  13. #include <math.h>
  14. #include "./backward_references_enc.h"
  15. #include "./histogram_enc.h"
  16. #include "../dsp/lossless.h"
  17. #include "../dsp/lossless_common.h"
  18. #include "../dsp/dsp.h"
  19. #include "../utils/color_cache_utils.h"
  20. #include "../utils/utils.h"
  21. #define VALUES_IN_BYTE 256
  22. #define MIN_BLOCK_SIZE 256 // minimum block size for backward references
  23. #define MAX_ENTROPY (1e30f)
  24. // 1M window (4M bytes) minus 120 special codes for short distances.
  25. #define WINDOW_SIZE_BITS 20
  26. #define WINDOW_SIZE ((1 << WINDOW_SIZE_BITS) - 120)
  27. // Minimum number of pixels for which it is cheaper to encode a
  28. // distance + length instead of each pixel as a literal.
  29. #define MIN_LENGTH 4
  30. // If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it
  31. // is used in VP8LHashChain.
  32. #define MAX_LENGTH_BITS 12
  33. // We want the max value to be attainable and stored in MAX_LENGTH_BITS bits.
  34. #define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1)
  35. #if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32
  36. #error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32"
  37. #endif
  38. // -----------------------------------------------------------------------------
  39. static const uint8_t plane_to_code_lut[128] = {
  40. 96, 73, 55, 39, 23, 13, 5, 1, 255, 255, 255, 255, 255, 255, 255, 255,
  41. 101, 78, 58, 42, 26, 16, 8, 2, 0, 3, 9, 17, 27, 43, 59, 79,
  42. 102, 86, 62, 46, 32, 20, 10, 6, 4, 7, 11, 21, 33, 47, 63, 87,
  43. 105, 90, 70, 52, 37, 28, 18, 14, 12, 15, 19, 29, 38, 53, 71, 91,
  44. 110, 99, 82, 66, 48, 35, 30, 24, 22, 25, 31, 36, 49, 67, 83, 100,
  45. 115, 108, 94, 76, 64, 50, 44, 40, 34, 41, 45, 51, 65, 77, 95, 109,
  46. 118, 113, 103, 92, 80, 68, 60, 56, 54, 57, 61, 69, 81, 93, 104, 114,
  47. 119, 116, 111, 106, 97, 88, 84, 74, 72, 75, 85, 89, 98, 107, 112, 117
  48. };
  49. static int DistanceToPlaneCode(int xsize, int dist) {
  50. const int yoffset = dist / xsize;
  51. const int xoffset = dist - yoffset * xsize;
  52. if (xoffset <= 8 && yoffset < 8) {
  53. return plane_to_code_lut[yoffset * 16 + 8 - xoffset] + 1;
  54. } else if (xoffset > xsize - 8 && yoffset < 7) {
  55. return plane_to_code_lut[(yoffset + 1) * 16 + 8 + (xsize - xoffset)] + 1;
  56. }
  57. return dist + 120;
  58. }
  59. // Returns the exact index where array1 and array2 are different. For an index
  60. // inferior or equal to best_len_match, the return value just has to be strictly
  61. // inferior to best_len_match. The current behavior is to return 0 if this index
  62. // is best_len_match, and the index itself otherwise.
  63. // If no two elements are the same, it returns max_limit.
  64. static WEBP_INLINE int FindMatchLength(const uint32_t* const array1,
  65. const uint32_t* const array2,
  66. int best_len_match, int max_limit) {
  67. // Before 'expensive' linear match, check if the two arrays match at the
  68. // current best length index.
  69. if (array1[best_len_match] != array2[best_len_match]) return 0;
  70. return VP8LVectorMismatch(array1, array2, max_limit);
  71. }
  72. // -----------------------------------------------------------------------------
  73. // VP8LBackwardRefs
  74. struct PixOrCopyBlock {
  75. PixOrCopyBlock* next_; // next block (or NULL)
  76. PixOrCopy* start_; // data start
  77. int size_; // currently used size
  78. };
  79. static void ClearBackwardRefs(VP8LBackwardRefs* const refs) {
  80. assert(refs != NULL);
  81. if (refs->tail_ != NULL) {
  82. *refs->tail_ = refs->free_blocks_; // recycle all blocks at once
  83. }
  84. refs->free_blocks_ = refs->refs_;
  85. refs->tail_ = &refs->refs_;
  86. refs->last_block_ = NULL;
  87. refs->refs_ = NULL;
  88. }
  89. void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs) {
  90. assert(refs != NULL);
  91. ClearBackwardRefs(refs);
  92. while (refs->free_blocks_ != NULL) {
  93. PixOrCopyBlock* const next = refs->free_blocks_->next_;
  94. WebPSafeFree(refs->free_blocks_);
  95. refs->free_blocks_ = next;
  96. }
  97. }
  98. void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) {
  99. assert(refs != NULL);
  100. memset(refs, 0, sizeof(*refs));
  101. refs->tail_ = &refs->refs_;
  102. refs->block_size_ =
  103. (block_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : block_size;
  104. }
  105. VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs) {
  106. VP8LRefsCursor c;
  107. c.cur_block_ = refs->refs_;
  108. if (refs->refs_ != NULL) {
  109. c.cur_pos = c.cur_block_->start_;
  110. c.last_pos_ = c.cur_pos + c.cur_block_->size_;
  111. } else {
  112. c.cur_pos = NULL;
  113. c.last_pos_ = NULL;
  114. }
  115. return c;
  116. }
  117. void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c) {
  118. PixOrCopyBlock* const b = c->cur_block_->next_;
  119. c->cur_pos = (b == NULL) ? NULL : b->start_;
  120. c->last_pos_ = (b == NULL) ? NULL : b->start_ + b->size_;
  121. c->cur_block_ = b;
  122. }
  123. // Create a new block, either from the free list or allocated
  124. static PixOrCopyBlock* BackwardRefsNewBlock(VP8LBackwardRefs* const refs) {
  125. PixOrCopyBlock* b = refs->free_blocks_;
  126. if (b == NULL) { // allocate new memory chunk
  127. const size_t total_size =
  128. sizeof(*b) + refs->block_size_ * sizeof(*b->start_);
  129. b = (PixOrCopyBlock*)WebPSafeMalloc(1ULL, total_size);
  130. if (b == NULL) {
  131. refs->error_ |= 1;
  132. return NULL;
  133. }
  134. b->start_ = (PixOrCopy*)((uint8_t*)b + sizeof(*b)); // not always aligned
  135. } else { // recycle from free-list
  136. refs->free_blocks_ = b->next_;
  137. }
  138. *refs->tail_ = b;
  139. refs->tail_ = &b->next_;
  140. refs->last_block_ = b;
  141. b->next_ = NULL;
  142. b->size_ = 0;
  143. return b;
  144. }
  145. static WEBP_INLINE void BackwardRefsCursorAdd(VP8LBackwardRefs* const refs,
  146. const PixOrCopy v) {
  147. PixOrCopyBlock* b = refs->last_block_;
  148. if (b == NULL || b->size_ == refs->block_size_) {
  149. b = BackwardRefsNewBlock(refs);
  150. if (b == NULL) return; // refs->error_ is set
  151. }
  152. b->start_[b->size_++] = v;
  153. }
  154. int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src,
  155. VP8LBackwardRefs* const dst) {
  156. const PixOrCopyBlock* b = src->refs_;
  157. ClearBackwardRefs(dst);
  158. assert(src->block_size_ == dst->block_size_);
  159. while (b != NULL) {
  160. PixOrCopyBlock* const new_b = BackwardRefsNewBlock(dst);
  161. if (new_b == NULL) return 0; // dst->error_ is set
  162. memcpy(new_b->start_, b->start_, b->size_ * sizeof(*b->start_));
  163. new_b->size_ = b->size_;
  164. b = b->next_;
  165. }
  166. return 1;
  167. }
  168. // -----------------------------------------------------------------------------
  169. // Hash chains
  170. int VP8LHashChainInit(VP8LHashChain* const p, int size) {
  171. assert(p->size_ == 0);
  172. assert(p->offset_length_ == NULL);
  173. assert(size > 0);
  174. p->offset_length_ =
  175. (uint32_t*)WebPSafeMalloc(size, sizeof(*p->offset_length_));
  176. if (p->offset_length_ == NULL) return 0;
  177. p->size_ = size;
  178. return 1;
  179. }
  180. void VP8LHashChainClear(VP8LHashChain* const p) {
  181. assert(p != NULL);
  182. WebPSafeFree(p->offset_length_);
  183. p->size_ = 0;
  184. p->offset_length_ = NULL;
  185. }
  186. // -----------------------------------------------------------------------------
  187. #define HASH_MULTIPLIER_HI (0xc6a4a793ULL)
  188. #define HASH_MULTIPLIER_LO (0x5bd1e996ULL)
  189. static WEBP_INLINE uint32_t GetPixPairHash64(const uint32_t* const argb) {
  190. uint32_t key;
  191. key = (argb[1] * HASH_MULTIPLIER_HI) & 0xffffffffu;
  192. key += (argb[0] * HASH_MULTIPLIER_LO) & 0xffffffffu;
  193. key = key >> (32 - HASH_BITS);
  194. return key;
  195. }
  196. // Returns the maximum number of hash chain lookups to do for a
  197. // given compression quality. Return value in range [8, 86].
  198. static int GetMaxItersForQuality(int quality) {
  199. return 8 + (quality * quality) / 128;
  200. }
  201. static int GetWindowSizeForHashChain(int quality, int xsize) {
  202. const int max_window_size = (quality > 75) ? WINDOW_SIZE
  203. : (quality > 50) ? (xsize << 8)
  204. : (quality > 25) ? (xsize << 6)
  205. : (xsize << 4);
  206. assert(xsize > 0);
  207. return (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size;
  208. }
  209. static WEBP_INLINE int MaxFindCopyLength(int len) {
  210. return (len < MAX_LENGTH) ? len : MAX_LENGTH;
  211. }
  212. int VP8LHashChainFill(VP8LHashChain* const p, int quality,
  213. const uint32_t* const argb, int xsize, int ysize,
  214. int low_effort) {
  215. const int size = xsize * ysize;
  216. const int iter_max = GetMaxItersForQuality(quality);
  217. const uint32_t window_size = GetWindowSizeForHashChain(quality, xsize);
  218. int pos;
  219. int argb_comp;
  220. uint32_t base_position;
  221. int32_t* hash_to_first_index;
  222. // Temporarily use the p->offset_length_ as a hash chain.
  223. int32_t* chain = (int32_t*)p->offset_length_;
  224. assert(size > 0);
  225. assert(p->size_ != 0);
  226. assert(p->offset_length_ != NULL);
  227. if (size <= 2) {
  228. p->offset_length_[0] = p->offset_length_[size - 1] = 0;
  229. return 1;
  230. }
  231. hash_to_first_index =
  232. (int32_t*)WebPSafeMalloc(HASH_SIZE, sizeof(*hash_to_first_index));
  233. if (hash_to_first_index == NULL) return 0;
  234. // Set the int32_t array to -1.
  235. memset(hash_to_first_index, 0xff, HASH_SIZE * sizeof(*hash_to_first_index));
  236. // Fill the chain linking pixels with the same hash.
  237. argb_comp = (argb[0] == argb[1]);
  238. for (pos = 0; pos < size - 2;) {
  239. uint32_t hash_code;
  240. const int argb_comp_next = (argb[pos + 1] == argb[pos + 2]);
  241. if (argb_comp && argb_comp_next) {
  242. // Consecutive pixels with the same color will share the same hash.
  243. // We therefore use a different hash: the color and its repetition
  244. // length.
  245. uint32_t tmp[2];
  246. uint32_t len = 1;
  247. tmp[0] = argb[pos];
  248. // Figure out how far the pixels are the same.
  249. // The last pixel has a different 64 bit hash, as its next pixel does
  250. // not have the same color, so we just need to get to the last pixel equal
  251. // to its follower.
  252. while (pos + (int)len + 2 < size && argb[pos + len + 2] == argb[pos]) {
  253. ++len;
  254. }
  255. if (len > MAX_LENGTH) {
  256. // Skip the pixels that match for distance=1 and length>MAX_LENGTH
  257. // because they are linked to their predecessor and we automatically
  258. // check that in the main for loop below. Skipping means setting no
  259. // predecessor in the chain, hence -1.
  260. memset(chain + pos, 0xff, (len - MAX_LENGTH) * sizeof(*chain));
  261. pos += len - MAX_LENGTH;
  262. len = MAX_LENGTH;
  263. }
  264. // Process the rest of the hash chain.
  265. while (len) {
  266. tmp[1] = len--;
  267. hash_code = GetPixPairHash64(tmp);
  268. chain[pos] = hash_to_first_index[hash_code];
  269. hash_to_first_index[hash_code] = pos++;
  270. }
  271. argb_comp = 0;
  272. } else {
  273. // Just move one pixel forward.
  274. hash_code = GetPixPairHash64(argb + pos);
  275. chain[pos] = hash_to_first_index[hash_code];
  276. hash_to_first_index[hash_code] = pos++;
  277. argb_comp = argb_comp_next;
  278. }
  279. }
  280. // Process the penultimate pixel.
  281. chain[pos] = hash_to_first_index[GetPixPairHash64(argb + pos)];
  282. WebPSafeFree(hash_to_first_index);
  283. // Find the best match interval at each pixel, defined by an offset to the
  284. // pixel and a length. The right-most pixel cannot match anything to the right
  285. // (hence a best length of 0) and the left-most pixel nothing to the left
  286. // (hence an offset of 0).
  287. assert(size > 2);
  288. p->offset_length_[0] = p->offset_length_[size - 1] = 0;
  289. for (base_position = size - 2; base_position > 0;) {
  290. const int max_len = MaxFindCopyLength(size - 1 - base_position);
  291. const uint32_t* const argb_start = argb + base_position;
  292. int iter = iter_max;
  293. int best_length = 0;
  294. uint32_t best_distance = 0;
  295. uint32_t best_argb;
  296. const int min_pos =
  297. (base_position > window_size) ? base_position - window_size : 0;
  298. const int length_max = (max_len < 256) ? max_len : 256;
  299. uint32_t max_base_position;
  300. pos = chain[base_position];
  301. if (!low_effort) {
  302. int curr_length;
  303. // Heuristic: use the comparison with the above line as an initialization.
  304. if (base_position >= (uint32_t)xsize) {
  305. curr_length = FindMatchLength(argb_start - xsize, argb_start,
  306. best_length, max_len);
  307. if (curr_length > best_length) {
  308. best_length = curr_length;
  309. best_distance = xsize;
  310. }
  311. --iter;
  312. }
  313. // Heuristic: compare to the previous pixel.
  314. curr_length =
  315. FindMatchLength(argb_start - 1, argb_start, best_length, max_len);
  316. if (curr_length > best_length) {
  317. best_length = curr_length;
  318. best_distance = 1;
  319. }
  320. --iter;
  321. // Skip the for loop if we already have the maximum.
  322. if (best_length == MAX_LENGTH) pos = min_pos - 1;
  323. }
  324. best_argb = argb_start[best_length];
  325. for (; pos >= min_pos && --iter; pos = chain[pos]) {
  326. int curr_length;
  327. assert(base_position > (uint32_t)pos);
  328. if (argb[pos + best_length] != best_argb) continue;
  329. curr_length = VP8LVectorMismatch(argb + pos, argb_start, max_len);
  330. if (best_length < curr_length) {
  331. best_length = curr_length;
  332. best_distance = base_position - pos;
  333. best_argb = argb_start[best_length];
  334. // Stop if we have reached a good enough length.
  335. if (best_length >= length_max) break;
  336. }
  337. }
  338. // We have the best match but in case the two intervals continue matching
  339. // to the left, we have the best matches for the left-extended pixels.
  340. max_base_position = base_position;
  341. while (1) {
  342. assert(best_length <= MAX_LENGTH);
  343. assert(best_distance <= WINDOW_SIZE);
  344. p->offset_length_[base_position] =
  345. (best_distance << MAX_LENGTH_BITS) | (uint32_t)best_length;
  346. --base_position;
  347. // Stop if we don't have a match or if we are out of bounds.
  348. if (best_distance == 0 || base_position == 0) break;
  349. // Stop if we cannot extend the matching intervals to the left.
  350. if (base_position < best_distance ||
  351. argb[base_position - best_distance] != argb[base_position]) {
  352. break;
  353. }
  354. // Stop if we are matching at its limit because there could be a closer
  355. // matching interval with the same maximum length. Then again, if the
  356. // matching interval is as close as possible (best_distance == 1), we will
  357. // never find anything better so let's continue.
  358. if (best_length == MAX_LENGTH && best_distance != 1 &&
  359. base_position + MAX_LENGTH < max_base_position) {
  360. break;
  361. }
  362. if (best_length < MAX_LENGTH) {
  363. ++best_length;
  364. max_base_position = base_position;
  365. }
  366. }
  367. }
  368. return 1;
  369. }
  370. static WEBP_INLINE int HashChainFindOffset(const VP8LHashChain* const p,
  371. const int base_position) {
  372. return p->offset_length_[base_position] >> MAX_LENGTH_BITS;
  373. }
  374. static WEBP_INLINE int HashChainFindLength(const VP8LHashChain* const p,
  375. const int base_position) {
  376. return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1);
  377. }
  378. static WEBP_INLINE void HashChainFindCopy(const VP8LHashChain* const p,
  379. int base_position,
  380. int* const offset_ptr,
  381. int* const length_ptr) {
  382. *offset_ptr = HashChainFindOffset(p, base_position);
  383. *length_ptr = HashChainFindLength(p, base_position);
  384. }
  385. static WEBP_INLINE void AddSingleLiteral(uint32_t pixel, int use_color_cache,
  386. VP8LColorCache* const hashers,
  387. VP8LBackwardRefs* const refs) {
  388. PixOrCopy v;
  389. if (use_color_cache) {
  390. const uint32_t key = VP8LColorCacheGetIndex(hashers, pixel);
  391. if (VP8LColorCacheLookup(hashers, key) == pixel) {
  392. v = PixOrCopyCreateCacheIdx(key);
  393. } else {
  394. v = PixOrCopyCreateLiteral(pixel);
  395. VP8LColorCacheSet(hashers, key, pixel);
  396. }
  397. } else {
  398. v = PixOrCopyCreateLiteral(pixel);
  399. }
  400. BackwardRefsCursorAdd(refs, v);
  401. }
  402. static int BackwardReferencesRle(int xsize, int ysize,
  403. const uint32_t* const argb,
  404. int cache_bits, VP8LBackwardRefs* const refs) {
  405. const int pix_count = xsize * ysize;
  406. int i, k;
  407. const int use_color_cache = (cache_bits > 0);
  408. VP8LColorCache hashers;
  409. if (use_color_cache && !VP8LColorCacheInit(&hashers, cache_bits)) {
  410. return 0;
  411. }
  412. ClearBackwardRefs(refs);
  413. // Add first pixel as literal.
  414. AddSingleLiteral(argb[0], use_color_cache, &hashers, refs);
  415. i = 1;
  416. while (i < pix_count) {
  417. const int max_len = MaxFindCopyLength(pix_count - i);
  418. const int rle_len = FindMatchLength(argb + i, argb + i - 1, 0, max_len);
  419. const int prev_row_len = (i < xsize) ? 0 :
  420. FindMatchLength(argb + i, argb + i - xsize, 0, max_len);
  421. if (rle_len >= prev_row_len && rle_len >= MIN_LENGTH) {
  422. BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, rle_len));
  423. // We don't need to update the color cache here since it is always the
  424. // same pixel being copied, and that does not change the color cache
  425. // state.
  426. i += rle_len;
  427. } else if (prev_row_len >= MIN_LENGTH) {
  428. BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(xsize, prev_row_len));
  429. if (use_color_cache) {
  430. for (k = 0; k < prev_row_len; ++k) {
  431. VP8LColorCacheInsert(&hashers, argb[i + k]);
  432. }
  433. }
  434. i += prev_row_len;
  435. } else {
  436. AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
  437. i++;
  438. }
  439. }
  440. if (use_color_cache) VP8LColorCacheClear(&hashers);
  441. return !refs->error_;
  442. }
  443. static int BackwardReferencesLz77(int xsize, int ysize,
  444. const uint32_t* const argb, int cache_bits,
  445. const VP8LHashChain* const hash_chain,
  446. VP8LBackwardRefs* const refs) {
  447. int i;
  448. int i_last_check = -1;
  449. int ok = 0;
  450. int cc_init = 0;
  451. const int use_color_cache = (cache_bits > 0);
  452. const int pix_count = xsize * ysize;
  453. VP8LColorCache hashers;
  454. if (use_color_cache) {
  455. cc_init = VP8LColorCacheInit(&hashers, cache_bits);
  456. if (!cc_init) goto Error;
  457. }
  458. ClearBackwardRefs(refs);
  459. for (i = 0; i < pix_count;) {
  460. // Alternative#1: Code the pixels starting at 'i' using backward reference.
  461. int offset = 0;
  462. int len = 0;
  463. int j;
  464. HashChainFindCopy(hash_chain, i, &offset, &len);
  465. if (len >= MIN_LENGTH) {
  466. const int len_ini = len;
  467. int max_reach = 0;
  468. assert(i + len < pix_count);
  469. // Only start from what we have not checked already.
  470. i_last_check = (i > i_last_check) ? i : i_last_check;
  471. // We know the best match for the current pixel but we try to find the
  472. // best matches for the current pixel AND the next one combined.
  473. // The naive method would use the intervals:
  474. // [i,i+len) + [i+len, length of best match at i+len)
  475. // while we check if we can use:
  476. // [i,j) (where j<=i+len) + [j, length of best match at j)
  477. for (j = i_last_check + 1; j <= i + len_ini; ++j) {
  478. const int len_j = HashChainFindLength(hash_chain, j);
  479. const int reach =
  480. j + (len_j >= MIN_LENGTH ? len_j : 1); // 1 for single literal.
  481. if (reach > max_reach) {
  482. len = j - i;
  483. max_reach = reach;
  484. }
  485. }
  486. } else {
  487. len = 1;
  488. }
  489. // Go with literal or backward reference.
  490. assert(len > 0);
  491. if (len == 1) {
  492. AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
  493. } else {
  494. BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
  495. if (use_color_cache) {
  496. for (j = i; j < i + len; ++j) VP8LColorCacheInsert(&hashers, argb[j]);
  497. }
  498. }
  499. i += len;
  500. }
  501. ok = !refs->error_;
  502. Error:
  503. if (cc_init) VP8LColorCacheClear(&hashers);
  504. return ok;
  505. }
  506. // -----------------------------------------------------------------------------
  507. typedef struct {
  508. double alpha_[VALUES_IN_BYTE];
  509. double red_[VALUES_IN_BYTE];
  510. double blue_[VALUES_IN_BYTE];
  511. double distance_[NUM_DISTANCE_CODES];
  512. double* literal_;
  513. } CostModel;
  514. static int BackwardReferencesTraceBackwards(
  515. int xsize, int ysize, const uint32_t* const argb, int quality,
  516. int cache_bits, const VP8LHashChain* const hash_chain,
  517. VP8LBackwardRefs* const refs);
  518. static void ConvertPopulationCountTableToBitEstimates(
  519. int num_symbols, const uint32_t population_counts[], double output[]) {
  520. uint32_t sum = 0;
  521. int nonzeros = 0;
  522. int i;
  523. for (i = 0; i < num_symbols; ++i) {
  524. sum += population_counts[i];
  525. if (population_counts[i] > 0) {
  526. ++nonzeros;
  527. }
  528. }
  529. if (nonzeros <= 1) {
  530. memset(output, 0, num_symbols * sizeof(*output));
  531. } else {
  532. const double logsum = VP8LFastLog2(sum);
  533. for (i = 0; i < num_symbols; ++i) {
  534. output[i] = logsum - VP8LFastLog2(population_counts[i]);
  535. }
  536. }
  537. }
  538. static int CostModelBuild(CostModel* const m, int cache_bits,
  539. VP8LBackwardRefs* const refs) {
  540. int ok = 0;
  541. VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits);
  542. if (histo == NULL) goto Error;
  543. VP8LHistogramCreate(histo, refs, cache_bits);
  544. ConvertPopulationCountTableToBitEstimates(
  545. VP8LHistogramNumCodes(histo->palette_code_bits_),
  546. histo->literal_, m->literal_);
  547. ConvertPopulationCountTableToBitEstimates(
  548. VALUES_IN_BYTE, histo->red_, m->red_);
  549. ConvertPopulationCountTableToBitEstimates(
  550. VALUES_IN_BYTE, histo->blue_, m->blue_);
  551. ConvertPopulationCountTableToBitEstimates(
  552. VALUES_IN_BYTE, histo->alpha_, m->alpha_);
  553. ConvertPopulationCountTableToBitEstimates(
  554. NUM_DISTANCE_CODES, histo->distance_, m->distance_);
  555. ok = 1;
  556. Error:
  557. VP8LFreeHistogram(histo);
  558. return ok;
  559. }
  560. static WEBP_INLINE double GetLiteralCost(const CostModel* const m, uint32_t v) {
  561. return m->alpha_[v >> 24] +
  562. m->red_[(v >> 16) & 0xff] +
  563. m->literal_[(v >> 8) & 0xff] +
  564. m->blue_[v & 0xff];
  565. }
  566. static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) {
  567. const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx;
  568. return m->literal_[literal_idx];
  569. }
  570. static WEBP_INLINE double GetLengthCost(const CostModel* const m,
  571. uint32_t length) {
  572. int code, extra_bits;
  573. VP8LPrefixEncodeBits(length, &code, &extra_bits);
  574. return m->literal_[VALUES_IN_BYTE + code] + extra_bits;
  575. }
  576. static WEBP_INLINE double GetDistanceCost(const CostModel* const m,
  577. uint32_t distance) {
  578. int code, extra_bits;
  579. VP8LPrefixEncodeBits(distance, &code, &extra_bits);
  580. return m->distance_[code] + extra_bits;
  581. }
  582. static void AddSingleLiteralWithCostModel(const uint32_t* const argb,
  583. VP8LColorCache* const hashers,
  584. const CostModel* const cost_model,
  585. int idx, int use_color_cache,
  586. double prev_cost, float* const cost,
  587. uint16_t* const dist_array) {
  588. double cost_val = prev_cost;
  589. const uint32_t color = argb[0];
  590. const int ix = use_color_cache ? VP8LColorCacheContains(hashers, color) : -1;
  591. if (ix >= 0) {
  592. // use_color_cache is true and hashers contains color
  593. const double mul0 = 0.68;
  594. cost_val += GetCacheCost(cost_model, ix) * mul0;
  595. } else {
  596. const double mul1 = 0.82;
  597. if (use_color_cache) VP8LColorCacheInsert(hashers, color);
  598. cost_val += GetLiteralCost(cost_model, color) * mul1;
  599. }
  600. if (cost[idx] > cost_val) {
  601. cost[idx] = (float)cost_val;
  602. dist_array[idx] = 1; // only one is inserted.
  603. }
  604. }
  605. // -----------------------------------------------------------------------------
  606. // CostManager and interval handling
  607. // Empirical value to avoid high memory consumption but good for performance.
  608. #define COST_CACHE_INTERVAL_SIZE_MAX 100
  609. // To perform backward reference every pixel at index index_ is considered and
  610. // the cost for the MAX_LENGTH following pixels computed. Those following pixels
  611. // at index index_ + k (k from 0 to MAX_LENGTH) have a cost of:
  612. // distance_cost_ at index_ + GetLengthCost(cost_model, k)
  613. // (named cost) (named cached cost)
  614. // and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an
  615. // array of size MAX_LENGTH.
  616. // Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the
  617. // minimal values using intervals, for which lower_ and upper_ bounds are kept.
  618. // An interval is defined by the index_ of the pixel that generated it and
  619. // is only useful in a range of indices from start_ to end_ (exclusive), i.e.
  620. // it contains the minimum value for pixels between start_ and end_.
  621. // Intervals are stored in a linked list and ordered by start_. When a new
  622. // interval has a better minimum, old intervals are split or removed.
  623. typedef struct CostInterval CostInterval;
  624. struct CostInterval {
  625. double lower_;
  626. double upper_;
  627. int start_;
  628. int end_;
  629. double distance_cost_;
  630. int index_;
  631. CostInterval* previous_;
  632. CostInterval* next_;
  633. };
  634. // The GetLengthCost(cost_model, k) part of the costs is also bounded for
  635. // efficiency in a set of intervals of a different type.
  636. // If those intervals are small enough, they are not used for comparison and
  637. // written into the costs right away.
  638. typedef struct {
  639. double lower_; // Lower bound of the interval.
  640. double upper_; // Upper bound of the interval.
  641. int start_;
  642. int end_; // Exclusive.
  643. int do_write_; // If !=0, the interval is saved to cost instead of being kept
  644. // for comparison.
  645. } CostCacheInterval;
  646. // This structure is in charge of managing intervals and costs.
  647. // It caches the different CostCacheInterval, caches the different
  648. // GetLengthCost(cost_model, k) in cost_cache_ and the CostInterval's (whose
  649. // count_ is limited by COST_CACHE_INTERVAL_SIZE_MAX).
  650. #define COST_MANAGER_MAX_FREE_LIST 10
  651. typedef struct {
  652. CostInterval* head_;
  653. int count_; // The number of stored intervals.
  654. CostCacheInterval* cache_intervals_;
  655. size_t cache_intervals_size_;
  656. double cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k).
  657. double min_cost_cache_; // The minimum value in cost_cache_[1:].
  658. double max_cost_cache_; // The maximum value in cost_cache_[1:].
  659. float* costs_;
  660. uint16_t* dist_array_;
  661. // Most of the time, we only need few intervals -> use a free-list, to avoid
  662. // fragmentation with small allocs in most common cases.
  663. CostInterval intervals_[COST_MANAGER_MAX_FREE_LIST];
  664. CostInterval* free_intervals_;
  665. // These are regularly malloc'd remains. This list can't grow larger than than
  666. // size COST_CACHE_INTERVAL_SIZE_MAX - COST_MANAGER_MAX_FREE_LIST, note.
  667. CostInterval* recycled_intervals_;
  668. // Buffer used in BackwardReferencesHashChainDistanceOnly to store the ends
  669. // of the intervals that can have impacted the cost at a pixel.
  670. int* interval_ends_;
  671. int interval_ends_size_;
  672. } CostManager;
  673. static int IsCostCacheIntervalWritable(int start, int end) {
  674. // 100 is the length for which we consider an interval for comparison, and not
  675. // for writing.
  676. // The first intervals are very small and go in increasing size. This constant
  677. // helps merging them into one big interval (up to index 150/200 usually from
  678. // which intervals start getting much bigger).
  679. // This value is empirical.
  680. return (end - start + 1 < 100);
  681. }
  682. static void CostIntervalAddToFreeList(CostManager* const manager,
  683. CostInterval* const interval) {
  684. interval->next_ = manager->free_intervals_;
  685. manager->free_intervals_ = interval;
  686. }
  687. static int CostIntervalIsInFreeList(const CostManager* const manager,
  688. const CostInterval* const interval) {
  689. return (interval >= &manager->intervals_[0] &&
  690. interval <= &manager->intervals_[COST_MANAGER_MAX_FREE_LIST - 1]);
  691. }
  692. static void CostManagerInitFreeList(CostManager* const manager) {
  693. int i;
  694. manager->free_intervals_ = NULL;
  695. for (i = 0; i < COST_MANAGER_MAX_FREE_LIST; ++i) {
  696. CostIntervalAddToFreeList(manager, &manager->intervals_[i]);
  697. }
  698. }
  699. static void DeleteIntervalList(CostManager* const manager,
  700. const CostInterval* interval) {
  701. while (interval != NULL) {
  702. const CostInterval* const next = interval->next_;
  703. if (!CostIntervalIsInFreeList(manager, interval)) {
  704. WebPSafeFree((void*)interval);
  705. } // else: do nothing
  706. interval = next;
  707. }
  708. }
  709. static void CostManagerClear(CostManager* const manager) {
  710. if (manager == NULL) return;
  711. WebPSafeFree(manager->costs_);
  712. WebPSafeFree(manager->cache_intervals_);
  713. WebPSafeFree(manager->interval_ends_);
  714. // Clear the interval lists.
  715. DeleteIntervalList(manager, manager->head_);
  716. manager->head_ = NULL;
  717. DeleteIntervalList(manager, manager->recycled_intervals_);
  718. manager->recycled_intervals_ = NULL;
  719. // Reset pointers, count_ and cache_intervals_size_.
  720. memset(manager, 0, sizeof(*manager));
  721. CostManagerInitFreeList(manager);
  722. }
  723. static int CostManagerInit(CostManager* const manager,
  724. uint16_t* const dist_array, int pix_count,
  725. const CostModel* const cost_model) {
  726. int i;
  727. const int cost_cache_size = (pix_count > MAX_LENGTH) ? MAX_LENGTH : pix_count;
  728. // This constant is tied to the cost_model we use.
  729. // Empirically, differences between intervals is usually of more than 1.
  730. const double min_cost_diff = 0.1;
  731. manager->costs_ = NULL;
  732. manager->cache_intervals_ = NULL;
  733. manager->interval_ends_ = NULL;
  734. manager->head_ = NULL;
  735. manager->recycled_intervals_ = NULL;
  736. manager->count_ = 0;
  737. manager->dist_array_ = dist_array;
  738. CostManagerInitFreeList(manager);
  739. // Fill in the cost_cache_.
  740. manager->cache_intervals_size_ = 1;
  741. manager->cost_cache_[0] = 0;
  742. for (i = 1; i < cost_cache_size; ++i) {
  743. manager->cost_cache_[i] = GetLengthCost(cost_model, i);
  744. // Get an approximation of the number of bound intervals.
  745. if (fabs(manager->cost_cache_[i] - manager->cost_cache_[i - 1]) >
  746. min_cost_diff) {
  747. ++manager->cache_intervals_size_;
  748. }
  749. // Compute the minimum of cost_cache_.
  750. if (i == 1) {
  751. manager->min_cost_cache_ = manager->cost_cache_[1];
  752. manager->max_cost_cache_ = manager->cost_cache_[1];
  753. } else if (manager->cost_cache_[i] < manager->min_cost_cache_) {
  754. manager->min_cost_cache_ = manager->cost_cache_[i];
  755. } else if (manager->cost_cache_[i] > manager->max_cost_cache_) {
  756. manager->max_cost_cache_ = manager->cost_cache_[i];
  757. }
  758. }
  759. // With the current cost models, we have 15 intervals, so we are safe by
  760. // setting a maximum of COST_CACHE_INTERVAL_SIZE_MAX.
  761. if (manager->cache_intervals_size_ > COST_CACHE_INTERVAL_SIZE_MAX) {
  762. manager->cache_intervals_size_ = COST_CACHE_INTERVAL_SIZE_MAX;
  763. }
  764. manager->cache_intervals_ = (CostCacheInterval*)WebPSafeMalloc(
  765. manager->cache_intervals_size_, sizeof(*manager->cache_intervals_));
  766. if (manager->cache_intervals_ == NULL) {
  767. CostManagerClear(manager);
  768. return 0;
  769. }
  770. // Fill in the cache_intervals_.
  771. {
  772. double cost_prev = -1e38f; // unprobably low initial value
  773. CostCacheInterval* prev = NULL;
  774. CostCacheInterval* cur = manager->cache_intervals_;
  775. const CostCacheInterval* const end =
  776. manager->cache_intervals_ + manager->cache_intervals_size_;
  777. // Consecutive values in cost_cache_ are compared and if a big enough
  778. // difference is found, a new interval is created and bounded.
  779. for (i = 0; i < cost_cache_size; ++i) {
  780. const double cost_val = manager->cost_cache_[i];
  781. if (i == 0 ||
  782. (fabs(cost_val - cost_prev) > min_cost_diff && cur + 1 < end)) {
  783. if (i > 1) {
  784. const int is_writable =
  785. IsCostCacheIntervalWritable(cur->start_, cur->end_);
  786. // Merge with the previous interval if both are writable.
  787. if (is_writable && cur != manager->cache_intervals_ &&
  788. prev->do_write_) {
  789. // Update the previous interval.
  790. prev->end_ = cur->end_;
  791. if (cur->lower_ < prev->lower_) {
  792. prev->lower_ = cur->lower_;
  793. } else if (cur->upper_ > prev->upper_) {
  794. prev->upper_ = cur->upper_;
  795. }
  796. } else {
  797. cur->do_write_ = is_writable;
  798. prev = cur;
  799. ++cur;
  800. }
  801. }
  802. // Initialize an interval.
  803. cur->start_ = i;
  804. cur->do_write_ = 0;
  805. cur->lower_ = cost_val;
  806. cur->upper_ = cost_val;
  807. } else {
  808. // Update the current interval bounds.
  809. if (cost_val < cur->lower_) {
  810. cur->lower_ = cost_val;
  811. } else if (cost_val > cur->upper_) {
  812. cur->upper_ = cost_val;
  813. }
  814. }
  815. cur->end_ = i + 1;
  816. cost_prev = cost_val;
  817. }
  818. manager->cache_intervals_size_ = cur + 1 - manager->cache_intervals_;
  819. }
  820. manager->costs_ = (float*)WebPSafeMalloc(pix_count, sizeof(*manager->costs_));
  821. if (manager->costs_ == NULL) {
  822. CostManagerClear(manager);
  823. return 0;
  824. }
  825. // Set the initial costs_ high for every pixel as we will keep the minimum.
  826. for (i = 0; i < pix_count; ++i) manager->costs_[i] = 1e38f;
  827. // The cost at pixel is influenced by the cost intervals from previous pixels.
  828. // Let us take the specific case where the offset is the same (which actually
  829. // happens a lot in case of uniform regions).
  830. // pixel i contributes to j>i a cost of: offset cost + cost_cache_[j-i]
  831. // pixel i+1 contributes to j>i a cost of: 2*offset cost + cost_cache_[j-i-1]
  832. // pixel i+2 contributes to j>i a cost of: 3*offset cost + cost_cache_[j-i-2]
  833. // and so on.
  834. // A pixel i influences the following length(j) < MAX_LENGTH pixels. What is
  835. // the value of j such that pixel i + j cannot influence any of those pixels?
  836. // This value is such that:
  837. // max of cost_cache_ < j*offset cost + min of cost_cache_
  838. // (pixel i + j 's cost cannot beat the worst cost given by pixel i).
  839. // This value will be used to optimize the cost computation in
  840. // BackwardReferencesHashChainDistanceOnly.
  841. {
  842. // The offset cost is computed in GetDistanceCost and has a minimum value of
  843. // the minimum in cost_model->distance_. The case where the offset cost is 0
  844. // will be dealt with differently later so we are only interested in the
  845. // minimum non-zero offset cost.
  846. double offset_cost_min = 0.;
  847. int size;
  848. for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
  849. if (cost_model->distance_[i] != 0) {
  850. if (offset_cost_min == 0.) {
  851. offset_cost_min = cost_model->distance_[i];
  852. } else if (cost_model->distance_[i] < offset_cost_min) {
  853. offset_cost_min = cost_model->distance_[i];
  854. }
  855. }
  856. }
  857. // In case all the cost_model->distance_ is 0, the next non-zero cost we
  858. // can have is from the extra bit in GetDistanceCost, hence 1.
  859. if (offset_cost_min < 1.) offset_cost_min = 1.;
  860. size = 1 + (int)ceil((manager->max_cost_cache_ - manager->min_cost_cache_) /
  861. offset_cost_min);
  862. // Empirically, we usually end up with a value below 100.
  863. if (size > MAX_LENGTH) size = MAX_LENGTH;
  864. manager->interval_ends_ =
  865. (int*)WebPSafeMalloc(size, sizeof(*manager->interval_ends_));
  866. if (manager->interval_ends_ == NULL) {
  867. CostManagerClear(manager);
  868. return 0;
  869. }
  870. manager->interval_ends_size_ = size;
  871. }
  872. return 1;
  873. }
  874. // Given the distance_cost for pixel 'index', update the cost at pixel 'i' if it
  875. // is smaller than the previously computed value.
  876. static WEBP_INLINE void UpdateCost(CostManager* const manager, int i, int index,
  877. double distance_cost) {
  878. int k = i - index;
  879. double cost_tmp;
  880. assert(k >= 0 && k < MAX_LENGTH);
  881. cost_tmp = distance_cost + manager->cost_cache_[k];
  882. if (manager->costs_[i] > cost_tmp) {
  883. manager->costs_[i] = (float)cost_tmp;
  884. manager->dist_array_[i] = k + 1;
  885. }
  886. }
  887. // Given the distance_cost for pixel 'index', update the cost for all the pixels
  888. // between 'start' and 'end' excluded.
  889. static WEBP_INLINE void UpdateCostPerInterval(CostManager* const manager,
  890. int start, int end, int index,
  891. double distance_cost) {
  892. int i;
  893. for (i = start; i < end; ++i) UpdateCost(manager, i, index, distance_cost);
  894. }
  895. // Given two intervals, make 'prev' be the previous one of 'next' in 'manager'.
  896. static WEBP_INLINE void ConnectIntervals(CostManager* const manager,
  897. CostInterval* const prev,
  898. CostInterval* const next) {
  899. if (prev != NULL) {
  900. prev->next_ = next;
  901. } else {
  902. manager->head_ = next;
  903. }
  904. if (next != NULL) next->previous_ = prev;
  905. }
  906. // Pop an interval in the manager.
  907. static WEBP_INLINE void PopInterval(CostManager* const manager,
  908. CostInterval* const interval) {
  909. CostInterval* const next = interval->next_;
  910. if (interval == NULL) return;
  911. ConnectIntervals(manager, interval->previous_, next);
  912. if (CostIntervalIsInFreeList(manager, interval)) {
  913. CostIntervalAddToFreeList(manager, interval);
  914. } else { // recycle regularly malloc'd intervals too
  915. interval->next_ = manager->recycled_intervals_;
  916. manager->recycled_intervals_ = interval;
  917. }
  918. --manager->count_;
  919. assert(manager->count_ >= 0);
  920. }
  921. // Update the cost at index i by going over all the stored intervals that
  922. // overlap with i.
  923. static WEBP_INLINE void UpdateCostPerIndex(CostManager* const manager, int i) {
  924. CostInterval* current = manager->head_;
  925. while (current != NULL && current->start_ <= i) {
  926. if (current->end_ <= i) {
  927. // We have an outdated interval, remove it.
  928. CostInterval* next = current->next_;
  929. PopInterval(manager, current);
  930. current = next;
  931. } else {
  932. UpdateCost(manager, i, current->index_, current->distance_cost_);
  933. current = current->next_;
  934. }
  935. }
  936. }
  937. // Given a current orphan interval and its previous interval, before
  938. // it was orphaned (which can be NULL), set it at the right place in the list
  939. // of intervals using the start_ ordering and the previous interval as a hint.
  940. static WEBP_INLINE void PositionOrphanInterval(CostManager* const manager,
  941. CostInterval* const current,
  942. CostInterval* previous) {
  943. assert(current != NULL);
  944. if (previous == NULL) previous = manager->head_;
  945. while (previous != NULL && current->start_ < previous->start_) {
  946. previous = previous->previous_;
  947. }
  948. while (previous != NULL && previous->next_ != NULL &&
  949. previous->next_->start_ < current->start_) {
  950. previous = previous->next_;
  951. }
  952. if (previous != NULL) {
  953. ConnectIntervals(manager, current, previous->next_);
  954. } else {
  955. ConnectIntervals(manager, current, manager->head_);
  956. }
  957. ConnectIntervals(manager, previous, current);
  958. }
  959. // Insert an interval in the list contained in the manager by starting at
  960. // interval_in as a hint. The intervals are sorted by start_ value.
  961. static WEBP_INLINE void InsertInterval(CostManager* const manager,
  962. CostInterval* const interval_in,
  963. double distance_cost, double lower,
  964. double upper, int index, int start,
  965. int end) {
  966. CostInterval* interval_new;
  967. if (IsCostCacheIntervalWritable(start, end) ||
  968. manager->count_ >= COST_CACHE_INTERVAL_SIZE_MAX) {
  969. // Write down the interval if it is too small.
  970. UpdateCostPerInterval(manager, start, end, index, distance_cost);
  971. return;
  972. }
  973. if (manager->free_intervals_ != NULL) {
  974. interval_new = manager->free_intervals_;
  975. manager->free_intervals_ = interval_new->next_;
  976. } else if (manager->recycled_intervals_ != NULL) {
  977. interval_new = manager->recycled_intervals_;
  978. manager->recycled_intervals_ = interval_new->next_;
  979. } else { // malloc for good
  980. interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new));
  981. if (interval_new == NULL) {
  982. // Write down the interval if we cannot create it.
  983. UpdateCostPerInterval(manager, start, end, index, distance_cost);
  984. return;
  985. }
  986. }
  987. interval_new->distance_cost_ = distance_cost;
  988. interval_new->lower_ = lower;
  989. interval_new->upper_ = upper;
  990. interval_new->index_ = index;
  991. interval_new->start_ = start;
  992. interval_new->end_ = end;
  993. PositionOrphanInterval(manager, interval_new, interval_in);
  994. ++manager->count_;
  995. }
  996. // When an interval has its start_ or end_ modified, it needs to be
  997. // repositioned in the linked list.
  998. static WEBP_INLINE void RepositionInterval(CostManager* const manager,
  999. CostInterval* const interval) {
  1000. if (IsCostCacheIntervalWritable(interval->start_, interval->end_)) {
  1001. // Maybe interval has been resized and is small enough to be removed.
  1002. UpdateCostPerInterval(manager, interval->start_, interval->end_,
  1003. interval->index_, interval->distance_cost_);
  1004. PopInterval(manager, interval);
  1005. return;
  1006. }
  1007. // Early exit if interval is at the right spot.
  1008. if ((interval->previous_ == NULL ||
  1009. interval->previous_->start_ <= interval->start_) &&
  1010. (interval->next_ == NULL ||
  1011. interval->start_ <= interval->next_->start_)) {
  1012. return;
  1013. }
  1014. ConnectIntervals(manager, interval->previous_, interval->next_);
  1015. PositionOrphanInterval(manager, interval, interval->previous_);
  1016. }
  1017. // Given a new cost interval defined by its start at index, its last value and
  1018. // distance_cost, add its contributions to the previous intervals and costs.
  1019. // If handling the interval or one of its subintervals becomes to heavy, its
  1020. // contribution is added to the costs right away.
  1021. static WEBP_INLINE void PushInterval(CostManager* const manager,
  1022. double distance_cost, int index,
  1023. int last) {
  1024. size_t i;
  1025. CostInterval* interval = manager->head_;
  1026. CostInterval* interval_next;
  1027. const CostCacheInterval* const cost_cache_intervals =
  1028. manager->cache_intervals_;
  1029. for (i = 0; i < manager->cache_intervals_size_ &&
  1030. cost_cache_intervals[i].start_ < last;
  1031. ++i) {
  1032. // Define the intersection of the ith interval with the new one.
  1033. int start = index + cost_cache_intervals[i].start_;
  1034. const int end = index + (cost_cache_intervals[i].end_ > last
  1035. ? last
  1036. : cost_cache_intervals[i].end_);
  1037. const double lower_in = cost_cache_intervals[i].lower_;
  1038. const double upper_in = cost_cache_intervals[i].upper_;
  1039. const double lower_full_in = distance_cost + lower_in;
  1040. const double upper_full_in = distance_cost + upper_in;
  1041. if (cost_cache_intervals[i].do_write_) {
  1042. UpdateCostPerInterval(manager, start, end, index, distance_cost);
  1043. continue;
  1044. }
  1045. for (; interval != NULL && interval->start_ < end && start < end;
  1046. interval = interval_next) {
  1047. const double lower_full_interval =
  1048. interval->distance_cost_ + interval->lower_;
  1049. const double upper_full_interval =
  1050. interval->distance_cost_ + interval->upper_;
  1051. interval_next = interval->next_;
  1052. // Make sure we have some overlap
  1053. if (start >= interval->end_) continue;
  1054. if (lower_full_in >= upper_full_interval) {
  1055. // When intervals are represented, the lower, the better.
  1056. // [**********************************************************]
  1057. // start end
  1058. // [----------------------------------]
  1059. // interval->start_ interval->end_
  1060. // If we are worse than what we already have, add whatever we have so
  1061. // far up to interval.
  1062. const int start_new = interval->end_;
  1063. InsertInterval(manager, interval, distance_cost, lower_in, upper_in,
  1064. index, start, interval->start_);
  1065. start = start_new;
  1066. continue;
  1067. }
  1068. // We know the two intervals intersect.
  1069. if (upper_full_in >= lower_full_interval) {
  1070. // There is no clear cut on which is best, so let's keep both.
  1071. // [*********[*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*]***********]
  1072. // start interval->start_ interval->end_ end
  1073. // OR
  1074. // [*********[*-*-*-*-*-*-*-*-*-*-*-]----------------------]
  1075. // start interval->start_ end interval->end_
  1076. const int end_new = (interval->end_ <= end) ? interval->end_ : end;
  1077. InsertInterval(manager, interval, distance_cost, lower_in, upper_in,
  1078. index, start, end_new);
  1079. start = end_new;
  1080. } else if (start <= interval->start_ && interval->end_ <= end) {
  1081. // [----------------------------------]
  1082. // interval->start_ interval->end_
  1083. // [**************************************************************]
  1084. // start end
  1085. // We can safely remove the old interval as it is fully included.
  1086. PopInterval(manager, interval);
  1087. } else {
  1088. if (interval->start_ <= start && end <= interval->end_) {
  1089. // [--------------------------------------------------------------]
  1090. // interval->start_ interval->end_
  1091. // [*****************************]
  1092. // start end
  1093. // We have to split the old interval as it fully contains the new one.
  1094. const int end_original = interval->end_;
  1095. interval->end_ = start;
  1096. InsertInterval(manager, interval, interval->distance_cost_,
  1097. interval->lower_, interval->upper_, interval->index_,
  1098. end, end_original);
  1099. } else if (interval->start_ < start) {
  1100. // [------------------------------------]
  1101. // interval->start_ interval->end_
  1102. // [*****************************]
  1103. // start end
  1104. interval->end_ = start;
  1105. } else {
  1106. // [------------------------------------]
  1107. // interval->start_ interval->end_
  1108. // [*****************************]
  1109. // start end
  1110. interval->start_ = end;
  1111. }
  1112. // The interval has been modified, we need to reposition it or write it.
  1113. RepositionInterval(manager, interval);
  1114. }
  1115. }
  1116. // Insert the remaining interval from start to end.
  1117. InsertInterval(manager, interval, distance_cost, lower_in, upper_in, index,
  1118. start, end);
  1119. }
  1120. }
  1121. static int BackwardReferencesHashChainDistanceOnly(
  1122. int xsize, int ysize, const uint32_t* const argb, int quality,
  1123. int cache_bits, const VP8LHashChain* const hash_chain,
  1124. VP8LBackwardRefs* const refs, uint16_t* const dist_array) {
  1125. int i;
  1126. int ok = 0;
  1127. int cc_init = 0;
  1128. const int pix_count = xsize * ysize;
  1129. const int use_color_cache = (cache_bits > 0);
  1130. const size_t literal_array_size = sizeof(double) *
  1131. (NUM_LITERAL_CODES + NUM_LENGTH_CODES +
  1132. ((cache_bits > 0) ? (1 << cache_bits) : 0));
  1133. const size_t cost_model_size = sizeof(CostModel) + literal_array_size;
  1134. CostModel* const cost_model =
  1135. (CostModel*)WebPSafeCalloc(1ULL, cost_model_size);
  1136. VP8LColorCache hashers;
  1137. const int skip_length = 32 + quality;
  1138. const int skip_min_distance_code = 2;
  1139. CostManager* cost_manager =
  1140. (CostManager*)WebPSafeMalloc(1ULL, sizeof(*cost_manager));
  1141. if (cost_model == NULL || cost_manager == NULL) goto Error;
  1142. cost_model->literal_ = (double*)(cost_model + 1);
  1143. if (use_color_cache) {
  1144. cc_init = VP8LColorCacheInit(&hashers, cache_bits);
  1145. if (!cc_init) goto Error;
  1146. }
  1147. if (!CostModelBuild(cost_model, cache_bits, refs)) {
  1148. goto Error;
  1149. }
  1150. if (!CostManagerInit(cost_manager, dist_array, pix_count, cost_model)) {
  1151. goto Error;
  1152. }
  1153. // We loop one pixel at a time, but store all currently best points to
  1154. // non-processed locations from this point.
  1155. dist_array[0] = 0;
  1156. // Add first pixel as literal.
  1157. AddSingleLiteralWithCostModel(argb + 0, &hashers, cost_model, 0,
  1158. use_color_cache, 0.0, cost_manager->costs_,
  1159. dist_array);
  1160. for (i = 1; i < pix_count - 1; ++i) {
  1161. int offset = 0, len = 0;
  1162. double prev_cost = cost_manager->costs_[i - 1];
  1163. HashChainFindCopy(hash_chain, i, &offset, &len);
  1164. if (len >= 2) {
  1165. // If we are dealing with a non-literal.
  1166. const int code = DistanceToPlaneCode(xsize, offset);
  1167. const double offset_cost = GetDistanceCost(cost_model, code);
  1168. const int first_i = i;
  1169. int j_max = 0, interval_ends_index = 0;
  1170. const int is_offset_zero = (offset_cost == 0.);
  1171. if (!is_offset_zero) {
  1172. j_max = (int)ceil(
  1173. (cost_manager->max_cost_cache_ - cost_manager->min_cost_cache_) /
  1174. offset_cost);
  1175. if (j_max < 1) {
  1176. j_max = 1;
  1177. } else if (j_max > cost_manager->interval_ends_size_ - 1) {
  1178. // This could only happen in the case of MAX_LENGTH.
  1179. j_max = cost_manager->interval_ends_size_ - 1;
  1180. }
  1181. } // else j_max is unused anyway.
  1182. // Instead of considering all contributions from a pixel i by calling:
  1183. // PushInterval(cost_manager, prev_cost + offset_cost, i, len);
  1184. // we optimize these contributions in case offset_cost stays the same for
  1185. // consecutive pixels. This describes a set of pixels similar to a
  1186. // previous set (e.g. constant color regions).
  1187. for (; i < pix_count - 1; ++i) {
  1188. int offset_next, len_next;
  1189. prev_cost = cost_manager->costs_[i - 1];
  1190. if (is_offset_zero) {
  1191. // No optimization can be made so we just push all of the
  1192. // contributions from i.
  1193. PushInterval(cost_manager, prev_cost, i, len);
  1194. } else {
  1195. // j_max is chosen as the smallest j such that:
  1196. // max of cost_cache_ < j*offset cost + min of cost_cache_
  1197. // Therefore, the pixel influenced by i-j_max, cannot be influenced
  1198. // by i. Only the costs after the end of what i contributed need to be
  1199. // updated. cost_manager->interval_ends_ is a circular buffer that
  1200. // stores those ends.
  1201. const double distance_cost = prev_cost + offset_cost;
  1202. int j = cost_manager->interval_ends_[interval_ends_index];
  1203. if (i - first_i <= j_max ||
  1204. !IsCostCacheIntervalWritable(j, i + len)) {
  1205. PushInterval(cost_manager, distance_cost, i, len);
  1206. } else {
  1207. for (; j < i + len; ++j) {
  1208. UpdateCost(cost_manager, j, i, distance_cost);
  1209. }
  1210. }
  1211. // Store the new end in the circular buffer.
  1212. assert(interval_ends_index < cost_manager->interval_ends_size_);
  1213. cost_manager->interval_ends_[interval_ends_index] = i + len;
  1214. if (++interval_ends_index > j_max) interval_ends_index = 0;
  1215. }
  1216. // Check whether i is the last pixel to consider, as it is handled
  1217. // differently.
  1218. if (i + 1 >= pix_count - 1) break;
  1219. HashChainFindCopy(hash_chain, i + 1, &offset_next, &len_next);
  1220. if (offset_next != offset) break;
  1221. len = len_next;
  1222. UpdateCostPerIndex(cost_manager, i);
  1223. AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i,
  1224. use_color_cache, prev_cost,
  1225. cost_manager->costs_, dist_array);
  1226. }
  1227. // Submit the last pixel.
  1228. UpdateCostPerIndex(cost_manager, i + 1);
  1229. // This if is for speedup only. It roughly doubles the speed, and
  1230. // makes compression worse by .1 %.
  1231. if (len >= skip_length && code <= skip_min_distance_code) {
  1232. // Long copy for short distances, let's skip the middle
  1233. // lookups for better copies.
  1234. // 1) insert the hashes.
  1235. if (use_color_cache) {
  1236. int k;
  1237. for (k = 0; k < len; ++k) {
  1238. VP8LColorCacheInsert(&hashers, argb[i + k]);
  1239. }
  1240. }
  1241. // 2) jump.
  1242. {
  1243. const int i_next = i + len - 1; // for loop does ++i, thus -1 here.
  1244. for (; i <= i_next; ++i) UpdateCostPerIndex(cost_manager, i + 1);
  1245. i = i_next;
  1246. }
  1247. goto next_symbol;
  1248. }
  1249. if (len > 2) {
  1250. // Also try the smallest interval possible (size 2).
  1251. double cost_total =
  1252. prev_cost + offset_cost + GetLengthCost(cost_model, 1);
  1253. if (cost_manager->costs_[i + 1] > cost_total) {
  1254. cost_manager->costs_[i + 1] = (float)cost_total;
  1255. dist_array[i + 1] = 2;
  1256. }
  1257. }
  1258. } else {
  1259. // The pixel is added as a single literal so just update the costs.
  1260. UpdateCostPerIndex(cost_manager, i + 1);
  1261. }
  1262. AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i,
  1263. use_color_cache, prev_cost,
  1264. cost_manager->costs_, dist_array);
  1265. next_symbol: ;
  1266. }
  1267. // Handle the last pixel.
  1268. if (i == (pix_count - 1)) {
  1269. AddSingleLiteralWithCostModel(
  1270. argb + i, &hashers, cost_model, i, use_color_cache,
  1271. cost_manager->costs_[pix_count - 2], cost_manager->costs_, dist_array);
  1272. }
  1273. ok = !refs->error_;
  1274. Error:
  1275. if (cc_init) VP8LColorCacheClear(&hashers);
  1276. CostManagerClear(cost_manager);
  1277. WebPSafeFree(cost_model);
  1278. WebPSafeFree(cost_manager);
  1279. return ok;
  1280. }
  1281. // We pack the path at the end of *dist_array and return
  1282. // a pointer to this part of the array. Example:
  1283. // dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232]
  1284. static void TraceBackwards(uint16_t* const dist_array,
  1285. int dist_array_size,
  1286. uint16_t** const chosen_path,
  1287. int* const chosen_path_size) {
  1288. uint16_t* path = dist_array + dist_array_size;
  1289. uint16_t* cur = dist_array + dist_array_size - 1;
  1290. while (cur >= dist_array) {
  1291. const int k = *cur;
  1292. --path;
  1293. *path = k;
  1294. cur -= k;
  1295. }
  1296. *chosen_path = path;
  1297. *chosen_path_size = (int)(dist_array + dist_array_size - path);
  1298. }
  1299. static int BackwardReferencesHashChainFollowChosenPath(
  1300. const uint32_t* const argb, int cache_bits,
  1301. const uint16_t* const chosen_path, int chosen_path_size,
  1302. const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs) {
  1303. const int use_color_cache = (cache_bits > 0);
  1304. int ix;
  1305. int i = 0;
  1306. int ok = 0;
  1307. int cc_init = 0;
  1308. VP8LColorCache hashers;
  1309. if (use_color_cache) {
  1310. cc_init = VP8LColorCacheInit(&hashers, cache_bits);
  1311. if (!cc_init) goto Error;
  1312. }
  1313. ClearBackwardRefs(refs);
  1314. for (ix = 0; ix < chosen_path_size; ++ix) {
  1315. const int len = chosen_path[ix];
  1316. if (len != 1) {
  1317. int k;
  1318. const int offset = HashChainFindOffset(hash_chain, i);
  1319. BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
  1320. if (use_color_cache) {
  1321. for (k = 0; k < len; ++k) {
  1322. VP8LColorCacheInsert(&hashers, argb[i + k]);
  1323. }
  1324. }
  1325. i += len;
  1326. } else {
  1327. PixOrCopy v;
  1328. const int idx =
  1329. use_color_cache ? VP8LColorCacheContains(&hashers, argb[i]) : -1;
  1330. if (idx >= 0) {
  1331. // use_color_cache is true and hashers contains argb[i]
  1332. // push pixel as a color cache index
  1333. v = PixOrCopyCreateCacheIdx(idx);
  1334. } else {
  1335. if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
  1336. v = PixOrCopyCreateLiteral(argb[i]);
  1337. }
  1338. BackwardRefsCursorAdd(refs, v);
  1339. ++i;
  1340. }
  1341. }
  1342. ok = !refs->error_;
  1343. Error:
  1344. if (cc_init) VP8LColorCacheClear(&hashers);
  1345. return ok;
  1346. }
  1347. // Returns 1 on success.
  1348. static int BackwardReferencesTraceBackwards(
  1349. int xsize, int ysize, const uint32_t* const argb, int quality,
  1350. int cache_bits, const VP8LHashChain* const hash_chain,
  1351. VP8LBackwardRefs* const refs) {
  1352. int ok = 0;
  1353. const int dist_array_size = xsize * ysize;
  1354. uint16_t* chosen_path = NULL;
  1355. int chosen_path_size = 0;
  1356. uint16_t* dist_array =
  1357. (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array));
  1358. if (dist_array == NULL) goto Error;
  1359. if (!BackwardReferencesHashChainDistanceOnly(
  1360. xsize, ysize, argb, quality, cache_bits, hash_chain,
  1361. refs, dist_array)) {
  1362. goto Error;
  1363. }
  1364. TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size);
  1365. if (!BackwardReferencesHashChainFollowChosenPath(
  1366. argb, cache_bits, chosen_path, chosen_path_size, hash_chain, refs)) {
  1367. goto Error;
  1368. }
  1369. ok = 1;
  1370. Error:
  1371. WebPSafeFree(dist_array);
  1372. return ok;
  1373. }
  1374. static void BackwardReferences2DLocality(int xsize,
  1375. const VP8LBackwardRefs* const refs) {
  1376. VP8LRefsCursor c = VP8LRefsCursorInit(refs);
  1377. while (VP8LRefsCursorOk(&c)) {
  1378. if (PixOrCopyIsCopy(c.cur_pos)) {
  1379. const int dist = c.cur_pos->argb_or_distance;
  1380. const int transformed_dist = DistanceToPlaneCode(xsize, dist);
  1381. c.cur_pos->argb_or_distance = transformed_dist;
  1382. }
  1383. VP8LRefsCursorNext(&c);
  1384. }
  1385. }
  1386. // Computes the entropies for a color cache size (in bits) between 0 (unused)
  1387. // and cache_bits_max (inclusive).
  1388. // Returns 1 on success, 0 in case of allocation error.
  1389. static int ComputeCacheEntropies(const uint32_t* argb,
  1390. const VP8LBackwardRefs* const refs,
  1391. int cache_bits_max, double entropies[]) {
  1392. int cc_init[MAX_COLOR_CACHE_BITS + 1] = { 0 };
  1393. VP8LColorCache hashers[MAX_COLOR_CACHE_BITS + 1];
  1394. VP8LRefsCursor c = VP8LRefsCursorInit(refs);
  1395. VP8LHistogram* histos[MAX_COLOR_CACHE_BITS + 1] = { NULL };
  1396. int ok = 0;
  1397. int i;
  1398. for (i = 0; i <= cache_bits_max; ++i) {
  1399. histos[i] = VP8LAllocateHistogram(i);
  1400. if (histos[i] == NULL) goto Error;
  1401. if (i == 0) continue;
  1402. cc_init[i] = VP8LColorCacheInit(&hashers[i], i);
  1403. if (!cc_init[i]) goto Error;
  1404. }
  1405. assert(cache_bits_max >= 0);
  1406. // Do not use the color cache for cache_bits=0.
  1407. while (VP8LRefsCursorOk(&c)) {
  1408. VP8LHistogramAddSinglePixOrCopy(histos[0], c.cur_pos);
  1409. VP8LRefsCursorNext(&c);
  1410. }
  1411. if (cache_bits_max > 0) {
  1412. c = VP8LRefsCursorInit(refs);
  1413. while (VP8LRefsCursorOk(&c)) {
  1414. const PixOrCopy* const v = c.cur_pos;
  1415. if (PixOrCopyIsLiteral(v)) {
  1416. const uint32_t pix = *argb++;
  1417. // The keys of the caches can be derived from the longest one.
  1418. int key = HashPix(pix, 32 - cache_bits_max);
  1419. for (i = cache_bits_max; i >= 1; --i, key >>= 1) {
  1420. if (VP8LColorCacheLookup(&hashers[i], key) == pix) {
  1421. ++histos[i]->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key];
  1422. } else {
  1423. VP8LColorCacheSet(&hashers[i], key, pix);
  1424. ++histos[i]->blue_[pix & 0xff];
  1425. ++histos[i]->literal_[(pix >> 8) & 0xff];
  1426. ++histos[i]->red_[(pix >> 16) & 0xff];
  1427. ++histos[i]->alpha_[pix >> 24];
  1428. }
  1429. }
  1430. } else {
  1431. // Update the histograms for distance/length.
  1432. int len = PixOrCopyLength(v);
  1433. int code_dist, code_len, extra_bits;
  1434. uint32_t argb_prev = *argb ^ 0xffffffffu;
  1435. VP8LPrefixEncodeBits(len, &code_len, &extra_bits);
  1436. VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code_dist, &extra_bits);
  1437. for (i = 1; i <= cache_bits_max; ++i) {
  1438. ++histos[i]->literal_[NUM_LITERAL_CODES + code_len];
  1439. ++histos[i]->distance_[code_dist];
  1440. }
  1441. // Update the colors caches.
  1442. do {
  1443. if (*argb != argb_prev) {
  1444. // Efficiency: insert only if the color changes.
  1445. int key = HashPix(*argb, 32 - cache_bits_max);
  1446. for (i = cache_bits_max; i >= 1; --i, key >>= 1) {
  1447. hashers[i].colors_[key] = *argb;
  1448. }
  1449. argb_prev = *argb;
  1450. }
  1451. argb++;
  1452. } while (--len != 0);
  1453. }
  1454. VP8LRefsCursorNext(&c);
  1455. }
  1456. }
  1457. for (i = 0; i <= cache_bits_max; ++i) {
  1458. entropies[i] = VP8LHistogramEstimateBits(histos[i]);
  1459. }
  1460. ok = 1;
  1461. Error:
  1462. for (i = 0; i <= cache_bits_max; ++i) {
  1463. if (cc_init[i]) VP8LColorCacheClear(&hashers[i]);
  1464. VP8LFreeHistogram(histos[i]);
  1465. }
  1466. return ok;
  1467. }
  1468. // Evaluate optimal cache bits for the local color cache.
  1469. // The input *best_cache_bits sets the maximum cache bits to use (passing 0
  1470. // implies disabling the local color cache). The local color cache is also
  1471. // disabled for the lower (<= 25) quality.
  1472. // Returns 0 in case of memory error.
  1473. static int CalculateBestCacheSize(const uint32_t* const argb,
  1474. int xsize, int ysize, int quality,
  1475. const VP8LHashChain* const hash_chain,
  1476. VP8LBackwardRefs* const refs,
  1477. int* const lz77_computed,
  1478. int* const best_cache_bits) {
  1479. int i;
  1480. int cache_bits_high = (quality <= 25) ? 0 : *best_cache_bits;
  1481. double entropy_min = MAX_ENTROPY;
  1482. double entropies[MAX_COLOR_CACHE_BITS + 1];
  1483. assert(cache_bits_high <= MAX_COLOR_CACHE_BITS);
  1484. *lz77_computed = 0;
  1485. if (cache_bits_high == 0) {
  1486. *best_cache_bits = 0;
  1487. // Local color cache is disabled.
  1488. return 1;
  1489. }
  1490. // Compute LZ77 with no cache (0 bits), as the ideal LZ77 with a color cache
  1491. // is not that different in practice.
  1492. if (!BackwardReferencesLz77(xsize, ysize, argb, 0, hash_chain, refs)) {
  1493. return 0;
  1494. }
  1495. // Find the cache_bits giving the lowest entropy. The search is done in a
  1496. // brute-force way as the function (entropy w.r.t cache_bits) can be
  1497. // anything in practice.
  1498. if (!ComputeCacheEntropies(argb, refs, cache_bits_high, entropies)) {
  1499. return 0;
  1500. }
  1501. for (i = 0; i <= cache_bits_high; ++i) {
  1502. if (i == 0 || entropies[i] < entropy_min) {
  1503. entropy_min = entropies[i];
  1504. *best_cache_bits = i;
  1505. }
  1506. }
  1507. return 1;
  1508. }
  1509. // Update (in-place) backward references for specified cache_bits.
  1510. static int BackwardRefsWithLocalCache(const uint32_t* const argb,
  1511. int cache_bits,
  1512. VP8LBackwardRefs* const refs) {
  1513. int pixel_index = 0;
  1514. VP8LColorCache hashers;
  1515. VP8LRefsCursor c = VP8LRefsCursorInit(refs);
  1516. if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0;
  1517. while (VP8LRefsCursorOk(&c)) {
  1518. PixOrCopy* const v = c.cur_pos;
  1519. if (PixOrCopyIsLiteral(v)) {
  1520. const uint32_t argb_literal = v->argb_or_distance;
  1521. const int ix = VP8LColorCacheContains(&hashers, argb_literal);
  1522. if (ix >= 0) {
  1523. // hashers contains argb_literal
  1524. *v = PixOrCopyCreateCacheIdx(ix);
  1525. } else {
  1526. VP8LColorCacheInsert(&hashers, argb_literal);
  1527. }
  1528. ++pixel_index;
  1529. } else {
  1530. // refs was created without local cache, so it can not have cache indexes.
  1531. int k;
  1532. assert(PixOrCopyIsCopy(v));
  1533. for (k = 0; k < v->len; ++k) {
  1534. VP8LColorCacheInsert(&hashers, argb[pixel_index++]);
  1535. }
  1536. }
  1537. VP8LRefsCursorNext(&c);
  1538. }
  1539. VP8LColorCacheClear(&hashers);
  1540. return 1;
  1541. }
  1542. static VP8LBackwardRefs* GetBackwardReferencesLowEffort(
  1543. int width, int height, const uint32_t* const argb,
  1544. int* const cache_bits, const VP8LHashChain* const hash_chain,
  1545. VP8LBackwardRefs refs_array[2]) {
  1546. VP8LBackwardRefs* refs_lz77 = &refs_array[0];
  1547. *cache_bits = 0;
  1548. if (!BackwardReferencesLz77(width, height, argb, 0, hash_chain, refs_lz77)) {
  1549. return NULL;
  1550. }
  1551. BackwardReferences2DLocality(width, refs_lz77);
  1552. return refs_lz77;
  1553. }
  1554. static VP8LBackwardRefs* GetBackwardReferences(
  1555. int width, int height, const uint32_t* const argb, int quality,
  1556. int* const cache_bits, const VP8LHashChain* const hash_chain,
  1557. VP8LBackwardRefs refs_array[2]) {
  1558. int lz77_is_useful;
  1559. int lz77_computed;
  1560. double bit_cost_lz77, bit_cost_rle;
  1561. VP8LBackwardRefs* best = NULL;
  1562. VP8LBackwardRefs* refs_lz77 = &refs_array[0];
  1563. VP8LBackwardRefs* refs_rle = &refs_array[1];
  1564. VP8LHistogram* histo = NULL;
  1565. if (!CalculateBestCacheSize(argb, width, height, quality, hash_chain,
  1566. refs_lz77, &lz77_computed, cache_bits)) {
  1567. goto Error;
  1568. }
  1569. if (lz77_computed) {
  1570. // Transform refs_lz77 for the optimized cache_bits.
  1571. if (*cache_bits > 0) {
  1572. if (!BackwardRefsWithLocalCache(argb, *cache_bits, refs_lz77)) {
  1573. goto Error;
  1574. }
  1575. }
  1576. } else {
  1577. if (!BackwardReferencesLz77(width, height, argb, *cache_bits, hash_chain,
  1578. refs_lz77)) {
  1579. goto Error;
  1580. }
  1581. }
  1582. if (!BackwardReferencesRle(width, height, argb, *cache_bits, refs_rle)) {
  1583. goto Error;
  1584. }
  1585. histo = VP8LAllocateHistogram(*cache_bits);
  1586. if (histo == NULL) goto Error;
  1587. {
  1588. // Evaluate LZ77 coding.
  1589. VP8LHistogramCreate(histo, refs_lz77, *cache_bits);
  1590. bit_cost_lz77 = VP8LHistogramEstimateBits(histo);
  1591. // Evaluate RLE coding.
  1592. VP8LHistogramCreate(histo, refs_rle, *cache_bits);
  1593. bit_cost_rle = VP8LHistogramEstimateBits(histo);
  1594. // Decide if LZ77 is useful.
  1595. lz77_is_useful = (bit_cost_lz77 < bit_cost_rle);
  1596. }
  1597. // Choose appropriate backward reference.
  1598. if (lz77_is_useful) {
  1599. // TraceBackwards is costly. Don't execute it at lower quality.
  1600. const int try_lz77_trace_backwards = (quality >= 25);
  1601. best = refs_lz77; // default guess: lz77 is better
  1602. if (try_lz77_trace_backwards) {
  1603. VP8LBackwardRefs* const refs_trace = refs_rle;
  1604. if (!VP8LBackwardRefsCopy(refs_lz77, refs_trace)) {
  1605. best = NULL;
  1606. goto Error;
  1607. }
  1608. if (BackwardReferencesTraceBackwards(width, height, argb, quality,
  1609. *cache_bits, hash_chain,
  1610. refs_trace)) {
  1611. double bit_cost_trace;
  1612. // Evaluate LZ77 coding.
  1613. VP8LHistogramCreate(histo, refs_trace, *cache_bits);
  1614. bit_cost_trace = VP8LHistogramEstimateBits(histo);
  1615. if (bit_cost_trace < bit_cost_lz77) {
  1616. best = refs_trace;
  1617. }
  1618. }
  1619. }
  1620. } else {
  1621. best = refs_rle;
  1622. }
  1623. BackwardReferences2DLocality(width, best);
  1624. Error:
  1625. VP8LFreeHistogram(histo);
  1626. return best;
  1627. }
  1628. VP8LBackwardRefs* VP8LGetBackwardReferences(
  1629. int width, int height, const uint32_t* const argb, int quality,
  1630. int low_effort, int* const cache_bits,
  1631. const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[2]) {
  1632. if (low_effort) {
  1633. return GetBackwardReferencesLowEffort(width, height, argb, cache_bits,
  1634. hash_chain, refs_array);
  1635. } else {
  1636. return GetBackwardReferences(width, height, argb, quality, cache_bits,
  1637. hash_chain, refs_array);
  1638. }
  1639. }