Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Unified Diff: ui/gfx/color_utils.cc

Issue 12335009: Implementation of principal-component color reduction. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/gfx/color_utils.cc
diff --git a/ui/gfx/color_utils.cc b/ui/gfx/color_utils.cc
index 07980d84d8c2cc37d832e3efe3e303a9afd10362..bdcfe1e6428960d6378e71f52802dd4a79b0f7ae 100644
--- a/ui/gfx/color_utils.cc
+++ b/ui/gfx/color_utils.cc
@@ -10,6 +10,7 @@
#endif
#include <algorithm>
+#include <limits>
#include "base/basictypes.h"
#include "base/logging.h"
@@ -18,6 +19,10 @@
#include "skia/ext/skia_utils_win.h"
#endif
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkUnPreMultiply.h"
+#include "ui/gfx/color_analysis.h"
+#include "ui/gfx/matrix3_f.h"
+#include "ui/gfx/vector3d_f.h"
namespace color_utils {
@@ -261,4 +266,104 @@ SkColor GetSysSkColor(int which) {
#endif
}
+gfx::Rect ApplyColorReduction(const SkBitmap& source_bitmap,
+ const gfx::Vector3dF& color_transform,
+ bool scale_result,
+ SkBitmap* target_bitmap) {
+ gfx::Rect result_rect;
+ if (!target_bitmap) {
+ NOTREACHED();
+ return result_rect;
+ }
+
+ SkAutoLockPixels source_lock(source_bitmap);
+ SkAutoLockPixels target_lock(*target_bitmap);
+
+ if (!source_bitmap.getPixels())
+ return result_rect;
+
+ if (!target_bitmap->getPixels()) {
+ NOTREACHED();
+ return result_rect;
+ }
+
+ DCHECK(source_bitmap.config() == SkBitmap::kARGB_8888_Config);
+ DCHECK(target_bitmap->config() == SkBitmap::kA8_Config);
+ DCHECK_EQ(source_bitmap.height(), target_bitmap->height());
+ DCHECK_EQ(source_bitmap.width(), target_bitmap->width());
+
+ int height = std::min(source_bitmap.height(), target_bitmap->height());
+ int width = std::min(source_bitmap.width(), target_bitmap->width());
Alexei Svitkine (slow) 2013/02/21 16:49:59 Instead of doing this, why not create the target_b
motek. 2013/02/21 18:38:43 As explained in the header, I believe the conventi
Alexei Svitkine (slow) 2013/02/21 19:49:33 Got it. Given that you already have DCHECKs() abou
+ DCHECK(height > 0 && width > 0);
+
+ result_rect.SetRect(0, 0, width, height);
+ float a0 = 0.0;
+ float scale = 1.0;
+ if (scale_result) {
+ // We will figure out min/max in a preprocessing step and adjust
+ // actual_transform as required.
+ float max_val = std::numeric_limits<float>::min();
+ float min_val = std::numeric_limits<float>::max();
+ for (int y = 0; y < height; ++y) {
+ SkPMColor* current_color = static_cast<uint32_t*>(
+ source_bitmap.getAddr32(0, y));
+ for (int x = 0; x < width; ++x, ++current_color) {
+ SkColor c = SkUnPreMultiply::PMColorToColor(*current_color);
+ float r = SkColorGetR(c);
+ float g = SkColorGetG(c);
+ float b = SkColorGetB(c);
+ float gray_level = gfx::DotProduct(color_transform, r, g, b);
+ max_val = std::max(max_val, gray_level);
+ min_val = std::min(min_val, gray_level);
+ }
+ }
+
+ // Adjust the transform so that the result is scalling.
+ a0 = -min_val;
+ if (max_val > min_val)
+ scale = 255.0 / (max_val - min_val);
+ else
+ scale = 0.0; // If min==max, uniform 0-level image is expected.
+ }
+
+ for (int y = 0; y < height; ++y) {
+ SkPMColor* current_color = static_cast<uint32_t*>(
+ source_bitmap.getAddr32(0, y));
+ uint8_t* target_color = target_bitmap->getAddr8(0, y);
+ for (int x = 0; x < width; ++x, ++current_color) {
+ SkColor c = SkUnPreMultiply::PMColorToColor(*current_color);
+ float r = SkColorGetR(c);
+ float g = SkColorGetG(c);
+ float b = SkColorGetB(c);
+
+ float gl = (a0 + gfx::DotProduct(color_transform, r, g, b)) * scale;
+ if (gl < 0)
+ gl = 0;
+ if (gl > 0xFF)
+ gl = 0xFF;
+ target_color[x] = static_cast<uint8_t>(gl);
+ }
+ }
+
+ return result_rect;
+}
+
+bool ComputePrincipalComponentImage(const SkBitmap& source_bitmap,
+ SkBitmap* target_bitmap) {
+ if (!target_bitmap) {
+ NOTREACHED();
+ return false;
+ }
+
+ gfx::Matrix3F covariance = ComputeColorCovariance(source_bitmap);
+ gfx::Matrix3F eigenvectors = gfx::Matrix3F::Zeros();
+ gfx::Vector3dF eigenvals = covariance.SolveEigenproblem(&eigenvectors);
+ gfx::Vector3dF principal = eigenvectors.get_column(0);
+ if (eigenvals == gfx::Vector3dF() || principal == gfx::Vector3dF())
+ return false; // This may happen for some edge cases.
+ gfx::Rect result_rect = ApplyColorReduction(
+ source_bitmap, principal, true, target_bitmap);
+ return !result_rect.IsEmpty();
+}
+
} // namespace color_utils

Powered by Google App Engine
This is Rietveld 408576698