Google Apps Script Color Space Conversions.

In Google Apps Script Color functions I introduced a bunch of functions to manipulate various color spaces from GAS. This was a migration from the same thing in VBA.

I extended this to include additional color spaces such as Hsl, hsv, Lch, Lab amongst others in VBA from which you can generate a selection of color palettes.  Here’s the Google Apps Script version. This extensive library of color conversions are available in this shared GAS library. I must admit I found the math a little trickier in the GAS version.

5 color pallete

Here’s some random colors and their 5 step palettes generated in GAS according to hue, lightness and saturation using the HSL and CIE-Lch color spaces.

 

Here’s the code to create these random palettes. You can find the whole thing in this workbook which also uses this shared GAS library
function getSomePalettes() {

    // these are the models& properties we are going to process
    var models = ["lch", "hsl"];
    var prop = ["hue", "lightness", "saturation"];
    var ncells = 9,
        swatchSize = 5,
        rowHeight = 20,
        columnWidth = 16,
        spaceHeight = rowHeight / 5,
        spaceWidth = columnWidth / 5;

    // get the data, colors and font colors for this sheet
    var sheetName = "palette";
    var cache = mcpher.sheetCache(sheetName).extend((arrayLength(models) + 1) * ncells + 1, (arrayLength(prop) + 1) * swatchSize + 1);
    var sheet = cache.xParent.getSheetObj(sheetName);
    var cacheFill = mcpher.sheetCache(sheet, "getBackgroundColors")

    var cacheColor = mcpher.sheetCache(sheet, "getFontColors");
    var r = mcpher.firstcell(cache.xWsRange);

    //--------create some random colors to test against, and format worksheet
    for (var n = 1; n <= ncells; n++) {
        var p = mcpher.makeColorProps(
            Math.floor((mcpher.VBCOLORS.vbWhite - mcpher.VBCOLORS.vbBlack + 1) * mcpher.Rnd() + mcpher.VBCOLORS.vbBlack));
        // reuse existing rather than random
        ///var p = mcpher.makeColorProps(mcpher.htmlHexToRgb(cache.getValue((n-1)*4+2,1)));
        var w = mcpher.vResize(mcpher.vOffset(r, (n - 1) * (2 + arrayLength(models)) + 1, 0), arrayLength(models) + 1);
        cacheColor.setRepeatValue(mcpher.rgbToHTMLHex(p.textColor), w);
        cacheFill.setRepeatValue(p.htmlHex, w);
        cache.setRepeatValue(mcpher.Empty(), w);
        cache.setRowHeight(rowHeight, w);
        cache.setColumnWidth(columnWidth, w);
        
        // name the columns
        for (var k = 0; k < models.length; k++)
            cache.setRepeatValue(models[k], mcpher.vResize(mcpher.vOffset(w, k + 1), 1, 1));

        // border around
        mcpher.borderAround(mcpher.vResize(mcpher.vOffset(w, 1), arrayLength(models), 1));

        // add a break line with reference color
        var v = mcpher.vResize(w, 1, arrayLength(prop) * (swatchSize + 1) + 1);
        cacheFill.setRepeatValue(p.htmlHex, v);
        cacheColor.setRepeatValue(mcpher.rgbToHTMLHex(p.textColor), v);
        cache.setRepeatValue(p.htmlHex, mcpher.vResize(v, undefined, 1));
        cache.setColumnWidth(columnWidth * 3, v);
        mcpher.borderAround(v);

        // add column breaks between props and name them
        for (var k = 0; k < prop.length; k++) {
            var v = mcpher.vResize(mcpher.vOffset(w, 0, 1 + (swatchSize + 1) * k), undefined, 1);
            cache.setColumnWidth(spaceWidth, v);
            cache.setRepeatValue(prop[k], mcpher.vResize(mcpher.vOffset(v, undefined, 1), 1, 1));
        }

        // add a break line after

        var v = mcpher.vResize(mcpher.vOffset(w, arrayLength(models) + 1), 1);
        cache.setRowHeight(spaceHeight, v);
        cacheFill.setRepeatValue(mcpher.rgbToHTMLHex(mcpher.VBCOLORS.vbWhite), v);
        cacheColor.setRepeatValue(mcpher.rgbToHTMLHex(mcpher.VBCOLORS.vbBlack), v);
        cache.setRepeatValue(mcpher.Empty(), v);
    }
    
    // create various palettes
    for (var k = 0; k < arrayLength(models); k++) {
        for (var j = 0; j < arrayLength(prop); j++) {
            for (var n = 1; n <= ncells; n++) {
                var rowOff = 1 + (n - 1) * (2 + arrayLength(models));
                var colOff = 1 + (1 + swatchSize) * (j);
                var w = mcpher.vOffset(r, rowOff, colOff);
                var a = makeAPalette(mcpher.htmlHexToRgb(cacheFill.getValue(w.getRow(), w.getColumn())), models[k],
                    prop[j], swatchSize, prop[j] == "lightness");

                var v = mcpher.vOffset(w, k+ 1);
                cacheFill.setRepeatValue(mcpher.VBCOLORS.vbWhite, v);
                for (var i = 0; i < arrayLength(a); i++) {
                    cacheFill.setRepeatValue(a[i].htmlHex, mcpher.vOffset(v,undefined, i+1));
                    // the code
                    //cache.setRepeatValue(a[i].htmlHex,mcpher.vOffset(v,undefined, i+1));
                }
                mcpher.borderAround(mcpher.vResize(mcpher.vOffset(v, undefined, 1), undefined, swatchSize));
            }
        }
    }

    // write everything out
    cacheColor.close();
    cacheFill.close();
    cache.close();
}

function arrayLength(a) {
    return a.length;
}

function makeAPalette(rgbColor, optModel, optiType, optHowMany, optDescending) {

    var model = mcpher.fixOptional(optModel, "lch");
    var iType = mcpher.fixOptional(optiType, "hue");
    var howMany = mcpher.fixOptional(optHowMany, 5);
    var ph,ps,pl,pf,h,pv,a=[],g;
    

    if (model == "lch") {
        ph = "hStar", ps = "cStar", pl = "LStar", pf = mcpher.lchToRgb;
    }
    else {
        ph = "hue", ps = "saturation", pl = "lightness", pf = mcpher.hslToRgb;
    }
    
    var top = (iType == "hue" ? 360 : 100);
    g = top / howMany;
    pv = (iType == "hue" ? ph : (iType == "saturation" ? ps : pl));
    var p = mcpher.makeColorProps(rgbColor); 
    h = p[pv];
    
    // do a number of equally spaced props and store in array
    for (var i =0;i < howMany ;i++ ) {
      if (h > top) h -= top;
      // store new value
      p[pv] =h;
      // convert back to rgb and redo
      p = mcpher.makeColorProps(pf(p));
      a.push(p);
      // make a new copy
      p = mcpher.makeColorProps(p.rgb);
      h += g;
    }

    return mcpher.sortColorProp (a, pv, optDescending);
    
}

For more stuff like this, see from VBA to Google Apps Script

About brucemcp 225 Articles
I am a Google Developer Expert and decided to investigate Google Apps Script in my spare time. The more I investigated the more content I created so this site is extremely rich. Now, in 2019, a lot of things have disappeared or don’t work anymore due to Google having retired some stuff. I am however leaving things as is and where I came across some deprecated stuff, I have indicated it. I decided to write a book about it and to also create videos to teach developers who want to learn Google Apps Script. If you find the material contained in this site useful, you can support me by buying my books and or videos.