Indesign CS6 Scripting - Exporting images - javascript

I'm having trouble writing a js script in indesign cs6 to export my formatted images. the code below (found on this website and slightly modified) only opens the document.
ideally the script would loop through all of the formatted/cropped images in my document and export them into a new folder on the desktop, but with the original file names.
any help would be much appreciated:
test();
function test(){
var myDoc = app.open('/Users/StudioA/Desktop/file.indd');
var myGroups = myDoc.groups;
//for each group...
for (var i = 0;i < myGroups.length; i++){
// for each rectangle in the group...
for(var r = 0; r< myGroups[i].rectangles.length; r++){
var myRect = myGroups[i].rectangles[r];
app.jpegExportPreferences.exportResolution = 300;
app.jpegExportPreferences.jpegQuality = JPEGOptionsQuality.MAXIMUM;
//give it a unique name
var myFile = new File('/Users/StudioA/Desktop/Export/' + myRect.name + '.jpg');
myRect.exportFile(ExportFormat.JPG, myFile);
}
}
}

The file name isn't located on the rectangle but on the link related to the placed graphic.
This should do what you want given an open document:
test();
function test() {
var myDoc = app.activeDocument, apis = myDoc.allPageItems, rect, fileName;
while ( rect = apis.pop() )
{
if ( !(rect instanceof Rectangle) || !rect.graphics[0].isValid ){ continue; }
fileName = File ( rect.graphics[0].itemLink.filePath ).name;
fileName = fileName.replace( /\.[a-z]{2,4}$/i, '.jpg' );
app.jpegExportPreferences.exportResolution = 300;
app.jpegExportPreferences.jpegQuality = JPEGOptionsQuality.MAXIMUM;
//give it a unique name
var myFile = new File (Folder.desktop+"/"+ fileName);
rect.exportFile(ExportFormat.JPG, myFile);
}
}

Just adding my verbose version of this, which works from the current selection in InDesign and provides console feedback. It renames the images with the prefix "crop_" and saves them to ~/temp
exportSelectedImages();
function exportSelectedImages() {
// configure export settings
app.jpegExportPreferences.exportResolution = 72;
app.jpegExportPreferences.jpegQuality = JPEGOptionsQuality.HIGH;
// collect selected objects
var selected = app.activeDocument.selection;
$.writeln("Got " + selected.length + " selected objects...");
// process selected objects
for (var i = 0; i < selected.length; i++) {
var cursor = selected[i];
var img = cursor.images;
$.writeln("Processing #" + (i+1) + "/" + selected.length);
$.writeln("\t Type: " + cursor.constructor.name);
// verify if object contains an image or not
if (cursor.images.length > 0) {
var img = cursor.images[0];
$.writeln("\t Contains image of type " + img.imageTypeName);
var imageFileName = cursor.images[0].itemLink.name;
$.writeln("\t File Name: " + imageFileName);
} else {
$.writeln("\t Not an image");
}
// save the object to a jpeg in path specified below
var myFile = new File('~/temp/' + "crop_" + imageFileName + '.jpg');
cursor.exportFile(ExportFormat.JPG, myFile);
}
$.writeln("Done.");
}

Related

Comparing JPG files with Photoshop Layers

