raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #include "SkColorSpaceXform_A2B.h" |
| 9 | |
| 10 | #include "SkColorPriv.h" |
| 11 | #include "SkColorSpace_A2B.h" |
| 12 | #include "SkColorSpace_XYZ.h" |
| 13 | #include "SkColorSpacePriv.h" |
| 14 | #include "SkColorSpaceXformPriv.h" |
| 15 | #include "SkMakeUnique.h" |
| 16 | #include "SkNx.h" |
| 17 | #include "SkSRGB.h" |
| 18 | #include "SkTypes.h" |
| 19 | |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 20 | bool SkColorSpaceXform_A2B::onApply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, |
| 21 | const void* src, int count, SkAlphaType alphaType) const { |
| 22 | SkRasterPipeline pipeline; |
| 23 | switch (srcFormat) { |
| 24 | case kBGRA_8888_ColorFormat: |
Mike Klein | 729b582 | 2016-11-28 18:23:23 -0500 | [diff] [blame] | 25 | pipeline.append(SkRasterPipeline::load_8888, &src); |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 26 | pipeline.append(SkRasterPipeline::swap_rb); |
| 27 | break; |
| 28 | case kRGBA_8888_ColorFormat: |
Mike Klein | 729b582 | 2016-11-28 18:23:23 -0500 | [diff] [blame] | 29 | pipeline.append(SkRasterPipeline::load_8888, &src); |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 30 | break; |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 31 | case kRGBA_U16_BE_ColorFormat: |
| 32 | pipeline.append(SkRasterPipeline::load_u16_be, &src); |
| 33 | break; |
Matt Sarett | 7a090c4 | 2017-01-17 12:22:48 -0500 | [diff] [blame^] | 34 | case kRGB_U16_BE_ColorFormat: |
| 35 | pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src); |
| 36 | break; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 37 | default: |
| 38 | SkCSXformPrintf("F16/F32 source color format not supported\n"); |
| 39 | return false; |
| 40 | } |
| 41 | |
| 42 | pipeline.extend(fElementsPipeline); |
| 43 | |
| 44 | if (kPremul_SkAlphaType == alphaType) { |
| 45 | pipeline.append(SkRasterPipeline::premul); |
| 46 | } |
| 47 | |
| 48 | switch (dstFormat) { |
| 49 | case kBGRA_8888_ColorFormat: |
| 50 | pipeline.append(SkRasterPipeline::swap_rb); |
| 51 | pipeline.append(SkRasterPipeline::store_8888, &dst); |
| 52 | break; |
| 53 | case kRGBA_8888_ColorFormat: |
| 54 | pipeline.append(SkRasterPipeline::store_8888, &dst); |
| 55 | break; |
| 56 | case kRGBA_F16_ColorFormat: |
| 57 | if (!fLinearDstGamma) { |
| 58 | return false; |
| 59 | } |
| 60 | pipeline.append(SkRasterPipeline::store_f16, &dst); |
| 61 | break; |
| 62 | case kRGBA_F32_ColorFormat: |
| 63 | if (!fLinearDstGamma) { |
| 64 | return false; |
| 65 | } |
| 66 | pipeline.append(SkRasterPipeline::store_f32, &dst); |
| 67 | break; |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 68 | default: |
| 69 | return false; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 70 | } |
Mike Klein | c789b61 | 2016-11-30 13:45:06 -0500 | [diff] [blame] | 71 | pipeline.run(0,0, count); |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 72 | |
| 73 | return true; |
| 74 | } |
| 75 | |
Ravi Mistry | 113d05f | 2016-12-17 01:31:03 +0000 | [diff] [blame] | 76 | static inline bool gamma_to_parametric(SkColorSpaceTransferFn* coeffs, const SkGammas& gammas, |
| 77 | int channel) { |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 78 | switch (gammas.type(channel)) { |
| 79 | case SkGammas::Type::kNamed_Type: |
Ravi Mistry | 113d05f | 2016-12-17 01:31:03 +0000 | [diff] [blame] | 80 | return named_to_parametric(coeffs, gammas.data(channel).fNamed); |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 81 | case SkGammas::Type::kValue_Type: |
Ravi Mistry | 113d05f | 2016-12-17 01:31:03 +0000 | [diff] [blame] | 82 | value_to_parametric(coeffs, gammas.data(channel).fValue); |
| 83 | return true; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 84 | case SkGammas::Type::kParam_Type: |
Ravi Mistry | 113d05f | 2016-12-17 01:31:03 +0000 | [diff] [blame] | 85 | *coeffs = gammas.params(channel); |
| 86 | return true; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 87 | default: |
Ravi Mistry | 113d05f | 2016-12-17 01:31:03 +0000 | [diff] [blame] | 88 | return false; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 89 | } |
| 90 | } |
| 91 | static inline SkColorSpaceTransferFn invert_parametric(const SkColorSpaceTransferFn& fn) { |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 92 | // Original equation is: y = (ax + b)^g + e for x >= d |
| 93 | // y = cx + f otherwise |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 94 | // |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 95 | // so 1st inverse is: (y - e)^(1/g) = ax + b |
| 96 | // x = ((y - e)^(1/g) - b) / a |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 97 | // |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 98 | // which can be re-written as: x = (1/a)(y - e)^(1/g) - b/a |
| 99 | // x = ((1/a)^g)^(1/g) * (y - e)^(1/g) - b/a |
| 100 | // x = ([(1/a)^g]y + [-((1/a)^g)e]) ^ [1/g] + [-b/a] |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 101 | // |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 102 | // and 2nd inverse is: x = (y - f) / c |
| 103 | // which can be re-written as: x = [1/c]y + [-f/c] |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 104 | // |
| 105 | // and now both can be expressed in terms of the same parametric form as the |
raftias | 197e311 | 2016-12-01 15:31:29 -0500 | [diff] [blame] | 106 | // original - parameters are enclosed in square brackets. |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 107 | |
| 108 | // find inverse for linear segment (if possible) |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 109 | float c, f; |
| 110 | if (0.f == fn.fC) { |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 111 | // otherwise assume it should be 0 as it is the lower segment |
| 112 | // as y = f is a constant function |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 113 | c = 0.f; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 114 | f = 0.f; |
| 115 | } else { |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 116 | c = 1.f / fn.fC; |
| 117 | f = -fn.fF / fn.fC; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 118 | } |
| 119 | // find inverse for the other segment (if possible) |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 120 | float g, a, b, e; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 121 | if (0.f == fn.fA || 0.f == fn.fG) { |
| 122 | // otherwise assume it should be 1 as it is the top segment |
| 123 | // as you can't invert the constant functions y = b^g + c, or y = 1 + c |
| 124 | g = 1.f; |
| 125 | a = 0.f; |
| 126 | b = 0.f; |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 127 | e = 1.f; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 128 | } else { |
| 129 | g = 1.f / fn.fG; |
| 130 | a = powf(1.f / fn.fA, fn.fG); |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 131 | b = -a * fn.fE; |
| 132 | e = -fn.fB / fn.fA; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 133 | } |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 134 | const float d = fn.fC * fn.fD + fn.fF; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 135 | return {g, a, b, c, d, e, f}; |
| 136 | } |
| 137 | |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 138 | SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace, |
| 139 | SkColorSpace_XYZ* dstSpace) |
| 140 | : fLinearDstGamma(kLinear_SkGammaNamed == dstSpace->gammaNamed()) { |
| 141 | #if (SkCSXformPrintfDefined) |
| 142 | static const char* debugGammaNamed[4] = { |
| 143 | "Linear", "SRGB", "2.2", "NonStandard" |
| 144 | }; |
| 145 | static const char* debugGammas[5] = { |
| 146 | "None", "Named", "Value", "Table", "Param" |
| 147 | }; |
| 148 | #endif |
Matt Sarett | 523116d | 2017-01-12 18:36:38 -0500 | [diff] [blame] | 149 | int currentChannels; |
| 150 | switch (srcSpace->iccType()) { |
| 151 | case SkColorSpace_Base::kRGB_ICCTypeFlag: |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 152 | currentChannels = 3; |
| 153 | break; |
Matt Sarett | 523116d | 2017-01-12 18:36:38 -0500 | [diff] [blame] | 154 | case SkColorSpace_Base::kCMYK_ICCTypeFlag: |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 155 | currentChannels = 4; |
| 156 | // CMYK images from JPEGs (the only format that supports it) are actually |
| 157 | // inverted CMYK, so we need to invert every channel. |
| 158 | // TransferFn is y = -x + 1 for x < 1.f, otherwise 0x + 0, ie y = 1 - x for x in [0,1] |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 159 | this->addTransferFns({1.f, 0.f, 0.f, -1.f, 1.f, 0.f, 1.f}, 4); |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 160 | break; |
| 161 | default: |
Matt Sarett | 523116d | 2017-01-12 18:36:38 -0500 | [diff] [blame] | 162 | currentChannels = 0; |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 163 | SkASSERT(false); |
| 164 | } |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 165 | // add in all input color space -> PCS xforms |
| 166 | for (int i = 0; i < srcSpace->count(); ++i) { |
| 167 | const SkColorSpace_A2B::Element& e = srcSpace->element(i); |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 168 | SkASSERT(e.inputChannels() == currentChannels); |
| 169 | currentChannels = e.outputChannels(); |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 170 | switch (e.type()) { |
| 171 | case SkColorSpace_A2B::Element::Type::kGammaNamed: |
Ravi Mistry | 113d05f | 2016-12-17 01:31:03 +0000 | [diff] [blame] | 172 | if (kLinear_SkGammaNamed == e.gammaNamed()) { |
| 173 | break; |
| 174 | } |
| 175 | |
raftias | 9752454 | 2016-12-14 13:15:05 -0500 | [diff] [blame] | 176 | // take the fast path for 3-channel named gammas |
| 177 | if (3 == currentChannels) { |
| 178 | if (k2Dot2Curve_SkGammaNamed == e.gammaNamed()) { |
| 179 | SkCSXformPrintf("fast path from 2.2\n"); |
| 180 | fElementsPipeline.append(SkRasterPipeline::from_2dot2); |
| 181 | break; |
| 182 | } else if (kSRGB_SkGammaNamed == e.gammaNamed()) { |
| 183 | SkCSXformPrintf("fast path from sRGB\n"); |
| 184 | // Images should always start the pipeline as unpremul |
| 185 | fElementsPipeline.append_from_srgb(kUnpremul_SkAlphaType); |
| 186 | break; |
| 187 | } |
| 188 | } |
Ravi Mistry | 113d05f | 2016-12-17 01:31:03 +0000 | [diff] [blame] | 189 | |
| 190 | SkCSXformPrintf("Gamma stage added: %s\n", debugGammaNamed[(int)e.gammaNamed()]); |
| 191 | SkColorSpaceTransferFn fn; |
| 192 | SkAssertResult(named_to_parametric(&fn, e.gammaNamed())); |
| 193 | this->addTransferFns(fn, currentChannels); |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 194 | break; |
| 195 | case SkColorSpace_A2B::Element::Type::kGammas: { |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 196 | const SkGammas& gammas = e.gammas(); |
| 197 | SkCSXformPrintf("Gamma stage added:"); |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 198 | for (int channel = 0; channel < gammas.channels(); ++channel) { |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 199 | SkCSXformPrintf(" %s", debugGammas[(int)gammas.type(channel)]); |
| 200 | } |
| 201 | SkCSXformPrintf("\n"); |
| 202 | bool gammaNeedsRef = false; |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 203 | for (int channel = 0; channel < gammas.channels(); ++channel) { |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 204 | if (SkGammas::Type::kTable_Type == gammas.type(channel)) { |
| 205 | SkTableTransferFn table = { |
| 206 | gammas.table(channel), |
| 207 | gammas.data(channel).fTable.fSize, |
| 208 | }; |
| 209 | |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 210 | this->addTableFn(table, channel); |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 211 | gammaNeedsRef = true; |
| 212 | } else { |
Ravi Mistry | 113d05f | 2016-12-17 01:31:03 +0000 | [diff] [blame] | 213 | SkColorSpaceTransferFn fn; |
| 214 | SkAssertResult(gamma_to_parametric(&fn, gammas, channel)); |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 215 | this->addTransferFn(fn, channel); |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 216 | } |
| 217 | } |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 218 | if (gammaNeedsRef) { |
| 219 | fGammaRefs.push_back(sk_ref_sp(&gammas)); |
| 220 | } |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 221 | break; |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 222 | } |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 223 | case SkColorSpace_A2B::Element::Type::kCLUT: |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 224 | SkCSXformPrintf("CLUT (%d -> %d) stage added\n", e.colorLUT().inputChannels(), |
| 225 | e.colorLUT().outputChannels()); |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 226 | fCLUTs.push_back(sk_ref_sp(&e.colorLUT())); |
| 227 | fElementsPipeline.append(SkRasterPipeline::color_lookup_table, |
| 228 | fCLUTs.back().get()); |
| 229 | break; |
| 230 | case SkColorSpace_A2B::Element::Type::kMatrix: |
| 231 | if (!e.matrix().isIdentity()) { |
| 232 | SkCSXformPrintf("Matrix stage added\n"); |
| 233 | addMatrix(e.matrix()); |
| 234 | } |
| 235 | break; |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | // Lab PCS -> XYZ PCS |
| 240 | if (SkColorSpace_A2B::PCS::kLAB == srcSpace->pcs()) { |
| 241 | SkCSXformPrintf("Lab -> XYZ element added\n"); |
| 242 | fElementsPipeline.append(SkRasterPipeline::lab_to_xyz); |
| 243 | } |
| 244 | |
raftias | 91db12d | 2016-12-02 11:56:59 -0500 | [diff] [blame] | 245 | // we should now be in XYZ PCS |
| 246 | SkASSERT(3 == currentChannels); |
| 247 | |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 248 | // and XYZ PCS -> output color space xforms |
| 249 | if (!dstSpace->fromXYZD50()->isIdentity()) { |
| 250 | addMatrix(*dstSpace->fromXYZD50()); |
| 251 | } |
| 252 | |
raftias | 9752454 | 2016-12-14 13:15:05 -0500 | [diff] [blame] | 253 | switch (dstSpace->gammaNamed()) { |
| 254 | case kLinear_SkGammaNamed: |
| 255 | // do nothing |
| 256 | break; |
| 257 | case k2Dot2Curve_SkGammaNamed: |
| 258 | fElementsPipeline.append(SkRasterPipeline::to_2dot2); |
| 259 | break; |
| 260 | case kSRGB_SkGammaNamed: |
| 261 | fElementsPipeline.append(SkRasterPipeline::to_srgb); |
| 262 | break; |
| 263 | case kNonStandard_SkGammaNamed: { |
| 264 | for (int channel = 0; channel < 3; ++channel) { |
| 265 | const SkGammas& gammas = *dstSpace->gammas(); |
| 266 | if (SkGammas::Type::kTable_Type == gammas.type(channel)) { |
| 267 | static constexpr int kInvTableSize = 256; |
| 268 | std::vector<float> storage(kInvTableSize); |
| 269 | invert_table_gamma(storage.data(), nullptr, storage.size(), |
| 270 | gammas.table(channel), |
| 271 | gammas.data(channel).fTable.fSize); |
| 272 | SkTableTransferFn table = { |
| 273 | storage.data(), |
| 274 | (int) storage.size(), |
| 275 | }; |
| 276 | fTableStorage.push_front(std::move(storage)); |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 277 | |
raftias | 9752454 | 2016-12-14 13:15:05 -0500 | [diff] [blame] | 278 | this->addTableFn(table, channel); |
| 279 | } else { |
Ravi Mistry | 113d05f | 2016-12-17 01:31:03 +0000 | [diff] [blame] | 280 | SkColorSpaceTransferFn fn; |
| 281 | SkAssertResult(gamma_to_parametric(&fn, gammas, channel)); |
| 282 | this->addTransferFn(invert_parametric(fn), channel); |
raftias | 9752454 | 2016-12-14 13:15:05 -0500 | [diff] [blame] | 283 | } |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 284 | } |
| 285 | } |
raftias | 9752454 | 2016-12-14 13:15:05 -0500 | [diff] [blame] | 286 | break; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 287 | } |
| 288 | } |
| 289 | |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 290 | void SkColorSpaceXform_A2B::addTransferFns(const SkColorSpaceTransferFn& fn, int channelCount) { |
| 291 | for (int i = 0; i < channelCount; ++i) { |
| 292 | this->addTransferFn(fn, i); |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | void SkColorSpaceXform_A2B::addTransferFn(const SkColorSpaceTransferFn& fn, int channelIndex) { |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 297 | fTransferFns.push_front(fn); |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 298 | switch (channelIndex) { |
| 299 | case 0: |
Mike Klein | 62458a6 | 2016-12-01 16:38:16 +0000 | [diff] [blame] | 300 | fElementsPipeline.append(SkRasterPipeline::parametric_r, &fTransferFns.front()); |
| 301 | break; |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 302 | case 1: |
Mike Klein | 62458a6 | 2016-12-01 16:38:16 +0000 | [diff] [blame] | 303 | fElementsPipeline.append(SkRasterPipeline::parametric_g, &fTransferFns.front()); |
| 304 | break; |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 305 | case 2: |
Mike Klein | 62458a6 | 2016-12-01 16:38:16 +0000 | [diff] [blame] | 306 | fElementsPipeline.append(SkRasterPipeline::parametric_b, &fTransferFns.front()); |
raftias | 51c3fcd | 2016-11-30 11:19:22 -0500 | [diff] [blame] | 307 | break; |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 308 | case 3: |
| 309 | fElementsPipeline.append(SkRasterPipeline::parametric_a, &fTransferFns.front()); |
| 310 | break; |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 311 | default: |
| 312 | SkASSERT(false); |
| 313 | } |
| 314 | } |
| 315 | |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 316 | void SkColorSpaceXform_A2B::addTableFn(const SkTableTransferFn& fn, int channelIndex) { |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 317 | fTableTransferFns.push_front(fn); |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 318 | switch (channelIndex) { |
| 319 | case 0: |
Mike Klein | 62458a6 | 2016-12-01 16:38:16 +0000 | [diff] [blame] | 320 | fElementsPipeline.append(SkRasterPipeline::table_r, &fTableTransferFns.front()); |
| 321 | break; |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 322 | case 1: |
Mike Klein | 62458a6 | 2016-12-01 16:38:16 +0000 | [diff] [blame] | 323 | fElementsPipeline.append(SkRasterPipeline::table_g, &fTableTransferFns.front()); |
| 324 | break; |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 325 | case 2: |
Mike Klein | 62458a6 | 2016-12-01 16:38:16 +0000 | [diff] [blame] | 326 | fElementsPipeline.append(SkRasterPipeline::table_b, &fTableTransferFns.front()); |
raftias | 51c3fcd | 2016-11-30 11:19:22 -0500 | [diff] [blame] | 327 | break; |
raftias | 5476128 | 2016-12-01 13:44:07 -0500 | [diff] [blame] | 328 | case 3: |
| 329 | fElementsPipeline.append(SkRasterPipeline::table_a, &fTableTransferFns.front()); |
| 330 | break; |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 331 | default: |
| 332 | SkASSERT(false); |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | void SkColorSpaceXform_A2B::addMatrix(const SkMatrix44& matrix) { |
| 337 | fMatrices.push_front(std::vector<float>(12)); |
| 338 | auto& m = fMatrices.front(); |
| 339 | m[ 0] = matrix.get(0, 0); |
| 340 | m[ 1] = matrix.get(1, 0); |
| 341 | m[ 2] = matrix.get(2, 0); |
| 342 | m[ 3] = matrix.get(0, 1); |
| 343 | m[ 4] = matrix.get(1, 1); |
| 344 | m[ 5] = matrix.get(2, 1); |
| 345 | m[ 6] = matrix.get(0, 2); |
| 346 | m[ 7] = matrix.get(1, 2); |
| 347 | m[ 8] = matrix.get(2, 2); |
| 348 | m[ 9] = matrix.get(0, 3); |
| 349 | m[10] = matrix.get(1, 3); |
| 350 | m[11] = matrix.get(2, 3); |
| 351 | SkASSERT(matrix.get(3, 0) == 0.f); |
| 352 | SkASSERT(matrix.get(3, 1) == 0.f); |
| 353 | SkASSERT(matrix.get(3, 2) == 0.f); |
| 354 | SkASSERT(matrix.get(3, 3) == 1.f); |
| 355 | fElementsPipeline.append(SkRasterPipeline::matrix_3x4, m.data()); |
| 356 | fElementsPipeline.append(SkRasterPipeline::clamp_0); |
Matt Sarett | db4d406 | 2016-11-16 16:07:15 -0500 | [diff] [blame] | 357 | fElementsPipeline.append(SkRasterPipeline::clamp_1); |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 358 | } |