| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gfx/color_analysis.h" | 5 #include "ui/gfx/color_analysis.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "third_party/skia/include/core/SkBitmap.h" | 13 #include "third_party/skia/include/core/SkBitmap.h" |
| 14 #include "third_party/skia/include/core/SkColorPriv.h" | |
| 15 #include "third_party/skia/include/core/SkUnPreMultiply.h" | 14 #include "third_party/skia/include/core/SkUnPreMultiply.h" |
| 16 #include "ui/gfx/codec/png_codec.h" | 15 #include "ui/gfx/codec/png_codec.h" |
| 17 #include "ui/gfx/color_utils.h" | 16 #include "ui/gfx/color_utils.h" |
| 18 | 17 |
| 19 namespace color_utils { | 18 namespace color_utils { |
| 20 namespace { | 19 namespace { |
| 21 | 20 |
| 22 // RGBA KMean Constants | 21 // RGBA KMean Constants |
| 23 const uint32_t kNumberOfClusters = 4; | 22 const uint32_t kNumberOfClusters = 4; |
| 24 const int kNumberOfIterations = 50; | 23 const int kNumberOfIterations = 50; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 // Holds the sum of all the points that make up this cluster. Used to | 122 // Holds the sum of all the points that make up this cluster. Used to |
| 124 // generate the next centroid as well as to check for convergence. | 123 // generate the next centroid as well as to check for convergence. |
| 125 uint32_t aggregate_[3]; | 124 uint32_t aggregate_[3]; |
| 126 uint32_t counter_; | 125 uint32_t counter_; |
| 127 | 126 |
| 128 // The weight of the cluster, determined by how many points were used | 127 // The weight of the cluster, determined by how many points were used |
| 129 // to generate the previous centroid. | 128 // to generate the previous centroid. |
| 130 uint32_t weight_; | 129 uint32_t weight_; |
| 131 }; | 130 }; |
| 132 | 131 |
| 133 // Un-premultiplies each pixel in |bitmap| into an output |buffer|. | 132 // Un-premultiplies each pixel in |bitmap| into an output |buffer|. Requires |
| 133 // approximately 10 microseconds for a 16x16 icon on an Intel Core i5. |
| 134 void UnPreMultiply(const SkBitmap& bitmap, uint32_t* buffer, int buffer_size) { | 134 void UnPreMultiply(const SkBitmap& bitmap, uint32_t* buffer, int buffer_size) { |
| 135 SkAutoLockPixels auto_lock(bitmap); | 135 SkAutoLockPixels auto_lock(bitmap); |
| 136 uint32_t* in = static_cast<uint32_t*>(bitmap.getPixels()); | 136 uint32_t* in = static_cast<uint32_t*>(bitmap.getPixels()); |
| 137 uint32_t* out = buffer; | 137 uint32_t* out = buffer; |
| 138 int pixel_count = std::min(bitmap.width() * bitmap.height(), buffer_size); | 138 int pixel_count = std::min(bitmap.width() * bitmap.height(), buffer_size); |
| 139 for (int i = 0; i < pixel_count; ++i) { | 139 for (int i = 0; i < pixel_count; ++i) |
| 140 int alpha = SkGetPackedA32(*in); | 140 *out++ = SkUnPreMultiply::PMColorToColor(*in++); |
| 141 if (alpha != 0 && alpha != 255) | |
| 142 *out++ = SkUnPreMultiply::PMColorToColor(*in++); | |
| 143 else | |
| 144 *out++ = *in++; | |
| 145 } | |
| 146 } | 141 } |
| 147 | 142 |
| 148 } // namespace | 143 } // namespace |
| 149 | 144 |
| 150 KMeanImageSampler::KMeanImageSampler() { | 145 KMeanImageSampler::KMeanImageSampler() { |
| 151 } | 146 } |
| 152 | 147 |
| 153 KMeanImageSampler::~KMeanImageSampler() { | 148 KMeanImageSampler::~KMeanImageSampler() { |
| 154 } | 149 } |
| 155 | 150 |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 int64_t rr_sum = 0; | 427 int64_t rr_sum = 0; |
| 433 int64_t gg_sum = 0; | 428 int64_t gg_sum = 0; |
| 434 int64_t bb_sum = 0; | 429 int64_t bb_sum = 0; |
| 435 int64_t rg_sum = 0; | 430 int64_t rg_sum = 0; |
| 436 int64_t rb_sum = 0; | 431 int64_t rb_sum = 0; |
| 437 int64_t gb_sum = 0; | 432 int64_t gb_sum = 0; |
| 438 | 433 |
| 439 for (int y = 0; y < bitmap.height(); ++y) { | 434 for (int y = 0; y < bitmap.height(); ++y) { |
| 440 SkPMColor* current_color = static_cast<uint32_t*>(bitmap.getAddr32(0, y)); | 435 SkPMColor* current_color = static_cast<uint32_t*>(bitmap.getAddr32(0, y)); |
| 441 for (int x = 0; x < bitmap.width(); ++x, ++current_color) { | 436 for (int x = 0; x < bitmap.width(); ++x, ++current_color) { |
| 442 SkColor c; | 437 SkColor c = SkUnPreMultiply::PMColorToColor(*current_color); |
| 443 int alpha = SkGetPackedA32(*current_color); | |
| 444 if (alpha != 0 && alpha != 255) | |
| 445 c = SkUnPreMultiply::PMColorToColor(*current_color); | |
| 446 else | |
| 447 c = *current_color; | |
| 448 | |
| 449 SkColor r = SkColorGetR(c); | 438 SkColor r = SkColorGetR(c); |
| 450 SkColor g = SkColorGetG(c); | 439 SkColor g = SkColorGetG(c); |
| 451 SkColor b = SkColorGetB(c); | 440 SkColor b = SkColorGetB(c); |
| 452 | 441 |
| 453 r_sum += r; | 442 r_sum += r; |
| 454 g_sum += g; | 443 g_sum += g; |
| 455 b_sum += b; | 444 b_sum += b; |
| 456 rr_sum += r * r; | 445 rr_sum += r * r; |
| 457 gg_sum += g * g; | 446 gg_sum += g * g; |
| 458 bb_sum += b * b; | 447 bb_sum += b * b; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 | 513 |
| 525 if (fit_to_range) { | 514 if (fit_to_range) { |
| 526 // We will figure out min/max in a preprocessing step and adjust | 515 // We will figure out min/max in a preprocessing step and adjust |
| 527 // actual_transform as required. | 516 // actual_transform as required. |
| 528 float max_val = std::numeric_limits<float>::min(); | 517 float max_val = std::numeric_limits<float>::min(); |
| 529 float min_val = std::numeric_limits<float>::max(); | 518 float min_val = std::numeric_limits<float>::max(); |
| 530 for (int y = 0; y < source_bitmap.height(); ++y) { | 519 for (int y = 0; y < source_bitmap.height(); ++y) { |
| 531 const SkPMColor* source_color_row = static_cast<SkPMColor*>( | 520 const SkPMColor* source_color_row = static_cast<SkPMColor*>( |
| 532 source_bitmap.getAddr32(0, y)); | 521 source_bitmap.getAddr32(0, y)); |
| 533 for (int x = 0; x < source_bitmap.width(); ++x) { | 522 for (int x = 0; x < source_bitmap.width(); ++x) { |
| 534 SkColor c; | 523 SkColor c = SkUnPreMultiply::PMColorToColor(source_color_row[x]); |
| 535 int alpha = SkGetPackedA32(source_color_row[x]); | |
| 536 if (alpha != 0 && alpha != 255) | |
| 537 c = SkUnPreMultiply::PMColorToColor(source_color_row[x]); | |
| 538 else | |
| 539 c = source_color_row[x]; | |
| 540 | |
| 541 uint8_t r = SkColorGetR(c); | 524 uint8_t r = SkColorGetR(c); |
| 542 uint8_t g = SkColorGetG(c); | 525 uint8_t g = SkColorGetG(c); |
| 543 uint8_t b = SkColorGetB(c); | 526 uint8_t b = SkColorGetB(c); |
| 544 float gray_level = tr * r + tg * g + tb * b; | 527 float gray_level = tr * r + tg * g + tb * b; |
| 545 max_val = std::max(max_val, gray_level); | 528 max_val = std::max(max_val, gray_level); |
| 546 min_val = std::min(min_val, gray_level); | 529 min_val = std::min(min_val, gray_level); |
| 547 } | 530 } |
| 548 } | 531 } |
| 549 | 532 |
| 550 // Adjust the transform so that the result is scaling. | 533 // Adjust the transform so that the result is scaling. |
| 551 float scale = 0.0; | 534 float scale = 0.0; |
| 552 t0 = -min_val; | 535 t0 = -min_val; |
| 553 if (max_val > min_val) | 536 if (max_val > min_val) |
| 554 scale = 255.0f / (max_val - min_val); | 537 scale = 255.0f / (max_val - min_val); |
| 555 t0 *= scale; | 538 t0 *= scale; |
| 556 tr *= scale; | 539 tr *= scale; |
| 557 tg *= scale; | 540 tg *= scale; |
| 558 tb *= scale; | 541 tb *= scale; |
| 559 } | 542 } |
| 560 | 543 |
| 561 for (int y = 0; y < source_bitmap.height(); ++y) { | 544 for (int y = 0; y < source_bitmap.height(); ++y) { |
| 562 const SkPMColor* source_color_row = static_cast<SkPMColor*>( | 545 const SkPMColor* source_color_row = static_cast<SkPMColor*>( |
| 563 source_bitmap.getAddr32(0, y)); | 546 source_bitmap.getAddr32(0, y)); |
| 564 uint8_t* target_color_row = target_bitmap->getAddr8(0, y); | 547 uint8_t* target_color_row = target_bitmap->getAddr8(0, y); |
| 565 for (int x = 0; x < source_bitmap.width(); ++x) { | 548 for (int x = 0; x < source_bitmap.width(); ++x) { |
| 566 SkColor c; | 549 SkColor c = SkUnPreMultiply::PMColorToColor(source_color_row[x]); |
| 567 int alpha = SkGetPackedA32(source_color_row[x]); | |
| 568 if (alpha != 0 && alpha != 255) | |
| 569 c = SkUnPreMultiply::PMColorToColor(source_color_row[x]); | |
| 570 else | |
| 571 c = source_color_row[x]; | |
| 572 | |
| 573 uint8_t r = SkColorGetR(c); | 550 uint8_t r = SkColorGetR(c); |
| 574 uint8_t g = SkColorGetG(c); | 551 uint8_t g = SkColorGetG(c); |
| 575 uint8_t b = SkColorGetB(c); | 552 uint8_t b = SkColorGetB(c); |
| 576 | 553 |
| 577 float gl = t0 + tr * r + tg * g + tb * b; | 554 float gl = t0 + tr * r + tg * g + tb * b; |
| 578 if (gl < 0) | 555 if (gl < 0) |
| 579 gl = 0; | 556 gl = 0; |
| 580 if (gl > 0xFF) | 557 if (gl > 0xFF) |
| 581 gl = 0xFF; | 558 gl = 0xFF; |
| 582 target_color_row[x] = static_cast<uint8_t>(gl); | 559 target_color_row[x] = static_cast<uint8_t>(gl); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 596 gfx::Matrix3F covariance = ComputeColorCovariance(source_bitmap); | 573 gfx::Matrix3F covariance = ComputeColorCovariance(source_bitmap); |
| 597 gfx::Matrix3F eigenvectors = gfx::Matrix3F::Zeros(); | 574 gfx::Matrix3F eigenvectors = gfx::Matrix3F::Zeros(); |
| 598 gfx::Vector3dF eigenvals = covariance.SolveEigenproblem(&eigenvectors); | 575 gfx::Vector3dF eigenvals = covariance.SolveEigenproblem(&eigenvectors); |
| 599 gfx::Vector3dF principal = eigenvectors.get_column(0); | 576 gfx::Vector3dF principal = eigenvectors.get_column(0); |
| 600 if (eigenvals == gfx::Vector3dF() || principal == gfx::Vector3dF()) | 577 if (eigenvals == gfx::Vector3dF() || principal == gfx::Vector3dF()) |
| 601 return false; // This may happen for some edge cases. | 578 return false; // This may happen for some edge cases. |
| 602 return ApplyColorReduction(source_bitmap, principal, true, target_bitmap); | 579 return ApplyColorReduction(source_bitmap, principal, true, target_bitmap); |
| 603 } | 580 } |
| 604 | 581 |
| 605 } // color_utils | 582 } // color_utils |
| OLD | NEW |