Skip to main content
Participating Frequently
September 30, 2024
Answered

CMYK table with vary by value k

  • September 30, 2024
  • 2 replies
  • 1153 views

Hello

Could some help me with creating table and change CMYK values by k value.

Or know where can I find such a script.

 

So i have base CMYK value in center. I want to add values to separate chanells.

example: center 50/50/50/50 , k value =2

to the right will be 50/50/52/50; 50/50/54/50; 50/50/56/50; 50/50/58/50; 50/50/60/50

to the left top: 52/52/50/50/50; 54/54/50/50; 56/56/50/50; 58/58/50/50; 60/60/50/50


Correct answer m1b

Hi @grafik2_5837, I've written a quick script to do this. Give it a try and let me know if it works for your case. I've configured the `adjustCMYKColor` function to match your logic. You can set the `cellCount`, `gap` and `colorStep` values.

- Mark

 

 

/**
 * @file Make Color Grid CMYK.js
 *
 * Usage:
 *   1. Draw a square in Illustrator, the size you want the color grid.
 *   2. Color the square (in CMYK for this example).
 *   3. Run script.
 *
 * Draws a grid squares over the selected square, with the original color
 * in the center, and with colors radiating out with modified values.
 *
 * Color values are modified by the `colorFunction`, eg. the example `increaseColorValues`.
 *
 * @author m1b
 * @version 2025-05-30
 * @discussion https://community.adobe.com/t5/illustrator-discussions/cmyk-table-with-vary-by-value-k/m-p/14888873
 */
(function () {

    var settings = {
        autoSteps: true,
        cellCount: 5,
        gap: 2,
        colorStep: 2,
        showUI: true,
    };

    var doc = app.activeDocument,
        item = doc.selection[0];

    if (
        !item
        || !item.hasOwnProperty('fillColor')
        || !item.hasOwnProperty('geometricBounds')
    )
        return alert('Please select a colored square and try again.');

    settings.centralColor = item.fillColor;

    if (settings.showUI) {

        var result = ui(settings);

        if (2 === result)
            // user cancelled
            return;

    }

    // calculate the step for each channel (if auto) or use the settings value for all channels
    var cyanStep = settings.autoSteps ? (100 - settings.centralColor.cyan) / settings.cellCount : settings.colorStep;
    var magentaStep = settings.autoSteps ? (100 - settings.centralColor.magenta) / settings.cellCount : settings.colorStep;
    var yellowStep = settings.autoSteps ? (100 - settings.centralColor.yellow) / settings.cellCount : settings.colorStep;
    var blackStep = settings.autoSteps ? (100 - settings.centralColor.black) / settings.cellCount : settings.colorStep;

    // make the color grid!
    makeColorGrid(doc, item, settings.cellCount, settings.gap, increaseColorValues);
    
    // or here is an example of using a custom `drawCellFunction`:
    // makeColorGrid(doc, item, settings.cellCount, settings.gap, increaseColorValues, drawCellWithDarkerCells);

    // ------------------- end of demo script ------------------------------------

    /**
     * Use as a `colorFunction` parameter with `makeColorGrid`.
     * 
     * Returns a new color, by increasing the color values
     * as the grid location is further from the center.
     * @param {Number} x - the x coordinate of the grid.
     * @param {Number} y - the y coordinate of the grid.
     * @returns {Color}
     */
    function increaseColorValues(x, y) {

        var cyan = settings.centralColor.cyan,
            magenta = settings.centralColor.magenta,
            yellow = settings.centralColor.yellow,
            black = settings.centralColor.black;

        if (x < 0)
            magenta -= x * magentaStep;
        else if (x > 0)
            yellow += x * yellowStep;

        if (y < 0)
            cyan -= y * cyanStep;
        else if (y > 0)
            black += y * blackStep;

        return makeColor([
            Math.min(cyan, 100),
            Math.min(magenta, 100),
            Math.min(yellow, 100),
            Math.min(black, 100),
        ]);

    };

    /**
     * Use as a `drawCellFunction` parameter with `makeColorGrid`.
     * 
     * Draws a color cell with smaller, darker, cells embedded.
     * @param {Document} doc - an Illustrator Document.
     * @param {Array<Number>} rect - [L, T, W, H].
     * @param {Color} color - the color of the cell.
     * @param {*} container - the location (parent) of the drawn cell.
     * @returns {GroupItem} - the main cell grouped with the small cells.
     */
    function drawCellWithDarkerCells(doc, rect, color, container) {

        // keep the cells in a group
        var group = container.groupItems.add();

        // draw the main cell
        drawRectangle(doc, rect, undefined, group, { fillColor: color });

        // darker colors
        var darker = [
            makeColor([color.cyan, color.magenta, color.yellow, Math.min(color.black + 25, 100)]),
            makeColor([color.cyan, color.magenta, color.yellow, Math.min(color.black + 50, 100)]),
            makeColor([color.cyan, color.magenta, color.yellow, Math.min(color.black + 75, 100)]),
        ];

        var smallCellSize = rect[2] / darker.length;

        // draw the smaller cells
        for (var i = 0, b; i < darker.length; i++) {

            b = [
                rect[0] + smallCellSize * i,
                rect[1] + rect[2] - smallCellSize,
                smallCellSize,
                smallCellSize,
            ];

            drawRectangle(doc, b, undefined, group, { fillColor: darker[i] });

        }

        return group;

    };


})();

