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 |