SkColorSpaceXform_A2B.cpp revision c7be00366bb0171e2d247ea71e291a64e3d10254
12563601fc2b0505619f905f86bd249ae630197ccraftias/* 22563601fc2b0505619f905f86bd249ae630197ccraftias * Copyright 2016 Google Inc. 32563601fc2b0505619f905f86bd249ae630197ccraftias * 42563601fc2b0505619f905f86bd249ae630197ccraftias * Use of this source code is governed by a BSD-style license that can be 52563601fc2b0505619f905f86bd249ae630197ccraftias * found in the LICENSE file. 62563601fc2b0505619f905f86bd249ae630197ccraftias */ 72563601fc2b0505619f905f86bd249ae630197ccraftias 82563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkColorSpaceXform_A2B.h" 92563601fc2b0505619f905f86bd249ae630197ccraftias 102563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkColorPriv.h" 112563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkColorSpace_A2B.h" 122563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkColorSpace_XYZ.h" 132563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkColorSpacePriv.h" 142563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkColorSpaceXformPriv.h" 152563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkMakeUnique.h" 162563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkNx.h" 172563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkSRGB.h" 182563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkTypes.h" 19c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein#include "../jumper/SkJumper.h" 202563601fc2b0505619f905f86bd249ae630197ccraftias 212563601fc2b0505619f905f86bd249ae630197ccraftiasbool SkColorSpaceXform_A2B::onApply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, 222563601fc2b0505619f905f86bd249ae630197ccraftias const void* src, int count, SkAlphaType alphaType) const { 232563601fc2b0505619f905f86bd249ae630197ccraftias SkRasterPipeline pipeline; 242563601fc2b0505619f905f86bd249ae630197ccraftias switch (srcFormat) { 252563601fc2b0505619f905f86bd249ae630197ccraftias case kBGRA_8888_ColorFormat: 26729b58296282da00fb9c0f92db2e2e8a8347d431Mike Klein pipeline.append(SkRasterPipeline::load_8888, &src); 272563601fc2b0505619f905f86bd249ae630197ccraftias pipeline.append(SkRasterPipeline::swap_rb); 282563601fc2b0505619f905f86bd249ae630197ccraftias break; 292563601fc2b0505619f905f86bd249ae630197ccraftias case kRGBA_8888_ColorFormat: 30729b58296282da00fb9c0f92db2e2e8a8347d431Mike Klein pipeline.append(SkRasterPipeline::load_8888, &src); 312563601fc2b0505619f905f86bd249ae630197ccraftias break; 32379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett case kRGBA_U16_BE_ColorFormat: 33379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett pipeline.append(SkRasterPipeline::load_u16_be, &src); 34379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett break; 355bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett case kRGB_U16_BE_ColorFormat: 365bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src); 375bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett break; 382563601fc2b0505619f905f86bd249ae630197ccraftias default: 394c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett SkCSXformPrintf("F16/F32 sources must be linear.\n"); 402563601fc2b0505619f905f86bd249ae630197ccraftias return false; 412563601fc2b0505619f905f86bd249ae630197ccraftias } 422563601fc2b0505619f905f86bd249ae630197ccraftias 432563601fc2b0505619f905f86bd249ae630197ccraftias pipeline.extend(fElementsPipeline); 442563601fc2b0505619f905f86bd249ae630197ccraftias 452563601fc2b0505619f905f86bd249ae630197ccraftias if (kPremul_SkAlphaType == alphaType) { 462563601fc2b0505619f905f86bd249ae630197ccraftias pipeline.append(SkRasterPipeline::premul); 472563601fc2b0505619f905f86bd249ae630197ccraftias } 482563601fc2b0505619f905f86bd249ae630197ccraftias 492563601fc2b0505619f905f86bd249ae630197ccraftias switch (dstFormat) { 502563601fc2b0505619f905f86bd249ae630197ccraftias case kBGRA_8888_ColorFormat: 512563601fc2b0505619f905f86bd249ae630197ccraftias pipeline.append(SkRasterPipeline::swap_rb); 522563601fc2b0505619f905f86bd249ae630197ccraftias pipeline.append(SkRasterPipeline::store_8888, &dst); 532563601fc2b0505619f905f86bd249ae630197ccraftias break; 542563601fc2b0505619f905f86bd249ae630197ccraftias case kRGBA_8888_ColorFormat: 552563601fc2b0505619f905f86bd249ae630197ccraftias pipeline.append(SkRasterPipeline::store_8888, &dst); 562563601fc2b0505619f905f86bd249ae630197ccraftias break; 572563601fc2b0505619f905f86bd249ae630197ccraftias case kRGBA_F16_ColorFormat: 582563601fc2b0505619f905f86bd249ae630197ccraftias if (!fLinearDstGamma) { 592563601fc2b0505619f905f86bd249ae630197ccraftias return false; 602563601fc2b0505619f905f86bd249ae630197ccraftias } 612563601fc2b0505619f905f86bd249ae630197ccraftias pipeline.append(SkRasterPipeline::store_f16, &dst); 622563601fc2b0505619f905f86bd249ae630197ccraftias break; 632563601fc2b0505619f905f86bd249ae630197ccraftias case kRGBA_F32_ColorFormat: 642563601fc2b0505619f905f86bd249ae630197ccraftias if (!fLinearDstGamma) { 652563601fc2b0505619f905f86bd249ae630197ccraftias return false; 662563601fc2b0505619f905f86bd249ae630197ccraftias } 672563601fc2b0505619f905f86bd249ae630197ccraftias pipeline.append(SkRasterPipeline::store_f32, &dst); 682563601fc2b0505619f905f86bd249ae630197ccraftias break; 693725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett case kBGR_565_ColorFormat: 703725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett if (kOpaque_SkAlphaType != alphaType) { 713725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett return false; 723725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett } 733725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett pipeline.append(SkRasterPipeline::store_565, &dst); 743725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett break; 75379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett default: 76379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett return false; 772563601fc2b0505619f905f86bd249ae630197ccraftias } 78319ba3d3a177498095c31696e0aec8b3af25f663Mike Klein pipeline.run(0,count); 792563601fc2b0505619f905f86bd249ae630197ccraftias 802563601fc2b0505619f905f86bd249ae630197ccraftias return true; 812563601fc2b0505619f905f86bd249ae630197ccraftias} 822563601fc2b0505619f905f86bd249ae630197ccraftias 83113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistrystatic inline bool gamma_to_parametric(SkColorSpaceTransferFn* coeffs, const SkGammas& gammas, 84113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry int channel) { 852563601fc2b0505619f905f86bd249ae630197ccraftias switch (gammas.type(channel)) { 862563601fc2b0505619f905f86bd249ae630197ccraftias case SkGammas::Type::kNamed_Type: 87113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry return named_to_parametric(coeffs, gammas.data(channel).fNamed); 882563601fc2b0505619f905f86bd249ae630197ccraftias case SkGammas::Type::kValue_Type: 89113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry value_to_parametric(coeffs, gammas.data(channel).fValue); 90113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry return true; 912563601fc2b0505619f905f86bd249ae630197ccraftias case SkGammas::Type::kParam_Type: 92113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry *coeffs = gammas.params(channel); 93113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry return true; 942563601fc2b0505619f905f86bd249ae630197ccraftias default: 95113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry return false; 962563601fc2b0505619f905f86bd249ae630197ccraftias } 972563601fc2b0505619f905f86bd249ae630197ccraftias} 982563601fc2b0505619f905f86bd249ae630197ccraftias 992563601fc2b0505619f905f86bd249ae630197ccraftiasSkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace, 1002563601fc2b0505619f905f86bd249ae630197ccraftias SkColorSpace_XYZ* dstSpace) 1012563601fc2b0505619f905f86bd249ae630197ccraftias : fLinearDstGamma(kLinear_SkGammaNamed == dstSpace->gammaNamed()) { 1022563601fc2b0505619f905f86bd249ae630197ccraftias#if (SkCSXformPrintfDefined) 1032563601fc2b0505619f905f86bd249ae630197ccraftias static const char* debugGammaNamed[4] = { 1042563601fc2b0505619f905f86bd249ae630197ccraftias "Linear", "SRGB", "2.2", "NonStandard" 1052563601fc2b0505619f905f86bd249ae630197ccraftias }; 1062563601fc2b0505619f905f86bd249ae630197ccraftias static const char* debugGammas[5] = { 1072563601fc2b0505619f905f86bd249ae630197ccraftias "None", "Named", "Value", "Table", "Param" 1082563601fc2b0505619f905f86bd249ae630197ccraftias }; 1092563601fc2b0505619f905f86bd249ae630197ccraftias#endif 110523116d9fee8b79af09563b55b19cbd267353300Matt Sarett int currentChannels; 111523116d9fee8b79af09563b55b19cbd267353300Matt Sarett switch (srcSpace->iccType()) { 112523116d9fee8b79af09563b55b19cbd267353300Matt Sarett case SkColorSpace_Base::kRGB_ICCTypeFlag: 1135476128f0a88217414f05e6a7ee518cdb411d026raftias currentChannels = 3; 1145476128f0a88217414f05e6a7ee518cdb411d026raftias break; 115c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein case SkColorSpace_Base::kCMYK_ICCTypeFlag: { 1165476128f0a88217414f05e6a7ee518cdb411d026raftias currentChannels = 4; 1175476128f0a88217414f05e6a7ee518cdb411d026raftias // CMYK images from JPEGs (the only format that supports it) are actually 1185476128f0a88217414f05e6a7ee518cdb411d026raftias // inverted CMYK, so we need to invert every channel. 1195476128f0a88217414f05e6a7ee518cdb411d026raftias // TransferFn is y = -x + 1 for x < 1.f, otherwise 0x + 0, ie y = 1 - x for x in [0,1] 120c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein SkColorSpaceTransferFn fn = {0,0,0,0,0,0,0}; 121c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fn.fG = 1; 122c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fn.fA = 0; 123c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fn.fB = 0; 124c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fn.fC = -1; 125c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fn.fD = 1; 126c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fn.fE = 0; 127c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fn.fF = 1; 128c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein this->addTransferFns(fn,4); 1295476128f0a88217414f05e6a7ee518cdb411d026raftias break; 130c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein } 1315476128f0a88217414f05e6a7ee518cdb411d026raftias default: 132523116d9fee8b79af09563b55b19cbd267353300Matt Sarett currentChannels = 0; 1335476128f0a88217414f05e6a7ee518cdb411d026raftias SkASSERT(false); 1345476128f0a88217414f05e6a7ee518cdb411d026raftias } 1352563601fc2b0505619f905f86bd249ae630197ccraftias // add in all input color space -> PCS xforms 1362563601fc2b0505619f905f86bd249ae630197ccraftias for (int i = 0; i < srcSpace->count(); ++i) { 1372563601fc2b0505619f905f86bd249ae630197ccraftias const SkColorSpace_A2B::Element& e = srcSpace->element(i); 1385476128f0a88217414f05e6a7ee518cdb411d026raftias SkASSERT(e.inputChannels() == currentChannels); 1395476128f0a88217414f05e6a7ee518cdb411d026raftias currentChannels = e.outputChannels(); 1402563601fc2b0505619f905f86bd249ae630197ccraftias switch (e.type()) { 1412563601fc2b0505619f905f86bd249ae630197ccraftias case SkColorSpace_A2B::Element::Type::kGammaNamed: 142113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry if (kLinear_SkGammaNamed == e.gammaNamed()) { 143113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry break; 144113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry } 145113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry 146c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein // Take the fast path for ordinary sRGB. 147c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein if (3 == currentChannels && kSRGB_SkGammaNamed == e.gammaNamed()) { 148c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein SkCSXformPrintf("fast path from sRGB\n"); 149c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein // Images should always start the pipeline as unpremul 150c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fElementsPipeline.append_from_srgb(kUnpremul_SkAlphaType); 151c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein break; 152975245407a16dba58ee42cb12f70f8db87f02da0raftias } 153113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry 154113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkCSXformPrintf("Gamma stage added: %s\n", debugGammaNamed[(int)e.gammaNamed()]); 155113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkColorSpaceTransferFn fn; 156113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkAssertResult(named_to_parametric(&fn, e.gammaNamed())); 157113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry this->addTransferFns(fn, currentChannels); 1582563601fc2b0505619f905f86bd249ae630197ccraftias break; 1592563601fc2b0505619f905f86bd249ae630197ccraftias case SkColorSpace_A2B::Element::Type::kGammas: { 160db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett const SkGammas& gammas = e.gammas(); 161db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett SkCSXformPrintf("Gamma stage added:"); 1625476128f0a88217414f05e6a7ee518cdb411d026raftias for (int channel = 0; channel < gammas.channels(); ++channel) { 163db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett SkCSXformPrintf(" %s", debugGammas[(int)gammas.type(channel)]); 164db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett } 165db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett SkCSXformPrintf("\n"); 166db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett bool gammaNeedsRef = false; 1675476128f0a88217414f05e6a7ee518cdb411d026raftias for (int channel = 0; channel < gammas.channels(); ++channel) { 168db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett if (SkGammas::Type::kTable_Type == gammas.type(channel)) { 169db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett SkTableTransferFn table = { 170db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett gammas.table(channel), 171db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett gammas.data(channel).fTable.fSize, 172db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett }; 173db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett 1745476128f0a88217414f05e6a7ee518cdb411d026raftias this->addTableFn(table, channel); 175db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett gammaNeedsRef = true; 176db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett } else { 177113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkColorSpaceTransferFn fn; 178113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkAssertResult(gamma_to_parametric(&fn, gammas, channel)); 1795476128f0a88217414f05e6a7ee518cdb411d026raftias this->addTransferFn(fn, channel); 1802563601fc2b0505619f905f86bd249ae630197ccraftias } 1812563601fc2b0505619f905f86bd249ae630197ccraftias } 182db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett if (gammaNeedsRef) { 183de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein this->copy(sk_ref_sp(&gammas)); 184db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett } 1852563601fc2b0505619f905f86bd249ae630197ccraftias break; 186db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett } 187de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein case SkColorSpace_A2B::Element::Type::kCLUT: { 1885476128f0a88217414f05e6a7ee518cdb411d026raftias SkCSXformPrintf("CLUT (%d -> %d) stage added\n", e.colorLUT().inputChannels(), 1895476128f0a88217414f05e6a7ee518cdb411d026raftias e.colorLUT().outputChannels()); 190c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein struct CallbackCtx : SkJumper_CallbackCtx { 191c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein sk_sp<const SkColorLookUpTable> clut; 192c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein // clut->interp() can't always safely alias its arguments, 193c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein // so we allocate a second buffer to hold our results. 194c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein float results[4*SkJumper_kMaxStride]; 195c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein }; 196c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein auto cb = fAlloc.make<CallbackCtx>(); 197c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein cb->clut = sk_ref_sp(&e.colorLUT()); 198c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein cb->read_from = cb->results; 199c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein cb->fn = [](SkJumper_CallbackCtx* ctx, int active_pixels) { 200c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein auto c = (CallbackCtx*)ctx; 201c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein for (int i = 0; i < active_pixels; i++) { 202c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein // Look up red, green, and blue for this pixel using 3-4 values from rgba. 203c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein c->clut->interp(c->results+4*i, c->rgba+4*i); 204c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein 205c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein // If we used 3 inputs (rgb) preserve the fourth as alpha. 206c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein // If we used 4 inputs (cmyk) force alpha to 1. 207c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein c->results[4*i+3] = (3 == c->clut->inputChannels()) ? c->rgba[4*i+3] : 1.0f; 208c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein } 209c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein }; 210c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein fElementsPipeline.append(SkRasterPipeline::callback, cb); 2112563601fc2b0505619f905f86bd249ae630197ccraftias break; 212de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein } 2132563601fc2b0505619f905f86bd249ae630197ccraftias case SkColorSpace_A2B::Element::Type::kMatrix: 2142563601fc2b0505619f905f86bd249ae630197ccraftias if (!e.matrix().isIdentity()) { 2152563601fc2b0505619f905f86bd249ae630197ccraftias SkCSXformPrintf("Matrix stage added\n"); 2162563601fc2b0505619f905f86bd249ae630197ccraftias addMatrix(e.matrix()); 2172563601fc2b0505619f905f86bd249ae630197ccraftias } 2182563601fc2b0505619f905f86bd249ae630197ccraftias break; 2192563601fc2b0505619f905f86bd249ae630197ccraftias } 2202563601fc2b0505619f905f86bd249ae630197ccraftias } 2212563601fc2b0505619f905f86bd249ae630197ccraftias 2222563601fc2b0505619f905f86bd249ae630197ccraftias // Lab PCS -> XYZ PCS 2232563601fc2b0505619f905f86bd249ae630197ccraftias if (SkColorSpace_A2B::PCS::kLAB == srcSpace->pcs()) { 2242563601fc2b0505619f905f86bd249ae630197ccraftias SkCSXformPrintf("Lab -> XYZ element added\n"); 2252563601fc2b0505619f905f86bd249ae630197ccraftias fElementsPipeline.append(SkRasterPipeline::lab_to_xyz); 2262563601fc2b0505619f905f86bd249ae630197ccraftias } 2272563601fc2b0505619f905f86bd249ae630197ccraftias 22891db12d89c214235e24599f3ec18df2f952e99ebraftias // we should now be in XYZ PCS 22991db12d89c214235e24599f3ec18df2f952e99ebraftias SkASSERT(3 == currentChannels); 23091db12d89c214235e24599f3ec18df2f952e99ebraftias 2312563601fc2b0505619f905f86bd249ae630197ccraftias // and XYZ PCS -> output color space xforms 2322563601fc2b0505619f905f86bd249ae630197ccraftias if (!dstSpace->fromXYZD50()->isIdentity()) { 2332563601fc2b0505619f905f86bd249ae630197ccraftias addMatrix(*dstSpace->fromXYZD50()); 2342563601fc2b0505619f905f86bd249ae630197ccraftias } 2352563601fc2b0505619f905f86bd249ae630197ccraftias 236975245407a16dba58ee42cb12f70f8db87f02da0raftias switch (dstSpace->gammaNamed()) { 237975245407a16dba58ee42cb12f70f8db87f02da0raftias case kLinear_SkGammaNamed: 238975245407a16dba58ee42cb12f70f8db87f02da0raftias // do nothing 239975245407a16dba58ee42cb12f70f8db87f02da0raftias break; 240c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein case k2Dot2Curve_SkGammaNamed: { 241c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein SkColorSpaceTransferFn fn = {0,0,0,0,0,0,0}; 242c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fn.fG = 1/2.2f; 243c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fn.fA = 1; 244c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein auto to_2dot2 = this->copy(fn); 245c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_r, to_2dot2); 246c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_g, to_2dot2); 247c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_b, to_2dot2); 248975245407a16dba58ee42cb12f70f8db87f02da0raftias break; 249c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein } 250975245407a16dba58ee42cb12f70f8db87f02da0raftias case kSRGB_SkGammaNamed: 251975245407a16dba58ee42cb12f70f8db87f02da0raftias fElementsPipeline.append(SkRasterPipeline::to_srgb); 252975245407a16dba58ee42cb12f70f8db87f02da0raftias break; 253975245407a16dba58ee42cb12f70f8db87f02da0raftias case kNonStandard_SkGammaNamed: { 254975245407a16dba58ee42cb12f70f8db87f02da0raftias for (int channel = 0; channel < 3; ++channel) { 255975245407a16dba58ee42cb12f70f8db87f02da0raftias const SkGammas& gammas = *dstSpace->gammas(); 256975245407a16dba58ee42cb12f70f8db87f02da0raftias if (SkGammas::Type::kTable_Type == gammas.type(channel)) { 257975245407a16dba58ee42cb12f70f8db87f02da0raftias static constexpr int kInvTableSize = 256; 258de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein auto storage = fAlloc.makeArray<float>(kInvTableSize); 259de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein invert_table_gamma(storage, nullptr, kInvTableSize, 260975245407a16dba58ee42cb12f70f8db87f02da0raftias gammas.table(channel), 261975245407a16dba58ee42cb12f70f8db87f02da0raftias gammas.data(channel).fTable.fSize); 262de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein SkTableTransferFn table = { storage, kInvTableSize }; 263975245407a16dba58ee42cb12f70f8db87f02da0raftias this->addTableFn(table, channel); 264975245407a16dba58ee42cb12f70f8db87f02da0raftias } else { 265113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkColorSpaceTransferFn fn; 266113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkAssertResult(gamma_to_parametric(&fn, gammas, channel)); 26773e627074839bc00569117235eb4e7d4fc3cc39fBrian Osman this->addTransferFn(fn.invert(), channel); 268975245407a16dba58ee42cb12f70f8db87f02da0raftias } 2692563601fc2b0505619f905f86bd249ae630197ccraftias } 2702563601fc2b0505619f905f86bd249ae630197ccraftias } 271975245407a16dba58ee42cb12f70f8db87f02da0raftias break; 272db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett } 273db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett} 274db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett 2755476128f0a88217414f05e6a7ee518cdb411d026raftiasvoid SkColorSpaceXform_A2B::addTransferFns(const SkColorSpaceTransferFn& fn, int channelCount) { 2765476128f0a88217414f05e6a7ee518cdb411d026raftias for (int i = 0; i < channelCount; ++i) { 2775476128f0a88217414f05e6a7ee518cdb411d026raftias this->addTransferFn(fn, i); 2785476128f0a88217414f05e6a7ee518cdb411d026raftias } 2795476128f0a88217414f05e6a7ee518cdb411d026raftias} 2805476128f0a88217414f05e6a7ee518cdb411d026raftias 2815476128f0a88217414f05e6a7ee518cdb411d026raftiasvoid SkColorSpaceXform_A2B::addTransferFn(const SkColorSpaceTransferFn& fn, int channelIndex) { 2825476128f0a88217414f05e6a7ee518cdb411d026raftias switch (channelIndex) { 2835476128f0a88217414f05e6a7ee518cdb411d026raftias case 0: 284de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_r, this->copy(fn)); 285db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett break; 2865476128f0a88217414f05e6a7ee518cdb411d026raftias case 1: 287de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_g, this->copy(fn)); 288db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett break; 2895476128f0a88217414f05e6a7ee518cdb411d026raftias case 2: 290de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_b, this->copy(fn)); 291db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett break; 2925476128f0a88217414f05e6a7ee518cdb411d026raftias case 3: 293de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_a, this->copy(fn)); 2945476128f0a88217414f05e6a7ee518cdb411d026raftias break; 295db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett default: 296db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett SkASSERT(false); 2972563601fc2b0505619f905f86bd249ae630197ccraftias } 2982563601fc2b0505619f905f86bd249ae630197ccraftias} 2992563601fc2b0505619f905f86bd249ae630197ccraftias 3005476128f0a88217414f05e6a7ee518cdb411d026raftiasvoid SkColorSpaceXform_A2B::addTableFn(const SkTableTransferFn& fn, int channelIndex) { 3015476128f0a88217414f05e6a7ee518cdb411d026raftias switch (channelIndex) { 3025476128f0a88217414f05e6a7ee518cdb411d026raftias case 0: 303de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::table_r, this->copy(fn)); 3042563601fc2b0505619f905f86bd249ae630197ccraftias break; 3055476128f0a88217414f05e6a7ee518cdb411d026raftias case 1: 306de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::table_g, this->copy(fn)); 3072563601fc2b0505619f905f86bd249ae630197ccraftias break; 3085476128f0a88217414f05e6a7ee518cdb411d026raftias case 2: 309de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::table_b, this->copy(fn)); 3102563601fc2b0505619f905f86bd249ae630197ccraftias break; 3115476128f0a88217414f05e6a7ee518cdb411d026raftias case 3: 312de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::table_a, this->copy(fn)); 3135476128f0a88217414f05e6a7ee518cdb411d026raftias break; 3142563601fc2b0505619f905f86bd249ae630197ccraftias default: 3152563601fc2b0505619f905f86bd249ae630197ccraftias SkASSERT(false); 3162563601fc2b0505619f905f86bd249ae630197ccraftias } 3172563601fc2b0505619f905f86bd249ae630197ccraftias} 3182563601fc2b0505619f905f86bd249ae630197ccraftias 319de1cad99b353bad080a04ccfde955a8f3c0af295Mike Kleinvoid SkColorSpaceXform_A2B::addMatrix(const SkMatrix44& m44) { 320de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein auto m = fAlloc.makeArray<float>(12); 321de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein m[0] = m44.get(0,0); m[ 1] = m44.get(1,0); m[ 2] = m44.get(2,0); 322de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein m[3] = m44.get(0,1); m[ 4] = m44.get(1,1); m[ 5] = m44.get(2,1); 323de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein m[6] = m44.get(0,2); m[ 7] = m44.get(1,2); m[ 8] = m44.get(2,2); 324de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein m[9] = m44.get(0,3); m[10] = m44.get(1,3); m[11] = m44.get(2,3); 325de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein 326de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein SkASSERT(m44.get(3,0) == 0.0f); 327de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein SkASSERT(m44.get(3,1) == 0.0f); 328de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein SkASSERT(m44.get(3,2) == 0.0f); 329de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein SkASSERT(m44.get(3,3) == 1.0f); 330de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein 331de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::matrix_3x4, m); 3322563601fc2b0505619f905f86bd249ae630197ccraftias fElementsPipeline.append(SkRasterPipeline::clamp_0); 333db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett fElementsPipeline.append(SkRasterPipeline::clamp_1); 3342563601fc2b0505619f905f86bd249ae630197ccraftias} 335