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 fit_to_range, | |
272 SkBitmap* target_bitmap) { | |
273 DCHECK(target_bitmap); | |
274 SkAutoLockPixels source_lock(source_bitmap); | |
275 SkAutoLockPixels target_lock(*target_bitmap); | |
276 | |
277 DCHECK(source_bitmap.getPixels()); | |
278 DCHECK(target_bitmap->getPixels()); | |
279 DCHECK(source_bitmap.config() == SkBitmap::kARGB_8888_Config); | |
Alexei Svitkine (slow)
2013/02/22 02:24:06
I am assuming DCHECK_EQ() results in a compile fai
motek.
2013/02/22 15:42:56
Done.
| |
280 DCHECK(target_bitmap->config() == SkBitmap::kA8_Config); | |
281 DCHECK_EQ(source_bitmap.height(), target_bitmap->height()); | |
282 DCHECK_EQ(source_bitmap.width(), target_bitmap->width()); | |
283 | |
284 DCHECK(source_bitmap.height() > 0 && source_bitmap.width() > 0); | |
Alexei Svitkine (slow)
2013/02/22 02:24:06
Nit: DCHECK(!source_bitmap.empty()) instead
motek.
2013/02/22 15:42:56
Done.
| |
285 | |
286 // Elements of color_transform are explicitly off-loaded to local values for | |
287 // efficiency reasons. Note that in practice images may correspond to entire | |
288 // tab captures. | |
289 float t0 = 0.0; | |
290 float tr = color_transform.x(); | |
291 float tg = color_transform.y(); | |
292 float tb = color_transform.z(); | |
293 | |
294 if (fit_to_range) { | |
295 // We will figure out min/max in a preprocessing step and adjust | |
296 // actual_transform as required. | |
297 float max_val = std::numeric_limits<float>::min(); | |
298 float min_val = std::numeric_limits<float>::max(); | |
299 for (int y = 0; y < source_bitmap.height(); ++y) { | |
300 SkPMColor* current_color = static_cast<SkPMColor*>( | |
301 source_bitmap.getAddr32(0, y)); | |
302 for (int x = 0; x < source_bitmap.width(); ++x, ++current_color) { | |
303 SkColor c = SkUnPreMultiply::PMColorToColor(*current_color); | |
304 float r = SkColorGetR(c); | |
305 float g = SkColorGetG(c); | |
306 float b = SkColorGetB(c); | |
307 float gray_level = tr * r + tg * g + tb * b; | |
308 max_val = std::max(max_val, gray_level); | |
309 min_val = std::min(min_val, gray_level); | |
310 } | |
311 } | |
312 | |
313 // Adjust the transform so that the result is scaling. | |
314 float scale = 0.0; | |
315 t0 = -min_val; | |
316 if (max_val > min_val) | |
317 scale = 255.0 / (max_val - min_val); | |
318 t0 *= scale; | |
319 tr *= scale; | |
320 tg *= scale; | |
321 tb *= scale; | |
322 } | |
323 | |
324 for (int y = 0; y < source_bitmap.height(); ++y) { | |
325 SkPMColor* current_color = static_cast<SkPMColor*>( | |
Alexei Svitkine (slow)
2013/02/22 02:24:06
Nit: How about |source_color_row| and make it cons
motek.
2013/02/22 15:42:56
Done.
| |
326 source_bitmap.getAddr32(0, y)); | |
327 uint8_t* target_color = target_bitmap->getAddr8(0, y); | |
Alexei Svitkine (slow)
2013/02/22 02:24:06
Nit: How about |target_color_row|
Here and in the
motek.
2013/02/22 15:42:56
Done.
| |
328 for (int x = 0; x < source_bitmap.width(); ++x, ++current_color) { | |
329 SkColor c = SkUnPreMultiply::PMColorToColor(*current_color); | |
Alexei Svitkine (slow)
2013/02/22 02:24:06
Nit: How about source_color_row[x] instead of doin
motek.
2013/02/22 15:42:56
Done.
| |
330 float r = SkColorGetR(c); | |
331 float g = SkColorGetG(c); | |
332 float b = SkColorGetB(c); | |
333 | |
334 float gl = t0 + tr * r + tg * g + tb * b; | |
335 if (gl < 0) | |
336 gl = 0; | |
337 if (gl > 0xFF) | |
338 gl = 0xFF; | |
339 target_color[x] = static_cast<uint8_t>(gl); | |
340 } | |
341 } | |
342 | |
343 return true; | |
344 } | |
345 | |
346 bool ComputePrincipalComponentImage(const SkBitmap& source_bitmap, | |
347 SkBitmap* target_bitmap) { | |
348 if (!target_bitmap) { | |
349 NOTREACHED(); | |
350 return false; | |
351 } | |
352 | |
353 gfx::Matrix3F covariance = ComputeColorCovariance(source_bitmap); | |
354 gfx::Matrix3F eigenvectors = gfx::Matrix3F::Zeros(); | |
355 gfx::Vector3dF eigenvals = covariance.SolveEigenproblem(&eigenvectors); | |
356 gfx::Vector3dF principal = eigenvectors.get_column(0); | |
357 if (eigenvals == gfx::Vector3dF() || principal == gfx::Vector3dF()) | |
358 return false; // This may happen for some edge cases. | |
359 return ApplyColorReduction(source_bitmap, principal, true, target_bitmap); | |
360 } | |
361 | |
264 } // namespace color_utils | 362 } // namespace color_utils |
OLD | NEW |