this tool allows placing an image in a grid layout in a new photoshop document. it has some examples for creating a simple ui in photoshop using javascript. it also has some examples of writing methods/creating variables in photoshop javascript. it also is an example of storing a photoshop ui file in separate file than the core of the tool. there may be bugs or better ways to implement so please modify/use at your own risk.
here is a video of the tool in action:
//ui.jsx
//a simple tool to create story panels from an input image. example from a blank panel
//tested in Photoshop 10.0.1
//please modify/use at your own risk
#include "core.jsx"
/*check if input path is a valid image path
Args:
path (str): path to check ex: Users/Nathaniel/Desktop/photoshopTools/storyPanels/test_scene.jpg
Returns:
(bool): true if path is a valid image.
*/
function isPathValidImage(path)
{
var fileObj = new File(path);
var validExtensions = ["jpg", "jpeg", "png", "tif"];
if(!fileObj.exists)
{
return false;
}
var pathExt = path.split('.').pop().toLowerCase();
//check if path's extension is in valid extensions
for(var i=0; i<validExtensions.length; i++)
{
if(pathExt == validExtensions[i])
{
//path is valid extension. dont need to check any more extensions
return true;
}
}
return false;
}
/*
Returns:
(bool): true if there is a document open false otherwise
*/
function isDocumentOpen()
{
return app.documents.length > 0
}
function showUI(){
if(!isDocumentOpen())
{
alert("requires a document open to use tool.")
return
}
var dlg = new Window("dialog", "Panel Importer UI");
dlg.orientation = "column";
dlg.preferredSize = [600, 200];
dlg.alignChildren = "left"; //align all widgets in window to the left
//stores options for generating panels
var parameterGroupLabel = dlg.add("statictext", undefined, "1. choose parameters for final panel layout")
var parameterGroup = dlg.add("group");
parameterGroup.orientation = "row";
var numRowsLabel = parameterGroup.add("statictext", undefined, "rows:");
var numRowsIntField = parameterGroup.add("edittext", undefined, "2");
numRowsIntField.characters = 4; //set width
var numColsLabel = parameterGroup.add("statictext", undefined, "cols:");
var numColsIntField = parameterGroup.add("edittext", undefined, "2");
numColsIntField.characters = 4; //set width
var borderWidthPixelsLabel = parameterGroup.add("statictext", undefined, "border width (pixels):");
var borderWidthPixelsIntField = parameterGroup.add("edittext", undefined, "20");
borderWidthPixelsIntField.characters = 4; //set width
//
//limit int fields to numbers only
var intFields = [numRowsIntField, numColsIntField, borderWidthPixelsIntField];
//limit int fields to numbers
var sharedOnChange = function()
{
//alert("field changed:" + this.text);
//remove non numeric character
this.text = this.text.replace(/[^\d]/g, '');
}
//assign shared onChange function
for(var j=0; j<intFields.length; j++)
{
intFields[j].onChanging = sharedOnChange;
}
//
//button
var addPathBtn = dlg.add("button", undefined, "2. add image path to use for panel")
//stores image path
var imagePathText = dlg.add("statictext", undefined, "No Image Selected");
imagePathText.preferredSize = [600, 50];
var createPanelBtn = dlg.add("button", undefined, "3. create panels from image");
var closeBtn = dlg.add("button", undefined, "close");
//add function to button click
addPathBtn.onClick = function()
{
var fileObj = File.openDialog("Select Image");
if(fileObj)
{
selectedPath = fileObj.fsName;
if(!isPathValidImage(selectedPath))
{
alert("selected path not a valid image. exiting");
return;
}
imagePathText.text = selectedPath;
}
}
createPanelBtn.onClick = function()
{
var imagePath = imagePathText.text;
//get parameters from ui
var numRows = parseInt(numRowsIntField.text);
var numCols = parseInt(numColsIntField.text);
var numPanels = numRows*numCols;
var borderWidth = parseInt(borderWidthPixelsIntField.text);
var panelImporter = new PanelImporter(imagePath=imagePath,
numPanels=numPanels,
numRows=numRows,
numCols=numCols,
borderWidth=borderWidth);
panelImporter.doIt();
alert("yaay creating storyboard panels done!");
dlg.close(); //close ui when done so active document refreshed with story panels
}
closeBtn.onClick = function()
{
dlg.close();
}
dlg.show();
}
showUI();
//core.jsx
//old style class with ability to import an image multiple times to form a panel layout
/*
Args:
imagePath(str): path to image to use for each panel
numPanels(int): number of panels to create
numRows(int): number of rows for storyboard
numCols(int): number of cols for storyboard
borderWidth(int): how many pixels to separate panels
*/
function PanelImporter(imagePath, numPanels, numRows, numCols, borderWidth)//(imagePath, numPanels, numRows, numCols, borderWidth)
{
this.doc = app.activeDocument; //assumes in a created document. todo make a document if there is none
this._imagePath = imagePath;
this._numPanels = numPanels;
this._numRows = numRows;
this._numCols = numCols;
this._borderWidth = borderWidth;
/*do any additional initializations for this class
apparently cant run a method of this class in its init. when using old style function for class
*/
this._init = function()
{
this._images = this._getImages(this._imagePath, this._numPanels);//will hold image paths to use for each panel
}
/*
Args:
imagePath(str): path to image to use for each panel ex: /Users/Nathaniel/Desktop/photoshopTools/storyPanels/test_scene.jpg
*/
this.doIt = function()
{
this._init();
this._createPanels();
}
/*
Args:
imagePath(str): path to image to use for each panel ex: /Users/Nathaniel/Desktop/photoshopTools/storyPanels/test_scene.jpg
numPanels(int): number of times to repeat imagePath
Returns:
list(str): the imagePath repeated numPanels many times
*/
this._getImages = function(imagePath, numPanels)
{
var images = [];
//var imagePath = "/Users/Nathaniel/Desktop/photoshopTools/storyPanels/test_scene.jpg";
for(var i=0; i<numPanels; i++)
{
images.push(imagePath);
}
return images;
}
/*creates storyboard panels using a single image for each panel
*/
this._createPanels = function()
{
//var doc = app.activeDocument;
var targetDoc = this.doc;//app.activeDocument;
var images = this._images;
var numRows = this._numRows;
var numCols = this._numCols;
var borderWidth = this._borderWidth;
var imageIndex = 0; //will be used to query images
var numImages = images.length;
if(numImages > numRows*numCols)
{
alert("too many images. make sure number of images is smaller than number of rows multiplied by number of columns");
return;
}
for(var i=0; i<numRows; i++)
{
for(var j=0; j<numCols; j++)
{
if(imageIndex >= numImages)
{
break;
}
var pathToImage = images[imageIndex];
var fileObj = new File(pathToImage);
if(!fileObj.exists){
alert("image file doesnt exist");
return;
}
//open image file
var imgDoc = app.open(fileObj);
//select all and copy
imgDoc.selection.selectAll();
imgDoc.selection.copy();
//close the opened image file
imgDoc.close(SaveOptions.DONOTSAVECHANGES);
//paste image into active document
var newLayer = targetDoc.paste();
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
//set goal x y pixels
//width = right - left
//bounds [left, top, right, bottom]
var widthImage = newLayer.bounds[2].value - newLayer.bounds[0].value;
var heightImage = newLayer.bounds[3].value - newLayer.bounds[1].value;
var goalX = j*widthImage + (j+1)*borderWidth; //the columns are used for x coordinate
var goalY = i*heightImage + (i+1)*borderWidth;//the rows are used for the y coordinate
var curX = newLayer.bounds[0].value;
var curY = newLayer.bounds[1].value;
var dx = goalX - curX;
var dy = goalY - curY;
//move imported image to goal x, y pixels
newLayer.translate(dx, dy);
//increment image index
imageIndex += 1;
}
}
//restore original untis
app.preferences.rulerUnits = originalRulerUnits;
}
}
Thanks for looking
