| 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" |
| 14 #include "third_party/skia/include/core/SkUnPreMultiply.h" | 15 #include "third_party/skia/include/core/SkUnPreMultiply.h" |
| 15 #include "ui/gfx/codec/png_codec.h" | 16 #include "ui/gfx/codec/png_codec.h" |
| 16 #include "ui/gfx/color_utils.h" | 17 #include "ui/gfx/color_utils.h" |
| 17 | 18 |
| 18 namespace color_utils { | 19 namespace color_utils { |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 // RGBA KMean Constants | 22 // RGBA KMean Constants |
| 22 const uint32_t kNumberOfClusters = 4; | 23 const uint32_t kNumberOfClusters = 4; |
| 23 const int kNumberOfIterations = 50; | 24 const int kNumberOfIterations = 50; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 // Holds the sum of all the points that make up this cluster. Used to | 123 // Holds the sum of all the points that make up this cluster. Used to |
| 123 // generate the next centroid as well as to check for convergence. | 124 // generate the next centroid as well as to check for convergence. |
| 124 uint32_t aggregate[3]; | 125 uint32_t aggregate[3]; |
| 125 uint32_t counter; | 126 uint32_t counter; |
| 126 | 127 |
| 127 // The weight of the cluster, determined by how many points were used | 128 // The weight of the cluster, determined by how many points were used |
| 128 // to generate the previous centroid. | 129 // to generate the previous centroid. |
| 129 uint32_t weight; | 130 uint32_t weight; |
| 130 }; | 131 }; |
| 131 | 132 |
| 132 // Un-premultiplies each pixel in |bitmap| into an output |buffer|. Requires | 133 // Un-premultiplies each pixel in |bitmap| into an output |buffer|. |
| 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 *out++ = SkUnPreMultiply::PMColorToColor(*in++); | 140 int alpha = SkGetPackedA32(*in); |
| 141 if (alpha != 0 && alpha != 255) |
| 142 *out++ = SkUnPreMultiply::PMColorToColor(*in++); |
| 143 else |
| 144 *out++ = *in++; |
| 145 } |
| 141 } | 146 } |
| 142 | 147 |
| 143 } // namespace | 148 } // namespace |
| 144 | 149 |
| 145 KMeanImageSampler::KMeanImageSampler() { | 150 KMeanImageSampler::KMeanImageSampler() { |
| 146 } | 151 } |
| 147 | 152 |
| 148 KMeanImageSampler::~KMeanImageSampler() { | 153 KMeanImageSampler::~KMeanImageSampler() { |
| 149 } | 154 } |
| 150 | 155 |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 int64_t rr_sum = 0; | 432 int64_t rr_sum = 0; |
| 428 int64_t gg_sum = 0; | 433 int64_t gg_sum = 0; |
| 429 int64_t bb_sum = 0; | 434 int64_t bb_sum = 0; |
| 430 int64_t rg_sum = 0; | 435 int64_t rg_sum = 0; |
| 431 int64_t rb_sum = 0; | 436 int64_t rb_sum = 0; |
| 432 int64_t gb_sum = 0; | 437 int64_t gb_sum = 0; |
| 433 | 438 |
| 434 for (int y = 0; y < bitmap.height(); ++y) { | 439 for (int y = 0; y < bitmap.height(); ++y) { |
| 435 SkPMColor* current_color = static_cast<uint32_t*>(bitmap.getAddr32(0, y)); | 440 SkPMColor* current_color = static_cast<uint32_t*>(bitmap.getAddr32(0, y)); |
| 436 for (int x = 0; x < bitmap.width(); ++x, ++current_color) { | 441 for (int x = 0; x < bitmap.width(); ++x, ++current_color) { |
| 437 SkColor c = SkUnPreMultiply::PMColorToColor(*current_color); | 442 SkColor c; |
| 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 |
| 438 SkColor r = SkColorGetR(c); | 449 SkColor r = SkColorGetR(c); |
| 439 SkColor g = SkColorGetG(c); | 450 SkColor g = SkColorGetG(c); |
| 440 SkColor b = SkColorGetB(c); | 451 SkColor b = SkColorGetB(c); |
| 441 | 452 |
| 442 r_sum += r; | 453 r_sum += r; |
| 443 g_sum += g; | 454 g_sum += g; |
| 444 b_sum += b; | 455 b_sum += b; |
| 445 rr_sum += r * r; | 456 rr_sum += r * r; |
| 446 gg_sum += g * g; | 457 gg_sum += g * g; |
| 447 bb_sum += b * b; | 458 bb_sum += b * b; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 | 515 |
| 505 if (fit_to_range) { | 516 if (fit_to_range) { |
| 506 // We will figure out min/max in a preprocessing step and adjust | 517 // We will figure out min/max in a preprocessing step and adjust |
| 507 // actual_transform as required. | 518 // actual_transform as required. |
| 508 float max_val = std::numeric_limits<float>::min(); | 519 float max_val = std::numeric_limits<float>::min(); |
| 509 float min_val = std::numeric_limits<float>::max(); | 520 float min_val = std::numeric_limits<float>::max(); |
| 510 for (int y = 0; y < source_bitmap.height(); ++y) { | 521 for (int y = 0; y < source_bitmap.height(); ++y) { |
| 511 const SkPMColor* source_color_row = static_cast<SkPMColor*>( | 522 const SkPMColor* source_color_row = static_cast<SkPMColor*>( |
| 512 source_bitmap.getAddr32(0, y)); | 523 source_bitmap.getAddr32(0, y)); |
| 513 for (int x = 0; x < source_bitmap.width(); ++x) { | 524 for (int x = 0; x < source_bitmap.width(); ++x) { |
| 514 SkColor c = SkUnPreMultiply::PMColorToColor(source_color_row[x]); | 525 SkColor c; |
| 526 int alpha = SkGetPackedA32(source_color_row[x]); |
| 527 if (alpha != 0 && alpha != 255) |
| 528 c = SkUnPreMultiply::PMColorToColor(source_color_row[x]); |
| 529 else |
| 530 c = source_color_row[x]; |
| 531 |
| 515 float r = SkColorGetR(c); | 532 float r = SkColorGetR(c); |
| 516 float g = SkColorGetG(c); | 533 float g = SkColorGetG(c); |
| 517 float b = SkColorGetB(c); | 534 float b = SkColorGetB(c); |
| 518 float gray_level = tr * r + tg * g + tb * b; | 535 float gray_level = tr * r + tg * g + tb * b; |
| 519 max_val = std::max(max_val, gray_level); | 536 max_val = std::max(max_val, gray_level); |
| 520 min_val = std::min(min_val, gray_level); | 537 min_val = std::min(min_val, gray_level); |
| 521 } | 538 } |
| 522 } | 539 } |
| 523 | 540 |
| 524 // Adjust the transform so that the result is scaling. | 541 // Adjust the transform so that the result is scaling. |
| 525 float scale = 0.0; | 542 float scale = 0.0; |
| 526 t0 = -min_val; | 543 t0 = -min_val; |
| 527 if (max_val > min_val) | 544 if (max_val > min_val) |
| 528 scale = 255.0 / (max_val - min_val); | 545 scale = 255.0 / (max_val - min_val); |
| 529 t0 *= scale; | 546 t0 *= scale; |
| 530 tr *= scale; | 547 tr *= scale; |
| 531 tg *= scale; | 548 tg *= scale; |
| 532 tb *= scale; | 549 tb *= scale; |
| 533 } | 550 } |
| 534 | 551 |
| 535 for (int y = 0; y < source_bitmap.height(); ++y) { | 552 for (int y = 0; y < source_bitmap.height(); ++y) { |
| 536 const SkPMColor* source_color_row = static_cast<SkPMColor*>( | 553 const SkPMColor* source_color_row = static_cast<SkPMColor*>( |
| 537 source_bitmap.getAddr32(0, y)); | 554 source_bitmap.getAddr32(0, y)); |
| 538 uint8_t* target_color_row = target_bitmap->getAddr8(0, y); | 555 uint8_t* target_color_row = target_bitmap->getAddr8(0, y); |
| 539 for (int x = 0; x < source_bitmap.width(); ++x) { | 556 for (int x = 0; x < source_bitmap.width(); ++x) { |
| 540 SkColor c = SkUnPreMultiply::PMColorToColor(source_color_row[x]); | 557 SkColor c; |
| 558 int alpha = SkGetPackedA32(source_color_row[x]); |
| 559 if (alpha != 0 && alpha != 255) |
| 560 c = SkUnPreMultiply::PMColorToColor(source_color_row[x]); |
| 561 else |
| 562 c = source_color_row[x]; |
| 563 |
| 541 float r = SkColorGetR(c); | 564 float r = SkColorGetR(c); |
| 542 float g = SkColorGetG(c); | 565 float g = SkColorGetG(c); |
| 543 float b = SkColorGetB(c); | 566 float b = SkColorGetB(c); |
| 544 | 567 |
| 545 float gl = t0 + tr * r + tg * g + tb * b; | 568 float gl = t0 + tr * r + tg * g + tb * b; |
| 546 if (gl < 0) | 569 if (gl < 0) |
| 547 gl = 0; | 570 gl = 0; |
| 548 if (gl > 0xFF) | 571 if (gl > 0xFF) |
| 549 gl = 0xFF; | 572 gl = 0xFF; |
| 550 target_color_row[x] = static_cast<uint8_t>(gl); | 573 target_color_row[x] = static_cast<uint8_t>(gl); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 564 gfx::Matrix3F covariance = ComputeColorCovariance(source_bitmap); | 587 gfx::Matrix3F covariance = ComputeColorCovariance(source_bitmap); |
| 565 gfx::Matrix3F eigenvectors = gfx::Matrix3F::Zeros(); | 588 gfx::Matrix3F eigenvectors = gfx::Matrix3F::Zeros(); |
| 566 gfx::Vector3dF eigenvals = covariance.SolveEigenproblem(&eigenvectors); | 589 gfx::Vector3dF eigenvals = covariance.SolveEigenproblem(&eigenvectors); |
| 567 gfx::Vector3dF principal = eigenvectors.get_column(0); | 590 gfx::Vector3dF principal = eigenvectors.get_column(0); |
| 568 if (eigenvals == gfx::Vector3dF() || principal == gfx::Vector3dF()) | 591 if (eigenvals == gfx::Vector3dF() || principal == gfx::Vector3dF()) |
| 569 return false; // This may happen for some edge cases. | 592 return false; // This may happen for some edge cases. |
| 570 return ApplyColorReduction(source_bitmap, principal, true, target_bitmap); | 593 return ApplyColorReduction(source_bitmap, principal, true, target_bitmap); |
| 571 } | 594 } |
| 572 | 595 |
| 573 } // color_utils | 596 } // color_utils |
| OLD | NEW |