Skip to main content
Todd_Morgan
Legend
September 14, 2023
Open for Voting

SCALE ARTBOARD AND CONTENT

  • September 14, 2023
  • 24 replies
  • 3158 views

Please get this into the next update.... or is there a script out there available??

24 replies

Stephen Marsh
Community Expert
Community Expert
October 24, 2024

As mentioned, here is a first draft of a new script for resizing artboards. It uses a different method than my previous script, using a script interface rather than an interactive free transform:

 

Currently, it is only for use with a single artboard selected at a time.

 

It has not had exhaustive testing on complex artboards. Work on duplicates of any important files for safety. As resizing artboards requires canvas resizing, the script uses the Trim command to force trim to transparency, and may also benefit with saving before or after resizing an artboard to force the "shrinkwrap on save" to kick in, as the next artboard resize may not work correctly. Your insights from testing may be invaluable for getting this to work. I don't use artboards very often and I hate scripting them.

 

Use with caution!

 

/*
Resize Artboard and Content scriptUI GUI.jsx
v1.0 - 24th October, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-ideas/scale-artboard-and-content/idi-p/14084466
//////////
Notes:
* The artboard and content will both be resized
* Layer content extending outside of the artboard bounds will also be resized
* Layer styles are transformed when the proportional resize is selected
//////////
*/

// Check the active layer
if (!isLayerSet()) {
    alert("Please select an artboard before running this script.");
}

// Artboard bounds - by Rune L-H
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var artBoardRect = executeActionGet(ref).getObjectValue(stringIDToTypeID("artboard")).getObjectValue(stringIDToTypeID("artboardRect"));
var artBoardRectWidth = new UnitValue(artBoardRect.getDouble(stringIDToTypeID("right")) - artBoardRect.getDouble(stringIDToTypeID("left")), "px");
var artBoardRectHeight = new UnitValue(artBoardRect.getDouble(stringIDToTypeID("bottom")) - artBoardRect.getDouble(stringIDToTypeID("top")), "px");
artBoardRectWidth = parseInt(artBoardRectWidth);
artBoardRectHeight = parseInt(artBoardRectHeight);

// Create the main dialog window
var dlg = new Window("dialog", "Resize Artboard & Content (v1.0)");
dlg.orientation = "column";
dlg.alignChildren = "fill";

// Create resize options panel
var resizePanel = dlg.add("panel", undefined, "Resize Options");
resizePanel.orientation = "column";
resizePanel.alignChildren = "left";
resizePanel.margins = 20;

resizePanel.add("statictext", undefined, "Original Artboard Dimensions: " + artBoardRectWidth + " x " + artBoardRectHeight + " px");

// Add radio buttons
var constrained = resizePanel.add("radiobutton", undefined, "Proportional Resize");
var unconstrained = resizePanel.add("radiobutton", undefined, "Unconstrained Resize");
constrained.value = true; // Set proportional as default

// Create groups for input fields
var constrainedGroup = resizePanel.add("group");
constrainedGroup.orientation = "row";
constrainedGroup.add("statictext", undefined, "New Width (px):");
var constrainedWidth = constrainedGroup.add("editnumber", undefined, artBoardRectWidth);
constrainedWidth.characters = 6;

var unconstrainedGroup = resizePanel.add("group");
unconstrainedGroup.orientation = "row";
unconstrainedGroup.add("statictext", undefined, "New Width (px):");
var unconstrainedWidth = unconstrainedGroup.add("editnumber", undefined, artBoardRectWidth);
unconstrainedWidth.characters = 6;
unconstrainedGroup.add("statictext", undefined, "New Height (px):");
var unconstrainedHeight = unconstrainedGroup.add("editnumber", undefined, artBoardRectHeight);
unconstrainedHeight.characters = 6;

// Add dropdown for interpolation type
resizePanel.add("statictext", undefined, "Interpolation Method:");
var interTypeDropdown = resizePanel.add("dropdownlist", undefined, ["Bilinear", "Bicubic", "Bicubic Smoother", "Bicubic Sharper", "Preserve Details", "Nearest Neighbor"]);
interTypeDropdown.selection = 1; // Default to "Bicubic"

// Create button group
var buttonGroup = dlg.add("group");
buttonGroup.orientation = "row";
buttonGroup.alignment = "right";
var cancelButton = buttonGroup.add("button", undefined, "Cancel");
var okButton = buttonGroup.add("button", undefined, "OK");

