How to automate Photoshop? - automation

I am trying to automate the process of scanning/cropping photos in Photoshop. I need to scan 3 photos at a time, then use Photoshop's Crop and Straighten Photos command, which creates 3 separate images. After that I'd like to save each of the newly created images as a PNG.
I looked at the JSX scripts and they seem to a lot of promise. Is what I described possible to automate in Photoshop using JavaScript or VBScript or whatever?

I just found this script just did the work for me! It automatically crop & straighten the photo and save each result to directory you specified.
http://www.tranberry.com/photoshop/photoshop_scripting/PS4GeeksOrlando/IntroScripts/cropAndStraightenBatch.jsx
Save it to local then run it in the PS=>File=>Command=>Browse
P.S I found in the comment it said the script can be executed directly by double clicking from Mac Finder or Windows Explorer.
Backup gist for the script here

I actually got the answer on the Photoshop forums over at adobe. It turns out that Photoshop CS4 is totally scriptable via JavaScript, VBScript and comes with a really kick-ass Developer IDE, that has everything you'd expect (debugger, watch window, color coding and more). I was totally impressed.
Following is an extract for reference:
you can run the following script that will create a new folder off the existing one and batch split all the files naming them existingFileName#001.png and put them in the new folder (edited)
#target Photoshop
app.bringToFront;
var inFolder = Folder.selectDialog("Please select folder to process");
if(inFolder != null){
var fileList = inFolder.getFiles(/\.(jpg|tif|psd|)$/i);
var outfolder = new Folder(decodeURI(inFolder) + "/Edited");
if (outfolder.exists == false) outfolder.create();
for(var a = 0 ;a < fileList.length; a++){
if(fileList[a] instanceof File){
var doc= open(fileList[a]);
doc.flatten();
var docname = fileList[a].name.slice(0,-4);
CropStraighten();
doc.close(SaveOptions.DONOTSAVECHANGES);
var count = 1;
while(app.documents.length){
var saveFile = new File(decodeURI(outfolder) + "/" + docname +"#"+ zeroPad(count,3) + ".png");
SavePNG(saveFile);
activeDocument.close(SaveOptions.DONOTSAVECHANGES) ;
count++;
}
}
}
};
function CropStraighten() {
function cTID(s) { return app.charIDToTypeID(s); };
function sTID(s) { return app.stringIDToTypeID(s); };
executeAction( sTID('CropPhotosAuto0001'), undefined, DialogModes.NO );
};
function SavePNG(saveFile){
pngSaveOptions = new PNGSaveOptions();
pngSaveOptions.embedColorProfile = true;
pngSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
pngSaveOptions.matte = MatteType.NONE;
pngSaveOptions.quality = 1;
pngSaveOptions.PNG8 = false; //24 bit PNG
pngSaveOptions.transparency = true;
activeDocument.saveAs(saveFile, pngSaveOptions, true, Extension.LOWERCASE);
}
function zeroPad(n, s) {
n = n.toString();
while (n.length < s) n = '0' + n;
return n;
};
Visit here for complete post.

Have you tried using Photoshop Actions? I don't now about the scanning part, but the rest can all be done by actions quite easily.

Related

Automating Photoshop to edit en rename +600 files with the name of the folder

I have +600 product images on my mac already cut out and catalogued in their own folder. They are all PSD's and I need a script that will do the following.
Grab the name of the folder
Grab all the PSD's in said folder
Combine them in one big PSD in the right order (the filenames are saved sequentially as 1843, 1845, 1846 so they need to open in that order)
save that PSD
save the separate layers as PNG with the name from the folder + _1, _2, _3
I have previous experience in Bash (former Linux user) and tried for hours in Automator but to no success.
Welcome to Stack Overflow. The quick answer is yes this is possible to do via scripting. I might even suggest breaking down into two scripts, one to grab and save the PSDs and the second to save out the layers.
It's not very clear about "combining" the PSDs or about "separate layers, only I don't know if they are different canvas sizes, where you want each PSD to be positioned (x, y offsets & layering) Remember none of use have your files infront of us to refer from.
In short, if you write out pseudo code of what is it you expect your code to do it makes it easier to answer your question.
Here's a few code snippets to get you started:
This will open a folder and retrieve alls the PSDs as an array:
// get all the files to process
var folderIn = Folder.selectDialog("Please select folder to process");
if (folderIn != null)
{
var tempFileList = folderIn.getFiles();
}
var fileList = new Array(); // real list to hold images, not folders
for (var i = 0; i < tempFileList.length; i++)
{
// get the psd extension
var ext = tempFileList[i].toString();
ext = ext.substring(ext.lastIndexOf("."), ext.length);
if (tempFileList[i] instanceof File)
{
if (ext == ".psd") fileList.push (tempFileList[i]);
// else (alert("Ignoring " + tempFileList[i]))
}
}
alert("Files:\n" + fileList.length);
You can save a png with this
function save_png(afilePath)
{
// Save as a png
var pngFile = new File(afilePath);
pngSaveOptions = new PNGSaveOptions();
pngSaveOptions.embedColorProfile = true;
pngSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
pngSaveOptions.matte = MatteType.NONE; pngSaveOptions.quality = 1;
activeDocument.saveAs(pngFile, pngSaveOptions, false, Extension.LOWERCASE);
}
To open a psd just use
app.open(fileRef);
To save it
function savePSD(afilePath)
{
// save out psd
var psdFile = new File(afilePath);
psdSaveOptions = new PhotoshopSaveOptions();
psdSaveOptions.embedColorProfile = true;
psdSaveOptions.alphaChannels = true;
activeDocument.saveAs(psdFile, psdSaveOptions, false, Extension.LOWERCASE);
}

