Index: ui/gfx/color_transform.cc |
diff --git a/ui/gfx/color_transform.cc b/ui/gfx/color_transform.cc |
index c6a114e94cdb471e8ab33fa5c7e0ffa48adcb857..1467ad23141a8bba38a3a9be75e247dc63f76c60 100644 |
--- a/ui/gfx/color_transform.cc |
+++ b/ui/gfx/color_transform.cc |
@@ -652,7 +652,7 @@ class ColorSpaceToColorSpaceTransform : public ColorTransform { |
} |
} |
- void transform(TriStim* colors, size_t num) override { |
+ void transform(TriStim* colors, size_t num) const override { |
for (size_t i = 0; i < num; i++) { |
TriStim c = colors[i]; |
a_.TransformPoint(&c); |
@@ -685,7 +685,7 @@ class QCMSColorTransform : public ColorTransform { |
qcms_profile_release(from_); |
qcms_profile_release(to_); |
} |
- void transform(TriStim* colors, size_t num) override { |
+ void transform(TriStim* colors, size_t num) const override { |
CHECK(sizeof(TriStim) == sizeof(float[3])); |
// QCMS doesn't like numbers outside 0..1 |
for (size_t i = 0; i < num; i++) { |
@@ -708,7 +708,7 @@ class ChainColorTransform : public ColorTransform { |
: a_(std::move(a)), b_(std::move(b)) {} |
private: |
- void transform(TriStim* colors, size_t num) override { |
+ void transform(TriStim* colors, size_t num) const override { |
a_->transform(colors, num); |
b_->transform(colors, num); |
} |
@@ -776,4 +776,81 @@ std::unique_ptr<ColorTransform> ColorTransform::NewColorTransform( |
} |
} |
+namespace { |
+ |
+float TriStimChannel(const ColorTransform::TriStim& t, int c) { |
+ switch (c) { |
+ case 0: |
+ return t.x(); |
+ case 1: |
+ return t.y(); |
+ case 2: |
+ return t.z(); |
+ case 3: |
+ return 1.0f; |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+ return 0.0f; |
+}; |
+ |
+} // namespace |
+ |
+bool ColorTransform::GetAffineApproximation(Transform* transform) const { |
+ const int num_points = 4; |
+ std::vector<TriStim> input(num_points * num_points * num_points); |
+ int i = 0; |
+ float offset = 0.1; |
+ float mult = 0.8 / num_points; |
+ for (int x = 0; x < num_points; x++) { |
+ for (int y = 0; y < num_points; y++) { |
+ for (int z = 0; z < num_points; z++) { |
+ input[i++] = ColorTransform::TriStim( |
+ offset + x * mult, offset + y * mult, offset + z * mult); |
+ } |
+ } |
+ } |
+ |
+ std::vector<TriStim> output(input); |
+ this->transform(output.data(), output.size()); |
+ SkMatrix44 XtX; |
+ for (int x = 0; x < 4; x++) { |
+ for (int y = 0; y < 4; y++) { |
+ double tmp = 0.0; |
+ for (int z = 0; z < num_points * num_points * num_points; z++) { |
+ tmp += TriStimChannel(input[z], x) * TriStimChannel(input[z], y); |
+ } |
+ XtX.setDouble(x, y, tmp); |
+ } |
+ } |
+ |
+ SkMatrix44 XtXinv; |
+ if (!XtX.invert(&XtXinv)) |
+ return false; |
+ |
+ SkVector4 results[4]; |
+ |
+ for (int x = 0; x < 4; x++) { |
+ double Xty[4]; |
+ for (int y = 0; y < 4; y++) { |
+ double tmp = 0.0; |
+ for (int z = 0; z < num_points * num_points * num_points; z++) { |
+ tmp += TriStimChannel(output[z], x) * TriStimChannel(input[z], y); |
+ } |
+ Xty[y] = tmp; |
+ } |
+ results[x] = XtXinv * SkVector4(Xty[0], Xty[1], Xty[2], Xty[3]); |
+ } |
+ |
+ *transform = |
+ Transform(results[0].fData[0], results[0].fData[1], results[0].fData[2], |
+ results[0].fData[3], results[1].fData[0], results[1].fData[1], |
+ results[1].fData[2], results[1].fData[3], results[2].fData[0], |
+ results[2].fData[1], results[2].fData[2], results[2].fData[3], |
+ results[3].fData[0], results[3].fData[1], results[3].fData[2], |
+ results[3].fData[3]); |
+ return true; |
+} |
+ |
} // namespace gfx |