Is it possible to compare filenames for a set of files that are imported as Photoshop layers ?
I have a folder of 50 jpg images which I have used in a PSD file.
Now I want to check whether all the JPG files are used or not ?
Is it possible to do so ?
As I've said, Photoshop scripting can help you achieve this by using File Objects and basic javascript knowledge. I've modified my old script as you've desired and now it should work well with any nested groups and images.
I highly encourage you to learn scripting and ask questions here wherever you feels confused.
Save below code as 'Script.jsx' and run it from 'File > Scripts > Browse'
Update 2 : Now it saves log.txt file too as per you requested. P.S. Learn from this script and tweak it to your desired result.
// Managing Document
var docs = app.documents;
// Progress Bar
var win = new Window("window{text:'Progress',bounds:[100,100,400,150],bar:Progressbar{bounds:[20,20,280,31] , value:0,maxvalue:100}};");
// assigning activeDocument
if (docs.length != 0) {
var docRef = app.activeDocument;
// Defining the folder
alert("You will be prompted for the folder containing your images.\n" +
"Files will be selected with a '.png'/'.jpg/.jpeg' on the end in the same folder.");
var folder = Folder.selectDialog();
if (!folder) {
exit;
}
var photoFiles = folder.getFiles(/\.(jpg|jpeg|png)$/i);
var matchFiles = [];
var photoFilesName = [];
//Searching for used images
var increment = parseFloat(0);
var divider = parseFloat(100/photoFiles.length);
win.show();
for (var i = 0; i < photoFiles.length; i++) {
increment = increment + divider;
var indexPhotoName = removeExtension(photoFiles[i].displayName);
photoFilesName.push(indexPhotoName);
var doc = activeDocument;
var curLayer;
goThroughLayers(doc, indexPhotoName);
}
function goThroughLayers(parentLayer, targetName) {
for (var i = 0; i < parentLayer.layers.length; i++) {
curLayer = parentLayer.layers[i];
doc.activeLayer = curLayer;
if (curLayer.typename == 'LayerSet') {
goThroughLayers(curLayer, targetName)
} else {
if (curLayer.name == targetName) {
// if (curLayer.name.match(/[e]/ig)) {
matchFiles.push(targetName);
// }
} //end if
} //end else
} //end loop
} //end function
function arr_diff(a1, a2) {
var a = [],
diff = [];
for (var i = 0; i < a1.length; i++) {
a[a1[i]] = true;
}
for (var i = 0; i < a2.length; i++) {
if (a[a2[i]]) {
delete a[a2[i]];
} else {
a[a2[i]] = true;
}
}
for (var k in a) {
diff.push(k);
}
return diff;
}
function removeExtension(str) {
return str.split('.').slice(0, -1).join('.');
}
var missItems = arr_diff(matchFiles, photoFilesName);
if (missItems.length > 0) {
var missFolder = new Folder(photoFiles[0].path + '/Missed%20Files');
if(!missFolder.exists){
missFolder.create();
}
for (var y = 0; y < photoFiles.length; y++) {
var photoTrimName = removeExtension(photoFiles[y].displayName);
for( var x = 0; x < missItems.length ; x++){
if(photoTrimName == missItems[x]){
photoFiles[y].copy(new File(missFolder+'/'+photoFiles[y].displayName));
}
}
};
win.close();
alert("You've missed total " + missItems.length + " files. Press OK to open folder containing missing files. Log report is generated wherever PSD is saved.");
var FileStr = "";
for(var m=0; m<missItems.length; m++){
FileStr = FileStr + '\n' + (m+1) + '. ' + missItems[m];
}
var str = "Your missed files are : " + FileStr;
saveTxt(str);
missFolder.execute();
} else {
win.close();
saveTxt('All Photos are used');
alert('All Photos are used');
}
} else {
alert('Open atleast one document');
}
function saveTxt(txt)
{
var Name = "LogReport_" + app.activeDocument.name.replace(/\.[^\.]+$/, '');
var Ext = decodeURI(app.activeDocument.name).replace(/^.*\./,'');
if (Ext.toLowerCase() != 'psd')
return;
var Path = app.activeDocument.path;
var saveFile = File(Path + "/" + Name +".txt");
if(saveFile.exists)
saveFile.remove();
saveFile.encoding = "UTF8";
saveFile.open("e", "TEXT", "????");
saveFile.writeln(txt);
saveFile.close();
}
In Javascript, it is possible to get some information related to PSD file layers using PSD.js library

export separate art boards as PNG illustrator script

