Skip to main content
Inspiring
March 1, 2023
Answered

How to make a smart object that would retain the crop of the original image

  • March 1, 2023
  • 2 replies
  • 3085 views

Hey everyone!

 

I've been trying to either write a script or come up with a quicker way to do what I've written in the Subject.

 

The idea is, you have a composition with tons of layers, some are going beyond the frame, some are within, but you have a certain crop. If you try to convert everything into a smart object, it will first run "Reveal All" command and then convert everything into a smart object, which means when you go inside that smart object, you will see every single pixel that was there, the original crop would be gone, it will just adapt a new crop to show whatever pixels you had in there.

 

My colleague found a way, that if you save the file that you want to convert to a smart object first and then drop this exact file into itself in photoshop as a smart object, it will actually retain the exact same crop when you try to go inside that smart object.

 

My question, it there an easier way through scripting or some hidden command that I'm not aware of, that you can just select all layers, convert them to a smart object and retain the exact same crop of the original file?

Correct answer levsavitskiy

I actually managed to write a whole script that does exactly what you suggested and those steps I wrote for the action. The layer renaming part looks like this in my version:

 

// Rename the layer to the currently opened fileName

// Get the currently opened file
var file = app.activeDocument;

// Get the name of the file
var fileName = file.name;

// Remove the file extension from the name
fileName = fileName.replace(/\.[^\.]+$/, '');

// Get the current layer
var layer = app.activeDocument.activeLayer;

// Rename the layer
layer.name = fileName;

 

It works just as intended, but I just found out that the approach you've initially suggested turned out to be way slower, than just dropping already saved document into itself. The bigger the file, the bigger the difference.

 

So now I've been trying to write a script to do exactly that, but I'm afraid my knowledge is not enough to figure it out.

 

I ended up with the following one:

 

// Get a reference to the active document
var doc = app.activeDocument;

// Get the file name of the active document
var fileName = doc.name;

// Get the file path of the active document
var filePath = doc.path;

 

var convertToSmartObject = function () {
var idnewPlacedLayer = stringIDToTypeID('newPlacedLayer');
executeAction(idnewPlacedLayer, undefined, DialogModes.NO);
};
var replaceSmartObjectContents = function (fileName, smartObj) {
app.activeDocument.activeLayer = smartObj;
var idplacedLayerReplaceContents = stringIDToTypeID("placedLayerReplaceContents");
var desc3 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc3.putPath(idnull, new File(fileName));
var idPgNm = charIDToTypeID("PgNm");
desc3.putInteger(idPgNm, 1);
executeAction(idplacedLayerReplaceContents, desc3, DialogModes.NO);
};


// Add a layer, this will now be the active layer
doc.artLayers.add();

// Convert active layer to Smart Object
convertToSmartObject();

// replace a provided layer with a provided file path
replaceSmartObjectContents(fileName, doc.activeLayer);

 

 

It creates an empty layer, turns it into a smart object and then should replace the contents of it with the same document that is opened, but in the case of this script it opens the Open file dialog box where you need to manually navigate to the file. It works, but it's semi-automatic. I cannot figure out a way to force it to grab the file without the Open dialog screen.

 

 

 

 


I actually figured it out! Read about the fullName attribute of the file and it seemed to work. 

 

Here's the working script exactly for what I needed:

 

// Get a reference to the active document
var doc = app.activeDocument;

// Get the file name of the active document
var fileName = doc.name;

// Get the file path of the active document
var filePath = doc.path;

var docName = doc.fullName;

var convertToSmartObject = function () {
var idnewPlacedLayer = stringIDToTypeID('newPlacedLayer');
executeAction(idnewPlacedLayer, undefined, DialogModes.NO);
};
var replaceSmartObjectContents = function (docName, filePath) {
app.activeDocument.activeLayer = filePath;
var idplacedLayerReplaceContents = stringIDToTypeID("placedLayerReplaceContents");
var desc3 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
desc3.putPath(idnull, new File(docName));
var idPgNm = charIDToTypeID("PgNm");
desc3.putInteger(idPgNm, 1);
executeAction(idplacedLayerReplaceContents, desc3, DialogModes.NO);
};


// Add a layer, this will now be the active layer
doc.artLayers.add();

// Convert active layer to Smart Object
convertToSmartObject();

// replace a provided layer with a provided file path
replaceSmartObjectContents(docName, doc.activeLayer);

 

2 replies

selondon
Community Expert
Community Expert
November 12, 2025

@c.pfaffenbichler 

Sorry for the delay........  Below is my parent document (a cropped S, but the rest of the S exists outside the visible area)

 

 

When I open the Smart Object (below),  I want it to match the crop above, not the crop of the whole canvas (although I wish to retain all exist pixels)

 

 

The reasoning behind this is that I won't be the 'creator' of the initial Smart Object. I may not even work with the creator. They could come from a different agency from which I have no control.

 

We do have workarounds but when files are 10/15gb, they involve multiple opening and saving.

 

Obviously the Smart Object may be scaled so there is another difficulty.

Surely Photoshop knows the co-ordinatess of the canvas outside of the visible area (as in the first image), so even with scaling, a crop area could be worked out?

 

 

c.pfaffenbichler
Community Expert
Community Expert
March 1, 2023

The idea is, you have a composition with tons of layers, some are going beyond the frame, some are within, but you have a certain crop. If you try to convert everything into a smart object, it will first run "Reveal All" command and then convert everything into a smart object, which means when you go inside that smart object, you will see every single pixel that was there, the original crop would be gone, it will just adapt a new crop to show whatever pixels you had in there.

The conversion simply uses the available content; if the Layer is smaller than the Canvas Size would you want the resulting SO to have the Canvas Size or just the pixel content’s? 

 

Why exactly do you want the SOs to have the containing document’s Canvas Size? 

 

• For Pixel Layers you could destroy the off-canvas content before converting with 

Select > All 

Image > Crop

• Alternatively you could apply a Select > All-Layer Mask to each Layer before converting. (Naturally that would be a problem if Layers already have Layer Masks.)

• A Script could group the Layers, apply a Layer Mask to the Group, convert to SO, open SO, crop to the Group’s Mask, save and close, center the SO in the containing document; do you have experience with JavaScript and Photoshop Scripting? 

Inspiring
March 1, 2023

The idea is to retain all the data that was originally there, but keep the same crop. I don't want to crop out elements that can be outside of the border, in case someone needs to move elements. Besides, some elements/models can be as their own smartobjects and also go beyond the border. If you just create a SO as is, it will reveal everything there is. If you drop the file into itself, it will create a smart object of it, but keep the exact same crop, because essentially when opening the SO, you'll be opening the original file. 

 

The script that you've suggested should do exactly that. I'm not very good with those, but I can try figuring it out. In fact, I think you can pull something similar with just actions. Hopefully, it will be quicker than dropping the document into itself, so you can safe a bit of time doing that.

Inspiring
March 1, 2023

In fact, I just tried it and it worked! You can do it with actions, but there are two minor things that I would like to correct, but at least it works.

 

Basically, it's exactly what you suggested:

1) Select all 

2) Apply mask

3) Create a group

4) Convert to SO

5) Open the SO

6) Select current mask

7) Crop, Apply crop

😎 Move everything outside the group and delete the group with mask (just to make it cleaner and so it looks like the original)

9) Save and close

10) Select all

11) Center horizontally and vertically

12) Deselect

 

The only thing I would like to add here is that the final smart object gets the name of the file, but that will most likely require using scripts. I am not aware of a way to do that with actions.