Copy link to clipboard
Copied
Can anyone point me in the right direction?
I found this forum and it seems similar to what I'm looking for, but I don't know how to create the action: https://community.adobe.com/t5/photoshop/action-that-uses-a-percentage-of-image-size-in-pixel-dimens...
Copy link to clipboard
Copied
The action mentioned in that thread will create an even horizontal/vertical sized border inside the image. Is this what you need help recreating? A 1000px width document with a 4% border based on the width would end up with a visible area of 920px on the width. This will cover existing content with the border.
The alternative would be a document that was 1080px on the width, extending the canvas and not covering exising content.
Copy link to clipboard
Copied
Hey thanks for the response, I wouldn't want a border that would cover up the image.
Basically what I want is to figure out how to make a border that looks consistent with all image sizes. Whenever I go into Image --> Canvas Size... --> and choose the "Percentage" option and add 5% on each option with "Relative" ticked, it'll make a nice border, but if the image is not completely square, one side will be longer than the other.
So what I'm trying to figure out is, how can I make a consistent-looking border for all image sizes and make it into an action?
Copy link to clipboard
Copied
As the other thread shows, sometimes one has to get creative in an action as they are sometimes limited compared to scripts.
It depends on what you call 'consistent', as % based is relative to the image while absolute in pixels is always going to deliver fixed values.
I have just created a script that currently only works on flattened images.
Do you need this to work on both flattened and layered, or only flattened.
Copy link to clipboard
Copied
Try this for horizontal images. The action creates a border of 10% of the narrow side.
For vertical images change the alignment type.
Copy link to clipboard
Copied
Oh this looks great! Could you possibly send me the download link for both versions? I'm not very familiar on how to recreate that, would raelly be appreciated!
Copy link to clipboard
Copied
What do you not understand there? ))
Here is a link to Action Set.
https://disk.yandex.ru/d/K_H2gO2tg2IGqQ
Start Action "Run".
To change the size of the border, edit Action "Transform".
The "Run" action works for both portrait and landscape orientations using an if condition.
P.S. It would be much simpler and more flexible to use a script instead of this Action.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
OK, here is that script that I was working on. It grew a little bit once I started the conditional check for a flattened or layered original, then I had to refactor and optimise the code etc.
It uses the document's width to base the border % size on. It is easy enough to change this to the doc's height (line 63), see the comments in the file.
Please let me know how it goes.
This script uses some GUI input to set colour and border size, it could be adjusted for use with batching.
/*
Extend Canvas Border by Percentage of Doc Width.jsx
Version 1.0
Stephen Marsh - 2021
Need Action That Makes an Equal-Sized Border for Images With Different Sizes
https://community.adobe.com/t5/photoshop/need-action-that-makes-an-equal-sized-border-for-images-with-different-sizes/td-p/11876979
Action that uses a percentage of image size in pixel dimensions
https://community.adobe.com/t5/photoshop/action-that-uses-a-percentage-of-image-size-in-pixel-dimensions/m-p/9897687
You can change the docWidth.value to docHeight.value for the basis of the frame size on line 63
*/
#target photoshop
app.bringToFront();
// Conditional Background layer check
if (app.activeDocument.activeLayer.isBackgroundLayer) {
setForeground();
addBorder();
}
// Otherwise run on layered files
else {
addBorder();
addColorFillLayer();
// "previous" or "next" or "front" or "back"
moveLayerRelativeStack("back");
}
function addBorder() {
// Save the current ruler units and set to pixels
var savedRuler = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// Loop the input prompt until a number is entered
var origInput;
while (isNaN(origInput = prompt("Enter the border size" + "\n" + "(based on a % of the document's width)", "4")));
// Test if cancel returns null, then terminate the script
if (origInput === null) {
alert('Script cancelled!');
return
}
// Test if an empty string is returned, then terminate the script
if (origInput === "") {
alert('A value was not entered, script cancelled!');
return
}
// Convert decimal input to integer
var borderSize = parseInt(origInput);
// Border size value in pixels
var doc = app.activeDocument;
var docWidth = doc.width;
var docHeight = doc.height;
// Change the docWidth.value to docHeight.value for the basis of the frame size
var canvasExtension = borderSize / 100 * docWidth.value;
// Resize canvas - relative width & height
extendCanvasRelative(true, canvasExtension, canvasExtension);
function extendCanvasRelative(relative, width, height) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
descriptor.putBoolean(s2t("relative"), relative);
descriptor.putUnitDouble(s2t("width"), s2t("pixelsUnit"), width);
descriptor.putUnitDouble(s2t("height"), s2t("pixelsUnit"), height);
descriptor.putEnumerated(s2t("horizontal"), s2t("horizontalLocation"), c2t("Cntr"));
descriptor.putEnumerated(s2t("vertical"), s2t("verticalLocation"), c2t("Cntr"));
descriptor.putEnumerated(s2t("canvasExtensionColorType"), s2t("canvasExtensionColorType"), s2t("foregroundColor"));
executeAction(s2t("canvasSize"), descriptor, DialogModes.NO);
}
// Restore the ruler units
app.preferences.rulerUnits = savedRuler;
}
function addColorFillLayer() {
getColorpickerColor();
var fColor = app.foregroundColor;
var R = fColor.rgb.red.toFixed(2);
var G = fColor.rgb.green.toFixed(2);
var B = fColor.rgb.blue.toFixed(2);
makeFill(R, G, B);
function makeFill(red, Grn, blue) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
var descriptor3 = new ActionDescriptor();
var descriptor4 = new ActionDescriptor();
var reference = new ActionReference();
reference.putClass(s2t("contentLayer"));
descriptor.putReference(c2t("null"), reference);
descriptor4.putDouble(s2t("red"), red);
descriptor4.putDouble(c2t("Grn "), Grn);
descriptor4.putDouble(s2t("blue"), blue);
descriptor3.putObject(s2t("color"), s2t("RGBColor"), descriptor4);
descriptor2.putObject(s2t("type"), s2t("solidColorLayer"), descriptor3);
descriptor.putObject(s2t("using"), s2t("contentLayer"), descriptor2);
executeAction(s2t("make"), descriptor, DialogModes.NO);
}
function getColorpickerColor() {
if (app.showColorPicker()) {
return app.foregroundColor;
} else {
return false;
}
}
}
function moveLayerRelativeStack(relPos) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
descriptor.putReference(c2t("null"), reference);
reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t(relPos));
descriptor.putReference(s2t("to"), reference2);
executeAction(s2t("move"), descriptor, DialogModes.NO);
}
function setForeground() {
var fColor = app.foregroundColor;
var R = fColor.rgb.red.toFixed(2);
var G = fColor.rgb.green.toFixed(2);
var B = fColor.rgb.blue.toFixed(2);
getColorpickerColor();
function getColorpickerColor() {
if (app.showColorPicker()) {
return app.foregroundColor;
} else {
return false;
}
}
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
That sounds great! How do I import a script to create an action though? Never done it that way, I usually just export the action 🤔
Copy link to clipboard
Copied
Follow the instructions linked above at my prepression blog. There is no need to record this GUI based script into an action.
If you need to batch process many files, then this script would need minor modification to remove the manual GUI steps so that it could be inserted/recorded into an action and used with Batch, Image Processor, Image Processor Pro or Picture Processor scripts.
Alternatively the batch processing code could be added into the script so that there is no dependency on actions and other batch scripts,
Copy link to clipboard
Copied
You might want to consider using the image's diagonal rather than the width, so that verticals and horizontal are more equal in boarder width.
Copy link to clipboard
Copied
Thanks for the suggestion Chuck... Math is not my strong area, do you mean something like this?
/*
Extend Canvas Border by Percentage of Hypotenuse.jsx
Version 1.0
Stephen Marsh - 2021
Need Action That Makes an Equal-Sized Border for Images With Different Sizes
https://community.adobe.com/t5/photoshop/need-action-that-makes-an-equal-sized-border-for-images-with-different-sizes/td-p/11876979
Action that uses a percentage of image size in pixel dimensions
https://community.adobe.com/t5/photoshop/action-that-uses-a-percentage-of-image-size-in-pixel-dimensions/m-p/9897687
*/
#target photoshop
app.bringToFront();
// Conditional Background layer check
if (app.activeDocument.activeLayer.isBackgroundLayer) {
setForeground();
addBorder();
}
// Otherwise run on layered files
else {
addBorder();
addColorFillLayer();
// "previous" or "next" or "front" or "back"
moveLayerRelativeStack("back");
}
function addBorder() {
// Save the current ruler units and set to pixels
var savedRuler = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// Loop the input prompt until a number is entered
var origInput;
while (isNaN(origInput = prompt("Enter the border size" + "\n" + "(based on a % of the document's hypotenuse)", "4")));
// Test if cancel returns null, then terminate the script
if (origInput === null) {
alert('Script cancelled!');
return
}
// Test if an empty string is returned, then terminate the script
if (origInput === "") {
alert('A value was not entered, script cancelled!');
return
}
// Convert decimal input to integer
var borderSize = parseInt(origInput);
// Border size value in pixels
var doc = app.activeDocument;
var docWidth = doc.width.value;
var docHeight = doc.height.value;
// Use the hypotenuse for the basis of the frame size
var hypot = Math.sqrt(docWidth * docWidth + docHeight * docHeight);
var canvasExtension = borderSize / 100 * hypot;
// Resize canvas - relative width & height
extendCanvasRelative(true, canvasExtension, canvasExtension);
function extendCanvasRelative(relative, width, height) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
descriptor.putBoolean(s2t("relative"), relative);
descriptor.putUnitDouble(s2t("width"), s2t("pixelsUnit"), width);
descriptor.putUnitDouble(s2t("height"), s2t("pixelsUnit"), height);
descriptor.putEnumerated(s2t("horizontal"), s2t("horizontalLocation"), c2t("Cntr"));
descriptor.putEnumerated(s2t("vertical"), s2t("verticalLocation"), c2t("Cntr"));
descriptor.putEnumerated(s2t("canvasExtensionColorType"), s2t("canvasExtensionColorType"), s2t("foregroundColor"));
executeAction(s2t("canvasSize"), descriptor, DialogModes.NO);
}
// Restore the ruler units
app.preferences.rulerUnits = savedRuler;
}
function addColorFillLayer() {
getColorpickerColor();
var fColor = app.foregroundColor;
var R = fColor.rgb.red.toFixed(2);
var G = fColor.rgb.green.toFixed(2);
var B = fColor.rgb.blue.toFixed(2);
makeFill(R, G, B);
function makeFill(red, Grn, blue) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
var descriptor3 = new ActionDescriptor();
var descriptor4 = new ActionDescriptor();
var reference = new ActionReference();
reference.putClass(s2t("contentLayer"));
descriptor.putReference(c2t("null"), reference);
descriptor4.putDouble(s2t("red"), red);
descriptor4.putDouble(c2t("Grn "), Grn);
descriptor4.putDouble(s2t("blue"), blue);
descriptor3.putObject(s2t("color"), s2t("RGBColor"), descriptor4);
descriptor2.putObject(s2t("type"), s2t("solidColorLayer"), descriptor3);
descriptor.putObject(s2t("using"), s2t("contentLayer"), descriptor2);
executeAction(s2t("make"), descriptor, DialogModes.NO);
}
function getColorpickerColor() {
if (app.showColorPicker()) {
return app.foregroundColor;
} else {
return false;
}
}
}
function moveLayerRelativeStack(relPos) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
descriptor.putReference(c2t("null"), reference);
reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t(relPos));
descriptor.putReference(s2t("to"), reference2);
executeAction(s2t("move"), descriptor, DialogModes.NO);
}
function setForeground() {
var fColor = app.foregroundColor;
var R = fColor.rgb.red.toFixed(2);
var G = fColor.rgb.green.toFixed(2);
var B = fColor.rgb.blue.toFixed(2);
getColorpickerColor();
function getColorpickerColor() {
if (app.showColorPicker()) {
return app.foregroundColor;
} else {
return false;
}
}
}
Copy link to clipboard
Copied
Yes, I think you got it using the hypotenuse formula.
Copy link to clipboard
Copied
Thank you Stephen and Chuck! Really appreciate the help ❤️ this will be very benefial for my work!
Copy link to clipboard
Copied
I am glad that you are happy, so thanks for the thanks.
I am a little mystified to tell you the truth... Images may potentially have different pixel widths, heights and diagonals between them all. Therefore each and every border will potentially be different sizes, leading to inconsistent thicknesses when using a % of the doc width or height or hypotenuse or area.
Therefore I would have thought that simply basing the border off of a fixed absolute pixel value would be best for consistency. If all of your images are the same size from the same camera, then the % based method would lead to a consistent result.
Curious minds need to know why...