I've created to a simple illustrator script to loop through the artboards and export each as a PNG back into the folder that the original illustrator file is in. At least I thought I had. I don't need to do anything complicated with layers or different formats this is just a speed up production sort of a thing. I'm a bit rusty on .jsx and appreciate there are similar solutions out there, but I can't get this to run. It seems to fail on the doc.ExportFile line but I really can't see what I'm doing wrong. I'd appreciate anyone taking a look:
var doc = activeDocument;;//Gets the active document
var numArtboards = doc.artboards.length;//returns the number of artboards in the document
var basePath = new File($.fileName).parent.fsName;
$.writeln(doc)
var options;
options = new ExportOptionsPNG24();
options.artBoardClipping = true;
options.matte = false;
options.horizontalScale = 100;
options.verticalScale = 100;
options.transparency = true;
for (var i = 0; i < numArtboards; i++ ) {
doc.artboards.setActiveArtboardIndex( i );
var artboardName = doc.artboards[i].name;
var destFile = new File('/' + artboardName + ".png");
doc.exportFile(destFile, ExportFormat.PNG24 , options);
}
The main problem seemed to be that you hve to have a destination path with the file name. This now seems to work: (You may need to altter the fileNamr generation as code just gets the first nune letters of a filename)
var doc = app.activeDocument;;//Gets the active document
var fleName = doc.name.slice(0, 9)//Get the file code number not the full name;
var numArtboards = doc.artboards.length;//returns the number of artboards in the document
var filePath = (app.activeDocument.fullName.parent.fsName).toString().replace(/\\/g, '/');
$.writeln("fleName= ",fleName)
$.writeln("numArtboards= ",numArtboards)
$.writeln("filePath= ",filePath);
var options = new ExportOptionsPNG24();
for (var i = 0; i < numArtboards; i++ ) {
doc.artboards.setActiveArtboardIndex( i );
options.artBoardClipping = true;
options.matte = false;
options.horizontalScale = 100;
options.verticalScale = 100;
options.transparency = true;
var artboardName = doc.artboards[i].name;
$.writeln("artboardName= ", artboardName);
var destFile = new File(filePath + "/" + fleName + " " + artboardName + ".png");
$.writeln("destFile= ",destFile);
doc.exportFile(destFile,ExportType.PNG24,options);
}

Script runs extremely slow, needs to be more efficient

Goal:
My script takes every folder and layer in photoshop, gets the center point coordinates, and saves them to a txt file.
Issue:
The script works very well and gives the exact data I need. However, the script runs extremely slow when I have lots of photoshop layers. For example I ran the script on a PSD that has lets say 200 small layers. This took about 20 minutes to get the output text file that I need. MY question, and bare in mind I am not a programmer, is how to increase the efficiency of this code, and have this run faster.
Here is a Sample of the Output Data:
1 -MUD ROOM/GARAGE: 483.5x,559y
130A: 307.5x,681y
Lighting_icon_square_4x copy 19: 382x,749y
Lighting_icon_square_4x copy 19: 382x,681y
Lighting_icon_square_4x copy 19: 382x,613y
Lighting_icon_square_4x copy 18: 233x,749y
Lighting_icon_square_4x copy 17: 233x,681y
Lighting_icon_square_4x copy 13: 233x,613y
The Code:
// Bring application forward
app.bringToFront();
// Set active Document variable and decode name for output
var docRef = app.activeDocument;
var docName = decodeURI(activeDocument.name).slice(0, -4);
// Define pixels as unit of measurement
var defaultRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
// Define variable for the number of layers in the active document
var layerNum = app.activeDocument.artLayers.length;
// Define variable for the active layer in the active document
var layerRef = app.activeDocument.activeLayer;
// Define varibles for x and y of layers
var x = (layerRef.bounds[2].value) - (layerRef.bounds[0].value);
var y = (layerRef.bounds[3].value) - (layerRef.bounds[1].value);
var coords = "";
// Loop to iterate through all layers
function recurseLayers(currLayers) {
for ( var i = 0; i < currLayers.layers.length; i++ ) {
layerRef = currLayers.layers[i];
x = (layerRef.bounds[2].value) - (layerRef.bounds[0].value);
y = (layerRef.bounds[3].value) - (layerRef.bounds[1].value);
coords += layerRef.name + ": " + (layerRef.bounds[0].value + x/2) + "x" + "," + (layerRef.bounds[1].value + y/2) + "y" + "\n";
//test if it's a layer set
if ( isLayerSet(currLayers.layers[i]) ) {
recurseLayers(currLayers.layers[i]);
}
}
}
//a test for a layer set
function isLayerSet(layer) {
try {
if ( layer.layers.length > 0 ) {
return true;
}
}
catch(err) {
return false;
}
}
// Ask the user for the folder to export to
var FPath = Folder.selectDialog("Save exported coordinates to");
// Detect line feed type
if ( $.os.search(/windows/i) !== -1 ) {
fileLineFeed = "Windows";
}
else {
fileLineFeed = "Macintosh";
}
// Export to txt file
function writeFile(info) {
try {
var f = new File(FPath + "/" + docName + ".txt");
f.remove();
f.open('a');
f.lineFeed = fileLineFeed;
f.write(info);
f.close();
}
catch(e){}
}
// Run the functions
recurseLayers(docRef);
preferences.rulerUnits = defaultRulerUnits; // Set preferences back to user 's defaults
writeFile(coords);
// Show results
if ( FPath == null ) {
alert("Export aborted", "Canceled");
}
else {
alert("Exported " + docName + " x/y coordinates to " + FPath + "/" + docName + ".txt ");
}
For the sake of other readers facing performance bugs, I've shortened your code up a bit. This runs fast on my machine.
function main() {
var file = File.saveDialog("Save exported coordinates");
if (file == null) return;
if (!file.open('w')) {
alert("Aborted", "Could not write file.");
return;
}
write(activeDocument.layers, file);
alert("Exported x/y coordinates to " + file.path);
}
function write(layers, file) {
for (var i = 0; i < layers.length; i++) {
var layer = layers[i];
var width = layer.bounds[2] - layer.bounds[0];
var height = layer.bounds[3] - layer.bounds[1];
file.write(layer.name + ": " + (layer.bounds[0] + width / 2).value +
"x, " + (layer.bounds[1] + height / 2).value + "y\n");
if (layer instanceof LayerSet) {
write(layer.layers, file);
}
}
}
main();