Is there a better way to fix my AS2 preloader?

I have a game with a preloader in scene 1, with the following code on the time line.
stop();
loadingBar._xscale = 1;
var loadingCall:Number = setInterval(preloadSite, 50);
function preloadSite():Void {
var siteLoaded:Number = _root.getBytesLoaded();
var siteTotal:Number = _root.getBytesTotal();
var percentage:Number = Math.round(siteLoaded/siteTotal*100);
loadingBar._xscale = percentage;
bytesDisplay.text = percentage + "%";
if (siteLoaded >= siteTotal) {
clearInterval(loadingCall);
gotoAndPlay("StartMenu", 1);
}
}
The code works fine when there are no music files linked to frame 1. If there are music files linked, then everything loads before the preloader shows up.
I found this great webpage about preloaders, which speaks about the linkage issue, and suggests I put all the big files on frame 2, after the preloader, then skip them. I put my large files on frame 2 as suggested and the preloader worked again.
My question is, is there a better way to do this. This solution seems like a hack.
The only better option I can think of, is to NOT store the MP3 file in your Flash file, but rather load it in your preloader with your flash file's content. This is provided that you're storing your MP3 file somewhere else online (like on a server).
stop();
loadingBar._xscale = 1;
var sound:Sound = new Sound();
sound.loadSound("http://www.example.com/sound.mp3", false);
var loadingCall:Number = setInterval(preloadSite, 50);
function preloadSite():Void {
var siteLoaded:Number = _root.getBytesLoaded()+sound.getBytesLoaded();
var siteTotal:Number = _root.getBytesTotal()+sound.getBytesTotal();
var percentage:Number = Math.round(siteLoaded / siteTotal * 100);
loadingBar._xscale = percentage;
bytesDisplay.text = percentage + "%";
if (siteLoaded >= siteTotal) {
clearInterval(loadingCall);
gotoAndPlay("StartMenu", 1);
sound.start();
}
}

Identify and extract or delete pages of a PDF based on a search string / text (action / javascript)

Good Evening (UK)
I'm trying to filter down a 1500+ page PDF file to only the pages which include a certain text string (typically one or two words). My laptop is locked down with respect to installing more software BUT I have used action(script)s quite a bit
I get the error below when I try to install this action into Abobe Acrobat X Pro (Win 7):
screen dump of error
called "Extract Commented Pages"... supposed to be OK for X and XI this looks like what I want.....
I wondered if there was something simple causing the problem but the actionscript file is rather... busy to say the least.
I used to have an action that I think was based on a legal redaction script but it is filed somewhere!
If you have already got an action that does this or a version of the above that doesn't give the error I get (unable to import the Action.... The file is either invalid or corrupt) I will forever by indebted to your gratitude
Many thanks, have a good weekend!
I recently came across a script found at the following link: http://forums.adobe.com/thread/1077118
I'm having some issues getting the script to run in Acrobat, despite everything looking alright in the script itself. I'll update if I find any errors.
Here is a copy of the script:
// Set the word to search for here
var sWord = "forms";
// Source document = current document
var sd = this;
var nWords, currWord, fp, fpa = [], nd;
var fn = sd.documentFileName.replace(/\.pdf$/i, "");
// Loop through the pages
for (var i = 0; i < sd.numPages; i += 1) {
// Get the number of words on the page
nWords = sd.getPageNumWords(i);
// Loop through the words on the page
for (var j = 0; j < nWords; j += 1) {
// Get the current word
currWord = sd.getPageNthWord(i, j);
if (currWord === sWord) {
// Extract the current page to a new file
fp = fn + "_" + i + ".pdf";
fpa.push(fp);
sd.extractPages({nStart: i, nEnd: i, cPath: fp});
// Stop searching this page
break;
}
}
}
// Combine the individual pages into one PDF
if (fpa.length) {
// Open the document that's the first extracted page
nd = app.openDoc({cPath: fpa[0], oDoc: sd});
// Append any other pages that were extracted
if (fpa.length > 1) {
for (var i = 1; i < fpa.length; i += 1) {
nd.insertPages({nPage: i - 1, cPath: fpa[i], nStart: 0, nEnd: 0});
}
}
// Save to a new document and close this one
nd.saveAs({cPath: fn + "_searched.pdf"});
nd.closeDoc({bNoSave: true});
}

