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 gfx::Rect ApplyColorReduction(const SkBitmap& source_bitmap, | |
270 const gfx::Vector3dF& color_transform, | |
271 bool scale_result, | |
272 SkBitmap* target_bitmap) { | |
273 gfx::Rect result_rect; | |
274 if (!target_bitmap) { | |
275 NOTREACHED(); | |
276 return result_rect; | |
277 } | |
278 | |
279 SkAutoLockPixels source_lock(source_bitmap); | |
280 SkAutoLockPixels target_lock(*target_bitmap); | |
281 | |
282 if (!source_bitmap.getPixels()) | |
283 return result_rect; | |
284 | |
285 if (!target_bitmap->getPixels()) { | |
286 NOTREACHED(); | |
287 return result_rect; | |
288 } | |
289 | |
290 DCHECK(source_bitmap.config() == SkBitmap::kARGB_8888_Config); | |
291 DCHECK(target_bitmap->config() == SkBitmap::kA8_Config); | |
292 DCHECK_EQ(source_bitmap.height(), target_bitmap->height()); | |
293 DCHECK_EQ(source_bitmap.width(), target_bitmap->width()); | |
294 | |
295 int height = std::min(source_bitmap.height(), target_bitmap->height()); | |
296 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
| |
297 DCHECK(height > 0 && width > 0); | |
298 | |
299 result_rect.SetRect(0, 0, width, height); | |
300 float a0 = 0.0; | |
301 float scale = 1.0; | |
302 if (scale_result) { | |
303 // We will figure out min/max in a preprocessing step and adjust | |
304 // actual_transform as required. | |
305 float max_val = std::numeric_limits<float>::min(); | |
306 float min_val = std::numeric_limits<float>::max(); | |
307 for (int y = 0; y < height; ++y) { | |
308 SkPMColor* current_color = static_cast<uint32_t*>( | |
309 source_bitmap.getAddr32(0, y)); | |
310 for (int x = 0; x < width; ++x, ++current_color) { | |
311 SkColor c = SkUnPreMultiply::PMColorToColor(*current_color); | |
312 float r = SkColorGetR(c); | |
313 float g = SkColorGetG(c); | |
314 float b = SkColorGetB(c); | |
315 float gray_level = gfx::DotProduct(color_transform, r, g, b); | |
316 max_val = std::max(max_val, gray_level); | |
317 min_val = std::min(min_val, gray_level); | |
318 } | |
319 } | |
320 | |
321 // Adjust the transform so that the result is scalling. | |
322 a0 = -min_val; | |
323 if (max_val > min_val) | |
324 scale = 255.0 / (max_val - min_val); | |
325 else | |
326 scale = 0.0; // If min==max, uniform 0-level image is expected. | |
327 } | |
328 | |
329 for (int y = 0; y < height; ++y) { | |
330 SkPMColor* current_color = static_cast<uint32_t*>( | |
331 source_bitmap.getAddr32(0, y)); | |
332 uint8_t* target_color = target_bitmap->getAddr8(0, y); | |
333 for (int x = 0; x < width; ++x, ++current_color) { | |
334 SkColor c = SkUnPreMultiply::PMColorToColor(*current_color); | |
335 float r = SkColorGetR(c); | |
336 float g = SkColorGetG(c); | |
337 float b = SkColorGetB(c); | |
338 | |
339 float gl = (a0 + gfx::DotProduct(color_transform, r, g, b)) * scale; | |
340 if (gl < 0) | |
341 gl = 0; | |
342 if (gl > 0xFF) | |
343 gl = 0xFF; | |
344 target_color[x] = static_cast<uint8_t>(gl); | |
345 } | |
346 } | |
347 | |
348 return result_rect; | |
349 } | |
350 | |
351 bool ComputePrincipalComponentImage(const SkBitmap& source_bitmap, | |
352 SkBitmap* target_bitmap) { | |
353 if (!target_bitmap) { | |
354 NOTREACHED(); | |
355 return false; | |
356 } | |
357 | |
358 gfx::Matrix3F covariance = ComputeColorCovariance(source_bitmap); | |
359 gfx::Matrix3F eigenvectors = gfx::Matrix3F::Zeros(); | |
360 gfx::Vector3dF eigenvals = covariance.SolveEigenproblem(&eigenvectors); | |
361 gfx::Vector3dF principal = eigenvectors.get_column(0); | |
362 if (eigenvals == gfx::Vector3dF() || principal == gfx::Vector3dF()) | |
363 return false; // This may happen for some edge cases. | |
364 gfx::Rect result_rect = ApplyColorReduction( | |
365 source_bitmap, principal, true, target_bitmap); | |
366 return !result_rect.IsEmpty(); | |
367 } | |
368 | |
264 } // namespace color_utils | 369 } // namespace color_utils |
OLD | NEW |