Cached data:url image not being loaded onto page

I made this code to take images from the page, convert them into data:url (what was it again... base64 encoded string), and save into localStorage. Then when the page is reloaded it should load the images from the localstorage and set the now empty image placeholders with the data:url image.
Issue now is that the images do not load and if you check the dimensions for the data:url image it is 300x150 when it was originally 40x40.
Here's the code:
var isChached, // Checks is the page's images have been chached into localStorage
isChangesd; // Checks if any images have been deleted or added to the
var img = [], // Used for loading from saved. img[] holds data:url image versions of the...
src = [], // ...images in src[]
saved = [], // All images that are to be saved are placed here
add = [], // New images are placed here
rem = []; // Images to be removed are placed here
var cnv = document.createElement("canvas");
ctx = cnv.getContext("2d");
if (window.localStorage) {
// Base Object
function Saver (width,height,path) {
this.width = width;
this.height = height;
this.src = path;
}
// These fucnctions will help you save, load, and convert the images to data:url
function save (_str) { // Saves to localStorage. _str is the key to which to save to. _path is the value that you plan on saving
var str = _str;
str += ""; // This way even if I input a none string value it is still converted into string
localStorage.setItem(str,JSON.stringify(saved));
} // Checks if this image isn't in the saved cache
function singleLoad(a,b) {
}
function loader (_str) { // Loads images from localStorage. _str is the key to be loaded
var str = _str;
str += ""; // This way even if I input a none string value it is still converted into string
var val = JSON.parse(localStorage.getItem(str)); // Save the now loaded and parsed object str into val
console.log('val '+JSON.stringify(val));
val.splice(0,1);
console.log('val2 '+JSON.stringify(val));
for (var i in val) { // Take loaded information and place it into it's proper position
img[i] = new Image(val[i].width,val[i].height);
img[i].src = val[i].src;
setTimeout(function () {
var imgs = document.getElementsByTagName("img"); // Get all images
for (var k = 0; k < imgs.length; k++) {
if (imgs[i].id == i) { // If the id is equal to the index name of the src[]
imgs[k].src = val[i].src;
imgs[k].height = img[i].height;
imgs[k].width = img[i].width;
console.log("array: "+imgs[i]+". img[i]"+img[i]);
}
}
},2000);
}
}
function addToAdd(_id,_path) { // Places on-page images into src[]
var id = _id;
id += ""; // Makes sure that the id variable is a string
var path = _path;
path += ""; // Makes sure that the path variable is a string
add[id] = new Image();
add[id].src = path;
var imgs = document.getElementsByTagName("img");
console.log(imgs);
for (var i = 0; i < imgs.length; i++) { // adds width and height attributes
if (imgs[i].id == id) {
setDim(add[id],imgs[i].width,imgs[i].height); // Send info to setDim()
}
}
}
// Not using this
function apply() { // takes images from img after being loaded and adds them to the page.
var images = document.getElementsByTagName("img");
for (var i = 0; i < images.length; i++) { // Check through the page's images
for (var k in img) { // Check through the img[] where the loaded images are now saved
if (images[i].id = k) { // Check if the id of the image on the page is
images[i].width = img[k].width;
images[i].height = img[k].height;
images[i].src = img[k].src;
console.log("source: "+images[i].src);
console.log("images: "+images[i]+". saved images "+img[k]);
}
}
}
}
function setDim(obj,w,h) { // Sets the dimension(width = w; height = h;) for obj (image object)
obj.width = w;
obj.height = h;
}
function saveToSrc(_id,_path,w,h) { // Places on-page images into src[]
var id = _id,data;
id += ""; // Makes sure that the id variable is a string
var path = _path;
path += ""; // Makes sure that the path variable is a string
src[id] = new Image();
src[id].src = path;
console.log("src image " + src[id]);
var imgs = document.getElementsByTagName("img");
console.log("page images " + imgs);
for (var i = 0; i < imgs.length; i++) { // adds width and height attributes
if (imgs[i].id == id) {
setDim(src[id],imgs[i].width,imgs[i].height); // Send info to setDim()
src[id].addEventListener("load",function() { // We convert images to data:url
console.log("saved image " + src);
ctx.drawImage(src[id],0,0,w,h);
data = cnv.toDataURL();
console.log("saved src " + data +" src width and height: "+src[id].width+","+src[id].height);
saved[id] = new Saver(src[id].width + "px",src[id].height + "px",data);
console.log("saver array: "+saved[id]);
})
}
}
}
function loadToPage(a) {
var imgs = document.getElementsByTagName("img"); // Get all images. Use this to change image src and dimensions
for (var i in a) { // Go through the a[] and load all the images inside onto page
for (var k = 0; k < imgs.length; k++) {
if (imgs[k].id == i) {
imgs[k].src = a[i].src;
imgs[k].height = a[i].height;
imgs[k].width = a[i].width;
}
}
}
}
// Here you place ID and path/location values into the src[] using the saveToSrc(). You can place the parameters in with quotation marks or without quotation marks
// **N.B** the location link will have to be changed to it's absolute form so that even if a 'scraper' gets our webpage the links still come to us \o/
if (localStorage.getItem("cached") == null) { // Check if the "cached" key exists.
// If it doesn't exist...
isCached = false;
localStorage.setItem("cached","true");
} else {
// ...If it does exist
isCached = true;
}
if (!isCached) {
// Now you take images from server and load onto page. And then save them.
window.onload = function() {
saveToSrc("1","img/1.png",40,40);
saveToSrc("2","img/2.png",40,40);
saveToSrc("3","img/3.png",40,40);
saveToSrc("4","img/4.png",40,40);
console.log("src "+src);
console.log("saved array " + saved);
loadToPage(src);
setTimeout(function() {
save('saved');
},3000)
}
}
/* Will Be Added Later. Same time as local host */
else {
window.onload = function (){
setTimeout(function() {
loader("saved");
apply
},3000)
}
}
}
I'm quite new to javascript(started using javascript this June, or was it May. anyways...) so please relax on the terminology.
To recap: Images saving correctly(-ish), not loading, and wrong image sizes saved

