Skip to main content
Known Participant
November 7, 2024
Answered

add tv screen automatically using script

  • November 7, 2024
  • 3 replies
  • 5812 views

It would be great if you could add TV and PC screens using a script without having to manually drag and drop them. Hope everyone can help ^_^

Correct answer c.pfaffenbichler

can you help me create a script to do that job. i thank you very much for that. it helps me a lot in my work


This one would transform a placed image according to a four-point path. 

// works only if the path for the tv-screens is comprised of only four corner points without handles;
// transforms the selected layer according to the selected or topmost path in the paths panel;
// use it at your own risk;
// 2008, pfaffenbichler;
#target photoshop
var myDocument = app.activeDocument;
var aPath = selectedPath2015 ();
var originalUnits = app.preferences.rulerUnits;
myDocument.pathItems[0].select();
myDocument.pathItems[0].deselect();
myDocument.selection.deselect();	
// switch units to pixels;
app.preferences.rulerUnits = Units.PIXELS;
// check path;
if (aPath == undefined) {var aPath = myDocument.pathItems[0]};
if (aPath != undefined) {
// confirm the  path has 4 points;
if (aPath.subPathItems.length == 1 && myDocument.pathItems[0].subPathItems[0].pathPoints.length == 4) {
// get the horicontal and vertical coordinates in pixels;
var hor1 = Number(aPath.subPathItems[0].pathPoints[0].anchor[0]);
var hor2 = Number(aPath.subPathItems[0].pathPoints[1].anchor[0]);
var hor3 = Number(aPath.subPathItems[0].pathPoints[2].anchor[0]);
var hor4 = Number(aPath.subPathItems[0].pathPoints[3].anchor[0]);
var ver1 = Number(aPath.subPathItems[0].pathPoints[0].anchor[1]);
var ver2 = Number(aPath.subPathItems[0].pathPoints[1].anchor[1]);
var ver3 = Number(aPath.subPathItems[0].pathPoints[2].anchor[1]);
var ver4 = Number(aPath.subPathItems[0].pathPoints[3].anchor[1]);
// order the horicontal and vertical coordinates;
var horList = [hor1, hor2, hor3, hor4];
var verList = [ver1, ver2, ver3, ver4];
horList.sort(sortNumber);
verList.sort(sortNumber);
// check the horicontal value;
var leftPoints = new Array;
var rightPoints = new Array;
for (var k=0; k<aPath.subPathItems[0].pathPoints.length; k++) {
	if (aPath.subPathItems[0].pathPoints[k].anchor[0] == horList[0] 
	||  aPath.subPathItems[0].pathPoints[k].anchor[0] == horList[1]) {
		leftPoints = leftPoints.concat(aPath.subPathItems[0].pathPoints[k].anchor)
		}
	else {
		rightPoints = rightPoints.concat(aPath.subPathItems[0].pathPoints[k].anchor)
		}
	};
// define the four cornerpoints;
if (leftPoints[1] <= leftPoints[3]) {
	var aTopLeft = [leftPoints[0], leftPoints[1]]
	var aBottomLeft = [leftPoints[2], leftPoints[3]];
	}
else {
	var aTopLeft = [leftPoints[2], leftPoints[3]]
	var aBottomLeft = [leftPoints[0], leftPoints[1]];
	};
if (rightPoints[1] <= rightPoints[3]) {
	var aTopRight = [rightPoints[0], rightPoints[1]]
	var aBottomRight = [rightPoints[2], rightPoints[3]];
	}
else {
	var aTopRight = [rightPoints[2], rightPoints[3]]
	var aBottomRight = [rightPoints[0], rightPoints[1]];
	};
// sort numbers, found at www.w3schools.com;
function sortNumber(a,b) {
	return a - b;
	};
//////////// transformation ////////////
// from adobe’s terminology.jsx;
const classChannel = app.charIDToTypeID('Chnl');
const classRectangle = app.charIDToTypeID('Rctn');
const enumNone = app.charIDToTypeID('None');
const eventSet = app.charIDToTypeID('setd');
const eventTransform = app.charIDToTypeID('Trnf');
const keySelection = app.charIDToTypeID('fsel');
const krectangleStr = app.stringIDToTypeID("rectangle");
const kquadrilateralStr = app.stringIDToTypeID("quadrilateral");
const keyBottom = app.charIDToTypeID('Btom');
const keyLeft = app.charIDToTypeID('Left');
const keyNull = app.charIDToTypeID('null');
const keyRight = app.charIDToTypeID('Rght');
const keyTo = app.charIDToTypeID('T   ');
const keyTop = app.charIDToTypeID('Top ');
const typeOrdinal = app.charIDToTypeID('Ordn');
const unitPixels = app.charIDToTypeID('#Pxl');
// from adobe’s geometry.jsx;
//
// =================================== TPoint ===================================
//
function TPoint( x, y )
{
	this.fX = x;
	this.fY = y;
}
// TPoint Constants
const kTPointOrigion = new TPoint( 0, 0 );
TPoint.kOrigin = kTPointOrigion;

const kTPointInfinite = new TPoint( Infinity, Infinity );
TPoint.kInfinite = kTPointInfinite;
const kTPointClassname = "TPoint";
TPoint.prototype.className = kTPointClassname;
// Overloaded math operators
TPoint.prototype["=="] = function( Src )
{
	return (this.fX == Src.fX) && (this.fY == Src.fY);
}

TPoint.prototype["+"] = function( b )
{
	return new TPoint( this.fX + b.fX, this.fY + b.fY );
}

TPoint.prototype["-"] = function( b, reversed )
{
	if (typeof(b) == "undefined")		// unary minus
		return new TPoint( -this.fX, -this.fY )
	else
	{
		if (reversed)
			return new TPoint( b.fX - this.fX, by.fY - this.fY );
		else
			return new TPoint( this.fX - b.fX, this.fY - b.fY);
	}
}
//
// Multiply and divide work with scalars as well as points
//
TPoint.prototype["*"] = function( b )
{
    if (typeof(b) == 'number')
		return new TPoint( this.fX * b, this.fY * b );
	else
		return new TPoint( this.fX * b.fX, this.fY * b.fY );
}
TPoint.prototype["/"] = function( b, reversed )
{
	if (reversed)
	{
		if (typeof(b) == "number")
			debugger;
// Can't divide a number by a point
		else
			return new TPoint( b.fX / this.fX, b.fY / this.fY );
	}
	else
	{
		if (typeof(b) == 'number')
			return new TPoint( this.fX / b, this.fY / b );
		else
			return new TPoint( this.fX / b.fX, this.fY / b.fY );
	}
}
TPoint.prototype.toString = function()
{
	return "[" + this.fX.toString() + "," + this.fY.toString() + "]";
}
TPoint.prototype.vectorLength = function()
{
    return Math.sqrt( this.fX * this.fX + this.fY * this.fY );
}
//////////// the new corners ////////////
transformActiveLayer( [new TPoint(aTopLeft[0], aTopLeft[1]), new TPoint(aTopRight[0], aTopRight[1]), new TPoint(aBottomRight[0], aBottomRight[1]), new TPoint(aBottomLeft[0], aBottomLeft[1])]);
// from adobe’s stacksupport.jsx;
// Apply a perspective transform to the current layer, with the
// corner TPoints given in newCorners (starts at top left, in clockwise order)
// Potential DOM fix
function transformActiveLayer( newCorners )
{
	function pxToNumber( px )
	{
		return px.as("px");
	}
	var saveUnits = app.preferences.rulerUnits;
	app.preferences.rulerUnits = Units.PIXELS;
	var i;
	var setArgs = new ActionDescriptor();
	var chanArg = new ActionReference();
	chanArg.putProperty( classChannel, keySelection );
//	setArgs.putReference( keyNull, chanArg );
	var boundsDesc = new ActionDescriptor();
	var layerBounds = app.activeDocument.activeLayer.bounds;
	boundsDesc.putUnitDouble( keyTop, unitPixels, pxToNumber( layerBounds[1] ) );
	boundsDesc.putUnitDouble( keyLeft, unitPixels, pxToNumber( layerBounds[0] ) );
	boundsDesc.putUnitDouble( keyRight, unitPixels, pxToNumber( layerBounds[2] ) );
	boundsDesc.putUnitDouble( keyBottom, unitPixels, pxToNumber( layerBounds[3] ) );
//	setArgs.putObject( keyTo, classRectangle, boundsDesc );
//	executeAction( eventSet, setArgs );
	var result = new ActionDescriptor();
	var args = new ActionDescriptor();
	var quadRect = new ActionList();
	quadRect.putUnitDouble( unitPixels, pxToNumber( layerBounds[0] ) );
// ActionList put is different from ActionDescriptor put
	quadRect.putUnitDouble( unitPixels, pxToNumber( layerBounds[1] ) );
	quadRect.putUnitDouble( unitPixels, pxToNumber( layerBounds[2] ) );
	quadRect.putUnitDouble( unitPixels, pxToNumber( layerBounds[3] ) );	
	var quadCorners = new ActionList();
	for (i = 0; i < 4; ++i)
	{
		quadCorners.putUnitDouble( unitPixels, newCorners[i].fX );
		quadCorners.putUnitDouble( unitPixels, newCorners[i].fY );
	}
	args.putList( krectangleStr, quadRect );
	args.putList( kquadrilateralStr, quadCorners );
	executeAction( eventTransform, args );	
	// Deselect
	deselArgs = new ActionDescriptor();
	deselRef = new ActionReference();
	deselRef.putProperty( classChannel, keySelection );
	deselArgs.putReference( keyNull, deselRef );
	deselArgs.putEnumerated( keyTo, typeOrdinal, enumNone );
	executeAction( eventSet, deselArgs );
	app.preferences.rulerUnits = saveUnits;
}
// resets the preferences units;
app.preferences.rulerUnits = originalUnits
}
else {
		alert ("the topmost path does not conform to the requirements, it either comprises of more than one path or does not have exactly four points")};
};
////// determine selected path, updated 09.2015 //////
function selectedPath2015 () {
try {
var ref = new ActionReference();
ref.putProperty (stringIDToTypeID("property"), stringIDToTypeID("targetPathIndex")); 
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var docDesc = executeActionGet(ref);
return app.activeDocument.pathItems[docDesc.getInteger(stringIDToTypeID("targetPathIndex"))]
}
catch (e) {return undefined}
};

 