/**
 * Divides a square into smaller squares
 * such that there will be a central square,
 * and `stepCount` squares along x and y axes.
 * The squares can be colored using a provided
 * function.
 * @author m1b
 * @version 2024-10-01
 * @param {Document} doc - an Illustrator Document.
 * @param {PageItem} item - a page item used for position and size (will be removed).
 * @param {Number} cellCount - the number of squares out from the central square.
 * @param {Number} [gap] - the gap between squares, in points (default: 0).
 * @param {Function} colorFunction - a function that, given cell coordinates, returns a color.
 * @param {Function} drawCellFunction - a function that, given cell bounds and color, draws the cell.
 */
function makeColorGrid(doc, item, cellCount, gap, colorFunction, drawCellFunction) {

    gap = gap || 0;
    drawCellFunction = drawCellFunction || basicDrawCellFunction;

    // calculate size of everything
    var center = centerOfBounds(item.geometricBounds),
        width = item.geometricBounds[2] - item.geometricBounds[0],
        allSteps = (cellCount * 2) + 1,
        cellSize = (width - (gap * (allSteps - 1))) / allSteps;

    // offset to the corner of the cell
    center[0] -= cellSize / 2;
    center[1] -= cellSize / 2;

    // draw the grid
    for (var u = -cellCount, cellRect, x, y, c; u <= cellCount; u++) {

        for (var v = -cellCount; v <= cellCount; v++) {

            x = center[0] + (u * (cellSize + gap));
            y = center[1] + (v * (cellSize + gap));
            cellRect = [x, y, cellSize, cellSize];
            c = colorFunction(u, v);

            drawCellFunction(doc, cellRect, c, item.parent);

        }

    }

    // remove the original square
    item.remove();

    /**
     * Basic function to draw the cell.
     * @param {Document} doc
     * @param {Array<Number>} cellRect
     * @param {Color} color
     * @param {Document|Layer|GroupItem} container
     */
    function basicDrawCellFunction(doc, cellRect, color, container) {
        return drawRectangle(doc, cellRect, undefined, container, { fillColor: color });
    };

};

/**
 * Draws a rectangle in the container.
 * Takes Large Scale Documents into account.
 * @author m1b
 * @version 2024-09-26
 * @param {Document} doc - an Illustrator document.
 * @param {Array<Number>} rect - the rectangle dimensions [left, top, width, height].
 * @param {Number} [unitFactor] - eg. 72 to convert to inches. All values will be scaled by this (default: 1).
 * @param {Document|Layer|GroupItem} [container] - an Illustrator page item container (default: doc).
 * @param {Object} [props] - properties to assign to the rectangle (default: none).
 * @return {PathItem}
 */
function drawRectangle(doc, rect, unitFactor, container, properties) {

    properties = properties || {};
    unitFactor = unitFactor || 1;
    container = container || doc;

    var sf = 1 / doc.scaleFactor * unitFactor;
    var rectangle = container.pathItems.rectangle(-rect[1] * sf, rect[0] * sf, rect[2] * sf, rect[3] * sf); // T,L,W,H

    // defaults
    rectangle.filled = true;
    rectangle.stroked = false;

    // apply properties
    for (var key in properties)
        if (
            properties.hasOwnProperty(key)
            && undefined != properties[key]
        )
            rectangle[key] = properties[key];

    return rectangle;

};

