Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(190)

Side by Side Diff: third_party/libwebp/enc/backward_references.c

Issue 116213006: Update libwebp to 0.4.0 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: After Blink Roll Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/libwebp/enc/backward_references.h ('k') | third_party/libwebp/enc/config.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 Google Inc. All Rights Reserved. 1 // Copyright 2012 Google Inc. All Rights Reserved.
2 // 2 //
3 // Use of this source code is governed by a BSD-style license 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 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 5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may 6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree. 7 // be found in the AUTHORS file in the root of the source tree.
8 // ----------------------------------------------------------------------------- 8 // -----------------------------------------------------------------------------
9 // 9 //
10 // Author: Jyrki Alakuijala (jyrki@google.com) 10 // Author: Jyrki Alakuijala (jyrki@google.com)
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 const int iter_mult = (quality < 27) ? 1 : 1 + ((quality - 27) >> 4); 149 const int iter_mult = (quality < 27) ? 1 : 1 + ((quality - 27) >> 4);
150 const int iter_neg = -iter_mult * (quality >> 1); 150 const int iter_neg = -iter_mult * (quality >> 1);
151 // Limit the backward-ref window size for lower qualities. 151 // Limit the backward-ref window size for lower qualities.
152 const int max_window_size = (quality > 50) ? WINDOW_SIZE 152 const int max_window_size = (quality > 50) ? WINDOW_SIZE
153 : (quality > 25) ? (xsize << 8) 153 : (quality > 25) ? (xsize << 8)
154 : (xsize << 4); 154 : (xsize << 4);
155 assert(xsize > 0); 155 assert(xsize > 0);
156 *window_size = (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE 156 *window_size = (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE
157 : max_window_size; 157 : max_window_size;
158 *iter_pos = 8 + (quality >> 3); 158 *iter_pos = 8 + (quality >> 3);
159 // For lower entropy images, the rigourous search loop in HashChainFindCopy 159 // For lower entropy images, the rigorous search loop in HashChainFindCopy
160 // can be relaxed. 160 // can be relaxed.
161 *iter_limit = (cache_bits > 0) ? iter_neg : iter_neg / 2; 161 *iter_limit = (cache_bits > 0) ? iter_neg : iter_neg / 2;
162 } 162 }
163 163
164 static int HashChainFindCopy(const HashChain* const p, 164 static int HashChainFindCopy(const HashChain* const p,
165 int base_position, int xsize_signed, 165 int base_position, int xsize_signed,
166 const uint32_t* const argb, int maxlen, 166 const uint32_t* const argb, int max_len,
167 int window_size, int iter_pos, int iter_limit, 167 int window_size, int iter_pos, int iter_limit,
168 int* const distance_ptr, 168 int* const distance_ptr,
169 int* const length_ptr) { 169 int* const length_ptr) {
170 const uint32_t* const argb_start = argb + base_position; 170 const uint32_t* const argb_start = argb + base_position;
171 uint64_t best_val = 0; 171 uint64_t best_val = 0;
172 uint32_t best_length = 1; 172 uint32_t best_length = 1;
173 uint32_t best_distance = 0; 173 uint32_t best_distance = 0;
174 const uint32_t xsize = (uint32_t)xsize_signed; 174 const uint32_t xsize = (uint32_t)xsize_signed;
175 const int min_pos = 175 const int min_pos =
176 (base_position > window_size) ? base_position - window_size : 0; 176 (base_position > window_size) ? base_position - window_size : 0;
177 int pos; 177 int pos;
178 assert(xsize > 0); 178 assert(xsize > 0);
179 if (max_len > MAX_LENGTH) {
180 max_len = MAX_LENGTH;
181 }
179 for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)]; 182 for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)];
180 pos >= min_pos; 183 pos >= min_pos;
181 pos = p->chain_[pos]) { 184 pos = p->chain_[pos]) {
182 uint64_t val; 185 uint64_t val;
183 uint32_t curr_length; 186 uint32_t curr_length;
184 uint32_t distance; 187 uint32_t distance;
188 const uint64_t* const ptr1 =
189 (const uint64_t*)(argb + pos + best_length - 1);
190 const uint64_t* const ptr2 =
191 (const uint64_t*)(argb_start + best_length - 1);
192
185 if (iter_pos < 0) { 193 if (iter_pos < 0) {
186 if (iter_pos < iter_limit || best_val >= 0xff0000) { 194 if (iter_pos < iter_limit || best_val >= 0xff0000) {
187 break; 195 break;
188 } 196 }
189 } 197 }
190 --iter_pos; 198 --iter_pos;
191 if (argb[pos + best_length - 1] != argb_start[best_length - 1]) { 199
192 continue; 200 // Before 'expensive' linear match, check if the two arrays match at the
193 } 201 // current best length index and also for the succeeding elements.
194 curr_length = FindMatchLength(argb + pos, argb_start, maxlen); 202 if (*ptr1 != *ptr2) continue;
195 if (curr_length < best_length) { 203
196 continue; 204 curr_length = FindMatchLength(argb + pos, argb_start, max_len);
197 } 205 if (curr_length < best_length) continue;
206
198 distance = (uint32_t)(base_position - pos); 207 distance = (uint32_t)(base_position - pos);
199 val = curr_length << 16; 208 val = curr_length << 16;
200 // Favoring 2d locality here gives savings for certain images. 209 // Favoring 2d locality here gives savings for certain images.
201 if (distance < 9 * xsize) { 210 if (distance < 9 * xsize) {
202 const uint32_t y = distance / xsize; 211 const uint32_t y = distance / xsize;
203 uint32_t x = distance % xsize; 212 uint32_t x = distance % xsize;
204 if (x > (xsize >> 1)) { 213 if (x > (xsize >> 1)) {
205 x = xsize - x; 214 x = xsize - x;
206 } 215 }
207 if (x <= 7) { 216 if (x <= 7) {
208 val += 9 * 9 + 9 * 9; 217 val += 9 * 9 + 9 * 9;
209 val -= y * y + x * x; 218 val -= y * y + x * x;
210 } 219 }
211 } 220 }
212 if (best_val < val) { 221 if (best_val < val) {
213 best_val = val; 222 best_val = val;
214 best_length = curr_length; 223 best_length = curr_length;
215 best_distance = distance; 224 best_distance = distance;
216 if (curr_length >= MAX_LENGTH) { 225 if (curr_length >= (uint32_t)max_len) {
217 break; 226 break;
218 } 227 }
219 if ((best_distance == 1 || distance == xsize) && 228 if ((best_distance == 1 || distance == xsize) &&
220 best_length >= 128) { 229 best_length >= 128) {
221 break; 230 break;
222 } 231 }
223 } 232 }
224 } 233 }
225 *distance_ptr = (int)best_distance; 234 *distance_ptr = (int)best_distance;
226 *length_ptr = best_length; 235 *length_ptr = best_length;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 if (!HashChainInit(hash_chain, pix_count)) goto Error; 293 if (!HashChainInit(hash_chain, pix_count)) goto Error;
285 294
286 refs->size = 0; 295 refs->size = 0;
287 GetParamsForHashChainFindCopy(quality, xsize, cache_bits, 296 GetParamsForHashChainFindCopy(quality, xsize, cache_bits,
288 &window_size, &iter_pos, &iter_limit); 297 &window_size, &iter_pos, &iter_limit);
289 for (i = 0; i < pix_count; ) { 298 for (i = 0; i < pix_count; ) {
290 // Alternative#1: Code the pixels starting at 'i' using backward reference. 299 // Alternative#1: Code the pixels starting at 'i' using backward reference.
291 int offset = 0; 300 int offset = 0;
292 int len = 0; 301 int len = 0;
293 if (i < pix_count - 1) { // FindCopy(i,..) reads pixels at [i] and [i + 1]. 302 if (i < pix_count - 1) { // FindCopy(i,..) reads pixels at [i] and [i + 1].
294 int maxlen = pix_count - i; 303 int max_len = pix_count - i;
295 if (maxlen > MAX_LENGTH) { 304 HashChainFindCopy(hash_chain, i, xsize, argb, max_len,
296 maxlen = MAX_LENGTH;
297 }
298 HashChainFindCopy(hash_chain, i, xsize, argb, maxlen,
299 window_size, iter_pos, iter_limit, 305 window_size, iter_pos, iter_limit,
300 &offset, &len); 306 &offset, &len);
301 } 307 }
302 if (len >= MIN_LENGTH) { 308 if (len >= MIN_LENGTH) {
303 // Alternative#2: Insert the pixel at 'i' as literal, and code the 309 // Alternative#2: Insert the pixel at 'i' as literal, and code the
304 // pixels starting at 'i + 1' using backward reference. 310 // pixels starting at 'i + 1' using backward reference.
305 int offset2 = 0; 311 int offset2 = 0;
306 int len2 = 0; 312 int len2 = 0;
307 int k; 313 int k;
308 HashChainInsert(hash_chain, &argb[i], i); 314 HashChainInsert(hash_chain, &argb[i], i);
309 if (i < pix_count - 2) { // FindCopy(i+1,..) reads [i + 1] and [i + 2]. 315 if (i < pix_count - 2) { // FindCopy(i+1,..) reads [i + 1] and [i + 2].
310 int maxlen = pix_count - (i + 1); 316 int max_len = pix_count - (i + 1);
311 if (maxlen > MAX_LENGTH) { 317 HashChainFindCopy(hash_chain, i + 1, xsize, argb, max_len,
312 maxlen = MAX_LENGTH;
313 }
314 HashChainFindCopy(hash_chain, i + 1, xsize, argb, maxlen,
315 window_size, iter_pos, iter_limit, 318 window_size, iter_pos, iter_limit,
316 &offset2, &len2); 319 &offset2, &len2);
317 if (len2 > len + 1) { 320 if (len2 > len + 1) {
318 const uint32_t pixel = argb[i]; 321 const uint32_t pixel = argb[i];
319 // Alternative#2 is a better match. So push pixel at 'i' as literal. 322 // Alternative#2 is a better match. So push pixel at 'i' as literal.
320 if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) { 323 if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) {
321 const int ix = VP8LColorCacheGetIndex(&hashers, pixel); 324 const int ix = VP8LColorCacheGetIndex(&hashers, pixel);
322 refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix); 325 refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix);
323 } else { 326 } else {
327 if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel);
324 refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel); 328 refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel);
325 } 329 }
326 ++refs->size; 330 ++refs->size;
327 if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel);
328 i++; // Backward reference to be done for next pixel. 331 i++; // Backward reference to be done for next pixel.
329 len = len2; 332 len = len2;
330 offset = offset2; 333 offset = offset2;
331 } 334 }
332 } 335 }
333 if (len >= MAX_LENGTH) { 336 if (len >= MAX_LENGTH) {
334 len = MAX_LENGTH - 1; 337 len = MAX_LENGTH - 1;
335 } 338 }
336 refs->refs[refs->size++] = PixOrCopyCreateCopy(offset, len); 339 refs->refs[refs->size++] = PixOrCopyCreateCopy(offset, len);
337 if (use_color_cache) { 340 if (use_color_cache) {
338 for (k = 0; k < len; ++k) { 341 for (k = 0; k < len; ++k) {
339 VP8LColorCacheInsert(&hashers, argb[i + k]); 342 VP8LColorCacheInsert(&hashers, argb[i + k]);
340 } 343 }
341 } 344 }
342 // Add to the hash_chain (but cannot add the last pixel). 345 // Add to the hash_chain (but cannot add the last pixel).
343 { 346 {
344 const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i; 347 const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i;
345 for (k = 1; k < last; ++k) { 348 for (k = 1; k < last; ++k) {
346 HashChainInsert(hash_chain, &argb[i + k], i + k); 349 HashChainInsert(hash_chain, &argb[i + k], i + k);
347 } 350 }
348 } 351 }
349 i += len; 352 i += len;
350 } else { 353 } else {
351 const uint32_t pixel = argb[i]; 354 const uint32_t pixel = argb[i];
352 if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) { 355 if (use_color_cache && VP8LColorCacheContains(&hashers, pixel)) {
353 // push pixel as a PixOrCopyCreateCacheIdx pixel 356 // push pixel as a PixOrCopyCreateCacheIdx pixel
354 const int ix = VP8LColorCacheGetIndex(&hashers, pixel); 357 const int ix = VP8LColorCacheGetIndex(&hashers, pixel);
355 refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix); 358 refs->refs[refs->size] = PixOrCopyCreateCacheIdx(ix);
356 } else { 359 } else {
360 if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel);
357 refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel); 361 refs->refs[refs->size] = PixOrCopyCreateLiteral(pixel);
358 } 362 }
359 ++refs->size; 363 ++refs->size;
360 if (use_color_cache) VP8LColorCacheInsert(&hashers, pixel);
361 if (i + 1 < pix_count) { 364 if (i + 1 < pix_count) {
362 HashChainInsert(hash_chain, &argb[i], i); 365 HashChainInsert(hash_chain, &argb[i], i);
363 } 366 }
364 ++i; 367 ++i;
365 } 368 }
366 } 369 }
367 ok = 1; 370 ok = 1;
368 Error: 371 Error:
369 if (cc_init) VP8LColorCacheClear(&hashers); 372 if (cc_init) VP8LColorCacheClear(&hashers);
370 HashChainDelete(hash_chain); 373 HashChainDelete(hash_chain);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 m->blue_[v & 0xff]; 455 m->blue_[v & 0xff];
453 } 456 }
454 457
455 static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) { 458 static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) {
456 const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx; 459 const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx;
457 return m->literal_[literal_idx]; 460 return m->literal_[literal_idx];
458 } 461 }
459 462
460 static WEBP_INLINE double GetLengthCost(const CostModel* const m, 463 static WEBP_INLINE double GetLengthCost(const CostModel* const m,
461 uint32_t length) { 464 uint32_t length) {
462 int code, extra_bits_count, extra_bits_value; 465 int code, extra_bits;
463 PrefixEncode(length, &code, &extra_bits_count, &extra_bits_value); 466 VP8LPrefixEncodeBits(length, &code, &extra_bits);
464 return m->literal_[VALUES_IN_BYTE + code] + extra_bits_count; 467 return m->literal_[VALUES_IN_BYTE + code] + extra_bits;
465 } 468 }
466 469
467 static WEBP_INLINE double GetDistanceCost(const CostModel* const m, 470 static WEBP_INLINE double GetDistanceCost(const CostModel* const m,
468 uint32_t distance) { 471 uint32_t distance) {
469 int code, extra_bits_count, extra_bits_value; 472 int code, extra_bits;
470 PrefixEncode(distance, &code, &extra_bits_count, &extra_bits_value); 473 VP8LPrefixEncodeBits(distance, &code, &extra_bits);
471 return m->distance_[code] + extra_bits_count; 474 return m->distance_[code] + extra_bits;
472 } 475 }
473 476
474 static int BackwardReferencesHashChainDistanceOnly( 477 static int BackwardReferencesHashChainDistanceOnly(
475 int xsize, int ysize, int recursive_cost_model, const uint32_t* const argb, 478 int xsize, int ysize, int recursive_cost_model, const uint32_t* const argb,
476 int quality, int cache_bits, uint32_t* const dist_array) { 479 int quality, int cache_bits, uint32_t* const dist_array) {
477 int i; 480 int i;
478 int ok = 0; 481 int ok = 0;
479 int cc_init = 0; 482 int cc_init = 0;
480 const int pix_count = xsize * ysize; 483 const int pix_count = xsize * ysize;
481 const int use_color_cache = (cache_bits > 0); 484 const int use_color_cache = (cache_bits > 0);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 for (i = 0; i < pix_count; ++i) { 518 for (i = 0; i < pix_count; ++i) {
516 double prev_cost = 0.0; 519 double prev_cost = 0.0;
517 int shortmax; 520 int shortmax;
518 if (i > 0) { 521 if (i > 0) {
519 prev_cost = cost[i - 1]; 522 prev_cost = cost[i - 1];
520 } 523 }
521 for (shortmax = 0; shortmax < 2; ++shortmax) { 524 for (shortmax = 0; shortmax < 2; ++shortmax) {
522 int offset = 0; 525 int offset = 0;
523 int len = 0; 526 int len = 0;
524 if (i < pix_count - 1) { // FindCopy reads pixels at [i] and [i + 1]. 527 if (i < pix_count - 1) { // FindCopy reads pixels at [i] and [i + 1].
525 int maxlen = shortmax ? 2 : MAX_LENGTH; 528 int max_len = shortmax ? 2 : pix_count - i;
526 if (maxlen > pix_count - i) { 529 HashChainFindCopy(hash_chain, i, xsize, argb, max_len,
527 maxlen = pix_count - i;
528 }
529 HashChainFindCopy(hash_chain, i, xsize, argb, maxlen,
530 window_size, iter_pos, iter_limit, 530 window_size, iter_pos, iter_limit,
531 &offset, &len); 531 &offset, &len);
532 } 532 }
533 if (len >= MIN_LENGTH) { 533 if (len >= MIN_LENGTH) {
534 const int code = DistanceToPlaneCode(xsize, offset); 534 const int code = DistanceToPlaneCode(xsize, offset);
535 const double distance_cost = 535 const double distance_cost =
536 prev_cost + GetDistanceCost(cost_model, code); 536 prev_cost + GetDistanceCost(cost_model, code);
537 int k; 537 int k;
538 for (k = 1; k < len; ++k) { 538 for (k = 1; k < len; ++k) {
539 const double cost_val = distance_cost + GetLengthCost(cost_model, k); 539 const double cost_val = distance_cost + GetLengthCost(cost_model, k);
(...skipping 30 matching lines...) Expand all
570 if (i < pix_count - 1) { 570 if (i < pix_count - 1) {
571 HashChainInsert(hash_chain, &argb[i], i); 571 HashChainInsert(hash_chain, &argb[i], i);
572 } 572 }
573 { 573 {
574 // inserting a literal pixel 574 // inserting a literal pixel
575 double cost_val = prev_cost; 575 double cost_val = prev_cost;
576 if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) { 576 if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) {
577 const int ix = VP8LColorCacheGetIndex(&hashers, argb[i]); 577 const int ix = VP8LColorCacheGetIndex(&hashers, argb[i]);
578 cost_val += GetCacheCost(cost_model, ix) * mul0; 578 cost_val += GetCacheCost(cost_model, ix) * mul0;
579 } else { 579 } else {
580 if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
580 cost_val += GetLiteralCost(cost_model, argb[i]) * mul1; 581 cost_val += GetLiteralCost(cost_model, argb[i]) * mul1;
581 } 582 }
582 if (cost[i] > cost_val) { 583 if (cost[i] > cost_val) {
583 cost[i] = (float)cost_val; 584 cost[i] = (float)cost_val;
584 dist_array[i] = 1; // only one is inserted. 585 dist_array[i] = 1; // only one is inserted.
585 } 586 }
586 if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
587 } 587 }
588 next_symbol: ; 588 next_symbol: ;
589 } 589 }
590 // Last pixel still to do, it can only be a single step if not reached 590 // Last pixel still to do, it can only be a single step if not reached
591 // through cheaper means already. 591 // through cheaper means already.
592 ok = 1; 592 ok = 1;
593 Error: 593 Error:
594 if (cc_init) VP8LColorCacheClear(&hashers); 594 if (cc_init) VP8LColorCacheClear(&hashers);
595 HashChainDelete(hash_chain); 595 HashChainDelete(hash_chain);
596 free(cost_model); 596 free(cost_model);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 cc_init = VP8LColorCacheInit(&hashers, cache_bits); 643 cc_init = VP8LColorCacheInit(&hashers, cache_bits);
644 if (!cc_init) goto Error; 644 if (!cc_init) goto Error;
645 } 645 }
646 646
647 refs->size = 0; 647 refs->size = 0;
648 GetParamsForHashChainFindCopy(quality, xsize, cache_bits, 648 GetParamsForHashChainFindCopy(quality, xsize, cache_bits,
649 &window_size, &iter_pos, &iter_limit); 649 &window_size, &iter_pos, &iter_limit);
650 for (ix = 0; ix < chosen_path_size; ++ix, ++size) { 650 for (ix = 0; ix < chosen_path_size; ++ix, ++size) {
651 int offset = 0; 651 int offset = 0;
652 int len = 0; 652 int len = 0;
653 int maxlen = chosen_path[ix]; 653 int max_len = chosen_path[ix];
654 if (maxlen != 1) { 654 if (max_len != 1) {
655 HashChainFindCopy(hash_chain, i, xsize, argb, maxlen, 655 HashChainFindCopy(hash_chain, i, xsize, argb, max_len,
656 window_size, iter_pos, iter_limit, 656 window_size, iter_pos, iter_limit,
657 &offset, &len); 657 &offset, &len);
658 assert(len == maxlen); 658 assert(len == max_len);
659 refs->refs[size] = PixOrCopyCreateCopy(offset, len); 659 refs->refs[size] = PixOrCopyCreateCopy(offset, len);
660 if (use_color_cache) { 660 if (use_color_cache) {
661 for (k = 0; k < len; ++k) { 661 for (k = 0; k < len; ++k) {
662 VP8LColorCacheInsert(&hashers, argb[i + k]); 662 VP8LColorCacheInsert(&hashers, argb[i + k]);
663 } 663 }
664 } 664 }
665 { 665 {
666 const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i; 666 const int last = (len < pix_count - 1 - i) ? len : pix_count - 1 - i;
667 for (k = 0; k < last; ++k) { 667 for (k = 0; k < last; ++k) {
668 HashChainInsert(hash_chain, &argb[i + k], i + k); 668 HashChainInsert(hash_chain, &argb[i + k], i + k);
669 } 669 }
670 } 670 }
671 i += len; 671 i += len;
672 } else { 672 } else {
673 if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) { 673 if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) {
674 // push pixel as a color cache index 674 // push pixel as a color cache index
675 const int idx = VP8LColorCacheGetIndex(&hashers, argb[i]); 675 const int idx = VP8LColorCacheGetIndex(&hashers, argb[i]);
676 refs->refs[size] = PixOrCopyCreateCacheIdx(idx); 676 refs->refs[size] = PixOrCopyCreateCacheIdx(idx);
677 } else { 677 } else {
678 if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
678 refs->refs[size] = PixOrCopyCreateLiteral(argb[i]); 679 refs->refs[size] = PixOrCopyCreateLiteral(argb[i]);
679 } 680 }
680 if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
681 if (i + 1 < pix_count) { 681 if (i + 1 < pix_count) {
682 HashChainInsert(hash_chain, &argb[i], i); 682 HashChainInsert(hash_chain, &argb[i], i);
683 } 683 }
684 ++i; 684 ++i;
685 } 685 }
686 } 686 }
687 assert(size <= refs->max_size); 687 assert(size <= refs->max_size);
688 refs->size = size; 688 refs->size = size;
689 ok = 1; 689 ok = 1;
690 Error: 690 Error:
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 // Evaluate RLE coding 773 // Evaluate RLE coding
774 VP8LHistogramCreate(histo, &refs_rle, cache_bits); 774 VP8LHistogramCreate(histo, &refs_rle, cache_bits);
775 bit_cost_rle = VP8LHistogramEstimateBits(histo); 775 bit_cost_rle = VP8LHistogramEstimateBits(histo);
776 // Decide if LZ77 is useful. 776 // Decide if LZ77 is useful.
777 lz77_is_useful = (bit_cost_lz77 < bit_cost_rle); 777 lz77_is_useful = (bit_cost_lz77 < bit_cost_rle);
778 free(histo); 778 free(histo);
779 } 779 }
780 780
781 // Choose appropriate backward reference. 781 // Choose appropriate backward reference.
782 if (lz77_is_useful) { 782 if (lz77_is_useful) {
783 // TraceBackwards is costly. Don't execute it at lower quality (q <= 10). 783 // TraceBackwards is costly. Don't execute it at lower quality.
784 const int try_lz77_trace_backwards = (quality > 10); 784 const int try_lz77_trace_backwards = (quality >= 25);
785 *best = refs_lz77; // default guess: lz77 is better 785 *best = refs_lz77; // default guess: lz77 is better
786 VP8LClearBackwardRefs(&refs_rle); 786 VP8LClearBackwardRefs(&refs_rle);
787 if (try_lz77_trace_backwards) { 787 if (try_lz77_trace_backwards) {
788 // Set recursion level for large images using a color cache. 788 // Set recursion level for large images using a color cache.
789 const int recursion_level = 789 const int recursion_level =
790 (num_pix < 320 * 200) && (cache_bits > 0) ? 1 : 0; 790 (num_pix < 320 * 200) && (cache_bits > 0) ? 1 : 0;
791 VP8LBackwardRefs refs_trace; 791 VP8LBackwardRefs refs_trace;
792 if (!VP8LBackwardRefsAlloc(&refs_trace, num_pix)) { 792 if (!VP8LBackwardRefsAlloc(&refs_trace, num_pix)) {
793 goto End; 793 goto End;
794 } 794 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 if (cache_bits == 0 || cur_entropy < lowest_entropy) { 885 if (cache_bits == 0 || cur_entropy < lowest_entropy) {
886 *best_cache_bits = cache_bits; 886 *best_cache_bits = cache_bits;
887 lowest_entropy = cur_entropy; 887 lowest_entropy = cur_entropy;
888 } 888 }
889 } 889 }
890 ok = 1; 890 ok = 1;
891 Error: 891 Error:
892 VP8LClearBackwardRefs(&refs); 892 VP8LClearBackwardRefs(&refs);
893 return ok; 893 return ok;
894 } 894 }
OLDNEW
« no previous file with comments | « third_party/libwebp/enc/backward_references.h ('k') | third_party/libwebp/enc/config.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698