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 10a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.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 { 23b24704d35f67f5b460be9c92794892e06adceb46Mike Klein SkRasterPipeline_<256> pipeline; 2445c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein 2545c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein SkJumper_MemoryCtx src_ctx = { (void*)src, 0 }, 2645c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein dst_ctx = { (void*)dst, 0 }; 2745c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein 282563601fc2b0505619f905f86bd249ae630197ccraftias switch (srcFormat) { 292563601fc2b0505619f905f86bd249ae630197ccraftias case kBGRA_8888_ColorFormat: 3045c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_bgra, &src_ctx); 312563601fc2b0505619f905f86bd249ae630197ccraftias break; 322563601fc2b0505619f905f86bd249ae630197ccraftias case kRGBA_8888_ColorFormat: 3345c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_8888, &src_ctx); 342563601fc2b0505619f905f86bd249ae630197ccraftias break; 35379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett case kRGBA_U16_BE_ColorFormat: 3645c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_u16_be, &src_ctx); 37379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett break; 385bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett case kRGB_U16_BE_ColorFormat: 3945c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src_ctx); 405bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett break; 412563601fc2b0505619f905f86bd249ae630197ccraftias default: 424c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett SkCSXformPrintf("F16/F32 sources must be linear.\n"); 432563601fc2b0505619f905f86bd249ae630197ccraftias return false; 442563601fc2b0505619f905f86bd249ae630197ccraftias } 452563601fc2b0505619f905f86bd249ae630197ccraftias 462563601fc2b0505619f905f86bd249ae630197ccraftias pipeline.extend(fElementsPipeline); 472563601fc2b0505619f905f86bd249ae630197ccraftias 482563601fc2b0505619f905f86bd249ae630197ccraftias if (kPremul_SkAlphaType == alphaType) { 492563601fc2b0505619f905f86bd249ae630197ccraftias pipeline.append(SkRasterPipeline::premul); 502563601fc2b0505619f905f86bd249ae630197ccraftias } 512563601fc2b0505619f905f86bd249ae630197ccraftias 522563601fc2b0505619f905f86bd249ae630197ccraftias switch (dstFormat) { 532563601fc2b0505619f905f86bd249ae630197ccraftias case kBGRA_8888_ColorFormat: 5445c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::store_bgra, &dst_ctx); 552563601fc2b0505619f905f86bd249ae630197ccraftias break; 562563601fc2b0505619f905f86bd249ae630197ccraftias case kRGBA_8888_ColorFormat: 5745c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::store_8888, &dst_ctx); 582563601fc2b0505619f905f86bd249ae630197ccraftias break; 592563601fc2b0505619f905f86bd249ae630197ccraftias case kRGBA_F16_ColorFormat: 602563601fc2b0505619f905f86bd249ae630197ccraftias if (!fLinearDstGamma) { 612563601fc2b0505619f905f86bd249ae630197ccraftias return false; 622563601fc2b0505619f905f86bd249ae630197ccraftias } 6345c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::store_f16, &dst_ctx); 642563601fc2b0505619f905f86bd249ae630197ccraftias break; 652563601fc2b0505619f905f86bd249ae630197ccraftias case kRGBA_F32_ColorFormat: 662563601fc2b0505619f905f86bd249ae630197ccraftias if (!fLinearDstGamma) { 672563601fc2b0505619f905f86bd249ae630197ccraftias return false; 682563601fc2b0505619f905f86bd249ae630197ccraftias } 6945c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::store_f32, &dst_ctx); 702563601fc2b0505619f905f86bd249ae630197ccraftias break; 713725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett case kBGR_565_ColorFormat: 723725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett if (kOpaque_SkAlphaType != alphaType) { 733725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett return false; 743725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett } 7545c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.append(SkRasterPipeline::store_565, &dst_ctx); 763725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett break; 77379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett default: 78379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett return false; 792563601fc2b0505619f905f86bd249ae630197ccraftias } 8045c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein pipeline.run(0,0, count,1); 812563601fc2b0505619f905f86bd249ae630197ccraftias 822563601fc2b0505619f905f86bd249ae630197ccraftias return true; 832563601fc2b0505619f905f86bd249ae630197ccraftias} 842563601fc2b0505619f905f86bd249ae630197ccraftias 85113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistrystatic inline bool gamma_to_parametric(SkColorSpaceTransferFn* coeffs, const SkGammas& gammas, 86113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry int channel) { 872563601fc2b0505619f905f86bd249ae630197ccraftias switch (gammas.type(channel)) { 882563601fc2b0505619f905f86bd249ae630197ccraftias case SkGammas::Type::kNamed_Type: 89113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry return named_to_parametric(coeffs, gammas.data(channel).fNamed); 902563601fc2b0505619f905f86bd249ae630197ccraftias case SkGammas::Type::kValue_Type: 91113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry value_to_parametric(coeffs, gammas.data(channel).fValue); 92113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry return true; 932563601fc2b0505619f905f86bd249ae630197ccraftias case SkGammas::Type::kParam_Type: 94113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry *coeffs = gammas.params(channel); 95113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry return true; 962563601fc2b0505619f905f86bd249ae630197ccraftias default: 97113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry return false; 982563601fc2b0505619f905f86bd249ae630197ccraftias } 992563601fc2b0505619f905f86bd249ae630197ccraftias} 1002563601fc2b0505619f905f86bd249ae630197ccraftias 1012563601fc2b0505619f905f86bd249ae630197ccraftiasSkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace, 1022563601fc2b0505619f905f86bd249ae630197ccraftias SkColorSpace_XYZ* dstSpace) 103b24704d35f67f5b460be9c92794892e06adceb46Mike Klein : fElementsPipeline(&fAlloc) 104b24704d35f67f5b460be9c92794892e06adceb46Mike Klein , fLinearDstGamma(kLinear_SkGammaNamed == dstSpace->gammaNamed()) { 1052563601fc2b0505619f905f86bd249ae630197ccraftias#if (SkCSXformPrintfDefined) 1062563601fc2b0505619f905f86bd249ae630197ccraftias static const char* debugGammaNamed[4] = { 1072563601fc2b0505619f905f86bd249ae630197ccraftias "Linear", "SRGB", "2.2", "NonStandard" 1082563601fc2b0505619f905f86bd249ae630197ccraftias }; 1092563601fc2b0505619f905f86bd249ae630197ccraftias static const char* debugGammas[5] = { 1102563601fc2b0505619f905f86bd249ae630197ccraftias "None", "Named", "Value", "Table", "Param" 1112563601fc2b0505619f905f86bd249ae630197ccraftias }; 1122563601fc2b0505619f905f86bd249ae630197ccraftias#endif 113523116d9fee8b79af09563b55b19cbd267353300Matt Sarett int currentChannels; 114523116d9fee8b79af09563b55b19cbd267353300Matt Sarett switch (srcSpace->iccType()) { 115f78b55cb94f4ac89b76a26d5a56d6380aa8fea6bLeon Scroggins III case SkColorSpace::kRGB_Type: 1165476128f0a88217414f05e6a7ee518cdb411d026raftias currentChannels = 3; 1175476128f0a88217414f05e6a7ee518cdb411d026raftias break; 118f78b55cb94f4ac89b76a26d5a56d6380aa8fea6bLeon Scroggins III case SkColorSpace::kCMYK_Type: { 1195476128f0a88217414f05e6a7ee518cdb411d026raftias currentChannels = 4; 1205476128f0a88217414f05e6a7ee518cdb411d026raftias // CMYK images from JPEGs (the only format that supports it) are actually 1215476128f0a88217414f05e6a7ee518cdb411d026raftias // inverted CMYK, so we need to invert every channel. 12250d0d053576a4895bdd4c837bf990b499da209cbMike Klein fElementsPipeline.append(SkRasterPipeline::invert); 1235476128f0a88217414f05e6a7ee518cdb411d026raftias break; 124c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein } 1255476128f0a88217414f05e6a7ee518cdb411d026raftias default: 126523116d9fee8b79af09563b55b19cbd267353300Matt Sarett currentChannels = 0; 1275476128f0a88217414f05e6a7ee518cdb411d026raftias SkASSERT(false); 1285476128f0a88217414f05e6a7ee518cdb411d026raftias } 1292563601fc2b0505619f905f86bd249ae630197ccraftias // add in all input color space -> PCS xforms 1302563601fc2b0505619f905f86bd249ae630197ccraftias for (int i = 0; i < srcSpace->count(); ++i) { 1312563601fc2b0505619f905f86bd249ae630197ccraftias const SkColorSpace_A2B::Element& e = srcSpace->element(i); 1325476128f0a88217414f05e6a7ee518cdb411d026raftias SkASSERT(e.inputChannels() == currentChannels); 1335476128f0a88217414f05e6a7ee518cdb411d026raftias currentChannels = e.outputChannels(); 1342563601fc2b0505619f905f86bd249ae630197ccraftias switch (e.type()) { 13550d0d053576a4895bdd4c837bf990b499da209cbMike Klein case SkColorSpace_A2B::Element::Type::kGammaNamed: { 136113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry if (kLinear_SkGammaNamed == e.gammaNamed()) { 137113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry break; 138113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry } 139113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry 140c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein // Take the fast path for ordinary sRGB. 141c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein if (3 == currentChannels && kSRGB_SkGammaNamed == e.gammaNamed()) { 142c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein SkCSXformPrintf("fast path from sRGB\n"); 143f1f1162273b382db99f8609e5bbfff24f5594821Mike Klein fElementsPipeline.append(SkRasterPipeline::from_srgb); 144c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein break; 145975245407a16dba58ee42cb12f70f8db87f02da0raftias } 146113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry 147113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkCSXformPrintf("Gamma stage added: %s\n", debugGammaNamed[(int)e.gammaNamed()]); 14850d0d053576a4895bdd4c837bf990b499da209cbMike Klein auto fn = fAlloc.make<SkColorSpaceTransferFn>(); 14950d0d053576a4895bdd4c837bf990b499da209cbMike Klein SkAssertResult(named_to_parametric(fn, e.gammaNamed())); 15050d0d053576a4895bdd4c837bf990b499da209cbMike Klein 151a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein if (is_just_gamma(*fn)) { 152a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein fElementsPipeline.append(SkRasterPipeline::gamma, &fn->fG); 153a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein } else { 154a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_r, fn); 155a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_g, fn); 156a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_b, fn); 157a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein } 1582563601fc2b0505619f905f86bd249ae630197ccraftias break; 15950d0d053576a4895bdd4c837bf990b499da209cbMike Klein } 1602563601fc2b0505619f905f86bd249ae630197ccraftias case SkColorSpace_A2B::Element::Type::kGammas: { 161db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett const SkGammas& gammas = e.gammas(); 162db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett SkCSXformPrintf("Gamma stage added:"); 1635476128f0a88217414f05e6a7ee518cdb411d026raftias for (int channel = 0; channel < gammas.channels(); ++channel) { 164db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett SkCSXformPrintf(" %s", debugGammas[(int)gammas.type(channel)]); 165db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett } 166db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett SkCSXformPrintf("\n"); 167db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett bool gammaNeedsRef = false; 1685476128f0a88217414f05e6a7ee518cdb411d026raftias for (int channel = 0; channel < gammas.channels(); ++channel) { 169db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett if (SkGammas::Type::kTable_Type == gammas.type(channel)) { 170db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett SkTableTransferFn table = { 171db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett gammas.table(channel), 172db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett gammas.data(channel).fTable.fSize, 173db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett }; 174db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett 1759d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett gammaNeedsRef |= !this->buildTableFn(&table); 1765476128f0a88217414f05e6a7ee518cdb411d026raftias this->addTableFn(table, channel); 177db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett } else { 178113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkColorSpaceTransferFn fn; 179113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkAssertResult(gamma_to_parametric(&fn, gammas, channel)); 1805476128f0a88217414f05e6a7ee518cdb411d026raftias this->addTransferFn(fn, channel); 1812563601fc2b0505619f905f86bd249ae630197ccraftias } 1822563601fc2b0505619f905f86bd249ae630197ccraftias } 183db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett if (gammaNeedsRef) { 184de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein this->copy(sk_ref_sp(&gammas)); 185db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett } 1862563601fc2b0505619f905f86bd249ae630197ccraftias break; 187db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett } 188de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein case SkColorSpace_A2B::Element::Type::kCLUT: { 1895476128f0a88217414f05e6a7ee518cdb411d026raftias SkCSXformPrintf("CLUT (%d -> %d) stage added\n", e.colorLUT().inputChannels(), 1905476128f0a88217414f05e6a7ee518cdb411d026raftias e.colorLUT().outputChannels()); 191c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein 192c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein struct Ctx : SkJumper_ColorLookupTableCtx { 193c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein sk_sp<const SkColorLookUpTable> clut; 194c17dc24fa9994eacc640d3adc6633a02fd96d3fcMike Klein }; 195c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein auto ctx = fAlloc.make<Ctx>(); 196c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein ctx->clut = sk_ref_sp(&e.colorLUT()); 197c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein ctx->table = ctx->clut->table(); 198c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein for (int i = 0; i < ctx->clut->inputChannels(); i++) { 199c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein ctx->limits[i] = ctx->clut->gridPoints(i); 200c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein } 201c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein 202c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein switch (e.colorLUT().inputChannels()) { 203c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein case 3: fElementsPipeline.append(SkRasterPipeline::clut_3D, ctx); break; 204c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein case 4: fElementsPipeline.append(SkRasterPipeline::clut_4D, ctx); break; 205c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein default: SkDEBUGFAIL("need to handle 1 or 2 channel color lookup tables."); 206c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein } 207c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein fElementsPipeline.append(SkRasterPipeline::clamp_0); 208c2f876bb8d8991e428467c1d7d24152eea629770Mike Klein fElementsPipeline.append(SkRasterPipeline::clamp_1); 2092563601fc2b0505619f905f86bd249ae630197ccraftias break; 210de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein } 2112563601fc2b0505619f905f86bd249ae630197ccraftias case SkColorSpace_A2B::Element::Type::kMatrix: 2122563601fc2b0505619f905f86bd249ae630197ccraftias if (!e.matrix().isIdentity()) { 2132563601fc2b0505619f905f86bd249ae630197ccraftias SkCSXformPrintf("Matrix stage added\n"); 2142563601fc2b0505619f905f86bd249ae630197ccraftias addMatrix(e.matrix()); 2152563601fc2b0505619f905f86bd249ae630197ccraftias } 2162563601fc2b0505619f905f86bd249ae630197ccraftias break; 2172563601fc2b0505619f905f86bd249ae630197ccraftias } 2182563601fc2b0505619f905f86bd249ae630197ccraftias } 2192563601fc2b0505619f905f86bd249ae630197ccraftias 2202563601fc2b0505619f905f86bd249ae630197ccraftias // Lab PCS -> XYZ PCS 2212563601fc2b0505619f905f86bd249ae630197ccraftias if (SkColorSpace_A2B::PCS::kLAB == srcSpace->pcs()) { 2222563601fc2b0505619f905f86bd249ae630197ccraftias SkCSXformPrintf("Lab -> XYZ element added\n"); 2232563601fc2b0505619f905f86bd249ae630197ccraftias fElementsPipeline.append(SkRasterPipeline::lab_to_xyz); 2242563601fc2b0505619f905f86bd249ae630197ccraftias } 2252563601fc2b0505619f905f86bd249ae630197ccraftias 22691db12d89c214235e24599f3ec18df2f952e99ebraftias // we should now be in XYZ PCS 22791db12d89c214235e24599f3ec18df2f952e99ebraftias SkASSERT(3 == currentChannels); 22891db12d89c214235e24599f3ec18df2f952e99ebraftias 2292563601fc2b0505619f905f86bd249ae630197ccraftias // and XYZ PCS -> output color space xforms 2302563601fc2b0505619f905f86bd249ae630197ccraftias if (!dstSpace->fromXYZD50()->isIdentity()) { 2312563601fc2b0505619f905f86bd249ae630197ccraftias addMatrix(*dstSpace->fromXYZD50()); 2322563601fc2b0505619f905f86bd249ae630197ccraftias } 2332563601fc2b0505619f905f86bd249ae630197ccraftias 234975245407a16dba58ee42cb12f70f8db87f02da0raftias switch (dstSpace->gammaNamed()) { 235975245407a16dba58ee42cb12f70f8db87f02da0raftias case kLinear_SkGammaNamed: 236975245407a16dba58ee42cb12f70f8db87f02da0raftias // do nothing 237975245407a16dba58ee42cb12f70f8db87f02da0raftias break; 238c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein case k2Dot2Curve_SkGammaNamed: { 239a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein fElementsPipeline.append(SkRasterPipeline::gamma, this->copy(1/2.2f)); 240975245407a16dba58ee42cb12f70f8db87f02da0raftias break; 241c7be00366bb0171e2d247ea71e291a64e3d10254Mike Klein } 242975245407a16dba58ee42cb12f70f8db87f02da0raftias case kSRGB_SkGammaNamed: 243975245407a16dba58ee42cb12f70f8db87f02da0raftias fElementsPipeline.append(SkRasterPipeline::to_srgb); 244975245407a16dba58ee42cb12f70f8db87f02da0raftias break; 245975245407a16dba58ee42cb12f70f8db87f02da0raftias case kNonStandard_SkGammaNamed: { 246975245407a16dba58ee42cb12f70f8db87f02da0raftias for (int channel = 0; channel < 3; ++channel) { 247975245407a16dba58ee42cb12f70f8db87f02da0raftias const SkGammas& gammas = *dstSpace->gammas(); 248975245407a16dba58ee42cb12f70f8db87f02da0raftias if (SkGammas::Type::kTable_Type == gammas.type(channel)) { 249975245407a16dba58ee42cb12f70f8db87f02da0raftias static constexpr int kInvTableSize = 256; 250de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein auto storage = fAlloc.makeArray<float>(kInvTableSize); 251de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein invert_table_gamma(storage, nullptr, kInvTableSize, 252975245407a16dba58ee42cb12f70f8db87f02da0raftias gammas.table(channel), 253975245407a16dba58ee42cb12f70f8db87f02da0raftias gammas.data(channel).fTable.fSize); 254de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein SkTableTransferFn table = { storage, kInvTableSize }; 255975245407a16dba58ee42cb12f70f8db87f02da0raftias this->addTableFn(table, channel); 256975245407a16dba58ee42cb12f70f8db87f02da0raftias } else { 257113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkColorSpaceTransferFn fn; 258113d05fa7b26797e3e468f78ea94a214476b63fbRavi Mistry SkAssertResult(gamma_to_parametric(&fn, gammas, channel)); 25973e627074839bc00569117235eb4e7d4fc3cc39fBrian Osman this->addTransferFn(fn.invert(), channel); 260975245407a16dba58ee42cb12f70f8db87f02da0raftias } 2612563601fc2b0505619f905f86bd249ae630197ccraftias } 2622563601fc2b0505619f905f86bd249ae630197ccraftias } 263975245407a16dba58ee42cb12f70f8db87f02da0raftias break; 264db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett } 265db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett} 266db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett 2675476128f0a88217414f05e6a7ee518cdb411d026raftiasvoid SkColorSpaceXform_A2B::addTransferFn(const SkColorSpaceTransferFn& fn, int channelIndex) { 2685476128f0a88217414f05e6a7ee518cdb411d026raftias switch (channelIndex) { 2695476128f0a88217414f05e6a7ee518cdb411d026raftias case 0: 270de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_r, this->copy(fn)); 271db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett break; 2725476128f0a88217414f05e6a7ee518cdb411d026raftias case 1: 273de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_g, this->copy(fn)); 274db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett break; 2755476128f0a88217414f05e6a7ee518cdb411d026raftias case 2: 276de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_b, this->copy(fn)); 277db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett break; 2785476128f0a88217414f05e6a7ee518cdb411d026raftias case 3: 279de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::parametric_a, this->copy(fn)); 2805476128f0a88217414f05e6a7ee518cdb411d026raftias break; 281db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett default: 282db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett SkASSERT(false); 2832563601fc2b0505619f905f86bd249ae630197ccraftias } 2842563601fc2b0505619f905f86bd249ae630197ccraftias} 2852563601fc2b0505619f905f86bd249ae630197ccraftias 2869d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett/** 2879d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett * |fn| is an in-out parameter. If the table is too small to perform reasonable table-lookups 2889d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett * without interpolation, we will build a bigger table. 2899d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett * 2909d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett * This returns false if we use the original table, meaning we do nothing here but need to keep 2919d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett * a reference to the original table. This returns true if we build a new table and the original 2929d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett * table can be discarded. 2939d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett */ 2949d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarettbool SkColorSpaceXform_A2B::buildTableFn(SkTableTransferFn* fn) { 2959d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett // Arbitrary, but seems like a reasonable guess. 2969d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett static constexpr int kMinTableSize = 256; 2979d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett 2989d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett if (fn->fSize >= kMinTableSize) { 2999d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett return false; 3009d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett } 3019d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett 3029d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett float* outTable = fAlloc.makeArray<float>(kMinTableSize); 3039d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett float step = 1.0f / (kMinTableSize - 1); 3049d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett for (int i = 0; i < kMinTableSize; i++) { 3059d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett outTable[i] = interp_lut(i * step, fn->fData, fn->fSize); 3069d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett } 3079d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett 3089d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett fn->fData = outTable; 3099d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett fn->fSize = kMinTableSize; 3109d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett return true; 3119d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett} 3129d2d7bfc920772b5e8ec31eae8e3ec88704e943fMatt Sarett 3135476128f0a88217414f05e6a7ee518cdb411d026raftiasvoid SkColorSpaceXform_A2B::addTableFn(const SkTableTransferFn& fn, int channelIndex) { 3145476128f0a88217414f05e6a7ee518cdb411d026raftias switch (channelIndex) { 3155476128f0a88217414f05e6a7ee518cdb411d026raftias case 0: 316de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::table_r, this->copy(fn)); 3172563601fc2b0505619f905f86bd249ae630197ccraftias break; 3185476128f0a88217414f05e6a7ee518cdb411d026raftias case 1: 319de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::table_g, this->copy(fn)); 3202563601fc2b0505619f905f86bd249ae630197ccraftias break; 3215476128f0a88217414f05e6a7ee518cdb411d026raftias case 2: 322de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::table_b, this->copy(fn)); 3232563601fc2b0505619f905f86bd249ae630197ccraftias break; 3245476128f0a88217414f05e6a7ee518cdb411d026raftias case 3: 325de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::table_a, this->copy(fn)); 3265476128f0a88217414f05e6a7ee518cdb411d026raftias break; 3272563601fc2b0505619f905f86bd249ae630197ccraftias default: 3282563601fc2b0505619f905f86bd249ae630197ccraftias SkASSERT(false); 3292563601fc2b0505619f905f86bd249ae630197ccraftias } 3302563601fc2b0505619f905f86bd249ae630197ccraftias} 3312563601fc2b0505619f905f86bd249ae630197ccraftias 332de1cad99b353bad080a04ccfde955a8f3c0af295Mike Kleinvoid SkColorSpaceXform_A2B::addMatrix(const SkMatrix44& m44) { 333de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein auto m = fAlloc.makeArray<float>(12); 334de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein m[0] = m44.get(0,0); m[ 1] = m44.get(1,0); m[ 2] = m44.get(2,0); 335de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein m[3] = m44.get(0,1); m[ 4] = m44.get(1,1); m[ 5] = m44.get(2,1); 336de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein m[6] = m44.get(0,2); m[ 7] = m44.get(1,2); m[ 8] = m44.get(2,2); 337de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein m[9] = m44.get(0,3); m[10] = m44.get(1,3); m[11] = m44.get(2,3); 338de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein 339de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein SkASSERT(m44.get(3,0) == 0.0f); 340de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein SkASSERT(m44.get(3,1) == 0.0f); 341de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein SkASSERT(m44.get(3,2) == 0.0f); 342de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein SkASSERT(m44.get(3,3) == 1.0f); 343de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein 344de1cad99b353bad080a04ccfde955a8f3c0af295Mike Klein fElementsPipeline.append(SkRasterPipeline::matrix_3x4, m); 3452563601fc2b0505619f905f86bd249ae630197ccraftias fElementsPipeline.append(SkRasterPipeline::clamp_0); 346db4d406e7e311113e56663b1f2286c18adcee985Matt Sarett fElementsPipeline.append(SkRasterPipeline::clamp_1); 3472563601fc2b0505619f905f86bd249ae630197ccraftias} 348