Adobe Illustrator - Scripting crashes when trying to fit to artboards command

activeDocument.fitArtboardToSelectedArt()
When calling this command, AI crashes on AI 5.1/6 32bit and 64bit versions. I can use the command from the menu. Has anyone encountered this? does anyone know of a work around?
The full code.
function exportFileToJPEG (dest) {
if ( app.documents.length > 0 ) {
activeDocument.selectObjectsOnActiveArtboard()
activeDocument.fitArtboardToSelectedArt()//crashes here
activeDocument.rearrangeArtboards()
var exportOptions = new ExportOptionsJPEG();
var type = ExportType.JPEG;
var fileSpec = new File(dest);
exportOptions.antiAliasing = true;
exportOptions.qualitySetting = 70;
app.activeDocument.exportFile( fileSpec, type, exportOptions );
}
}
var file_name = 'some eps file.eps'
var eps_file = File(file_name)
var fileRef = eps_file;
if (fileRef != null) {
var optRef = new OpenOptions();
optRef.updateLegacyText = true;
var docRef = open(fileRef, DocumentColorSpace.RGB, optRef);
}
exportFileToJPEG ("output_file.jpg")
I can reproduce the bug with AI CS5.
It seems that fitArtboardToSelectedArt() takes the index of an artboard as an optional parameter. When the parameter is set, Illustrator doesn't crash. (probably a bug in the code handling the situation of no parameter passed)
As a workaround you could use:
activeDocument.fitArtboardToSelectedArt(
activeDocument.artboards.getActiveArtboardIndex()
);
to pass the index of the active artboard with to the function. Hope this works for you too.
Also it's good practice to never omit the semicolon at the end of a statement.

Adobe AIR NativeProcess fails with spaces in arguments?

