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 |