Copy link to clipboard
Copied
Hi All,
I'm working on a project where I need to place a frame inside each of the 20 white boxes in my Photoshop file and create an action to fill each frame with a photo. The photos will be copied and pasted directly into Photoshop and won’t be saved as separate files beforehand.
I'm looking to automate placing each photo into a frame and resizing it to fit as closely as possible.
The challenge I’m facing is image resizing. Since all the photos will have different dimensions, I can’t just use free transform manually for each image.
I’ve tried using the "Image Size" option in the Edit menu, but it resizes the entire canvas, which isn’t what I want.
I’d appreciate any tips or workflows that can help streamline this process.
Thanks in advance for your help!
Kate
Copy link to clipboard
Copied
Please provide the layered sample-file.
It should be possible to automate the scaling with a Script, but I am not sure what exactly you mean by »The photos will be copied and pasted directly into Photoshop and won’t be saved as separate files beforehand.«.
Copy link to clipboard
Copied
Thanks for your response! I've attached a version of the file.
I mentioned copy-pasting because most advice I’ve seen about batch resizing seems to apply only to saved files. However, our workflow involves copying photos directly from a customer chat on the internet and pasting them into Photoshop. Saving each file beforehand would slow down the process significantly.
In this case, we’d copy and paste 20 pictures and then edit them to fit a specific size within a template.
Thanks again!
Copy link to clipboard
Copied
The frames are already filled.
Edit: What is your actual workflow? Do you really start with frames that already have content or empty frames?
Copy link to clipboard
Copied
It should be possible to automate the scaling with a Script, but I am not sure what exactly you mean by »The photos will be copied and pasted directly into Photoshop and won’t be saved as separate files beforehand.«.
By @c.pfaffenbichler
I read this as clipboard content, which I do not like and always recommend linking or embedding to a saved file.
Copy link to clipboard
Copied
I'm sorry if I'm not being clear. I have attached a file with the pictures as they would be when we paste them into photoshop, it wouldnt let me upload a file with all 20 as it was too large so I've uploaded a file with less.
Worflow Would be -
Paste customers photos into photoshop
Shrink & place in frame
Adjust to fit perfectly
Thank you again,
Kate
Copy link to clipboard
Copied
// fill empty frames with selected layers;
// 2025, use it at your own risk;
if (app.documents.length > 0) {
var myDocument = activeDocument;
var theFiles = smartifyAndGetSelectedLayersIdxEtc();
var theFrames = collectFrames (true);
if (theFiles.length <= theFrames.length) {
for (var m = theFiles.length-1; m >= 0; m--) {
selectLayerByID(theFiles[m][0], false);
moveIntoFrame (getIndexFromIdentifier(theFrames[m][1])-1);
var w1 = theFiles[m][3];
var h1 = theFiles[m][4];
var w2 = theFrames[m][5];
var h2 = theFrames[m][6];
if (w1/h1 > w2/h2) {var theScale = w2/w1*100}
else {var theScale = h2/h1*100};
scaleRotateLayer (theScale, theScale, 0, 0, 0)
}
} else {alert ("not enough frames")};
};
////// frame //////
function fillFrame (theFrame, theFile) {
selectLayerByID(theFrame,false);
var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
var idplaceEvent = stringIDToTypeID( "placeEvent" );
var idlayer = stringIDToTypeID( "layer" );
var idoffset = stringIDToTypeID( "offset" );
var desc7 = new ActionDescriptor();
desc7.putInteger( stringIDToTypeID( "ID" ), theFrame );
desc7.putPath( stringIDToTypeID( "null" ), new File( theFile ) );
desc7.putEnumerated( stringIDToTypeID( "freeTransformCenterState" ), stringIDToTypeID( "quadCenterState" ), stringIDToTypeID( "QCSAverage" ) );
var desc8 = new ActionDescriptor();
desc8.putUnitDouble( stringIDToTypeID( "horizontal" ), idpixelsUnit, 0.000000 );
desc8.putUnitDouble( stringIDToTypeID( "vertical" ), idpixelsUnit, 0.000000 );
desc7.putObject( idoffset, idoffset, desc8 );
/*var desc9 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putIdentifier( idlayer, 4 );
desc9.putReference( stringIDToTypeID( "from" ), ref1 );
var ref2 = new ActionReference();
ref2.putIdentifier( idlayer, 34 );
desc9.putReference( stringIDToTypeID( "to" ), ref2 );
desc7.putObject( stringIDToTypeID( "replaceLayer" ), idplaceEvent, desc9 );*/
executeAction( idplaceEvent, desc7, DialogModes.NO );
};
////// select file //////
function selectFile (multi) {
if (multi == true) {var theString = "please select files"}
else {var theString = "please select one file"};
if ($.os.search(/windows/i) != -1) {var theFiles = File.openDialog (theString, '*.jpg;*.tif;*.psd;*.png', multi)}
else {var theFiles = File.openDialog (theString, getFiles, multi)};
////// filter files for mac //////
function getFiles (theFile) {
if (theFile.name.match(/\.(jpg|tif|psd|png)$/i) || theFile.constructor.name == "Folder") {
return true
};
};
return theFiles
};
////// collect layers //////
function collectFrames (isEmpty) {
// get number of layers;
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID('property'), stringIDToTypeID('numberOfLayers'));
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if group collect values;
if (layerSet != "layerSectionEnd" /*&& layerSet != "layerSectionStart" && isBackground != true*/) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var hasFrame = layerDesc.hasKey(stringIDToTypeID("framedGroup"));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
// dimensions;
var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
var halfWidth = theBounds.getUnitDoubleValue(stringIDToTypeID("width")) / 2;
var halfHeight = theBounds.getUnitDoubleValue(stringIDToTypeID("height")) / 2;
var theX = theBounds.getUnitDoubleValue(stringIDToTypeID("left")) + halfWidth;
var theY = theBounds.getUnitDoubleValue(stringIDToTypeID("top")) + halfHeight;
// check next layer to verify if frame is empty;
var theCheck = true;
var ref2 = new ActionReference();
ref2.putProperty(stringIDToTypeID ("property"), stringIDToTypeID("layerSection"));
ref2.putIndex( charIDToTypeID("Lyr "), theIndex - 1 );
var layerDesc2 = executeActionGet(ref2);
var theSection = layerDesc2.getEnumerationValue(stringIDToTypeID("layerSection"));
var layerSection = typeIDToStringID(theSection);
// layerSectionEnd
if (layerSection == "layerSectionContent") {
//alert (theName)
if (isEmpty == true) {theCheck = false}
};
var theColor = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("color")));
if (layerSet == "layerSectionStart" && hasFrame == true && theCheck == true) {
theLayers.push([theName, theID, theIndex, theX, theY, halfWidth, halfHeight])
};
};
}
catch (e) {};
};
return theLayers
};
////// based on code by mike hale, via paul riggott //////
function selectLayerByID(id,add){
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), id);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
////// move into frame //////
function moveIntoFrame (theIndex) {
var idmove = stringIDToTypeID( "move" );
var desc5 = new ActionDescriptor();
var idnull = stringIDToTypeID( "null" );
var ref1 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
ref1.putEnumerated( idlayer, idordinal, idtargetEnum );
desc5.putReference( idnull, ref1 );
var idto = stringIDToTypeID( "to" );
var ref2 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
ref2.putIndex( idlayer, theIndex );
desc5.putReference( idto, ref2 );
var idadjustment = stringIDToTypeID( "adjustment" );
desc5.putBoolean( idadjustment, false );
var idversion = stringIDToTypeID( "version" );
desc5.putInteger( idversion, 5 );
var idlayerID = stringIDToTypeID( "layerID" );
var list1 = new ActionList();
list1.putInteger( 307 );
desc5.putList( idlayerID, list1 );
executeAction( idmove, desc5, DialogModes.NO );
/*var desc5 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated( stringIDToTypeID( "layer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ) );
desc5.putReference( stringIDToTypeID( "null" ), ref1 );
var idto = stringIDToTypeID( "to" );
var ref2 = new ActionReference();
ref2.putIdentifier( stringIDToTypeID( "layer" ), theIndex );
// ref2.putIndex( stringIDToTypeID( "layer" ), theIndex );
desc5.putReference( idto, ref2 );
desc5.putBoolean( stringIDToTypeID( "adjustment" ), false );
desc5.putInteger( stringIDToTypeID( "version" ), 5 );
var list1 = new ActionList();
list1.putInteger( 307 );
desc5.putList( stringIDToTypeID( "layerID" ), list1 );
executeAction( stringIDToTypeID( "move" ), desc5, DialogModes.NO );*/
};
////// layer index from layer identifier //////
function getIndexFromIdentifier (theID) {
try {var ref = new ActionReference();
ref.putIdentifier( charIDToTypeID("Lyr "), theID );
var layerDesc = executeActionGet(ref);
var theIndex = layerDesc.getInteger(stringIDToTypeID("itemIndex"));
return theIndex} catch (e) {alert (theID)}
};
////// get array of arrays of smart objects witrh index, center and half-dimensions //////
function smartifyAndGetSelectedLayersIdxEtc(){
if (ScriptUI.environment.keyboardState.shiftKey == true) {var excludeSO = false}
else {var excludeSO = true};
var selectedLayers = new Array;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref);
if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ){
desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
var c = desc.count;
var selectedLayers = new Array();
for(var i=0;i<c;i++){
try{
activeDocument.backgroundLayer;
selectedLayers.push( desc.getReference( i ).getIndex() );
}catch(e){
selectedLayers.push( desc.getReference( i ).getIndex()+1 );
};
}
}else{
var ref = new ActionReference();
ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "ItmI" ));
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
try{
activeDocument.backgroundLayer;
selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" ))-1);
}catch(e){
selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" )));
};
};
////////////////////////////////////
var theArray = new Array;
var theIDs = new Array;
for (var m = 0; m < selectedLayers.length; m++) {
var thisIndex = selectedLayers[m];
var ref = new ActionReference();
ref.putIndex( charIDToTypeID("Lyr "), thisIndex);
var layerDesc = executeActionGet(ref);
var thisID = layerDesc.getInteger(stringIDToTypeID("layerID"));
var theKind = layerDesc.getInteger(stringIDToTypeID("layerKind"));
var theName = layerDesc.getString(stringIDToTypeID("name"));
var theVisibility = layerDesc.getInteger(stringIDToTypeID("visible"));
var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
var halfWidth = theBounds.getUnitDoubleValue(stringIDToTypeID("width")) / 2;
var halfHeight = theBounds.getUnitDoubleValue(stringIDToTypeID("height")) / 2;
var theX = theBounds.getUnitDoubleValue(stringIDToTypeID("left")) + halfWidth;
var theY = theBounds.getUnitDoubleValue(stringIDToTypeID("top")) + halfHeight;
var isSmartObject = layerDesc.hasKey(stringIDToTypeID('smartObject'));
// is normal, shape, smart object, pattern, gradiet, solid color;
if (theKind == 1 || theKind == 4 || theKind == 5 || theKind == 9 || theKind == 10 || theKind == 11) {
if (theVisibility == true) {
theIDs.push ([thisID, theX, theY, halfWidth, halfHeight, theName, isSmartObject])
}
}
};
////////////////////////////////////
for (var n = 0; n < theIDs.length; n++) {
if (theIDs[n][6] == false) {var theCheck = true}
else {
var theCheck = false;
if (excludeSO == false) {theCheck = true}
};
if (theCheck == true) {
try {
selectLayerByID(theIDs[n][0], false);
executeAction( stringIDToTypeID( "newPlacedLayer" ), undefined, DialogModes.NO );
theArray.push([getLayerId(app.activeDocument.activeLayer), theIDs[n][1], theIDs[n][2], theIDs[n][3], theIDs[n][4], theIDs[n][5]]);
} catch (e) {}
}
else {theArray.push(theIDs[n])};
};
////////////////////////////////////
if (theArray.length == 0) {return};
// select;
selectLayerByID(theArray[0][0],false);
for (var a = 1; a < theArray.length; a++) {selectLayerByID(theArray[a][0], true)};
//return;
return theArray
////////////////////////////////////
};
////// scale active layer to canvas dimensions //////
function scaleRotateLayer (theScaleX, theScaleY, theAngle, offsetX, offsetY) {
try {
// scale layer:
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// transform;
var desc23 = new ActionDescriptor();
var ref2 = new ActionReference();
ref2.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc23.putReference( charIDToTypeID( "null" ), ref2 );
var idOfst = charIDToTypeID( "Ofst" );
var desc24 = new ActionDescriptor();
var idPxl = charIDToTypeID( "#Pxl" );
desc24.putUnitDouble( charIDToTypeID( "Hrzn" ), idPxl, offsetX );
desc24.putUnitDouble( charIDToTypeID( "Vrtc" ), idPxl, offsetY );
desc23.putObject( idOfst, idOfst, desc24 );
var idPrc = charIDToTypeID( "#Prc" );
desc23.putUnitDouble( charIDToTypeID( "Wdth" ), idPrc, theScaleX );
desc23.putUnitDouble( charIDToTypeID( "Hght" ), idPrc, theScaleY );
desc23.putUnitDouble( charIDToTypeID( "Angl" ), charIDToTypeID( "#Ang" ), theAngle );
desc23.putEnumerated( charIDToTypeID( "Intr" ), charIDToTypeID( "Intp" ), stringIDToTypeID( "bicubicAutomatic" ) );
desc23.putEnumerated( stringIDToTypeID( "freeTransformCenterState" ), stringIDToTypeID( "quadCenterState" ), stringIDToTypeID( "QCSAverage" ) );
executeAction( charIDToTypeID( "Trnf" ), desc23, DialogModes.NO );
app.preferences.rulerUnits = originalRulerUnits;
} catch (e) {alert ("NONONO")}
};
Copy link to clipboard
Copied
Thank you so much for this. I will give it a go tomorrow!
Again, I really appreciate your help!
Kate
Copy link to clipboard
Copied
Does it work for you?
Copy link to clipboard
Copied
@c.pfaffenbichler – great job!