I have a problem running the NativeProcess if I put spaces in the arguments
if (Capabilities.os.toLowerCase().indexOf("win") > -1)
{
fPath = "C:\\Windows\\System32\\cmd.exe";
args.push("/c");
args.push(scriptDir.resolvePath("helloworld.bat").nativePath);
}
file = new File(fPath);
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
args.push("blah");
nativeProcessStartupInfo.arguments = args;
process = new NativeProcess();
process.start(nativeProcessStartupInfo);
in the above code, if I use
args.push("blah") everything works fine
if I use
args.push("blah blah") the program breaks as if the file wasn't found.
Seems like I'm not the only one:
http://tech.groups.yahoo.com/group/flexcoders/message/159521
As one of the users their pointed out, it really seems like an awful limitation by a cutting edge SDK of 21st century. Even Alex Harui didn't have the answer there and he's known to workaround every Adobe bug:)
Any ideas?
I am using AIR 2.6 SDK in JavaScript like this, and it is working fine even for spaces.
please check your code with this one.
var file = air.File.applicationDirectory;
file = file.resolvePath("apps");
if (air.Capabilities.os.toLowerCase().indexOf("win") > -1)
{
file = file.resolvePath(appFile);
}
var nativeProcessStartupInfo = new air.NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
var args =new air.Vector["<String>"]();
for(i=0; i<arguments.length; i++)
args.push(arguments[i]);
nativeProcessStartupInfo.arguments = args;
process = new air.NativeProcess();
process.addEventListener(air.ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
process.addEventListener(air.ProgressEvent.STANDARD_INPUT_PROGRESS, inputProgressListener);
process.start(nativeProcessStartupInfo);
To expand on this: The reason that this works (see post above):
var args =new air.Vector["<String>"]();
for(i=0; i<arguments.length; i++)
args.push(arguments[i]);
nativeProcessStartupInfo.arguments = args;
is that air expects that the arguments being passed to the nativeProcess are delimited by spaces. It chokes if you pass "C:\folder with spaces\myfile.doc" (and BTW for AIR a file path for windows needs to be "C:\\folder with spaces\\myfile.doc") you would need to do this:
args.push("C:\\folder");
args.push("with");
args.push("spaces\\myfile.doc");
Hence, something like this works:
var processArgs = new air.Vector["<String>"]();
var path = "C:\\folder with spaces\\myfile.doc"
var args = path.split(" ")
for (var i=0; i<args.length; i++) {
processArgs.push(args[i]);
};
UPDATE - SOLUTION
The string generated by the File object by either nativePath or resolvePath uses "\" for the path. Replace "\" with "/" and it works.
I'm having the same problem trying to call 7za.exe using NativeProcess. If you try to access various windows directories the whole thing fails horribly. Even trying to run command.exe and calling a batch file fails because you still have to try to pass a path with spaces through "arguments" on the NativeProcessStartupInfo object.
I've spent the better part of a day trying to get this to work and it will not work. Whatever happens to spaces in "arguments" totally destroys the path.
Example 7za.exe from command line:
7za.exe a MyZip.7z "D:\docs\My Games\Some Game Title\Maps\The Map.map"
This works fine. Now try that with Native Process in AIR. The AIR arguments sanitizer is FUBAR.
I have tried countless ways to put in arguments and it just fails. Interesting I can get it to spit out a zip file but with no content in the zip. I figure this is due to the first argument set finally working but then failing for the path argument.
For example:
processArgs[0] = 'a';
processArgs[1] = 'D:\apps\flash builder 4.5\project1\bin-debug\MyZip.7z';
processArgs[2] = 'D:\docs\My Games\Some Game Title\Maps\The Map.map';
For some reason this spits out a zip file named: bin-debugMyZip.7z But the zip is empty.
Whatever AIR is doing it is fraking up path strings. I've tried adding quotes around those paths in various ways. Nothing works.
I thought I could fall back on calling a batch file from this example:
http://technodesk.wordpress.com/2010/04/15/air-2-0-native-process-batch-file/
But it fails as well because it still requires the path to be passed through arguments.
Anyone have any luck calling 7z or dealing with full paths in the NativeProcess? All these little happy tutorials don't deal with real windows folder structure.
Solution that works for me - set path_with_space as "nativeProcessStartupInfo.workingDirectory" property. See example below:
public function openPdf(pathToPdf:String):void
}
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
var file:File = File.applicationDirectory.resolvePath("C:\\Windows\\System32\\cmd.exe");
nativeProcessStartupInfo.executable = file;
if (Capabilities.os.toLowerCase().indexOf("win") > -1)
{
nativeProcessStartupInfo.workingDirectory = File.applicationDirectory.resolvePath(pathToPdf).parent;
var processArgs:Vector.<String> = new Vector.<String>();
processArgs[0] = "/k";
processArgs[1] = "start";
processArgs[2] = "test.pdf";
nativeProcessStartupInfo.arguments = processArgs;
process = new NativeProcess();
process.start(nativeProcessStartupInfo);
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
}
args.push( '"blah blah"' );
Command line after all supports spaces if they are nested whithin "".
So if lets say you have a file argument :
'test/folder with space/blah'
Convert it to the following
'test/"folder with space"/blah'
Optionally use a filter:
I once had a problem like this in AIR, i just simply filter the text before i push it into the array. My refrence use CASA lib though
import org.casalib.util.ArrayUtil;
http://casalib.org/
/**
* Filters a string input for 'safe handling', and returns it
**/
public function stringFilter(inString:String, addPermitArr:Array = null, permitedArr:Array = null):String {
var sourceArr:Array = inString.split(''); //Splits the string input up
var outArr:Array = new Array();
if(permitedArr == null) {
permitedArr = ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" as String).split('');
}
if( addPermitArr != null ) {
permitedArr = permitedArr.concat( addPermitArr );
}
for(var i:int = 0; i < sourceArr.length; i++) {
if( ArrayUtil.contains( permitedArr, sourceArr[i] ) != 0 ) { //it is allowed
outArr.push( sourceArr[i] );
}
}
return (outArr.join('') as String);
}
And just filter it via
args.push( stringFilter( 'blah blah', new Array('.') ) );
Besides, it is really bad practice to use spaces in file names / arguments, use '_' instead. This seems to be originating from linux though. (The question of spaces in file names)
This works for me on Windws7:
var Xargs:Array = String("/C#echo#a trully hacky way to do this :)#>#C:\\Users\\Benjo\\AppData\\Roaming\\com.eblagajna.eBlagajna.POS\\Local Store\\a.a").split("#");
var args:Vector.<String> = new Vector.<String>();
for (var i:int=0; i<Xargs.length; i++) {
trace("Pushing: "+Xargs[i]);
args.push(Xargs[i]);
};
NPI.arguments = args;
If your application path or parameter contains spaces, make sure to wrap it in quotes. For example path of the application has spaces C:\Program Files (x86)\Camera\Camera.exe use quotes like:
"C:\Program Files (x86)\Camera\Camera.exe"