Copy link to clipboard
Copied
I have a PSD template with five layer templates, which include the background layer and four others converted to smart objects. The named layers are 'Table', 'Chair', 'Bed', and 'Oval' (an ellipse). My objective is to use the Photoshop API to fill these specific smart object layers with a single image, accommodating the varying aspect ratios.
I tried with 2 methods:
1st Option: using the /smartObject endpoint like this:
require('dotenv').config();
const express = require('express');
const axios = require('axios');
const bodyParser = require('body-parser');
const cors = require('cors');
const sharp = require('sharp');
const Dropbox = require('dropbox').Dropbox;
const app = express();
const port = 3001; // You can change the port as needed
const dbx = new Dropbox({ accessToken: process.env.DROPBOX_ACCESS_TOKEN });
app.use(cors());
app.use(bodyParser.json());
app.post('/exportData', async (req, res) => {
console.log('Export data request received:', req.body);
try {
const clientId = process.env.PHOTOSHOP_CLIENT_ID;
console.log(clientId);
const clientSecret = process.env.PHOTOSHOP_SECRET_KEY;
const accessTokenResponse = await axios.post(
`https://ims-na1.adobelogin.com/ims/token/v3`,
`grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}&scope=AdobeID,openid`,
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
}
);
const accessToken = accessTokenResponse.data.access_token;
const filePath = '/test.psd';
const imagePath = '/resized_texture_test.psd';
let linkRequestInput = await dbx.filesGetTemporaryLink({ path: filePath });
console.log(linkRequestInput);
let inputUrl = linkRequestInput.result.link;
let linkRequestOptional = await dbx.filesGetTemporaryLink({ path: imagePath });
console.log(linkRequestOptional);
let optionalUrl = linkRequestOptional.result.link;
let linkRequestOutput = await dbx.filesGetTemporaryUploadLink({ commit_info: {path: '/test_output.psd', mode: 'overwrite'}});
console.log(linkRequestOutput);
let outputUrl = linkRequestOutput.result.link;
let requestBody = {
"inputs":[
{
"href": inputUrl,
"storage": "dropbox"
}
],
"options":{
"layers":[
{
"name": "Bed",
"input": {
"href": optionalUrl,
"storage": "dropbox"
}
},
{
"name": "Table",
"input": {
"href": optionalUrl,
"storage": "dropbox"
}
},
{
"name": "Oval",
"input": {
"href": optionalUrl,
"storage": "dropbox"
}
},
{
"name": "Chair",
"visible": false,
"input": {
"href": optionalUrl,
"storage": "dropbox"
}
}
]
},
"outputs":[
{
"storage": "dropbox",
"href": outputUrl,
"type": "image/vnd.adobe.photoshop",
}
]
}
const smartObjectReplacementResponse = await axios.post(
'https://image.adobe.io/pie/psdService/smartObject',
requestBody,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-api-key': clientId,
'Content-Type': 'application/json',
},
}
);
console.log('Photoshop API call successful:', smartObjectReplacementResponse.data);
res.json({ success: true, message: 'Export data successful.' });
} catch (error) {
console.error('Error:', error);
res.status(500).json({ success: false, message: 'Error occurred while processing the request.' });
}
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
I attempted to use the /smartObject endpoint with both JPEG and PSD images. However, it appears that I must adhere to the aspect ratio specified in the API call body when filling the designated layer as a smart object. What I intended was for the provided image to fit the selected layer in the PSD template, even if the image has a different aspect ratio than the layer. In my results, for instance, in the elliptical form, the image doesn't maintain the elliptical shape and instead displays as a square (the image itself is a square). Similarly, for the rectangles, it seems to preserve the image's aspect ratio instead of filling the rectangles.
2nd Option: using the /actionJSON endpoint:
I created a .pat file manually in Photoshop using the image I previously used. I recorded actions for applying a pattern to a specific layer, resulting in the following code snippet:
let linkRequestInput = await dbx.filesGetTemporaryLink({ path: '/test.psd' });
//console.log(linkRequestInput);
let inputUrl = linkRequestInput.result.link;
let linkRequestPattern = await dbx.filesGetTemporaryLink({ path: '/pattern_test.pat' });
//console.log(linkRequestPattern);
let patternUrl = linkRequestPattern.result.link;
let linkRequestOutputApplyPattern = await dbx.filesGetTemporaryUploadLink({ commit_info: {path: '/test_output.jpg', mode: 'overwrite'}});
//console.log(linkRequestOutputApplyPattern);
let outputApplyPatternUrl = linkRequestOutputApplyPattern.result.link;
let requestBodyApplyPattern = {
"inputs":[
{
"href": inputUrl,
"storage": "dropbox"
}
],
"options":{
"actionJSON": [
{"_obj":"select","_target":[{"_name":"Oval","_ref":"layer"}],"makeVisible":false},
{"_obj":"gaussianBlur","radius":{"_unit":"pixelsUnit","_value":10.0}},
{"_obj":"fill","antiAlias":true,"from":{"_obj":"paint","horizontal":{"_unit":"pixelsUnit","_value":2815.0},"vertical":{"_unit":"pixelsUnit","_value":1059.0}},"pattern":"ACTION_JSON_OPTIONS_PATTERNS_0","tolerance":32,"using":{"_enum":"fillContents","_value":"pattern"}}
],
"patterns": [
{
"href": patternUrl,
"storage": "dropbox"
}
]
},
"outputs":[
{
"storage": "dropbox",
"href": outputApplyPatternUrl,
"type": "image/jpeg",
}
]
}
const applyPattern = await axios.post(
'https://image.adobe.io/pie/psdService/actionJSON',
requestBodyApplyPattern,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-api-key': clientId,
'Content-Type': 'application/json',
},
}
);
console.log('Photoshop API call successful:', applyPattern.data);
With this option I am able to select the layer and I used a sample action to see if, at least, the selection of the layer works, and it really works because the gaussian action is applied on the layer but then, applying the pattern does not work at all and I don't know what else I can do. I've already tried different approaches but it seems I can't get what I want.
How can I get what I desire?
Feel free to ask more questions about it if you dont understand everything.
Thanks in advance!
Have something to add?
Find more inspiration, events, and resources on the new Adobe Community
Explore Now