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

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

Issue 16871017: libwebp-0.3.1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 0.3.1 final -> no changes since rc2 Created 7 years, 6 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 // This code is licensed under the same terms as WebM: 3 // Use of this source code is governed by a BSD-style license
4 // Software License Agreement: http://www.webmproject.org/license/software/ 4 // that can be found in the COPYING file in the root of the source
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 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.
6 // ----------------------------------------------------------------------------- 8 // -----------------------------------------------------------------------------
7 // 9 //
8 // Author: Jyrki Alakuijala (jyrki@google.com) 10 // Author: Jyrki Alakuijala (jyrki@google.com)
9 // 11 //
10 12
11 #include <assert.h> 13 #include <assert.h>
12 #include <math.h> 14 #include <math.h>
13 #include <stdio.h> 15 #include <stdio.h>
14 16
15 #include "./backward_references.h" 17 #include "./backward_references.h"
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 137
136 // Insertion of two pixels at a time. 138 // Insertion of two pixels at a time.
137 static void HashChainInsert(HashChain* const p, 139 static void HashChainInsert(HashChain* const p,
138 const uint32_t* const argb, int pos) { 140 const uint32_t* const argb, int pos) {
139 const uint64_t hash_code = GetPixPairHash64(argb); 141 const uint64_t hash_code = GetPixPairHash64(argb);
140 p->chain_[pos] = p->hash_to_first_index_[hash_code]; 142 p->chain_[pos] = p->hash_to_first_index_[hash_code];
141 p->hash_to_first_index_[hash_code] = pos; 143 p->hash_to_first_index_[hash_code] = pos;
142 } 144 }
143 145
144 static void GetParamsForHashChainFindCopy(int quality, int xsize, 146 static void GetParamsForHashChainFindCopy(int quality, int xsize,
145 int* window_size, int* iter_pos, 147 int cache_bits, int* window_size,
146 int* iter_limit) { 148 int* iter_pos, int* iter_limit) {
147 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);
148 // Limit the backward-ref window size for lower qualities. 151 // Limit the backward-ref window size for lower qualities.
149 const int max_window_size = (quality > 50) ? WINDOW_SIZE 152 const int max_window_size = (quality > 50) ? WINDOW_SIZE
150 : (quality > 25) ? (xsize << 8) 153 : (quality > 25) ? (xsize << 8)
151 : (xsize << 4); 154 : (xsize << 4);
152 assert(xsize > 0); 155 assert(xsize > 0);
153 *window_size = (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE 156 *window_size = (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE
154 : max_window_size; 157 : max_window_size;
155 *iter_pos = 5 + (quality >> 3); 158 *iter_pos = 8 + (quality >> 3);
156 *iter_limit = -quality * iter_mult; 159 // For lower entropy images, the rigourous search loop in HashChainFindCopy
160 // can be relaxed.
161 *iter_limit = (cache_bits > 0) ? iter_neg : iter_neg / 2;
157 } 162 }
158 163
159 static int HashChainFindCopy(const HashChain* const p, 164 static int HashChainFindCopy(const HashChain* const p,
160 int base_position, int xsize, 165 int base_position, int xsize_signed,
161 const uint32_t* const argb, int maxlen, 166 const uint32_t* const argb, int maxlen,
162 int window_size, int iter_pos, int iter_limit, 167 int window_size, int iter_pos, int iter_limit,
163 int* const distance_ptr, 168 int* const distance_ptr,
164 int* const length_ptr) { 169 int* const length_ptr) {
165 const uint64_t hash_code = GetPixPairHash64(&argb[base_position]);
166 int prev_length = 0;
167 int64_t best_val = 0;
168 int best_length = 0;
169 int best_distance = 0;
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;
172 uint32_t best_length = 1;
173 uint32_t best_distance = 0;
174 const uint32_t xsize = (uint32_t)xsize_signed;
171 const int min_pos = 175 const int min_pos =
172 (base_position > window_size) ? base_position - window_size : 0; 176 (base_position > window_size) ? base_position - window_size : 0;
173 int pos; 177 int pos;
174
175 assert(xsize > 0); 178 assert(xsize > 0);
176 for (pos = p->hash_to_first_index_[hash_code]; 179 for (pos = p->hash_to_first_index_[GetPixPairHash64(argb_start)];
177 pos >= min_pos; 180 pos >= min_pos;
178 pos = p->chain_[pos]) { 181 pos = p->chain_[pos]) {
179 int64_t val; 182 uint64_t val;
180 int curr_length; 183 uint32_t curr_length;
184 uint32_t distance;
181 if (iter_pos < 0) { 185 if (iter_pos < 0) {
182 if (iter_pos < iter_limit || best_val >= 0xff0000) { 186 if (iter_pos < iter_limit || best_val >= 0xff0000) {
183 break; 187 break;
184 } 188 }
185 } 189 }
186 --iter_pos; 190 --iter_pos;
187 if (best_length != 0 && 191 if (argb[pos + best_length - 1] != argb_start[best_length - 1]) {
188 argb[pos + best_length - 1] != argb_start[best_length - 1]) {
189 continue; 192 continue;
190 } 193 }
191 curr_length = FindMatchLength(argb + pos, argb_start, maxlen); 194 curr_length = FindMatchLength(argb + pos, argb_start, maxlen);
192 if (curr_length < prev_length) { 195 if (curr_length < best_length) {
193 continue; 196 continue;
194 } 197 }
195 val = 65536 * curr_length; 198 distance = (uint32_t)(base_position - pos);
199 val = curr_length << 16;
196 // Favoring 2d locality here gives savings for certain images. 200 // Favoring 2d locality here gives savings for certain images.
197 if (base_position - pos < 9 * xsize) { 201 if (distance < 9 * xsize) {
198 const int y = (base_position - pos) / xsize; 202 const uint32_t y = distance / xsize;
199 int x = (base_position - pos) % xsize; 203 uint32_t x = distance % xsize;
200 if (x > xsize / 2) { 204 if (x > (xsize >> 1)) {
201 x = xsize - x; 205 x = xsize - x;
202 } 206 }
203 if (x <= 7 && x >= -8) { 207 if (x <= 7) {
208 val += 9 * 9 + 9 * 9;
204 val -= y * y + x * x; 209 val -= y * y + x * x;
205 } else {
206 val -= 9 * 9 + 9 * 9;
207 } 210 }
208 } else {
209 val -= 9 * 9 + 9 * 9;
210 } 211 }
211 if (best_val < val) { 212 if (best_val < val) {
212 prev_length = curr_length;
213 best_val = val; 213 best_val = val;
214 best_length = curr_length; 214 best_length = curr_length;
215 best_distance = base_position - pos; 215 best_distance = distance;
216 if (curr_length >= MAX_LENGTH) { 216 if (curr_length >= MAX_LENGTH) {
217 break; 217 break;
218 } 218 }
219 if ((best_distance == 1 || best_distance == xsize) && 219 if ((best_distance == 1 || distance == xsize) &&
220 best_length >= 128) { 220 best_length >= 128) {
221 break; 221 break;
222 } 222 }
223 } 223 }
224 } 224 }
225 *distance_ptr = best_distance; 225 *distance_ptr = (int)best_distance;
226 *length_ptr = best_length; 226 *length_ptr = best_length;
227 return (best_length >= MIN_LENGTH); 227 return (best_length >= MIN_LENGTH);
228 } 228 }
229 229
230 static WEBP_INLINE void PushBackCopy(VP8LBackwardRefs* const refs, int length) { 230 static WEBP_INLINE void PushBackCopy(VP8LBackwardRefs* const refs, int length) {
231 int size = refs->size; 231 int size = refs->size;
232 while (length >= MAX_LENGTH) { 232 while (length >= MAX_LENGTH) {
233 refs->refs[size++] = PixOrCopyCreateCopy(1, MAX_LENGTH); 233 refs->refs[size++] = PixOrCopyCreateCopy(1, MAX_LENGTH);
234 length -= MAX_LENGTH; 234 length -= MAX_LENGTH;
235 } 235 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 277
278 if (hash_chain == NULL) return 0; 278 if (hash_chain == NULL) return 0;
279 if (use_color_cache) { 279 if (use_color_cache) {
280 cc_init = VP8LColorCacheInit(&hashers, cache_bits); 280 cc_init = VP8LColorCacheInit(&hashers, cache_bits);
281 if (!cc_init) goto Error; 281 if (!cc_init) goto Error;
282 } 282 }
283 283
284 if (!HashChainInit(hash_chain, pix_count)) goto Error; 284 if (!HashChainInit(hash_chain, pix_count)) goto Error;
285 285
286 refs->size = 0; 286 refs->size = 0;
287 GetParamsForHashChainFindCopy(quality, xsize, &window_size, &iter_pos, 287 GetParamsForHashChainFindCopy(quality, xsize, cache_bits,
288 &iter_limit); 288 &window_size, &iter_pos, &iter_limit);
289 for (i = 0; i < pix_count; ) { 289 for (i = 0; i < pix_count; ) {
290 // Alternative#1: Code the pixels starting at 'i' using backward reference. 290 // Alternative#1: Code the pixels starting at 'i' using backward reference.
291 int offset = 0; 291 int offset = 0;
292 int len = 0; 292 int len = 0;
293 if (i < pix_count - 1) { // FindCopy(i,..) reads pixels at [i] and [i + 1]. 293 if (i < pix_count - 1) { // FindCopy(i,..) reads pixels at [i] and [i + 1].
294 int maxlen = pix_count - i; 294 int maxlen = pix_count - i;
295 if (maxlen > MAX_LENGTH) { 295 if (maxlen > MAX_LENGTH) {
296 maxlen = MAX_LENGTH; 296 maxlen = MAX_LENGTH;
297 } 297 }
298 HashChainFindCopy(hash_chain, i, xsize, argb, maxlen, 298 HashChainFindCopy(hash_chain, i, xsize, argb, maxlen,
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 if (!CostModelBuild(cost_model, xsize, ysize, recursive_cost_model, argb, 503 if (!CostModelBuild(cost_model, xsize, ysize, recursive_cost_model, argb,
504 quality, cache_bits)) { 504 quality, cache_bits)) {
505 goto Error; 505 goto Error;
506 } 506 }
507 507
508 for (i = 0; i < pix_count; ++i) cost[i] = 1e38f; 508 for (i = 0; i < pix_count; ++i) cost[i] = 1e38f;
509 509
510 // We loop one pixel at a time, but store all currently best points to 510 // We loop one pixel at a time, but store all currently best points to
511 // non-processed locations from this point. 511 // non-processed locations from this point.
512 dist_array[0] = 0; 512 dist_array[0] = 0;
513 GetParamsForHashChainFindCopy(quality, xsize, &window_size, &iter_pos, 513 GetParamsForHashChainFindCopy(quality, xsize, cache_bits,
514 &iter_limit); 514 &window_size, &iter_pos, &iter_limit);
515 for (i = 0; i < pix_count; ++i) { 515 for (i = 0; i < pix_count; ++i) {
516 double prev_cost = 0.0; 516 double prev_cost = 0.0;
517 int shortmax; 517 int shortmax;
518 if (i > 0) { 518 if (i > 0) {
519 prev_cost = cost[i - 1]; 519 prev_cost = cost[i - 1];
520 } 520 }
521 for (shortmax = 0; shortmax < 2; ++shortmax) { 521 for (shortmax = 0; shortmax < 2; ++shortmax) {
522 int offset = 0; 522 int offset = 0;
523 int len = 0; 523 int len = 0;
524 if (i < pix_count - 1) { // FindCopy reads pixels at [i] and [i + 1]. 524 if (i < pix_count - 1) { // FindCopy reads pixels at [i] and [i + 1].
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 638
639 if (hash_chain == NULL || !HashChainInit(hash_chain, pix_count)) { 639 if (hash_chain == NULL || !HashChainInit(hash_chain, pix_count)) {
640 goto Error; 640 goto Error;
641 } 641 }
642 if (use_color_cache) { 642 if (use_color_cache) {
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, &window_size, &iter_pos, 648 GetParamsForHashChainFindCopy(quality, xsize, cache_bits,
649 &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 maxlen = chosen_path[ix];
654 if (maxlen != 1) { 654 if (maxlen != 1) {
655 HashChainFindCopy(hash_chain, i, xsize, argb, maxlen, 655 HashChainFindCopy(hash_chain, i, xsize, argb, maxlen,
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 == maxlen);
659 refs->refs[size] = PixOrCopyCreateCopy(offset, len); 659 refs->refs[size] = PixOrCopyCreateCopy(offset, len);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 (q <= 10).
784 const int try_lz77_trace_backwards = (quality > 10); 784 const int try_lz77_trace_backwards = (quality > 10);
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 const int recursion_level = (num_pix < 320 * 200) ? 1 : 0; 788 // Set recursion level for large images using a color cache.
789 const int recursion_level =
790 (num_pix < 320 * 200) && (cache_bits > 0) ? 1 : 0;
789 VP8LBackwardRefs refs_trace; 791 VP8LBackwardRefs refs_trace;
790 if (!VP8LBackwardRefsAlloc(&refs_trace, num_pix)) { 792 if (!VP8LBackwardRefsAlloc(&refs_trace, num_pix)) {
791 goto End; 793 goto End;
792 } 794 }
793 if (BackwardReferencesTraceBackwards(width, height, recursion_level, argb, 795 if (BackwardReferencesTraceBackwards(width, height, recursion_level, argb,
794 quality, cache_bits, &refs_trace)) { 796 quality, cache_bits, &refs_trace)) {
795 VP8LClearBackwardRefs(&refs_lz77); 797 VP8LClearBackwardRefs(&refs_lz77);
796 *best = refs_trace; 798 *best = refs_trace;
797 } 799 }
798 } 800 }
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 if (cache_bits == 0 || cur_entropy < lowest_entropy) { 885 if (cache_bits == 0 || cur_entropy < lowest_entropy) {
884 *best_cache_bits = cache_bits; 886 *best_cache_bits = cache_bits;
885 lowest_entropy = cur_entropy; 887 lowest_entropy = cur_entropy;
886 } 888 }
887 } 889 }
888 ok = 1; 890 ok = 1;
889 Error: 891 Error:
890 VP8LClearBackwardRefs(&refs); 892 VP8LClearBackwardRefs(&refs);
891 return ok; 893 return ok;
892 } 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