Index: ui/gfx/color_analysis.cc |
diff --git a/ui/gfx/color_analysis.cc b/ui/gfx/color_analysis.cc |
index 2925c06531c43cdee2770b92c1486f00e22d6729..f89642d2c7af19823670fffa1f029e948ce1e069 100644 |
--- a/ui/gfx/color_analysis.cc |
+++ b/ui/gfx/color_analysis.cc |
@@ -7,6 +7,7 @@ |
#include <algorithm> |
#include <vector> |
+#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
#include "third_party/skia/include/core/SkBitmap.h" |
#include "third_party/skia/include/core/SkUnPreMultiply.h" |
@@ -399,4 +400,65 @@ SkColor CalculateKMeanColorOfBitmap(const SkBitmap& bitmap) { |
return color; |
} |
+gfx::Matrix3F ComputeColorCovariance(const SkBitmap& bitmap) { |
+ // First need basic stats to normalize each channel separately. |
+ SkAutoLockPixels bitmap_lock(bitmap); |
+ gfx::Matrix3F covariance = gfx::Matrix3F::Zeros(); |
+ if (!bitmap.getPixels()) |
+ return covariance; |
+ |
+ // Assume ARGB_8888 format. |
+ DCHECK(bitmap.config() == SkBitmap::kARGB_8888_Config); |
+ |
+ double r_sum = 0; |
+ double g_sum = 0; |
+ double b_sum = 0; |
+ double rr_sum = 0; |
+ double gg_sum = 0; |
+ double bb_sum = 0; |
+ double rg_sum = 0; |
+ double rb_sum = 0; |
+ double gb_sum = 0; |
+ |
+ for (int y = 0; y < bitmap.height(); ++y) { |
reed1
2013/02/12 19:34:51
SkBitmap stores its pixels in SkPMColor format, no
motek.
2013/02/12 19:58:13
Ah, I see. It seems I should un-pre-multiply and u
|
+ SkColor* current_color = static_cast<uint32_t*>(bitmap.getAddr32(0, y)); |
+ for (int x = 0; x < bitmap.width(); ++x, ++current_color) { |
+ SkColor r = SkColorGetR(*current_color); |
+ SkColor g = SkColorGetG(*current_color); |
+ SkColor b = SkColorGetB(*current_color); |
+ |
+ r_sum += r; |
+ g_sum += g; |
+ b_sum += b; |
+ rr_sum += r * r; |
+ gg_sum += g * g; |
+ bb_sum += b * b; |
+ rg_sum += r * g; |
+ rb_sum += r * b; |
+ gb_sum += g * b; |
+ } |
+ } |
+ |
+ int pixel_n = bitmap.width() * bitmap.height(); |
+ r_sum /= pixel_n; |
+ g_sum /= pixel_n; |
+ b_sum /= pixel_n; |
+ rr_sum /= pixel_n; |
+ gg_sum /= pixel_n; |
+ bb_sum /= pixel_n; |
+ rg_sum /= pixel_n; |
+ rb_sum /= pixel_n; |
+ gb_sum /= pixel_n; |
+ |
+ // Covariance (not normalized) is E(X*X.t) - m * m.t and this is how it |
+ // is calculated below. |
+ // Each row below represents a row of the matrix describing (co)variances |
+ // of R, G and B channels with (R, G, B) |
+ covariance.set( |
+ rr_sum - r_sum * r_sum, rg_sum - r_sum * g_sum, rb_sum - r_sum * b_sum, |
+ rg_sum - r_sum * g_sum, gg_sum - g_sum * g_sum, gb_sum - g_sum * b_sum, |
+ rb_sum - r_sum * b_sum, gb_sum - g_sum * b_sum, bb_sum - b_sum * b_sum); |
+ return covariance; |
+} |
+ |
} // color_utils |