// Initial state of input fields
unconstrainedGroup.enabled = false;

// Add event listeners for radio buttons
constrained.onClick = function () {
    constrainedGroup.enabled = true;
    unconstrainedGroup.enabled = false;
}

unconstrained.onClick = function () {
    constrainedGroup.enabled = false;
    unconstrainedGroup.enabled = true;
}

// Handle button clicks
cancelButton.onClick = function () {
    dlg.close();
}

okButton.onClick = function () {

    try {

        function main() {

            var savedRuler = app.preferences.rulerUnits;
            app.preferences.rulerUnits = Units.PIXELS;

            // Convert the selected layer to an embedded smart object
            executeAction(stringIDToTypeID("newPlacedLayer"), undefined, DialogModes.NO);

            // Edit the selected smart object layer
            executeAction(stringIDToTypeID("placedLayerEditContents"), new ActionDescriptor(), DialogModes.NO);

            // Trim to transparency
            app.activeDocument.trim(TrimType.TRANSPARENT);

            // Get the interpolation type
            var interType = getInterpolationType(interTypeDropdown.selection.index);
            if (constrained.value) {
                constrainedResize(parseInt(constrainedWidth.text), interType);
            } else {
                unconstrainedResize(parseInt(unconstrainedWidth.text), parseInt(unconstrainedHeight.text), interType);
            }

            // Close and save
            app.activeDocument.close(SaveOptions.SAVECHANGES);

            // Convert the smart object back to layers
            executeAction(stringIDToTypeID("placedLayerConvertToLayers"), undefined, DialogModes.NO);

            // Unlock the artboard nesting
            try {
                unlockLayer();
            } catch (e) {
                alert(e);
            }

            // Trim to transparency
            app.activeDocument.trim(TrimType.TRANSPARENT);

            // Save the document for the artboard "shrinkwrap on save" canvas resizing
            //app.activeDocument.save();
            executeAction(stringIDToTypeID("save"), undefined, DialogModes.NO);

            app.preferences.rulerUnits = savedRuler;

            dlg.close();
        }

        app.activeDocument.suspendHistory("Resize Artboard & Content", "main()");

    } catch (e) {
        alert("Error: " + e);
    }
}

/*
// Check if the document has unsaved changes and prompt to save
if (!app.activeDocument.saved) {
    var saveConfirm = confirm("The doc needs to be saved to ensure correct artboard resizing... Would you like to save it now?");
    if (saveConfirm) {
        // Save the document for the artboard "shrinkwrap on save" canvas resizing
        activeDocument.save();
    }
}
*/

// Trim to transparency
app.activeDocument.trim(TrimType.TRANSPARENT);

dlg.show();


///// Functions /////

function isLayerSet() {
    try {
        // Create a reference to the active layer
        var ref = new ActionReference();
        ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
        // Get the layer info
        var desc = executeActionGet(ref);
        // Check if the layer is a layer set (group)
        var layerKind = desc.getInteger(stringIDToTypeID("layerKind"));
        // LayerKind.LAYERSET = 7
        return layerKind === 7;
    } catch (e) {
        alert("Error checking layer type: " + e);
        return false;
    }
}

// Constrained proportions resize function
function constrainedResize(constrainedWidth, interType) {
    var idimageSize = stringIDToTypeID("imageSize");
    var desc384 = new ActionDescriptor();
    var idwidth = stringIDToTypeID("width");
    var idpixelsUnit = stringIDToTypeID("pixelsUnit");
    desc384.putUnitDouble(idwidth, idpixelsUnit, constrainedWidth);
    var idscaleStyles = stringIDToTypeID("scaleStyles");
    desc384.putBoolean(idscaleStyles, true);
    var idconstrainProportions = stringIDToTypeID("constrainProportions");
    desc384.putBoolean(idconstrainProportions, true);
    var idinterpolationType = stringIDToTypeID("interpolationType");
    desc384.putEnumerated(idinterpolationType, idinterpolationType, interType);
    executeAction(idimageSize, desc384, DialogModes.NO);
}