How to .setValue of a cell in spreadsheets being copied/named in a for loop?

I (with help) created a script that creates folders, copies a file 15 times, renames the file, and puts the new renamed files into the folders it created.
I am trying to edit the script so it uses .setValue to edit the new file it has copied, setting the "I9" cell of the new copied files to:
.setValue('=IMPORTRANGE("ID", "Question Details!C' + j + 3 + ':AX' + j + 3 + ')');
I don't know how to edit the newly created spreadsheets as its looping through and creating them. I'm not sure how to edit a sheet that is an "object" in the script. When I would run the script, it would say it couldn't get copySheet.getRange(1,9,1,1); of an object.
Now, I was trying to use "J" from the for loop in the new formula added to this cell so I can get it to increase dynamically according to the value of "J" and I can't get it to work. (This for loop is used to increase the number in the name of the sheet already) I'm sure that my syntax is way off. But, forgive me. I am still learning and really enjoy learning from the help on SO.
I also wondered if it made more sense to set it to loop through the these new folders/files afterwards and edit the "I9" cell in each? Not sure...
SCRIPT BELOW
The code that I tried to add in script is notated at the bottom of the script. I'm sure it's way off base, but I'm trying. Any help you guys could give me would be much appreciated!
Thanks!
Brandon
var folderIds = [];
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('Data System Tool')
.addItem('Create Data System Folders', 'copyAndRenameTemplate')
.addToUi();
}
function copyAndRenameTemplate() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = ss.getSheetByName('Sheet1');
var rangeOfFileNames = ss.getRange("B4:B");
var twoD_Array = rangeOfFileNames.getValues();
var arrayOfFileNames = twoD_Array.join().split(",");
var folderType = theSheet.getRange(2,1);
var cell = folderType.getValue();
Logger.log(folderType);
Logger.log(cell);
// throw new Error('Script Halted! Check out the logs!!');
var fldrNamesRng = theSheet.getRange(4,1,theSheet.getLastRow()-3,1);
Logger.log('fldrNamesRng: ' + fldrNamesRng);
var folderNames = fldrNamesRng.getValues();
Logger.log('folderNames: ' + folderNames);
var oneD_FolderNames = folderNames.join().split(",");
Logger.log('oneD_FolderNames: ' + oneD_FolderNames);
makeTheFolders(oneD_FolderNames);
putFilesIntoFolders(oneD_FolderNames);
};
function makeTheFolders(theFolderNames,cell) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = ss.getSheetByName('Sheet1');
var folderType = theSheet.getRange(2,1);
var cell = folderType.getValue();
var i=0,
folderObj;
for (i=0;i<theFolderNames.length;i+=1) {
folderObj = DriveApp.createFolder(theFolderNames[i] + " " + cell);
folderIds.push(folderObj.getId())
};
};
function putFilesIntoFolders(arrayOfFolderNames,theFolderNames,cell) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = ss.getSheetByName('Sheet1');
var folderType = theSheet.getRange(2,1);
var cell = folderType.getValue();
var file = DriveApp.getFileById("File to Copy");
var dest_folder = "";
var baseFileName = "",
newfile,
newFileName = "",
i=0,
j=0;
for (i=0;i<arrayOfFolderNames.length;i+=1) {
var source_folder = DriveApp.getFolderById("Folder that has File to be Copied");
dest_folder = DriveApp.getFolderById(folderIds[i]);
Logger.log('dest_folder' + dest_folder);
baseFileName = arrayOfFolderNames[i];
for (j=1; j<16; j+=1) {
var newFileName = baseFileName + " " + cell + " " + j.toString();
var fileCopy = file.makeCopy();
/* Code I tried */
// var copyID = fileCopy.getId();
// var copySs = DriveApp.getFileById(copyID);
// var copySheet = copySs.getSheets()[0];
// var copyCell = copySheet.getRange(1,9,1,1);
// copyCell.setValue('=IMPORTRANGE("ID", "Question Details!C' + j + 3 + ':AX' + j + 3 + ')');
var namedFileCopy = fileCopy.setName("_" + newFileName);
if (j<10) {
dest_folder.addFile(namedFileCopy);
source_folder.removeFile(fileCopy);
} else {
var namedFileCopy = fileCopy.setName(newFileName);
dest_folder.addFile(namedFileCopy);
source_folder.removeFile(fileCopy);
};
};
};
};
You've got the right idea, you just need to make sure you open the new (copied) spreadsheet as a Spreadsheet object so that you can use Spreadsheet methods on it.
Instead of:
var copySs = DriveApp.getFileById(copyID);
Use:
var copySs = SpreadsheetApp.openById(copyID);
By doing so, copySs will be a variable that represents a Spreadsheet object, and the other lines you already wrote will actually make sense!
var copySheet = copySs.getSheets()[0];
var copyCell = copySheet.getRange(1,9,1,1);
copyCell.setValue('=IMPORTRANGE("ID", "Question Details!C' + j + 3 + ':AX' + j + 3 + ')');

Categories