| OLD | NEW |
| 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 // Misc. common utility functions | 10 // Misc. common utility functions |
| 11 // | 11 // |
| 12 // Author: Skal (pascal.massimino@gmail.com) | 12 // Author: Skal (pascal.massimino@gmail.com) |
| 13 | 13 |
| 14 #include <stdlib.h> | 14 #include <stdlib.h> |
| 15 #include <string.h> // for memcpy() | 15 #include <string.h> // for memcpy() |
| 16 #include "../webp/decode.h" | 16 #include "../webp/decode.h" |
| 17 #include "../webp/encode.h" | 17 #include "../webp/encode.h" |
| 18 #include "../webp/format_constants.h" // for MAX_PALETTE_SIZE | 18 #include "../webp/format_constants.h" // for MAX_PALETTE_SIZE |
| 19 #include "./utils.h" | 19 #include "./utils.h" |
| 20 | 20 |
| 21 // If PRINT_MEM_INFO is defined, extra info (like total memory used, number of | 21 // If PRINT_MEM_INFO is defined, extra info (like total memory used, number of |
| 22 // alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, | 22 // alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, |
| 23 // and not multi-thread safe!). | 23 // and not multi-thread safe!). |
| 24 // An interesting alternative is valgrind's 'massif' tool: | 24 // An interesting alternative is valgrind's 'massif' tool: |
| 25 // http://valgrind.org/docs/manual/ms-manual.html | 25 // http://valgrind.org/docs/manual/ms-manual.html |
| 26 // Here is an example command line: | 26 // Here is an example command line: |
| 27 /* valgrind --tool=massif --massif-out-file=massif.out \ | 27 /* valgrind --tool=massif --massif-out-file=massif.out \ |
| 28 --stacks=yes --alloc-fn=WebPSafeAlloc --alloc-fn=WebPSafeCalloc | 28 --stacks=yes --alloc-fn=WebPSafeMalloc --alloc-fn=WebPSafeCalloc |
| 29 ms_print massif.out | 29 ms_print massif.out |
| 30 */ | 30 */ |
| 31 // In addition: | 31 // In addition: |
| 32 // * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles | 32 // * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles |
| 33 // are printed. | 33 // are printed. |
| 34 // * if MALLOC_FAIL_AT is defined, the global environment variable | 34 // * if MALLOC_FAIL_AT is defined, the global environment variable |
| 35 // $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc | 35 // $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc |
| 36 // is called for the nth time. Example usage: | 36 // is called for the nth time. Example usage: |
| 37 // export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png | 37 // export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png |
| 38 // * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT | 38 // * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { | 236 void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { |
| 237 assert(src != NULL && dst != NULL); | 237 assert(src != NULL && dst != NULL); |
| 238 assert(src->width == dst->width && src->height == dst->height); | 238 assert(src->width == dst->width && src->height == dst->height); |
| 239 assert(src->use_argb && dst->use_argb); | 239 assert(src->use_argb && dst->use_argb); |
| 240 WebPCopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb, | 240 WebPCopyPlane((uint8_t*)src->argb, 4 * src->argb_stride, (uint8_t*)dst->argb, |
| 241 4 * dst->argb_stride, 4 * src->width, src->height); | 241 4 * dst->argb_stride, 4 * src->width, src->height); |
| 242 } | 242 } |
| 243 | 243 |
| 244 //------------------------------------------------------------------------------ | 244 //------------------------------------------------------------------------------ |
| 245 | 245 |
| 246 #define MAX_COLOR_COUNT MAX_PALETTE_SIZE | 246 #define COLOR_HASH_SIZE (MAX_PALETTE_SIZE * 4) |
| 247 #define COLOR_HASH_SIZE (MAX_COLOR_COUNT * 4) | |
| 248 #define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE). | 247 #define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE). |
| 249 | 248 |
| 250 int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { | 249 int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { |
| 251 int i; | 250 int i; |
| 252 int x, y; | 251 int x, y; |
| 253 int num_colors = 0; | 252 int num_colors = 0; |
| 254 uint8_t in_use[COLOR_HASH_SIZE] = { 0 }; | 253 uint8_t in_use[COLOR_HASH_SIZE] = { 0 }; |
| 255 uint32_t colors[COLOR_HASH_SIZE]; | 254 uint32_t colors[COLOR_HASH_SIZE]; |
| 256 static const uint32_t kHashMul = 0x1e35a7bdU; | 255 static const uint64_t kHashMul = 0x1e35a7bdull; |
| 257 const uint32_t* argb = pic->argb; | 256 const uint32_t* argb = pic->argb; |
| 258 const int width = pic->width; | 257 const int width = pic->width; |
| 259 const int height = pic->height; | 258 const int height = pic->height; |
| 260 uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] | 259 uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] |
| 261 assert(pic != NULL); | 260 assert(pic != NULL); |
| 262 assert(pic->use_argb); | 261 assert(pic->use_argb); |
| 263 | 262 |
| 264 for (y = 0; y < height; ++y) { | 263 for (y = 0; y < height; ++y) { |
| 265 for (x = 0; x < width; ++x) { | 264 for (x = 0; x < width; ++x) { |
| 266 int key; | 265 int key; |
| 267 if (argb[x] == last_pix) { | 266 if (argb[x] == last_pix) { |
| 268 continue; | 267 continue; |
| 269 } | 268 } |
| 270 last_pix = argb[x]; | 269 last_pix = argb[x]; |
| 271 key = (kHashMul * last_pix) >> COLOR_HASH_RIGHT_SHIFT; | 270 key = ((last_pix * kHashMul) & 0xffffffffu) >> COLOR_HASH_RIGHT_SHIFT; |
| 272 while (1) { | 271 while (1) { |
| 273 if (!in_use[key]) { | 272 if (!in_use[key]) { |
| 274 colors[key] = last_pix; | 273 colors[key] = last_pix; |
| 275 in_use[key] = 1; | 274 in_use[key] = 1; |
| 276 ++num_colors; | 275 ++num_colors; |
| 277 if (num_colors > MAX_COLOR_COUNT) { | 276 if (num_colors > MAX_PALETTE_SIZE) { |
| 278 return MAX_COLOR_COUNT + 1; // Exact count not needed. | 277 return MAX_PALETTE_SIZE + 1; // Exact count not needed. |
| 279 } | 278 } |
| 280 break; | 279 break; |
| 281 } else if (colors[key] == last_pix) { | 280 } else if (colors[key] == last_pix) { |
| 282 break; // The color is already there. | 281 break; // The color is already there. |
| 283 } else { | 282 } else { |
| 284 // Some other color sits here, so do linear conflict resolution. | 283 // Some other color sits here, so do linear conflict resolution. |
| 285 ++key; | 284 ++key; |
| 286 key &= (COLOR_HASH_SIZE - 1); // Key mask. | 285 key &= (COLOR_HASH_SIZE - 1); // Key mask. |
| 287 } | 286 } |
| 288 } | 287 } |
| 289 } | 288 } |
| 290 argb += pic->argb_stride; | 289 argb += pic->argb_stride; |
| 291 } | 290 } |
| 292 | 291 |
| 293 if (palette != NULL) { // Fill the colors into palette. | 292 if (palette != NULL) { // Fill the colors into palette. |
| 294 num_colors = 0; | 293 num_colors = 0; |
| 295 for (i = 0; i < COLOR_HASH_SIZE; ++i) { | 294 for (i = 0; i < COLOR_HASH_SIZE; ++i) { |
| 296 if (in_use[i]) { | 295 if (in_use[i]) { |
| 297 palette[num_colors] = colors[i]; | 296 palette[num_colors] = colors[i]; |
| 298 ++num_colors; | 297 ++num_colors; |
| 299 } | 298 } |
| 300 } | 299 } |
| 301 } | 300 } |
| 302 return num_colors; | 301 return num_colors; |
| 303 } | 302 } |
| 304 | 303 |
| 305 #undef MAX_COLOR_COUNT | |
| 306 #undef COLOR_HASH_SIZE | 304 #undef COLOR_HASH_SIZE |
| 307 #undef COLOR_HASH_RIGHT_SHIFT | 305 #undef COLOR_HASH_RIGHT_SHIFT |
| 308 | 306 |
| 309 //------------------------------------------------------------------------------ | 307 //------------------------------------------------------------------------------ |
| 308 |
| 309 #if defined(WEBP_NEED_LOG_TABLE_8BIT) |
| 310 const uint8_t WebPLogTable8bit[256] = { // 31 ^ clz(i) |
| 311 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, |
| 312 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
| 313 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| 314 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
| 315 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
| 316 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
| 317 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
| 318 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
| 319 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
| 320 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
| 321 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
| 322 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
| 323 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
| 324 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
| 325 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
| 326 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 |
| 327 }; |
| 328 #endif |
| 329 |
| 330 //------------------------------------------------------------------------------ |
| OLD | NEW |