// Unconstrained proportions resize function
function unconstrainedResize(unconstrainedWidth, unconstrainedHeight, interType) {
    var idimageSize = stringIDToTypeID("imageSize");
    var desc398 = new ActionDescriptor();
    var idwidth = stringIDToTypeID("width");
    var idpixelsUnit = stringIDToTypeID("pixelsUnit");
    desc398.putUnitDouble(idwidth, idpixelsUnit, unconstrainedWidth);
    var idheight = stringIDToTypeID("height");
    desc398.putUnitDouble(idheight, idpixelsUnit, unconstrainedHeight);
    var idinterpolationType = stringIDToTypeID("interpolationType");
    desc398.putEnumerated(idinterpolationType, idinterpolationType, interType);
    executeAction(idimageSize, desc398, DialogModes.NO);
}

function unlockLayer() {
    var desc = new ActionDescriptor();
    var ref = new ActionReference();
    ref.putEnumerated(
        stringIDToTypeID("layer"),
        stringIDToTypeID("ordinal"),
        stringIDToTypeID("targetEnum")
    );
    desc.putReference(stringIDToTypeID("null"), ref);
    var lockingDesc = new ActionDescriptor();
    lockingDesc.putBoolean(stringIDToTypeID("protectNone"), true);
    desc.putObject(
        stringIDToTypeID("layerLocking"),
        stringIDToTypeID("layerLocking"),
        lockingDesc
    );
    executeAction(stringIDToTypeID("applyLocking"), desc, DialogModes.NO);
}

// Function to map dropdown selection to stringIDToTypeID for interpolation
function getInterpolationType(index) {
    switch (index) {
        case 0: return stringIDToTypeID("bilinear");
        case 1: return stringIDToTypeID("bicubic");
        case 2: return stringIDToTypeID("bicubicSmoother");
        case 3: return stringIDToTypeID("bicubicSharper");
        case 4: return stringIDToTypeID("preserveDetailsUpscale");
        case 5: return stringIDToTypeID("nearestNeighbor");
        default: return stringIDToTypeID("bicubic");
    }
}

 

 

Stephen Marsh
Community Expert
Community Expert
October 23, 2024

@Todd_Morgan 

 

Baby steps, once It is working for one artboard, the script can then be modified to cycle over all artboards.

 

P.S. Why not keep each artboard at 3000 px and resize the output to 2000 px when using Export As?

Todd_Morgan
Legend
October 23, 2024

OK. I wish this was already part of PSD as I have several PSB files with each 30 artboards that need resizing from 3000x to 2000x scaled content... lot's of work and I don't have any coding skills

Stephen Marsh
Community Expert
Community Expert
October 23, 2024

@Todd_Morgan 

 

I'll test for that, the script was only ever intended for use on a single artboard at one time.


I'm working on a new version that handles content outside of the artboard, again this is only intended for one artboard at a time.

Todd_Morgan
Legend
October 23, 2024

OK so the script works if I have one artboard open and all layers selected... but if I have several artboards selected (layers are twirled closed) then I get that error...

Todd_Morgan
Legend
October 23, 2024

still getting error - I am using the latest version of PSD

Stephen Marsh
Community Expert
Community Expert
October 22, 2024

@Todd_Morgan 

 

I just tested in Photoshop 2021 and 2024 and the script works as expected without error.

 

Looking at line 88, I'm not sure why you would get that error.

 

What version are you using?

 

You could try changing line 88 from:

 

var tempGroup = sourceGroup.layerSets.add();

 

To this:

 

var tempGroup = app.activeDocument.activeLayer.layerSets.add();

 

Todd_Morgan
Legend
October 22, 2024

 i get this when running script

 

Participating Frequently
October 4, 2023

yes you understood me completly, unfortently i usually have extended content in my artboards

but i love that someone trying to do this kind of script and i hope adobe will notice and know that creating auto adjustment for artboards is a must since i think alot of people need to create banners in a lot of different sizes and auto layout/sizing is importnat for this kind of work.

so again thank u

Stephen Marsh
Community Expert
Community Expert
October 3, 2023
quote

thanks for that, i tried using it and set the free transform to scle 30% and it did scale all the layers but it didnt scale the artboard, it actully made it larger than before, since the backgroung layer it much larger than the artboard.


By @Lital5E82 

 

 

Thank you for the feedback!

 

In my tests, having a true Background layer shouldn't matter, as the artboard size and content is what is being resized.

 

So do you mean that you have content in the artboard that extends beyond the visible bounds of the artboard? That would be problematic for resizing with the current coding, as that wasn't expected/taken into account.

 

I have updated the notes to include this limitation. At the moment I can't think of an easy work-around without a major rewrite of the code.