/**
 * Returns point at center of bounds.
 * Works with Illustrator or Indesign bounds.
 * @author m1b
 * @version 2024-09-14
 * @param {Array} bounds - a bounds array.
 * @returns {Array} - point array [x, y].
 */
function centerOfBounds(bounds) {

    return [
        bounds[0] + (bounds[2] - bounds[0]) / 2,
        -bounds[1] - (bounds[3] - bounds[1]) / 2
    ];

};


/**
 * Makes a color from a array of color values;
 * @author m1b
 * @version 2022-10-03
 * @param {Array<Number>} breakdown - the color values.
 * @returns {GrayColor|RGBColor|CMYKColor}
 */
function makeColor(breakdown) {

    var c;

    if (breakdown.length == 1) {

        c = new GrayColor();
        c.gray = Math.min(breakdown[0], 100);

    }

    else if (breakdown.length == 3) {

        c = new RGBColor();
        c.red = Math.min(breakdown[0], 255);
        c.green = Math.min(breakdown[1], 255);
        c.blue = Math.min(breakdown[2], 255);

    }

    else if (breakdown.length == 4) {

        c = new CMYKColor();
        c.cyan = Math.min(breakdown[0], 100);
        c.magenta = Math.min(breakdown[1], 100);
        c.yellow = Math.min(breakdown[2], 100);
        c.black = Math.min(breakdown[3], 100);

    }

    return c;

};

/**
 * Rounds a number to `places` decimal places.
 * @author m1b
 * @version 2022-08-02
 * @param {Number} num - the Number to round.
 * @param {Number} [places] - round to this many decimal places.
 * @return {Number} - the rounded Number.
 */
function round(num, places) {

    places = Math.pow(10, places || 1);
    return Math.round(num * places) / places;

};

/**
 * UI for "Make Color Grid".
 * @param {Object} settings - an object accessed by the UI.
 * @returns {Number} - 1 == success, 2 == user cancelled.
 */
function ui(settings) {

    var w = new Window("dialog", 'Make Color Grid'),
        columns = w.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","top"], margins:[0,0,0,0] }'),
        column1 = columns.add('group {orientation:"column", alignment:["fill","top"], alignChildren: ["fill","top"], margins:[10,10,10,20] }'),
        column2 = columns.add('group {orientation:"column", alignment:["fill","top"], alignChildren: ["fill","top"], margins:[10,10,10,20] }'),

        colorLabel = column1.add("statictext { text: 'Central Color:', alignment: ['left','top'] }"),
        cyanGroup = column1.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0] }'),
        cyanLabel = cyanGroup.add("statictext { text: 'C', alignment: ['left','center'], preferredSize:[12,-1] }"),
        cyanField = cyanGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),
        magentaGroup = column1.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0] }'),
        magentaLabel = magentaGroup.add("statictext { text: 'M', alignment: ['left','center'], preferredSize:[12,-1] }"),
        magentaField = magentaGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),
        yellowGroup = column1.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0] }'),
        yellowLabel = yellowGroup.add("statictext { text: 'Y', alignment: ['left','center'], preferredSize:[12,-1] }"),
        yellowField = yellowGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),
        blackGroup = column1.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0] }'),
        blackLabel = blackGroup.add("statictext { text: 'K', alignment: ['left','center'], preferredSize:[12,-1] }"),
        blackField = blackGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),

        cellCountGroup = column2.add('group {orientation:"row", alignment:["right","fill"], alignChildren: ["right","center"], margins:[0,0,0,0] }'),
        cellCountLabel = cellCountGroup.add("statictext { text: 'Cell count:', justify:'right', alignment: ['right','center'], preferredSize:[95,-1] }"),
        cellCountField = cellCountGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),
        gapGroup = column2.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0] }'),
        gapLabel = gapGroup.add("statictext { text: 'Gap:', justify:'right', alignment: ['right','center'], preferredSize:[95,-1] }"),
        gapField = gapGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),
        autoStepsCheckBox = column2.add("checkBox { text: 'Auto step', value: false, alignment:['right','top'] }"),
        colorStepGroup = column2.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0], visible: true }'),
        colorStepLabel = colorStepGroup.add("statictext { text: 'Colour step %:', justify:'right', alignment: ['right','center'], preferredSize:[95,-1] }"),
        colorStepField = colorStepGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),

        buttons = w.add("Group {orientation:'row', alignment:['right','top'] }"),
        cancelButton = buttons.add('button', undefined, 'Cancel', { name: 'cancel' }),
        applyButton = buttons.add('button', undefined, 'Apply', { name: 'ok' });

    applyButton.onClick = apply;
    autoStepsCheckBox.onClick = refreshUI;

    function refreshUI() {
        colorStepGroup.visible = !autoStepsCheckBox.value;
    };

    updateUI();

    w.center();
    return w.show();

    function updateUI() {

        // update the SUI controls from settings
        cyanField.text = round(settings.centralColor.cyan, 1);
        magentaField.text = round(settings.centralColor.magenta, 1);
        yellowField.text = round(settings.centralColor.yellow, 1);
        blackField.text = round(settings.centralColor.black, 1);
        cellCountField.text = settings.cellCount;
        gapField.text = settings.gap;
        colorStepField.text = settings.colorStep;
        autoStepsCheckBox.value = settings.autoSteps;

        refreshUI();

    };

    function apply() {

        // update settings from SUI controls
        settings.centralColor.cyan = Number(cyanField.text);
        settings.centralColor.magenta = Number(magentaField.text);
        settings.centralColor.yellow = Number(yellowField.text);
        settings.centralColor.black = Number(blackField.text);
        settings.cellCount = Number(cellCountField.text);
        settings.gap = Number(gapField.text);
        settings.colorStep = Number(colorStepField.text);
        settings.autoSteps = autoStepsCheckBox.value;

        // return approval code
        w.close(1);

    };

};

