You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// The reference for understanding CIECAM02 is:// http://www.springer.com/cda/content/document/cda_downloaddocument/9781441961891-c1.pdfimport*asciebasefrom"ciebase";import*asciecam02from"ciecam02";import{merge}from"mout/object";var{rgb, workspace, illuminant}=ciebase,{cfs}=ciecam02,xyz=ciebase.xyz(workspace.sRGB,illuminant.D65);varviewingConditions={whitePoint: illuminant.D65,adaptingLuminance: 40,backgroundLuminance: 20,surroundType: "average",discounting: false};// By default, 7 correlates are returned when converting from XYZ to CAM.// For the purpose of this example, we will limit ourselves to the JCh correlates.// (J is the lightness, C the chroma and h the hue.)varcam=ciecam02.cam(viewingConditions,cfs("JCh")),gamut=ciecam02.gamut(xyz,cam),{min, max}=Math;functionhexToCam(hex){returncam.fromXyz(xyz.fromRgb(rgb.fromHex(hex)));}functioncamToHex(CAM){returnrgb.toHex(xyz.toRgb(cam.toXyz(CAM)));}functioncrop(v){returnmax(0,min(1,v));}varcamSand=hexToCam("e0cda9"),// {J: 77.82, C: 16.99, h: 81.01}camOrange=merge(camSand,{C: 90}),// {J: 77.82, C: 90.00, h: 81.01}[isInside,rgbOrange]=gamut.contains(camOrange);// [false, [1.09, 0.73, -0.7]]if(!isInside){// The gamut.limit function interpolates between an inside and an outside point// and return an inside point as close as possible to the boundary.// (The gamut is the set of CAM values that maps to valid RGB coordinates.)letcamOrange1=gamut.limit(camSand,camOrange),// {J: 77.82, C: 55.23, h: 81.01}// The alternative method is to simply crop the RGB coordinatescamOrange2=cam.fromXyz(xyz.fromRgb(rgbOrange.map(crop)));// {J: 74.43, C: 67.60, h: 81.30}console.log([camOrange1,camOrange2].map(camToHex));// #ffc447 #ffb900}else{console.log(rgb.toHex(rgbOrange));}
import{map}from"mout/object";var{hq}=ciecam02,ucs=ciecam02.ucs();functionucsLimit(camIn,camOut,prec=1e-3){// UCS is based on the JMh correlatesvar[ucsIn,ucsOut]=[camIn,camOut].map(v=>ucs.fromCam(cam.fillOut(cfs("JMh"),v)));while(ucs.distance(ucsIn,ucsOut)>prec){letucsMid=lerp(ucsIn,ucsOut,0.5),[isInside,]=gamut.contains(ucs.toCam(ucsMid));if(isInside){ucsIn=ucsMid;}else{ucsOut=ucsMid;}}returncam.fillOut(map(camIn,v=>true),ucs.toCam(ucsIn));}// The hue notation is a different writting of the hue quadrant,// of the form a(p?b)? where a and b are in {R, Y, G, B} (a ≠ b)// and p is in ]0, 100[. apb = b(100-p)a, ab = a50b.functionhue(N){returnhq.toHue(hq.fromNotation(N));}vartopChroma=max(...["f00","0f0","00f"].map(v=>hexToCam(v).C)),camRed={J: 60,h: hue("R")},camYellow={J: 90,h: hue("Y")},camGreen={J: 90,h: hue("G")},camBlue={J: 70,h: hue("B")};varhexCodes=[camRed,camYellow,camGreen,camBlue].map(function(CAM){CAM=merge(CAM,{C: topChroma+1});CAM=ucsLimit(gamut.spine(CAM.J/100),CAM);returncamToHex(CAM);});