Chromium Code Reviews| 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_utils.h" | 5 #include "ui/gfx/color_utils.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 #if defined(OS_WIN) | 8 #if defined(OS_WIN) |
| 9 #include <windows.h> | 9 #include <windows.h> |
| 10 #endif | 10 #endif |
| 11 | 11 |
| 12 #include <algorithm> | 12 #include <algorithm> |
| 13 #include <limits> | |
| 13 | 14 |
| 14 #include "base/basictypes.h" | 15 #include "base/basictypes.h" |
| 15 #include "base/logging.h" | 16 #include "base/logging.h" |
| 16 #include "build/build_config.h" | 17 #include "build/build_config.h" |
| 17 #if defined(OS_WIN) | 18 #if defined(OS_WIN) |
| 18 #include "skia/ext/skia_utils_win.h" | 19 #include "skia/ext/skia_utils_win.h" |
| 19 #endif | 20 #endif |
| 20 #include "third_party/skia/include/core/SkBitmap.h" | 21 #include "third_party/skia/include/core/SkBitmap.h" |
| 22 #include "third_party/skia/include/core/SkUnPreMultiply.h" | |
| 23 #include "ui/gfx/color_analysis.h" | |
| 24 #include "ui/gfx/matrix3_f.h" | |
| 25 #include "ui/gfx/vector3d_f.h" | |
| 21 | 26 |
| 22 namespace color_utils { | 27 namespace color_utils { |
| 23 | 28 |
| 24 // Helper functions ----------------------------------------------------------- | 29 // Helper functions ----------------------------------------------------------- |
| 25 | 30 |
| 26 namespace { | 31 namespace { |
| 27 | 32 |
| 28 int calcHue(double temp1, double temp2, double hue) { | 33 int calcHue(double temp1, double temp2, double hue) { |
| 29 if (hue < 0.0) | 34 if (hue < 0.0) |
| 30 ++hue; | 35 ++hue; |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 254 | 259 |
| 255 SkColor GetSysSkColor(int which) { | 260 SkColor GetSysSkColor(int which) { |
| 256 #if defined(OS_WIN) | 261 #if defined(OS_WIN) |
| 257 return skia::COLORREFToSkColor(GetSysColor(which)); | 262 return skia::COLORREFToSkColor(GetSysColor(which)); |
| 258 #else | 263 #else |
| 259 NOTIMPLEMENTED(); | 264 NOTIMPLEMENTED(); |
| 260 return SK_ColorLTGRAY; | 265 return SK_ColorLTGRAY; |
| 261 #endif | 266 #endif |
| 262 } | 267 } |
| 263 | 268 |
| 269 bool ApplyColorReduction(const SkBitmap& source_bitmap, | |
| 270 const gfx::Vector3dF& color_transform, | |
| 271 bool scale_result, | |
| 272 SkBitmap* target_bitmap) { | |
| 273 if (!target_bitmap) { | |
|
Alexei Svitkine (slow)
2013/02/21 19:49:33
Do you really need all these early returns? Can yo
motek.
2013/02/21 22:45:03
I think I borrowed this idiom from somewhere. Like
| |
| 274 NOTREACHED(); | |
| 275 return false; | |
| 276 } | |
| 277 | |
| 278 SkAutoLockPixels source_lock(source_bitmap); | |
| 279 SkAutoLockPixels target_lock(*target_bitmap); | |
| 280 | |
| 281 if (!source_bitmap.getPixels()) | |
| 282 return false; | |
| 283 | |
| 284 if (!target_bitmap->getPixels()) { | |
| 285 NOTREACHED(); | |
| 286 return false; | |
| 287 } | |
| 288 | |
| 289 DCHECK(source_bitmap.config() == SkBitmap::kARGB_8888_Config); | |
| 290 DCHECK(target_bitmap->config() == SkBitmap::kA8_Config); | |
| 291 DCHECK_EQ(source_bitmap.height(), target_bitmap->height()); | |
| 292 DCHECK_EQ(source_bitmap.width(), target_bitmap->width()); | |
| 293 | |
| 294 int height = std::min(source_bitmap.height(), target_bitmap->height()); | |
| 295 int width = std::min(source_bitmap.width(), target_bitmap->width()); | |
| 296 DCHECK(height > 0 && width > 0); | |
| 297 | |
| 298 float a0 = 0.0; | |
| 299 float scale = 1.0; | |
| 300 if (scale_result) { | |
|
Alexei Svitkine (slow)
2013/02/21 19:49:33
I think it would be cleaner to do the scaling in a
motek.
2013/02/21 22:45:03
I don't really follow. To know how to scale I need
Alexei Svitkine (slow)
2013/02/22 02:24:06
Ah, you're right, I didn't realise we couldn't re-
| |
| 301 // We will figure out min/max in a preprocessing step and adjust | |
| 302 // actual_transform as required. | |
| 303 float max_val = std::numeric_limits<float>::min(); | |
| 304 float min_val = std::numeric_limits<float>::max(); | |
| 305 for (int y = 0; y < height; ++y) { | |
| 306 SkPMColor* current_color = static_cast<uint32_t*>( | |
|
Alexei Svitkine (slow)
2013/02/21 19:49:33
Should this be a static_cast<SkPMColor*>?
motek.
2013/02/21 22:45:03
Seems you are right. Done.
| |
| 307 source_bitmap.getAddr32(0, y)); | |
| 308 for (int x = 0; x < width; ++x, ++current_color) { | |
| 309 SkColor c = SkUnPreMultiply::PMColorToColor(*current_color); | |
| 310 float r = SkColorGetR(c); | |
| 311 float g = SkColorGetG(c); | |
| 312 float b = SkColorGetB(c); | |
| 313 float gray_level = gfx::DotProduct(color_transform, r, g, b); | |
| 314 max_val = std::max(max_val, gray_level); | |
| 315 min_val = std::min(min_val, gray_level); | |
| 316 } | |
| 317 } | |
| 318 | |
| 319 // Adjust the transform so that the result is scalling. | |
| 320 a0 = -min_val; | |
| 321 if (max_val > min_val) | |
| 322 scale = 255.0 / (max_val - min_val); | |
| 323 else | |
| 324 scale = 0.0; // If min==max, uniform 0-level image is expected. | |
| 325 } | |
| 326 | |
| 327 for (int y = 0; y < height; ++y) { | |
| 328 SkPMColor* current_color = static_cast<uint32_t*>( | |
|
Alexei Svitkine (slow)
2013/02/21 19:49:33
Likewise, cast to SkPMColor*?
motek.
2013/02/21 22:45:03
Done.
| |
| 329 source_bitmap.getAddr32(0, y)); | |
| 330 uint8_t* target_color = target_bitmap->getAddr8(0, y); | |
| 331 for (int x = 0; x < width; ++x, ++current_color) { | |
| 332 SkColor c = SkUnPreMultiply::PMColorToColor(*current_color); | |
| 333 float r = SkColorGetR(c); | |
| 334 float g = SkColorGetG(c); | |
| 335 float b = SkColorGetB(c); | |
| 336 | |
| 337 float gl = (a0 + gfx::DotProduct(color_transform, r, g, b)) * scale; | |
| 338 if (gl < 0) | |
| 339 gl = 0; | |
| 340 if (gl > 0xFF) | |
| 341 gl = 0xFF; | |
| 342 target_color[x] = static_cast<uint8_t>(gl); | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 return true; | |
| 347 } | |
| 348 | |
| 349 bool ComputePrincipalComponentImage(const SkBitmap& source_bitmap, | |
| 350 SkBitmap* target_bitmap) { | |
| 351 if (!target_bitmap) { | |
| 352 NOTREACHED(); | |
| 353 return false; | |
| 354 } | |
| 355 | |
| 356 gfx::Matrix3F covariance = ComputeColorCovariance(source_bitmap); | |
| 357 gfx::Matrix3F eigenvectors = gfx::Matrix3F::Zeros(); | |
| 358 gfx::Vector3dF eigenvals = covariance.SolveEigenproblem(&eigenvectors); | |
| 359 gfx::Vector3dF principal = eigenvectors.get_column(0); | |
| 360 if (eigenvals == gfx::Vector3dF() || principal == gfx::Vector3dF()) | |
| 361 return false; // This may happen for some edge cases. | |
| 362 return ApplyColorReduction(source_bitmap, principal, true, target_bitmap); | |
| 363 } | |
| 364 | |
| 264 } // namespace color_utils | 365 } // namespace color_utils |
| OLD | NEW |