Edit 2024-10-01: oops, forgot to add screenshot.

Edit 2024-10-01: added UI.

Edit 2025-05-30: fixed bad bug—a typo—that I must have introduced during the last update that ruined the whole script (it's been broken for 7 months! Sorry!) Also added a "AutoStep" settings and UI. AutoStep means it calculates the step amount for a color such that the outer grid square always is 100% of that color. Turn this off if you want exact control. I also included an example custom drawCellFunction that draws the main cell plus three smaller, darker cells over it. This example is currently commented out.

2 replies

m1b
Community Expert
m1bCommunity ExpertCorrect answer
Community Expert
October 1, 2024

Hi @grafik2_5837, I've written a quick script to do this. Give it a try and let me know if it works for your case. I've configured the `adjustCMYKColor` function to match your logic. You can set the `cellCount`, `gap` and `colorStep` values.

- Mark

 

 

/**
 * @file Make Color Grid CMYK.js
 *
 * Usage:
 *   1. Draw a square in Illustrator, the size you want the color grid.
 *   2. Color the square (in CMYK for this example).
 *   3. Run script.
 *
 * Draws a grid squares over the selected square, with the original color
 * in the center, and with colors radiating out with modified values.
 *
 * Color values are modified by the `colorFunction`, eg. the example `increaseColorValues`.
 *
 * @author m1b
 * @version 2025-05-30
 * @discussion https://community.adobe.com/t5/illustrator-discussions/cmyk-table-with-vary-by-value-k/m-p/14888873
 */
(function () {

    var settings = {
        autoSteps: true,
        cellCount: 5,
        gap: 2,
        colorStep: 2,
        showUI: true,
    };

    var doc = app.activeDocument,
        item = doc.selection[0];

    if (
        !item
        || !item.hasOwnProperty('fillColor')
        || !item.hasOwnProperty('geometricBounds')
    )
        return alert('Please select a colored square and try again.');

    settings.centralColor = item.fillColor;

    if (settings.showUI) {

        var result = ui(settings);

        if (2 === result)
            // user cancelled
            return;

    }

    // calculate the step for each channel (if auto) or use the settings value for all channels
    var cyanStep = settings.autoSteps ? (100 - settings.centralColor.cyan) / settings.cellCount : settings.colorStep;
    var magentaStep = settings.autoSteps ? (100 - settings.centralColor.magenta) / settings.cellCount : settings.colorStep;
    var yellowStep = settings.autoSteps ? (100 - settings.centralColor.yellow) / settings.cellCount : settings.colorStep;
    var blackStep = settings.autoSteps ? (100 - settings.centralColor.black) / settings.cellCount : settings.colorStep;

    // make the color grid!
    makeColorGrid(doc, item, settings.cellCount, settings.gap, increaseColorValues);
    
    // or here is an example of using a custom `drawCellFunction`:
    // makeColorGrid(doc, item, settings.cellCount, settings.gap, increaseColorValues, drawCellWithDarkerCells);

    // ------------------- end of demo script ------------------------------------

    /**
     * Use as a `colorFunction` parameter with `makeColorGrid`.
     * 
     * Returns a new color, by increasing the color values
     * as the grid location is further from the center.
     * @param {Number} x - the x coordinate of the grid.
     * @param {Number} y - the y coordinate of the grid.
     * @returns {Color}
     */
    function increaseColorValues(x, y) {

        var cyan = settings.centralColor.cyan,
            magenta = settings.centralColor.magenta,
            yellow = settings.centralColor.yellow,
            black = settings.centralColor.black;

        if (x < 0)
            magenta -= x * magentaStep;
        else if (x > 0)
            yellow += x * yellowStep;

        if (y < 0)
            cyan -= y * cyanStep;
        else if (y > 0)
            black += y * blackStep;

        return makeColor([
            Math.min(cyan, 100),
            Math.min(magenta, 100),
            Math.min(yellow, 100),
            Math.min(black, 100),
        ]);

    };

    /**
     * Use as a `drawCellFunction` parameter with `makeColorGrid`.
     * 
     * Draws a color cell with smaller, darker, cells embedded.
     * @param {Document} doc - an Illustrator Document.
     * @param {Array<Number>} rect - [L, T, W, H].
     * @param {Color} color - the color of the cell.
     * @param {*} container - the location (parent) of the drawn cell.
     * @returns {GroupItem} - the main cell grouped with the small cells.
     */
    function drawCellWithDarkerCells(doc, rect, color, container) {

        // keep the cells in a group
        var group = container.groupItems.add();

        // draw the main cell
        drawRectangle(doc, rect, undefined, group, { fillColor: color });

        // darker colors
        var darker = [
            makeColor([color.cyan, color.magenta, color.yellow, Math.min(color.black + 25, 100)]),
            makeColor([color.cyan, color.magenta, color.yellow, Math.min(color.black + 50, 100)]),
            makeColor([color.cyan, color.magenta, color.yellow, Math.min(color.black + 75, 100)]),
        ];

        var smallCellSize = rect[2] / darker.length;

        // draw the smaller cells
        for (var i = 0, b; i < darker.length; i++) {

            b = [
                rect[0] + smallCellSize * i,
                rect[1] + rect[2] - smallCellSize,
                smallCellSize,
                smallCellSize,
            ];

            drawRectangle(doc, b, undefined, group, { fillColor: darker[i] });

        }

        return group;

    };


})();

/**
 * Divides a square into smaller squares
 * such that there will be a central square,
 * and `stepCount` squares along x and y axes.
 * The squares can be colored using a provided
 * function.
 * @author m1b
 * @version 2024-10-01
 * @param {Document} doc - an Illustrator Document.
 * @param {PageItem} item - a page item used for position and size (will be removed).
 * @param {Number} cellCount - the number of squares out from the central square.
 * @param {Number} [gap] - the gap between squares, in points (default: 0).
 * @param {Function} colorFunction - a function that, given cell coordinates, returns a color.
 * @param {Function} drawCellFunction - a function that, given cell bounds and color, draws the cell.
 */
function makeColorGrid(doc, item, cellCount, gap, colorFunction, drawCellFunction) {

    gap = gap || 0;
    drawCellFunction = drawCellFunction || basicDrawCellFunction;

    // calculate size of everything
    var center = centerOfBounds(item.geometricBounds),
        width = item.geometricBounds[2] - item.geometricBounds[0],
        allSteps = (cellCount * 2) + 1,
        cellSize = (width - (gap * (allSteps - 1))) / allSteps;

    // offset to the corner of the cell
    center[0] -= cellSize / 2;
    center[1] -= cellSize / 2;

    // draw the grid
    for (var u = -cellCount, cellRect, x, y, c; u <= cellCount; u++) {

        for (var v = -cellCount; v <= cellCount; v++) {

            x = center[0] + (u * (cellSize + gap));
            y = center[1] + (v * (cellSize + gap));
            cellRect = [x, y, cellSize, cellSize];
            c = colorFunction(u, v);

            drawCellFunction(doc, cellRect, c, item.parent);

        }

    }

    // remove the original square
    item.remove();

    /**
     * Basic function to draw the cell.
     * @param {Document} doc
     * @param {Array<Number>} cellRect
     * @param {Color} color
     * @param {Document|Layer|GroupItem} container
     */
    function basicDrawCellFunction(doc, cellRect, color, container) {
        return drawRectangle(doc, cellRect, undefined, container, { fillColor: color });
    };

};

/**
 * Draws a rectangle in the container.
 * Takes Large Scale Documents into account.
 * @author m1b
 * @version 2024-09-26
 * @param {Document} doc - an Illustrator document.
 * @param {Array<Number>} rect - the rectangle dimensions [left, top, width, height].
 * @param {Number} [unitFactor] - eg. 72 to convert to inches. All values will be scaled by this (default: 1).
 * @param {Document|Layer|GroupItem} [container] - an Illustrator page item container (default: doc).
 * @param {Object} [props] - properties to assign to the rectangle (default: none).
 * @return {PathItem}
 */
function drawRectangle(doc, rect, unitFactor, container, properties) {

    properties = properties || {};
    unitFactor = unitFactor || 1;
    container = container || doc;

    var sf = 1 / doc.scaleFactor * unitFactor;
    var rectangle = container.pathItems.rectangle(-rect[1] * sf, rect[0] * sf, rect[2] * sf, rect[3] * sf); // T,L,W,H

    // defaults
    rectangle.filled = true;
    rectangle.stroked = false;

    // apply properties
    for (var key in properties)
        if (
            properties.hasOwnProperty(key)
            && undefined != properties[key]
        )
            rectangle[key] = properties[key];

    return rectangle;

};

/**
 * Returns point at center of bounds.
 * Works with Illustrator or Indesign bounds.
 * @author m1b
 * @version 2024-09-14
 * @param {Array} bounds - a bounds array.
 * @returns {Array} - point array [x, y].
 */
function centerOfBounds(bounds) {

    return [
        bounds[0] + (bounds[2] - bounds[0]) / 2,
        -bounds[1] - (bounds[3] - bounds[1]) / 2
    ];

};


/**
 * Makes a color from a array of color values;
 * @author m1b
 * @version 2022-10-03
 * @param {Array<Number>} breakdown - the color values.
 * @returns {GrayColor|RGBColor|CMYKColor}
 */
function makeColor(breakdown) {

    var c;

    if (breakdown.length == 1) {

        c = new GrayColor();
        c.gray = Math.min(breakdown[0], 100);

    }

    else if (breakdown.length == 3) {

        c = new RGBColor();
        c.red = Math.min(breakdown[0], 255);
        c.green = Math.min(breakdown[1], 255);
        c.blue = Math.min(breakdown[2], 255);

    }

    else if (breakdown.length == 4) {

        c = new CMYKColor();
        c.cyan = Math.min(breakdown[0], 100);
        c.magenta = Math.min(breakdown[1], 100);
        c.yellow = Math.min(breakdown[2], 100);
        c.black = Math.min(breakdown[3], 100);

    }

    return c;

};

/**
 * Rounds a number to `places` decimal places.
 * @author m1b
 * @version 2022-08-02
 * @param {Number} num - the Number to round.
 * @param {Number} [places] - round to this many decimal places.
 * @return {Number} - the rounded Number.
 */
function round(num, places) {

    places = Math.pow(10, places || 1);
    return Math.round(num * places) / places;

};

/**
 * UI for "Make Color Grid".
 * @param {Object} settings - an object accessed by the UI.
 * @returns {Number} - 1 == success, 2 == user cancelled.
 */
function ui(settings) {

    var w = new Window("dialog", 'Make Color Grid'),
        columns = w.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","top"], margins:[0,0,0,0] }'),
        column1 = columns.add('group {orientation:"column", alignment:["fill","top"], alignChildren: ["fill","top"], margins:[10,10,10,20] }'),
        column2 = columns.add('group {orientation:"column", alignment:["fill","top"], alignChildren: ["fill","top"], margins:[10,10,10,20] }'),

        colorLabel = column1.add("statictext { text: 'Central Color:', alignment: ['left','top'] }"),
        cyanGroup = column1.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0] }'),
        cyanLabel = cyanGroup.add("statictext { text: 'C', alignment: ['left','center'], preferredSize:[12,-1] }"),
        cyanField = cyanGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),
        magentaGroup = column1.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0] }'),
        magentaLabel = magentaGroup.add("statictext { text: 'M', alignment: ['left','center'], preferredSize:[12,-1] }"),
        magentaField = magentaGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),
        yellowGroup = column1.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0] }'),
        yellowLabel = yellowGroup.add("statictext { text: 'Y', alignment: ['left','center'], preferredSize:[12,-1] }"),
        yellowField = yellowGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),
        blackGroup = column1.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0] }'),
        blackLabel = blackGroup.add("statictext { text: 'K', alignment: ['left','center'], preferredSize:[12,-1] }"),
        blackField = blackGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),

        cellCountGroup = column2.add('group {orientation:"row", alignment:["right","fill"], alignChildren: ["right","center"], margins:[0,0,0,0] }'),
        cellCountLabel = cellCountGroup.add("statictext { text: 'Cell count:', justify:'right', alignment: ['right','center'], preferredSize:[95,-1] }"),
        cellCountField = cellCountGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),
        gapGroup = column2.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0] }'),
        gapLabel = gapGroup.add("statictext { text: 'Gap:', justify:'right', alignment: ['right','center'], preferredSize:[95,-1] }"),
        gapField = gapGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),
        autoStepsCheckBox = column2.add("checkBox { text: 'Auto step', value: false, alignment:['right','top'] }"),
        colorStepGroup = column2.add('group {orientation:"row", alignment:["fill","fill"], alignChildren: ["fill","center"], margins:[0,0,0,0], visible: true }'),
        colorStepLabel = colorStepGroup.add("statictext { text: 'Colour step %:', justify:'right', alignment: ['right','center'], preferredSize:[95,-1] }"),
        colorStepField = colorStepGroup.add("edittext { text: '', preferredSize: [50,-1], alignment:['left','center']  }"),

        buttons = w.add("Group {orientation:'row', alignment:['right','top'] }"),
        cancelButton = buttons.add('button', undefined, 'Cancel', { name: 'cancel' }),
        applyButton = buttons.add('button', undefined, 'Apply', { name: 'ok' });

    applyButton.onClick = apply;
    autoStepsCheckBox.onClick = refreshUI;

    function refreshUI() {
        colorStepGroup.visible = !autoStepsCheckBox.value;
    };

    updateUI();

    w.center();
    return w.show();

    function updateUI() {

        // update the SUI controls from settings
        cyanField.text = round(settings.centralColor.cyan, 1);
        magentaField.text = round(settings.centralColor.magenta, 1);
        yellowField.text = round(settings.centralColor.yellow, 1);
        blackField.text = round(settings.centralColor.black, 1);
        cellCountField.text = settings.cellCount;
        gapField.text = settings.gap;
        colorStepField.text = settings.colorStep;
        autoStepsCheckBox.value = settings.autoSteps;

        refreshUI();

    };

    function apply() {

        // update settings from SUI controls
        settings.centralColor.cyan = Number(cyanField.text);
        settings.centralColor.magenta = Number(magentaField.text);
        settings.centralColor.yellow = Number(yellowField.text);
        settings.centralColor.black = Number(blackField.text);
        settings.cellCount = Number(cellCountField.text);
        settings.gap = Number(gapField.text);
        settings.colorStep = Number(colorStepField.text);
        settings.autoSteps = autoStepsCheckBox.value;

        // return approval code
        w.close(1);

    };

};

Edit 2024-10-01: oops, forgot to add screenshot.

Edit 2024-10-01: added UI.

Edit 2025-05-30: fixed bad bug—a typo—that I must have introduced during the last update that ruined the whole script (it's been broken for 7 months! Sorry!) Also added a "AutoStep" settings and UI. AutoStep means it calculates the step amount for a color such that the outer grid square always is 100% of that color. Turn this off if you want exact control. I also included an example custom drawCellFunction that draws the main cell plus three smaller, darker cells over it. This example is currently commented out.

Participating Frequently
October 1, 2024

WORKS BRILLIANT !

Thank YOU !

 

Save amount ot time is our Print House.

 

I'm not imposing, but could a window appear in which we enterColorStep manually.
If not will create separate scripts

THANK YOU again !
m1b
Community Expert
Community Expert
October 1, 2024

Good to hear! I've put a UI on the script above, so try the new one.

Ton Frederiks
Community Expert
Community Expert
September 30, 2024

You can use Blends.

See page 2/3 of attached pdf. It is about spots, but you can use simple colors the same way.