Copy link to clipboard
Copied
When i try to center two images that are smart objects with layer masks with the align buttons in photoshop it alignes it according to the whole image and not only my selection. How can i center only my selection to an other mask and not the whole images?
Copy link to clipboard
Copied
Just want to say thank you @Stephen Marsh! I've created a ton of work arounds for this very issue...wish I knew a simple solution was just a good search away.
I did notice that if you're trying to center a group that's masked it stops working as intended. Any idea on how to extend it to work with groups?
-Matt
By @Little_Matty
I have updated the previous scriptUI version to 1.1, however, I have not yet looked at aligning groups.
You could try converting each group to a smart object, aligning, and then converting the smart object back to a layer.
Copy link to clipboard
Copied
Vote to add an option to align using mask bounds instead of layer bounds here:
Copy link to clipboard
Copied
This 1.2 version should work correctly to align masked layer groups to the canvas.
/*
Align Masked Layers to Canvas Using Mask Bounds ScriptUI v1-2.jsx
Stephen Marsh
v1.0 - 24th May 2022: Initial release using a Radio Button UI
v1.1 - 7th April 2025: Revised to use Dropdown Menus
v1.2 - 7th April 2025: Revised to process layer groups (requires Photoshop 21.0)
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-center-2-layer-masks-at-selection-in-photoshop/td-p/12934857
Features: * Unlike the standard align feature, this script works correctly with layer masked content
* Works with selected standard, smart object or layer groups containing layer masks
* Single history step undo
*/
#target photoshop;
// Ensure that version 2021 or later is being used
var versionNumber = app.version.split(".");
var versionCheck = parseInt(versionNumber);
if (versionCheck < 22) {
alert("You must use Photoshop 2021 or later to run this v1.2 script!");
} else {
function main() {
(function () {
var savedRuler = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
var userInput = showDialog();
if (userInput === null) {
app.preferences.rulerUnits = savedRuler;
return;
}
if (/^(No Change|Left|Center|Right),(No Change|Top|Center|Bottom)$/.test(userInput)) {
// Align the selected layers
processSelectedLayers(userInput);
}
app.preferences.rulerUnits = savedRuler;
function showDialog() {
// Create the dialog window
var dlg = new Window("dialog", "Align Masked Layers to Canvas (v1.2)");
dlg.orientation = "column";
dlg.alignChildren = "left";
dlg.preferredSize.width = 300;
// Add the panel for the dropdowns
var dropdownGroup = dlg.add("panel", undefined, "Alignment Options");
dropdownGroup.orientation = "column";
dropdownGroup.alignChildren = "fill";
dropdownGroup.margins = [10, 15, 10, 10];
dropdownGroup.alignment = "fill";
dropdownGroup.add("statictext", undefined, "X Alignment:");
var xDropdown = dropdownGroup.add("dropdownlist", undefined, ["No Change", "Left", "Center", "Right"]);
xDropdown.selection = 0;
dropdownGroup.add("statictext", undefined, "Y Alignment:");
var yDropdown = dropdownGroup.add("dropdownlist", undefined, ["No Change", "Top", "Center", "Bottom"]);
yDropdown.selection = 0;
var btnGroup = dlg.add("group");
btnGroup.orientation = "row";
btnGroup.alignment = "right";
var cancel = btnGroup.add("button", undefined, "Cancel");
var ok = btnGroup.add("button", undefined, "OK", { name: "ok" });
ok.preferredSize.width = 80;
cancel.preferredSize.width = 80;
// Button event handlers
var result = null;
ok.onClick = function () {
result = xDropdown.selection.text + "," + yDropdown.selection.text;
dlg.close();
};
cancel.onClick = function () {
result = null;
dlg.close();
};
dlg.show();
return result;
}
function processSelectedLayers(alignmentString) {
var s2t = stringIDToTypeID;
// Get the IDs of the currently selected layers
var ref = new ActionReference();
ref.putProperty(s2t("property"), s2t("targetLayersIDs"));
ref.putEnumerated(s2t("document"), s2t("ordinal"), s2t("targetEnum"));
var layerList = executeActionGet(ref).getList(s2t("targetLayersIDs"));
var selectedIDs = [];
for (var i = 0; i < layerList.count; i++) {
selectedIDs.push(layerList.getReference(i).getIdentifier(s2t("layerID")));
}
var tempSmartObjects = []; // Store [originalLayerID, newSmartObjectID]
var finalLayerIDs = selectedIDs.slice(); // Ensure this is an array copy
// Select the layers and align them
for (var j = 0; j < selectedIDs.length; j++) {
selectLayerByID(selectedIDs[j]);
if (isLayerGroup()) {
executeAction(s2t("newPlacedLayer"), undefined, DialogModes.NO);
var newID = getActiveLayerID();
tempSmartObjects.push([selectedIDs[j], newID]);
}
alignByMask(alignmentString);
}
// Convert temporary smart objects back to layers and update final IDs
// Requires Photoshop 21.0 or later
for (var i = 0; i < tempSmartObjects.length; i++) {
selectLayerByID(tempSmartObjects[i][1]);
executeAction(s2t("placedLayerConvertToLayers"), undefined, DialogModes.NO);
var newLayerID = getActiveLayerID();
// Safely update finalLayerIDs
var originalID = tempSmartObjects[i][0];
var originalIndex = -1;
for (var k = 0; k < finalLayerIDs.length; k++) {
if (finalLayerIDs[k] === originalID) {
originalIndex = k;
break;
}
}
if (originalIndex !== -1) {
finalLayerIDs[originalIndex] = newLayerID;
} else {
// If not found, append the new ID (shouldn't happen, but as a fallback)
finalLayerIDs.push(newLayerID);
}
}
// Re-select the original layers
if (finalLayerIDs.length > 0) {
// Deselect all layers first
var deselectDesc = new ActionDescriptor();
var deselectRef = new ActionReference();
deselectRef.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("allEnum"));
deselectDesc.putReference(s2t("target"), deselectRef);
executeAction(s2t("selectNoLayers"), deselectDesc, DialogModes.NO);
// Select all layers in finalLayerIDs
for (var k = 0; k < finalLayerIDs.length; k++) {
var selDesc = new ActionDescriptor();
var selRef = new ActionReference();
selRef.putIdentifier(s2t("layer"), finalLayerIDs[k]);
selDesc.putReference(s2t("target"), selRef);
if (k > 0) {
selDesc.putEnumerated(s2t("selectionModifier"), s2t("selectionModifierType"), s2t("addToSelection"));
}
selDesc.putBoolean(s2t("makeVisible"), false);
executeAction(s2t("select"), selDesc, DialogModes.NO);
}
}
}
function isLayerGroup() {
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("layerSection"));
ref.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
var desc = executeActionGet(ref);
var type = desc.getEnumerationValue(stringIDToTypeID("layerSection"));
var typeString = typeIDToStringID(type);
return typeString === "layerSectionStart";
}
function getActiveLayerID() {
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("layerID"));
ref.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
return executeActionGet(ref).getInteger(stringIDToTypeID("layerID"));
}
function selectLayerByID(ID) {
var ref = new ActionReference();
ref.putIdentifier(stringIDToTypeID("layer"), ID);
var desc = new ActionDescriptor();
desc.putReference(stringIDToTypeID("target"), ref);
desc.putBoolean(stringIDToTypeID("makeVisible"), false);
executeAction(stringIDToTypeID("select"), desc, DialogModes.NO);
}
function alignByMask(userInput) {
var parts = userInput.split(",");
var xAlign = parts[0];
var yAlign = parts[1];
var canvasLeft = 0;
var canvasTop = 0;
var canvasRight = activeDocument.width.value;
var canvasBottom = activeDocument.height.value;
var canvasXCenter = activeDocument.width.value / 2;
var canvasYCenter = activeDocument.height.value / 2;
var bounds = activeDocument.activeLayer.bounds;
var layerLeft = bounds[0].value;
var layerTop = bounds[1].value;
var layerRight = bounds[2].value;
var layerBottom = bounds[3].value;
var layerWidth = layerRight - layerLeft;
var layerHeight = layerBottom - layerTop;
var dx = 0;
var dy = 0;
switch (xAlign) {
case "Left": dx = canvasLeft - layerLeft; break;
case "Center": dx = canvasXCenter - layerLeft - layerWidth / 2; break;
case "Right": dx = canvasRight - layerRight; break;
}
switch (yAlign) {
case "Top": dy = canvasTop - layerTop; break;
case "Center": dy = canvasYCenter - layerTop - layerHeight / 2; break;
case "Bottom": dy = canvasBottom - layerBottom; break;
}
activeDocument.activeLayer.translate(dx, dy);
}
})();
}
}
activeDocument.suspendHistory("Align Masked Layers to Canvas", "main()");
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
Copy link to clipboard
Copied
@Little_Matty - You're welcome! I cheated using temporary smart objects. Time permitting I'll look into using the bounds of the mask.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now