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

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

Issue 2584033003: libwebp-0.5.2-rc2 (Closed)
Patch Set: layout tests Created 3 years, 12 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
OLDNEW
1 // Copyright 2014 Google Inc. All Rights Reserved. 1 // Copyright 2014 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 // WebPPicture utils for colorspace conversion 10 // WebPPicture utils for colorspace conversion
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 static WEBP_INLINE uint8_t ConvertRGBToU(int r, int g, int b) { 374 static WEBP_INLINE uint8_t ConvertRGBToU(int r, int g, int b) {
375 const int u = -9719 * r - 19081 * g + 28800 * b + SROUNDER; 375 const int u = -9719 * r - 19081 * g + 28800 * b + SROUNDER;
376 return clip_8b(128 + (u >> (YUV_FIX + SFIX))); 376 return clip_8b(128 + (u >> (YUV_FIX + SFIX)));
377 } 377 }
378 378
379 static WEBP_INLINE uint8_t ConvertRGBToV(int r, int g, int b) { 379 static WEBP_INLINE uint8_t ConvertRGBToV(int r, int g, int b) {
380 const int v = +28800 * r - 24116 * g - 4684 * b + SROUNDER; 380 const int v = +28800 * r - 24116 * g - 4684 * b + SROUNDER;
381 return clip_8b(128 + (v >> (YUV_FIX + SFIX))); 381 return clip_8b(128 + (v >> (YUV_FIX + SFIX)));
382 } 382 }
383 383
384 static int ConvertWRGBToYUV(const fixed_y_t* const best_y, 384 static int ConvertWRGBToYUV(const fixed_y_t* best_y, const fixed_t* best_uv,
385 const fixed_t* const best_uv,
386 WebPPicture* const picture) { 385 WebPPicture* const picture) {
387 int i, j; 386 int i, j;
387 uint8_t* dst_y = picture->y;
388 uint8_t* dst_u = picture->u;
389 uint8_t* dst_v = picture->v;
390 const fixed_t* const best_uv_base = best_uv;
388 const int w = (picture->width + 1) & ~1; 391 const int w = (picture->width + 1) & ~1;
389 const int h = (picture->height + 1) & ~1; 392 const int h = (picture->height + 1) & ~1;
390 const int uv_w = w >> 1; 393 const int uv_w = w >> 1;
391 const int uv_h = h >> 1; 394 const int uv_h = h >> 1;
392 for (j = 0; j < picture->height; ++j) { 395 for (best_uv = best_uv_base, j = 0; j < picture->height; ++j) {
393 for (i = 0; i < picture->width; ++i) { 396 for (i = 0; i < picture->width; ++i) {
394 const int off = 3 * ((i >> 1) + (j >> 1) * uv_w); 397 const int off = 3 * (i >> 1);
395 const int off2 = i + j * picture->y_stride; 398 const int W = best_y[i];
396 const int W = best_y[i + j * w];
397 const int r = best_uv[off + 0] + W; 399 const int r = best_uv[off + 0] + W;
398 const int g = best_uv[off + 1] + W; 400 const int g = best_uv[off + 1] + W;
399 const int b = best_uv[off + 2] + W; 401 const int b = best_uv[off + 2] + W;
400 picture->y[off2] = ConvertRGBToY(r, g, b); 402 dst_y[i] = ConvertRGBToY(r, g, b);
401 } 403 }
404 best_y += w;
405 best_uv += (j & 1) * 3 * uv_w;
406 dst_y += picture->y_stride;
402 } 407 }
403 for (j = 0; j < uv_h; ++j) { 408 for (best_uv = best_uv_base, j = 0; j < uv_h; ++j) {
404 uint8_t* const dst_u = picture->u + j * picture->uv_stride;
405 uint8_t* const dst_v = picture->v + j * picture->uv_stride;
406 for (i = 0; i < uv_w; ++i) { 409 for (i = 0; i < uv_w; ++i) {
407 const int off = 3 * (i + j * uv_w); 410 const int off = 3 * i;
408 const int r = best_uv[off + 0]; 411 const int r = best_uv[off + 0];
409 const int g = best_uv[off + 1]; 412 const int g = best_uv[off + 1];
410 const int b = best_uv[off + 2]; 413 const int b = best_uv[off + 2];
411 dst_u[i] = ConvertRGBToU(r, g, b); 414 dst_u[i] = ConvertRGBToU(r, g, b);
412 dst_v[i] = ConvertRGBToV(r, g, b); 415 dst_v[i] = ConvertRGBToV(r, g, b);
413 } 416 }
417 best_uv += 3 * uv_w;
418 dst_u += picture->uv_stride;
419 dst_v += picture->uv_stride;
414 } 420 }
415 return 1; 421 return 1;
416 } 422 }
417 423
418 //------------------------------------------------------------------------------ 424 //------------------------------------------------------------------------------
419 // Main function 425 // Main function
420 426
421 #define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((W) * (H), sizeof(T))) 427 #define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((W) * (H), sizeof(T)))
422 428
423 static int PreprocessARGB(const uint8_t* const r_ptr, 429 static int PreprocessARGB(const uint8_t* r_ptr,
424 const uint8_t* const g_ptr, 430 const uint8_t* g_ptr,
425 const uint8_t* const b_ptr, 431 const uint8_t* b_ptr,
426 int step, int rgb_stride, 432 int step, int rgb_stride,
427 WebPPicture* const picture) { 433 WebPPicture* const picture) {
428 // we expand the right/bottom border if needed 434 // we expand the right/bottom border if needed
429 const int w = (picture->width + 1) & ~1; 435 const int w = (picture->width + 1) & ~1;
430 const int h = (picture->height + 1) & ~1; 436 const int h = (picture->height + 1) & ~1;
431 const int uv_w = w >> 1; 437 const int uv_w = w >> 1;
432 const int uv_h = h >> 1; 438 const int uv_h = h >> 1;
433 int i, j, iter; 439 int i, j, iter;
434 440
435 // TODO(skal): allocate one big memory chunk. But for now, it's easier 441 // TODO(skal): allocate one big memory chunk. But for now, it's easier
436 // for valgrind debugging to have several chunks. 442 // for valgrind debugging to have several chunks.
437 fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch 443 fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch
438 fixed_y_t* const best_y = SAFE_ALLOC(w, h, fixed_y_t); 444 fixed_y_t* const best_y_base = SAFE_ALLOC(w, h, fixed_y_t);
439 fixed_y_t* const target_y = SAFE_ALLOC(w, h, fixed_y_t); 445 fixed_y_t* const target_y_base = SAFE_ALLOC(w, h, fixed_y_t);
440 fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t); 446 fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t);
441 fixed_t* const best_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); 447 fixed_t* const best_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
442 fixed_t* const target_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); 448 fixed_t* const target_uv_base = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t);
443 fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t); 449 fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t);
450 fixed_y_t* best_y = best_y_base;
451 fixed_y_t* target_y = target_y_base;
452 fixed_t* best_uv = best_uv_base;
453 fixed_t* target_uv = target_uv_base;
444 int ok; 454 int ok;
445 int diff_sum = 0; 455 int diff_sum = 0;
446 const int first_diff_threshold = (int)(2.5 * w * h); 456 const int first_diff_threshold = (int)(2.5 * w * h);
447 const int min_improvement = 5; // stop if improvement is below this % 457 const int min_improvement = 5; // stop if improvement is below this %
448 const int min_first_improvement = 80; 458 const int min_first_improvement = 80;
449 459
450 if (best_y == NULL || best_uv == NULL || 460 if (best_y_base == NULL || best_uv_base == NULL ||
451 target_y == NULL || target_uv == NULL || 461 target_y_base == NULL || target_uv_base == NULL ||
452 best_rgb_y == NULL || best_rgb_uv == NULL || 462 best_rgb_y == NULL || best_rgb_uv == NULL ||
453 tmp_buffer == NULL) { 463 tmp_buffer == NULL) {
454 ok = WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); 464 ok = WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
455 goto End; 465 goto End;
456 } 466 }
457 assert(picture->width >= kMinDimensionIterativeConversion); 467 assert(picture->width >= kMinDimensionIterativeConversion);
458 assert(picture->height >= kMinDimensionIterativeConversion); 468 assert(picture->height >= kMinDimensionIterativeConversion);
459 469
460 // Import RGB samples to W/RGB representation. 470 // Import RGB samples to W/RGB representation.
461 for (j = 0; j < picture->height; j += 2) { 471 for (j = 0; j < picture->height; j += 2) {
462 const int is_last_row = (j == picture->height - 1); 472 const int is_last_row = (j == picture->height - 1);
463 fixed_y_t* const src1 = tmp_buffer; 473 fixed_y_t* const src1 = tmp_buffer;
464 fixed_y_t* const src2 = tmp_buffer + 3 * w; 474 fixed_y_t* const src2 = tmp_buffer + 3 * w;
465 const int off1 = j * rgb_stride;
466 const int off2 = off1 + rgb_stride;
467 const int uv_off = (j >> 1) * 3 * uv_w;
468 fixed_y_t* const dst_y = best_y + j * w;
469 475
470 // prepare two rows of input 476 // prepare two rows of input
471 ImportOneRow(r_ptr + off1, g_ptr + off1, b_ptr + off1, 477 ImportOneRow(r_ptr, g_ptr, b_ptr, step, picture->width, src1);
472 step, picture->width, src1);
473 if (!is_last_row) { 478 if (!is_last_row) {
474 ImportOneRow(r_ptr + off2, g_ptr + off2, b_ptr + off2, 479 ImportOneRow(r_ptr + rgb_stride, g_ptr + rgb_stride, b_ptr + rgb_stride,
475 step, picture->width, src2); 480 step, picture->width, src2);
476 } else { 481 } else {
477 memcpy(src2, src1, 3 * w * sizeof(*src2)); 482 memcpy(src2, src1, 3 * w * sizeof(*src2));
478 } 483 }
479 UpdateW(src1, target_y + (j + 0) * w, w); 484 UpdateW(src1, target_y, w);
480 UpdateW(src2, target_y + (j + 1) * w, w); 485 UpdateW(src2, target_y + w, w);
481 diff_sum += UpdateChroma(src1, src2, target_uv + uv_off, dst_y, uv_w); 486 diff_sum += UpdateChroma(src1, src2, target_uv, best_y, uv_w);
482 memcpy(best_uv + uv_off, target_uv + uv_off, 3 * uv_w * sizeof(*best_uv)); 487 memcpy(best_uv, target_uv, 3 * uv_w * sizeof(*best_uv));
483 memcpy(dst_y + w, dst_y, w * sizeof(*dst_y)); 488 memcpy(best_y + w, best_y, w * sizeof(*best_y));
489 best_y += 2 * w;
490 best_uv += 3 * uv_w;
491 target_y += 2 * w;
492 target_uv += 3 * uv_w;
493 r_ptr += 2 * rgb_stride;
494 g_ptr += 2 * rgb_stride;
495 b_ptr += 2 * rgb_stride;
484 } 496 }
485 497
486 // Iterate and resolve clipping conflicts. 498 // Iterate and resolve clipping conflicts.
487 for (iter = 0; iter < kNumIterations; ++iter) { 499 for (iter = 0; iter < kNumIterations; ++iter) {
488 int k; 500 int k;
489 const fixed_t* cur_uv = best_uv; 501 const fixed_t* cur_uv = best_uv_base;
490 const fixed_t* prev_uv = best_uv; 502 const fixed_t* prev_uv = best_uv_base;
491 const int old_diff_sum = diff_sum; 503 const int old_diff_sum = diff_sum;
492 diff_sum = 0; 504 diff_sum = 0;
505
506 best_y = best_y_base;
507 best_uv = best_uv_base;
508 target_y = target_y_base;
509 target_uv = target_uv_base;
493 for (j = 0; j < h; j += 2) { 510 for (j = 0; j < h; j += 2) {
494 fixed_y_t* const src1 = tmp_buffer; 511 fixed_y_t* const src1 = tmp_buffer;
495 fixed_y_t* const src2 = tmp_buffer + 3 * w; 512 fixed_y_t* const src2 = tmp_buffer + 3 * w;
496 { 513 {
497 const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0); 514 const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0);
498 InterpolateTwoRows(best_y + j * w, prev_uv, cur_uv, next_uv, 515 InterpolateTwoRows(best_y, prev_uv, cur_uv, next_uv, w, src1, src2);
499 w, src1, src2);
500 prev_uv = cur_uv; 516 prev_uv = cur_uv;
501 cur_uv = next_uv; 517 cur_uv = next_uv;
502 } 518 }
503 519
504 UpdateW(src1, best_rgb_y + 0 * w, w); 520 UpdateW(src1, best_rgb_y + 0 * w, w);
505 UpdateW(src2, best_rgb_y + 1 * w, w); 521 UpdateW(src2, best_rgb_y + 1 * w, w);
506 diff_sum += UpdateChroma(src1, src2, best_rgb_uv, NULL, uv_w); 522 diff_sum += UpdateChroma(src1, src2, best_rgb_uv, NULL, uv_w);
507 523
508 // update two rows of Y and one row of RGB 524 // update two rows of Y and one row of RGB
509 for (i = 0; i < 2 * w; ++i) { 525 for (i = 0; i < 2 * w; ++i) {
510 const int off = i + j * w; 526 const int diff_y = target_y[i] - best_rgb_y[i];
511 const int diff_y = target_y[off] - best_rgb_y[i]; 527 const int new_y = (int)best_y[i] + diff_y;
512 const int new_y = (int)best_y[off] + diff_y; 528 best_y[i] = clip_y(new_y);
513 best_y[off] = clip_y(new_y);
514 } 529 }
515 for (i = 0; i < uv_w; ++i) { 530 for (i = 0; i < uv_w; ++i) {
516 const int off = 3 * (i + (j >> 1) * uv_w); 531 const int off = 3 * i;
517 int W; 532 int W;
518 for (k = 0; k <= 2; ++k) { 533 for (k = 0; k <= 2; ++k) {
519 const int diff_uv = (int)target_uv[off + k] - best_rgb_uv[3 * i + k]; 534 const int diff_uv = (int)target_uv[off + k] - best_rgb_uv[off + k];
520 best_uv[off + k] += diff_uv; 535 best_uv[off + k] += diff_uv;
521 } 536 }
522 W = RGBToGray(best_uv[off + 0], best_uv[off + 1], best_uv[off + 2]); 537 W = RGBToGray(best_uv[off + 0], best_uv[off + 1], best_uv[off + 2]);
523 for (k = 0; k <= 2; ++k) { 538 for (k = 0; k <= 2; ++k) {
524 best_uv[off + k] -= W; 539 best_uv[off + k] -= W;
525 } 540 }
526 } 541 }
542 best_y += 2 * w;
543 best_uv += 3 * uv_w;
544 target_y += 2 * w;
545 target_uv += 3 * uv_w;
527 } 546 }
528 // test exit condition 547 // test exit condition
529 if (diff_sum > 0) { 548 if (diff_sum > 0) {
530 const int improvement = 100 * abs(diff_sum - old_diff_sum) / diff_sum; 549 const int improvement = 100 * abs(diff_sum - old_diff_sum) / diff_sum;
531 // Check if first iteration gave good result already, without a large 550 // Check if first iteration gave good result already, without a large
532 // jump of improvement (otherwise it means we need to try few extra 551 // jump of improvement (otherwise it means we need to try few extra
533 // iterations, just to be sure). 552 // iterations, just to be sure).
534 if (iter == 0 && diff_sum < first_diff_threshold && 553 if (iter == 0 && diff_sum < first_diff_threshold &&
535 improvement < min_first_improvement) { 554 improvement < min_first_improvement) {
536 break; 555 break;
537 } 556 }
538 // then, check if improvement is stalling. 557 // then, check if improvement is stalling.
539 if (improvement < min_improvement) { 558 if (improvement < min_improvement) {
540 break; 559 break;
541 } 560 }
542 } else { 561 } else {
543 break; 562 break;
544 } 563 }
545 } 564 }
546 565
547 // final reconstruction 566 // final reconstruction
548 ok = ConvertWRGBToYUV(best_y, best_uv, picture); 567 ok = ConvertWRGBToYUV(best_y_base, best_uv_base, picture);
549 568
550 End: 569 End:
551 WebPSafeFree(best_y); 570 WebPSafeFree(best_y_base);
552 WebPSafeFree(best_uv); 571 WebPSafeFree(best_uv_base);
553 WebPSafeFree(target_y); 572 WebPSafeFree(target_y_base);
554 WebPSafeFree(target_uv); 573 WebPSafeFree(target_uv_base);
555 WebPSafeFree(best_rgb_y); 574 WebPSafeFree(best_rgb_y);
556 WebPSafeFree(best_rgb_uv); 575 WebPSafeFree(best_rgb_uv);
557 WebPSafeFree(tmp_buffer); 576 WebPSafeFree(tmp_buffer);
558 return ok; 577 return ok;
559 } 578 }
560 #undef SAFE_ALLOC 579 #undef SAFE_ALLOC
561 580
562 //------------------------------------------------------------------------------ 581 //------------------------------------------------------------------------------
563 // "Fast" regular RGB->YUV 582 // "Fast" regular RGB->YUV
564 583
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 int width, 842 int width,
824 VP8Random* const rg) { 843 VP8Random* const rg) {
825 int i; 844 int i;
826 for (i = 0; i < width; i += 1, rgb += 4) { 845 for (i = 0; i < width; i += 1, rgb += 4) {
827 const int r = rgb[0], g = rgb[1], b = rgb[2]; 846 const int r = rgb[0], g = rgb[1], b = rgb[2];
828 dst_u[i] = RGBToU(r, g, b, rg); 847 dst_u[i] = RGBToU(r, g, b, rg);
829 dst_v[i] = RGBToV(r, g, b, rg); 848 dst_v[i] = RGBToV(r, g, b, rg);
830 } 849 }
831 } 850 }
832 851
833 static int ImportYUVAFromRGBA(const uint8_t* const r_ptr, 852 static int ImportYUVAFromRGBA(const uint8_t* r_ptr,
834 const uint8_t* const g_ptr, 853 const uint8_t* g_ptr,
835 const uint8_t* const b_ptr, 854 const uint8_t* b_ptr,
836 const uint8_t* const a_ptr, 855 const uint8_t* a_ptr,
837 int step, // bytes per pixel 856 int step, // bytes per pixel
838 int rgb_stride, // bytes per scanline 857 int rgb_stride, // bytes per scanline
839 float dithering, 858 float dithering,
840 int use_iterative_conversion, 859 int use_iterative_conversion,
841 WebPPicture* const picture) { 860 WebPPicture* const picture) {
842 int y; 861 int y;
843 const int width = picture->width; 862 const int width = picture->width;
844 const int height = picture->height; 863 const int height = picture->height;
845 const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride); 864 const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride);
846 const int is_rgb = (r_ptr < b_ptr); // otherwise it's bgr 865 const int is_rgb = (r_ptr < b_ptr); // otherwise it's bgr
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 use_dsp = 0; // can't use dsp in this case 912 use_dsp = 0; // can't use dsp in this case
894 } 913 }
895 WebPInitConvertARGBToYUV(); 914 WebPInitConvertARGBToYUV();
896 InitGammaTables(); 915 InitGammaTables();
897 916
898 if (tmp_rgb == NULL) return 0; // malloc error 917 if (tmp_rgb == NULL) return 0; // malloc error
899 918
900 // Downsample Y/U/V planes, two rows at a time 919 // Downsample Y/U/V planes, two rows at a time
901 for (y = 0; y < (height >> 1); ++y) { 920 for (y = 0; y < (height >> 1); ++y) {
902 int rows_have_alpha = has_alpha; 921 int rows_have_alpha = has_alpha;
903 const int off1 = (2 * y + 0) * rgb_stride;
904 const int off2 = (2 * y + 1) * rgb_stride;
905 if (use_dsp) { 922 if (use_dsp) {
906 if (is_rgb) { 923 if (is_rgb) {
907 WebPConvertRGB24ToY(r_ptr + off1, dst_y, width); 924 WebPConvertRGB24ToY(r_ptr, dst_y, width);
908 WebPConvertRGB24ToY(r_ptr + off2, dst_y + picture->y_stride, width); 925 WebPConvertRGB24ToY(r_ptr + rgb_stride,
926 dst_y + picture->y_stride, width);
909 } else { 927 } else {
910 WebPConvertBGR24ToY(b_ptr + off1, dst_y, width); 928 WebPConvertBGR24ToY(b_ptr, dst_y, width);
911 WebPConvertBGR24ToY(b_ptr + off2, dst_y + picture->y_stride, width); 929 WebPConvertBGR24ToY(b_ptr + rgb_stride,
930 dst_y + picture->y_stride, width);
912 } 931 }
913 } else { 932 } else {
914 ConvertRowToY(r_ptr + off1, g_ptr + off1, b_ptr + off1, step, 933 ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg);
915 dst_y, width, rg); 934 ConvertRowToY(r_ptr + rgb_stride,
916 ConvertRowToY(r_ptr + off2, g_ptr + off2, b_ptr + off2, step, 935 g_ptr + rgb_stride,
936 b_ptr + rgb_stride, step,
917 dst_y + picture->y_stride, width, rg); 937 dst_y + picture->y_stride, width, rg);
918 } 938 }
919 dst_y += 2 * picture->y_stride; 939 dst_y += 2 * picture->y_stride;
920 if (has_alpha) { 940 if (has_alpha) {
921 rows_have_alpha &= !WebPExtractAlpha(a_ptr + off1, rgb_stride, 941 rows_have_alpha &= !WebPExtractAlpha(a_ptr, rgb_stride, width, 2,
922 width, 2,
923 dst_a, picture->a_stride); 942 dst_a, picture->a_stride);
924 dst_a += 2 * picture->a_stride; 943 dst_a += 2 * picture->a_stride;
925 } 944 }
926 // Collect averaged R/G/B(/A) 945 // Collect averaged R/G/B(/A)
927 if (!rows_have_alpha) { 946 if (!rows_have_alpha) {
928 AccumulateRGB(r_ptr + off1, g_ptr + off1, b_ptr + off1, 947 AccumulateRGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, tmp_rgb, width);
929 step, rgb_stride, tmp_rgb, width);
930 } else { 948 } else {
931 AccumulateRGBA(r_ptr + off1, g_ptr + off1, b_ptr + off1, a_ptr + off1, 949 AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, rgb_stride, tmp_rgb, width);
932 rgb_stride, tmp_rgb, width);
933 } 950 }
934 // Convert to U/V 951 // Convert to U/V
935 if (rg == NULL) { 952 if (rg == NULL) {
936 WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); 953 WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width);
937 } else { 954 } else {
938 ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); 955 ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg);
939 } 956 }
940 dst_u += picture->uv_stride; 957 dst_u += picture->uv_stride;
941 dst_v += picture->uv_stride; 958 dst_v += picture->uv_stride;
959 r_ptr += 2 * rgb_stride;
960 b_ptr += 2 * rgb_stride;
961 g_ptr += 2 * rgb_stride;
962 if (has_alpha) a_ptr += 2 * rgb_stride;
942 } 963 }
943 if (height & 1) { // extra last row 964 if (height & 1) { // extra last row
944 const int off = 2 * y * rgb_stride;
945 int row_has_alpha = has_alpha; 965 int row_has_alpha = has_alpha;
946 if (use_dsp) { 966 if (use_dsp) {
947 if (r_ptr < b_ptr) { 967 if (r_ptr < b_ptr) {
948 WebPConvertRGB24ToY(r_ptr + off, dst_y, width); 968 WebPConvertRGB24ToY(r_ptr, dst_y, width);
949 } else { 969 } else {
950 WebPConvertBGR24ToY(b_ptr + off, dst_y, width); 970 WebPConvertBGR24ToY(b_ptr, dst_y, width);
951 } 971 }
952 } else { 972 } else {
953 ConvertRowToY(r_ptr + off, g_ptr + off, b_ptr + off, step, 973 ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg);
954 dst_y, width, rg);
955 } 974 }
956 if (row_has_alpha) { 975 if (row_has_alpha) {
957 row_has_alpha &= !WebPExtractAlpha(a_ptr + off, 0, width, 1, dst_a, 0); 976 row_has_alpha &= !WebPExtractAlpha(a_ptr, 0, width, 1, dst_a, 0);
958 } 977 }
959 // Collect averaged R/G/B(/A) 978 // Collect averaged R/G/B(/A)
960 if (!row_has_alpha) { 979 if (!row_has_alpha) {
961 // Collect averaged R/G/B 980 // Collect averaged R/G/B
962 AccumulateRGB(r_ptr + off, g_ptr + off, b_ptr + off, 981 AccumulateRGB(r_ptr, g_ptr, b_ptr, step, /* rgb_stride = */ 0,
963 step, /* rgb_stride = */ 0, tmp_rgb, width); 982 tmp_rgb, width);
964 } else { 983 } else {
965 AccumulateRGBA(r_ptr + off, g_ptr + off, b_ptr + off, a_ptr + off, 984 AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, /* rgb_stride = */ 0,
966 /* rgb_stride = */ 0, tmp_rgb, width); 985 tmp_rgb, width);
967 } 986 }
968 if (rg == NULL) { 987 if (rg == NULL) {
969 WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); 988 WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width);
970 } else { 989 } else {
971 ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); 990 ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg);
972 } 991 }
973 } 992 }
974 WebPSafeFree(tmp_rgb); 993 WebPSafeFree(tmp_rgb);
975 } 994 }
976 return 1; 995 return 1;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 return 1; 1098 return 1;
1080 } 1099 }
1081 1100
1082 //------------------------------------------------------------------------------ 1101 //------------------------------------------------------------------------------
1083 // automatic import / conversion 1102 // automatic import / conversion
1084 1103
1085 static int Import(WebPPicture* const picture, 1104 static int Import(WebPPicture* const picture,
1086 const uint8_t* const rgb, int rgb_stride, 1105 const uint8_t* const rgb, int rgb_stride,
1087 int step, int swap_rb, int import_alpha) { 1106 int step, int swap_rb, int import_alpha) {
1088 int y; 1107 int y;
1089 const uint8_t* const r_ptr = rgb + (swap_rb ? 2 : 0); 1108 const uint8_t* r_ptr = rgb + (swap_rb ? 2 : 0);
1090 const uint8_t* const g_ptr = rgb + 1; 1109 const uint8_t* g_ptr = rgb + 1;
1091 const uint8_t* const b_ptr = rgb + (swap_rb ? 0 : 2); 1110 const uint8_t* b_ptr = rgb + (swap_rb ? 0 : 2);
1092 const uint8_t* const a_ptr = import_alpha ? rgb + 3 : NULL; 1111 const uint8_t* a_ptr = import_alpha ? rgb + 3 : NULL;
1093 const int width = picture->width; 1112 const int width = picture->width;
1094 const int height = picture->height; 1113 const int height = picture->height;
1095 1114
1096 if (!picture->use_argb) { 1115 if (!picture->use_argb) {
1097 return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, 1116 return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride,
1098 0.f /* no dithering */, 0, picture); 1117 0.f /* no dithering */, 0, picture);
1099 } 1118 }
1100 if (!WebPPictureAlloc(picture)) return 0; 1119 if (!WebPPictureAlloc(picture)) return 0;
1101 1120
1102 VP8EncDspARGBInit(); 1121 VP8EncDspARGBInit();
1103 1122
1104 if (import_alpha) { 1123 if (import_alpha) {
1124 uint32_t* dst = picture->argb;
1105 assert(step == 4); 1125 assert(step == 4);
1106 for (y = 0; y < height; ++y) { 1126 for (y = 0; y < height; ++y) {
1107 uint32_t* const dst = &picture->argb[y * picture->argb_stride]; 1127 VP8PackARGB(a_ptr, r_ptr, g_ptr, b_ptr, width, dst);
1108 const int offset = y * rgb_stride; 1128 a_ptr += rgb_stride;
1109 VP8PackARGB(a_ptr + offset, r_ptr + offset, g_ptr + offset, 1129 r_ptr += rgb_stride;
1110 b_ptr + offset, width, dst); 1130 g_ptr += rgb_stride;
1131 b_ptr += rgb_stride;
1132 dst += picture->argb_stride;
1111 } 1133 }
1112 } else { 1134 } else {
1135 uint32_t* dst = picture->argb;
1113 assert(step >= 3); 1136 assert(step >= 3);
1114 for (y = 0; y < height; ++y) { 1137 for (y = 0; y < height; ++y) {
1115 uint32_t* const dst = &picture->argb[y * picture->argb_stride]; 1138 VP8PackRGB(r_ptr, g_ptr, b_ptr, width, step, dst);
1116 const int offset = y * rgb_stride; 1139 r_ptr += rgb_stride;
1117 VP8PackRGB(r_ptr + offset, g_ptr + offset, b_ptr + offset, 1140 g_ptr += rgb_stride;
1118 width, step, dst); 1141 b_ptr += rgb_stride;
1142 dst += picture->argb_stride;
1119 } 1143 }
1120 } 1144 }
1121 return 1; 1145 return 1;
1122 } 1146 }
1123 1147
1124 // Public API 1148 // Public API
1125 1149
1126 int WebPPictureImportRGB(WebPPicture* picture, 1150 int WebPPictureImportRGB(WebPPicture* picture,
1127 const uint8_t* rgb, int rgb_stride) { 1151 const uint8_t* rgb, int rgb_stride) {
1128 return (picture != NULL && rgb != NULL) 1152 return (picture != NULL && rgb != NULL)
(...skipping 30 matching lines...) Expand all
1159 } 1183 }
1160 1184
1161 int WebPPictureImportBGRX(WebPPicture* picture, 1185 int WebPPictureImportBGRX(WebPPicture* picture,
1162 const uint8_t* rgba, int rgba_stride) { 1186 const uint8_t* rgba, int rgba_stride) {
1163 return (picture != NULL && rgba != NULL) 1187 return (picture != NULL && rgba != NULL)
1164 ? Import(picture, rgba, rgba_stride, 4, 1, 0) 1188 ? Import(picture, rgba, rgba_stride, 4, 1, 0)
1165 : 0; 1189 : 0;
1166 } 1190 }
1167 1191
1168 //------------------------------------------------------------------------------ 1192 //------------------------------------------------------------------------------
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698