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 |