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

Side by Side Diff: ui/gfx/color_transform.cc

Issue 2742273002: color: Use classic locale for printing (Closed)
Patch Set: Created 3 years, 9 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 unified diff | Download patch
« no previous file with comments | « no previous file | ui/gfx/color_transform_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2016 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_transform.h" 5 #include "ui/gfx/color_transform.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <list> 9 #include <list>
10 #include <memory> 10 #include <memory>
11 #include <sstream>
11 12
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
14 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
15 #include "third_party/qcms/src/qcms.h" 16 #include "third_party/qcms/src/qcms.h"
16 #include "ui/gfx/color_space.h" 17 #include "ui/gfx/color_space.h"
17 #include "ui/gfx/icc_profile.h" 18 #include "ui/gfx/icc_profile.h"
18 #include "ui/gfx/skia_color_space_util.h" 19 #include "ui/gfx/skia_color_space_util.h"
19 #include "ui/gfx/transform.h" 20 #include "ui/gfx/transform.h"
20 21
21 #ifndef THIS_MUST_BE_INCLUDED_AFTER_QCMS_H 22 #ifndef THIS_MUST_BE_INCLUDED_AFTER_QCMS_H
22 extern "C" { 23 extern "C" {
23 #include "third_party/qcms/src/chain.h" 24 #include "third_party/qcms/src/chain.h"
24 }; 25 };
25 #endif 26 #endif
26 27
27 using std::exp; 28 using std::exp;
28 using std::log; 29 using std::log;
29 using std::max; 30 using std::max;
30 using std::min; 31 using std::min;
31 using std::pow; 32 using std::pow;
32 using std::sqrt; 33 using std::sqrt;
33 34
34 namespace gfx { 35 namespace gfx {
35 36
36 namespace { 37 namespace {
37 38
39 void InitStringStream(std::stringstream* ss) {
40 ss->imbue(std::locale::classic());
41 ss->precision(8);
42 *ss << std::scientific;
43 }
44
38 std::string Str(float f) { 45 std::string Str(float f) {
39 return base::StringPrintf("%+1.8e", f); 46 std::stringstream ss;
47 InitStringStream(&ss);
48 ss << f;
49 return ss.str();
40 } 50 }
41 51
42 // Helper for scoped QCMS profiles. 52 // Helper for scoped QCMS profiles.
43 struct QcmsProfileDeleter { 53 struct QcmsProfileDeleter {
44 void operator()(qcms_profile* p) { 54 void operator()(qcms_profile* p) {
45 if (p) { 55 if (p) {
46 qcms_profile_release(p); 56 qcms_profile_release(p);
47 } 57 }
48 } 58 }
49 }; 59 };
50 using ScopedQcmsProfile = std::unique_ptr<qcms_profile, QcmsProfileDeleter>; 60 using ScopedQcmsProfile = std::unique_ptr<qcms_profile, QcmsProfileDeleter>;
51 61
52 Transform Invert(const Transform& t) { 62 Transform Invert(const Transform& t) {
53 Transform ret = t; 63 Transform ret = t;
54 if (!t.GetInverse(&ret)) { 64 if (!t.GetInverse(&ret)) {
55 LOG(ERROR) << "Inverse should alsways be possible."; 65 LOG(ERROR) << "Inverse should always be possible.";
56 } 66 }
57 return ret; 67 return ret;
58 } 68 }
59 69
60 float FromLinear(ColorSpace::TransferID id, float v) { 70 float FromLinear(ColorSpace::TransferID id, float v) {
61 switch (id) { 71 switch (id) {
62 case ColorSpace::TransferID::SMPTEST2084_NON_HDR: 72 case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
63 // Should already be handled. 73 // Should already be handled.
64 break; 74 break;
65 75
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 262
253 // Join methods, returns true if the |next| transform was successfully 263 // Join methods, returns true if the |next| transform was successfully
254 // assimilated into |this|. 264 // assimilated into |this|.
255 // If Join() returns true, |next| is no longer needed and can be deleted. 265 // If Join() returns true, |next| is no longer needed and can be deleted.
256 virtual bool Join(ColorTransformStep* next) { return false; } 266 virtual bool Join(ColorTransformStep* next) { return false; }
257 267
258 // Return true if this is a null transform. 268 // Return true if this is a null transform.
259 virtual bool IsNull() { return false; } 269 virtual bool IsNull() { return false; }
260 virtual void Transform(ColorTransform::TriStim* color, size_t num) const = 0; 270 virtual void Transform(ColorTransform::TriStim* color, size_t num) const = 0;
261 virtual bool CanAppendShaderSource() { return false; } 271 virtual bool CanAppendShaderSource() { return false; }
262 virtual void AppendShaderSource(std::string* result) { NOTREACHED(); } 272 virtual void AppendShaderSource(std::stringstream* result) { NOTREACHED(); }
263 273
264 private: 274 private:
265 DISALLOW_COPY_AND_ASSIGN(ColorTransformStep); 275 DISALLOW_COPY_AND_ASSIGN(ColorTransformStep);
266 }; 276 };
267 277
268 class ColorTransformInternal : public ColorTransform { 278 class ColorTransformInternal : public ColorTransform {
269 public: 279 public:
270 ColorTransformInternal(const ColorSpace& from, 280 ColorTransformInternal(const ColorSpace& from,
271 const ColorSpace& to, 281 const ColorSpace& to,
272 Intent intent); 282 Intent intent);
(...skipping 20 matching lines...) Expand all
293 // Retrieve the ICC profile from which |color_space| was created, only if that 303 // Retrieve the ICC profile from which |color_space| was created, only if that
294 // is a more precise representation of the color space than the primaries and 304 // is a more precise representation of the color space than the primaries and
295 // transfer function in |color_space|. 305 // transfer function in |color_space|.
296 ScopedQcmsProfile GetQCMSProfileIfNecessary(const ColorSpace& color_space); 306 ScopedQcmsProfile GetQCMSProfileIfNecessary(const ColorSpace& color_space);
297 307
298 std::list<std::unique_ptr<ColorTransformStep>> steps_; 308 std::list<std::unique_ptr<ColorTransformStep>> steps_;
299 gfx::ColorSpace src_; 309 gfx::ColorSpace src_;
300 gfx::ColorSpace dst_; 310 gfx::ColorSpace dst_;
301 }; 311 };
302 312
303 #define SRC(...) \
304 do { \
305 *result += std::string(" ") + base::StringPrintf(__VA_ARGS__) + \
306 std::string("\n"); \
307 } while (0)
308
309 class ColorTransformNull : public ColorTransformStep { 313 class ColorTransformNull : public ColorTransformStep {
310 public: 314 public:
311 ColorTransformNull* GetNull() override { return this; } 315 ColorTransformNull* GetNull() override { return this; }
312 bool IsNull() override { return true; } 316 bool IsNull() override { return true; }
313 void Transform(ColorTransform::TriStim* color, size_t num) const override {} 317 void Transform(ColorTransform::TriStim* color, size_t num) const override {}
314 bool CanAppendShaderSource() override { return true; } 318 bool CanAppendShaderSource() override { return true; }
315 void AppendShaderSource(std::string* result) override {} 319 void AppendShaderSource(std::stringstream* result) override {}
316 }; 320 };
317 321
318 class ColorTransformMatrix : public ColorTransformStep { 322 class ColorTransformMatrix : public ColorTransformStep {
319 public: 323 public:
320 explicit ColorTransformMatrix(const class Transform& matrix) 324 explicit ColorTransformMatrix(const class Transform& matrix)
321 : matrix_(matrix) {} 325 : matrix_(matrix) {}
322 ColorTransformMatrix* GetMatrix() override { return this; } 326 ColorTransformMatrix* GetMatrix() override { return this; }
323 bool Join(ColorTransformStep* next_untyped) override { 327 bool Join(ColorTransformStep* next_untyped) override {
324 ColorTransformMatrix* next = next_untyped->GetMatrix(); 328 ColorTransformMatrix* next = next_untyped->GetMatrix();
325 if (!next) 329 if (!next)
326 return false; 330 return false;
327 class Transform tmp = next->matrix_; 331 class Transform tmp = next->matrix_;
328 tmp *= matrix_; 332 tmp *= matrix_;
329 matrix_ = tmp; 333 matrix_ = tmp;
330 return true; 334 return true;
331 } 335 }
332 336
333 bool IsNull() override { 337 bool IsNull() override {
334 return SkMatrixIsApproximatelyIdentity(matrix_.matrix()); 338 return SkMatrixIsApproximatelyIdentity(matrix_.matrix());
335 } 339 }
336 340
337 void Transform(ColorTransform::TriStim* colors, size_t num) const override { 341 void Transform(ColorTransform::TriStim* colors, size_t num) const override {
338 for (size_t i = 0; i < num; i++) 342 for (size_t i = 0; i < num; i++)
339 matrix_.TransformPoint(colors + i); 343 matrix_.TransformPoint(colors + i);
340 } 344 }
341 345
342 bool CanAppendShaderSource() override { return true; } 346 bool CanAppendShaderSource() override { return true; }
343 347
344 void AppendShaderSource(std::string* result) override { 348 void AppendShaderSource(std::stringstream* result) override {
345 const SkMatrix44& m = matrix_.matrix(); 349 const SkMatrix44& m = matrix_.matrix();
346 SRC("color = mat3(%+1.8e, %+1.8e, %+1.8e,", // column 1 350 *result << " color = mat3(";
347 m.get(0, 0), m.get(1, 0), m.get(2, 0)); 351 *result << m.get(0, 0) << ", " << m.get(1, 0) << ", " << m.get(2, 0) << ",";
348 SRC(" %+1.8e, %+1.8e, %+1.8e,", // column 2 352 *result << std::endl;
349 m.get(0, 1), m.get(1, 1), m.get(2, 1)); 353 *result << " ";
350 SRC(" %+1.8e, %+1.8e, %+1.8e) * color;", // column 3 354 *result << m.get(0, 1) << ", " << m.get(1, 1) << ", " << m.get(2, 1) << ",";
351 m.get(0, 2), m.get(1, 2), m.get(2, 2)); 355 *result << std::endl;
352 SRC("color = vec3(%+1.8e, %+1.8e, %+1.8e) + color;", // column 4 356 *result << " ";
353 m.get(0, 3), m.get(1, 3), m.get(2, 3)); 357 *result << m.get(0, 2) << ", " << m.get(1, 2) << ", " << m.get(2, 2) << ")";
358 *result << " * color;" << std::endl;
359
360 // Only print the translational component if it isn't the identity.
361 if (m.get(0, 3) != 0.f || m.get(1, 3) != 0.f || m.get(2, 3) != 0.f) {
362 *result << " color += vec3(";
363 *result << m.get(0, 3) << ", " << m.get(1, 3) << ", " << m.get(2, 3);
364 *result << ");" << std::endl;
365 }
354 } 366 }
355 367
356 private: 368 private:
357 class Transform matrix_; 369 class Transform matrix_;
358 }; 370 };
359 371
360 class ColorTransformSkTransferFn : public ColorTransformStep { 372 class ColorTransformSkTransferFn : public ColorTransformStep {
361 public: 373 public:
362 explicit ColorTransformSkTransferFn(const SkColorSpaceTransferFn& fn) 374 explicit ColorTransformSkTransferFn(const SkColorSpaceTransferFn& fn)
363 : fn_(fn) {} 375 : fn_(fn) {}
(...skipping 22 matching lines...) Expand all
386 void Transform(ColorTransform::TriStim* colors, size_t num) const override { 398 void Transform(ColorTransform::TriStim* colors, size_t num) const override {
387 for (size_t i = 0; i < num; i++) { 399 for (size_t i = 0; i < num; i++) {
388 colors[i].set_x(SkTransferFnEval(fn_, colors[i].x())); 400 colors[i].set_x(SkTransferFnEval(fn_, colors[i].x()));
389 colors[i].set_y(SkTransferFnEval(fn_, colors[i].y())); 401 colors[i].set_y(SkTransferFnEval(fn_, colors[i].y()));
390 colors[i].set_z(SkTransferFnEval(fn_, colors[i].z())); 402 colors[i].set_z(SkTransferFnEval(fn_, colors[i].z()));
391 } 403 }
392 } 404 }
393 405
394 bool CanAppendShaderSource() override { return true; } 406 bool CanAppendShaderSource() override { return true; }
395 407
396 void AppendShaderSourceChannel(std::string* result, const char* value) { 408 void AppendShaderSourceChannel(std::stringstream* result, const char* value) {
397 const float kEpsilon = 1.f / 1024.f; 409 const float kEpsilon = 1.f / 1024.f;
398 410
399 // Construct the linear segment 411 // Construct the linear segment
400 // linear = C * x + F 412 // linear = C * x + F
401 // Elide operations that will be close to the identity. 413 // Elide operations that will be close to the identity.
402 std::string linear = value; 414 std::string linear = value;
403 if (std::abs(fn_.fC - 1.f) > kEpsilon) 415 if (std::abs(fn_.fC - 1.f) > kEpsilon)
404 linear = Str(fn_.fC) + " * " + linear; 416 linear = Str(fn_.fC) + " * " + linear;
405 if (std::abs(fn_.fF) > kEpsilon) 417 if (std::abs(fn_.fF) > kEpsilon)
406 linear = linear + " + " + Str(fn_.fF); 418 linear = linear + " + " + Str(fn_.fF);
407 419
408 // Construct the nonlinear segment. 420 // Construct the nonlinear segment.
409 // nonlinear = pow(A * x + B, G) + E 421 // nonlinear = pow(A * x + B, G) + E
410 // Elide operations (especially the pow) that will be close to the 422 // Elide operations (especially the pow) that will be close to the
411 // identity. 423 // identity.
412 std::string nonlinear = value; 424 std::string nonlinear = value;
413 if (std::abs(fn_.fA - 1.f) > kEpsilon) 425 if (std::abs(fn_.fA - 1.f) > kEpsilon)
414 nonlinear = Str(fn_.fA) + " * " + nonlinear; 426 nonlinear = Str(fn_.fA) + " * " + nonlinear;
415 if (std::abs(fn_.fB) > kEpsilon) 427 if (std::abs(fn_.fB) > kEpsilon)
416 nonlinear = nonlinear + " + " + Str(fn_.fB); 428 nonlinear = nonlinear + " + " + Str(fn_.fB);
417 if (std::abs(fn_.fG - 1.f) > kEpsilon) 429 if (std::abs(fn_.fG - 1.f) > kEpsilon)
418 nonlinear = "pow(" + nonlinear + ", " + Str(fn_.fG) + ")"; 430 nonlinear = "pow(" + nonlinear + ", " + Str(fn_.fG) + ")";
419 if (std::abs(fn_.fE) > kEpsilon) 431 if (std::abs(fn_.fE) > kEpsilon)
420 nonlinear = nonlinear + " + " + Str(fn_.fE); 432 nonlinear = nonlinear + " + " + Str(fn_.fE);
421 433
422 // Add both parts, skpping the if clause if possible. 434 // Add both parts, skpping the if clause if possible.
423 if (fn_.fD > kEpsilon) { 435 if (fn_.fD > kEpsilon) {
424 SRC("if (%s < %f)", value, fn_.fD); 436 *result << " if (" << value << " < " << Str(fn_.fD) << ")" << std::endl;
425 SRC(" %s = %s;", value, linear.c_str()); 437 *result << " " << value << " = " << linear << ";" << std::endl;
426 SRC("else"); 438 *result << " else" << std::endl;
427 SRC(" %s = %s;", value, nonlinear.c_str()); 439 *result << " " << value << " = " << nonlinear << ";" << std::endl;
428 } else { 440 } else {
429 SRC("%s = %s;", value, nonlinear.c_str()); 441 *result << " " << value << " = " << nonlinear << ";" << std::endl;
430 } 442 }
431 } 443 }
432 444
433 void AppendShaderSource(std::string* result) override { 445 void AppendShaderSource(std::stringstream* result) override {
434 // Append the transfer function for each channel. 446 // Append the transfer function for each channel.
435 AppendShaderSourceChannel(result, "color.r"); 447 AppendShaderSourceChannel(result, "color.r");
436 AppendShaderSourceChannel(result, "color.g"); 448 AppendShaderSourceChannel(result, "color.g");
437 AppendShaderSourceChannel(result, "color.b"); 449 AppendShaderSourceChannel(result, "color.b");
438 } 450 }
439 451
440 private: 452 private:
441 SkColorSpaceTransferFn fn_; 453 SkColorSpaceTransferFn fn_;
442 }; 454 };
443 455
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 if (dst_profile) { 821 if (dst_profile) {
810 steps_.push_back(base::MakeUnique<QCMSColorTransform>( 822 steps_.push_back(base::MakeUnique<QCMSColorTransform>(
811 GetXYZD50Profile(), std::move(dst_profile))); 823 GetXYZD50Profile(), std::move(dst_profile)));
812 } 824 }
813 825
814 if (intent != Intent::TEST_NO_OPT) 826 if (intent != Intent::TEST_NO_OPT)
815 Simplify(); 827 Simplify();
816 } 828 }
817 829
818 std::string ColorTransformInternal::GetShaderSource() const { 830 std::string ColorTransformInternal::GetShaderSource() const {
819 std::string result; 831 std::stringstream result;
820 result += "vec3 DoColorConversion(vec3 color) {\n"; 832 InitStringStream(&result);
833 result << "vec3 DoColorConversion(vec3 color) {" << std::endl;
821 for (const auto& step : steps_) 834 for (const auto& step : steps_)
822 step->AppendShaderSource(&result); 835 step->AppendShaderSource(&result);
823 result += " return color;\n"; 836 result << " return color;" << std::endl;
824 result += "}\n"; 837 result << "}" << std::endl;
825 return result; 838 return result.str();
826 } 839 }
827 840
828 bool ColorTransformInternal::CanGetShaderSource() const { 841 bool ColorTransformInternal::CanGetShaderSource() const {
829 for (const auto& step : steps_) { 842 for (const auto& step : steps_) {
830 if (!step->CanAppendShaderSource()) 843 if (!step->CanAppendShaderSource())
831 return false; 844 return false;
832 } 845 }
833 return true; 846 return true;
834 } 847 }
835 848
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 const ColorSpace& to, 885 const ColorSpace& to,
873 Intent intent) { 886 Intent intent) {
874 return std::unique_ptr<ColorTransform>( 887 return std::unique_ptr<ColorTransform>(
875 new ColorTransformInternal(from, to, intent)); 888 new ColorTransformInternal(from, to, intent));
876 } 889 }
877 890
878 ColorTransform::ColorTransform() {} 891 ColorTransform::ColorTransform() {}
879 ColorTransform::~ColorTransform() {} 892 ColorTransform::~ColorTransform() {}
880 893
881 } // namespace gfx 894 } // namespace gfx
OLDNEW
« no previous file with comments | « no previous file | ui/gfx/color_transform_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698