3 replies

New Participant
March 7, 2025

"That’s a great suggestion! Automating the addition of TV and PC screens with a script would definitely save time and effort. It would also be useful for projects related to Arabic television, making content creation more efficient. Hope the team can explore this!"

c.pfaffenbichler
Community Expert
November 8, 2024

Please explain the actual task. 

Do you have to insert many screens into one (or several pictures), the same screen in multiple images, …? 

Known Participant
November 8, 2024

only 1 image per screen. The important thing is that it can be stretched to fit the selection you create.

c.pfaffenbichler
Community Expert
November 8, 2024

The transformation could be automated if you create a four-point-path instead of a Selection. 

Known Participant
November 8, 2024

I have a code but it has too many steps, what I need is for it to fill the TV

 

(function () {

// Script variables
var abort;
var bounds;
var docMaster;
var mask;
var maskC;
var maskH;
var maskW;
var title = "Adobe Script Tutorial 8";

// Reusable UI variables
var g; // group
var p; // panel
var w; // window

// SETUP

if (!app.documents.length) {
alert("Open the master document", title, false);
return;
}
app.displayDialogs = DialogModes.NO;
app.preferences.rulerUnits = Units.PIXELS;
docMaster = app.activeDocument;
mask = docMaster.channels.getByName("mask");
docMaster.selection.load(mask);
bounds = docMaster.selection.bounds;
maskW = bounds[2] - bounds[0];
maskH = bounds[3] - bounds[1];
maskC = [bounds[0] + (maskW / 2), bounds[1] + (maskH / 2)];

function maskLayer() {
// Mask active layer using document selection.
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
desc1.putClass(charIDToTypeID("Nw "), charIDToTypeID("Chnl"));
ref1.putEnumerated(charIDToTypeID("Chnl"), charIDToTypeID("Chnl"), charIDToTypeID("Msk "));
desc1.putReference(charIDToTypeID("At "), ref1);
desc1.putEnumerated(charIDToTypeID("Usng"), charIDToTypeID("UsrM"), charIDToTypeID("RvlS"));
executeAction(charIDToTypeID("Mk "), desc1, DialogModes.NO);
}

function processFile(file) {
var doc;
var docWork;
var fileJpg;
var layer;
var layerC;
var layerH;
var layerW;
var saveOptions;
var scale;
var scaleH;
var scaleW;
docWork = docMaster.duplicate();
doc = app.open(file);
try {
progress.message(File.decode(doc.name));
// Do something with image here
app.activeDocument = doc;
doc.flatten();
// Resize image
scaleH = maskH / doc.height;
scaleW = maskW / doc.width;
scale = Math.max(scaleH, scaleW);
doc.resizeImage(doc.width * scale, doc.height * scale, null, ResampleMethod.BICUBICSHARPER);
// Copy image to work document.
layer = doc.layers[0].duplicate(docWork);
app.activeDocument = docWork;
docWork.activeLayer = layer;
// Resize image to fit in master mask.
bounds = layer.bounds;
layerW = bounds[2] - bounds[0];
layerH = bounds[3] - bounds[1];
layerC = [bounds[0] + (layerW / 2), bounds[1] + (layerH / 2)];
layer.translate(maskC[0] - layerC[0], maskC[1] - layerC[1]);
docWork.selection.load(mask);
maskLayer();
// Save JPG
fileJpg = new File(txtFolderOutput.text + "/" + doc.name.replace(/\.[^\.]*$/, "") + "-framed.jpg");
saveOptions = new JPEGSaveOptions();
saveOptions.embedColorProfile = true;
saveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
saveOptions.quality = 12;
docWork.saveAs(fileJpg, saveOptions);
progress.increment();
} finally {
doc.close(SaveOptions.DONOTSAVECHANGES);
docWork.close(SaveOptions.DONOTSAVECHANGES);
}
}

function progress(message) {
var b;
var t;
var w;
w = new Window("palette", "Progress", undefined, {
closeButton: false
});
t = w.add("statictext", undefined, message);
t.preferredSize = [450, -1];
b = w.add("progressbar");
b.preferredSize = [450, -1];
progress.close = function () {
w.close();
};
progress.increment = function () {
b.value++;
};
progress.message = function (message) {
t.text = message;
app.refresh();
};
progress.set = function (steps) {
b.value = 0;
b.minvalue = 0;
b.maxvalue = steps;
};
w.show();
app.refresh();
}

})();