Copy link to clipboard
Copied
Hello !
I am working on a script that resizes the artboard (800x600) then adapts the size and position of an original JPG picture so that the artboard is fully covered by the picture.Then it is saved as SVG.
It works well on one file, but from the second file, it gets into an infinite loop, always prompting if I want to save as .AI.
Here is the base script (sorry for the uncleaned code with unused variables) :
sourceFolder = Folder.selectDialog();
// filesToProcess = sourceFolder.getFiles("*.ai");
var TypeList = prompt("Enter file types to act on","ai,eps,pdf,jpg,png","File Types");
var reg = new RegExp("\.(" + TypeList.replace(/,/g, '|') + ")$", 'i');
var filesToProcess = sourceFolder.getFiles(reg);
var x = 400;
var y = 300;
var w = 800;
var h = 600;
var userDesktop = Folder.desktop;
var f = new File(userDesktop+'/Satz 2.aia'); // make a file object first, using a string
// Create progress bar
var win = new Window("palette", "ProgressBar", [300, 150, 750, 280]);
win.pnl = win.add("panel", [10, 10, 440, 120], "Script Progress");
win.pnl.progBar = win.pnl.add("progressbar", [20, 35, 410, 60], 0, 100);
win.pnl.progBarLabel = win.pnl.add("statictext", [20, 20, 320, 35], "0%");
win.pnl.fileLabel = win.pnl.add("statictext", [20, 65, 410, 80], "File processed: none");
win.show();
// Increment through the files
for (i=0; i < filesToProcess.length; i++) {
app.open(filesToProcess);
app.activeDocument.artboards[0].artboardRect = [x, -y, (x + w), -(y + h)];
#include "fitObjectToArtboardBounds.jsx"
// Update open file info
win.pnl.fileLabel.text = "File: " + app.activeDocument.name;
// win.pnl.fileLabel = "File: " + doc.path; // Show full path
win.update();
var userDesktop = Folder.desktop;
var g = new File(userDesktop+'/Satz 4.aia'); // make a file object first, using a string
app.loadAction (g); // the argument here is a file object
app.doScript ('Aktion3', 'Satz 4');
app.activeDocument.close();
// Update progress bar
win.pnl.progBar.value = parseInt( (i/filesToProcess.length)*100 );
win.pnl.progBarLabel.text = win.pnl.progBar.value+"%";
win.update();
}
win.pnl.progBar.value = 100;
win.pnl.progBarLabel.text = win.pnl.progBar.value+"%";
win.update();
alert('Done!');
// Close progress bar
win.close(
// Update progress bar
win.pnl.progBar.value = parseInt( (i/filesToProcess.length)*100 );
win.pnl.progBarLabel.text = win.pnl.progBar.value+"%";
win.update();
}
win.pnl.progBar.value = 100;
win.pnl.progBarLabel.text = win.pnl.progBar.value+"%";
win.update();
alert('Done!');
// Close progress bar
win.close();
);
The linked fitObjectToArtboardBounds.jsx contains the following code, it is used to resize the picture :
var idoc = app.activeDocument;
var scriptID = "Random Select v0.2";
selec = idoc.selection;
if (idoc.selection.length == 0) {
for (i = 0; i < idoc.pageItems.length; i++) {
idoc.pageItems.selected = true;
}
}
selec = idoc.selection;
if (selec.length==1)
{
// get document bounds
var docw = idoc.width;
var doch = idoc.height;
var activeAB = idoc.artboards[idoc.artboards.getActiveArtboardIndex()]; // get active AB
docLeft = activeAB.artboardRect[0];
docTop = activeAB.artboardRect[1];
// get selection bounds
var sel = idoc.selection[0];
var selVB = sel.visibleBounds;
var selVw = selVB[2]-selVB[0];
var selVh = selVB[1]-selVB[3];
var selGB = sel.geometricBounds;
var selGw = selGB[2]-selGB[0];
var selGh = selGB[1]-selGB[3];
// get the difference between Visible & Geometric Bounds
var deltaX = selVw-selGw;
var deltaY = selVh-selGh;
if (sel.width > sel.height) {
var newHeight = doch-deltaY;
var ratio = sel.height / newHeight;
sel.height = newHeight;
sel.width = sel.width / ratio;
//var newWidth = docw-deltaX;
//var ratio = sel.width / newWidth;
//sel.width = newWidth; // width is Geometric width, so we need to make it smaller...to accomodate the visible portion.
//sel.height = sel.height / ratio;
} else {
var newHeight = doch-deltaY;
var ratio = sel.height / newHeight;
sel.height = newHeight;
sel.width = sel.width / ratio;
}
sel.top = (doch / 2) - (sel.height / 2);
sel.left = (docw / 2) - (sel.width / 2);
var userDesktop = Folder.desktop;
var f = new File(userDesktop+'/Satz 3.aia'); // make a file object first, using a string
app.loadAction (f); // the argument here is a file object
app.doScript ('Aktion1', 'Satz 3');
app.executeMenuCommand ('fitall');
}
else
{
alert("select ONE object before running");
}
And the Satz 4 Illustrator action is described here, it is used to save as SVG, Basically it is just made by recording a 2 clicks save, but it looks quite long in my opinion, though I do not understand what is written there :
/version 3
/name [ 6
5361747a2034
]
/isOpen 1
/actionCount 1
/action-1 {
/name [ 7
416b74696f6e33
]
/keyIndex 0
/colorIndex 0
/isOpen 1
/eventCount 1
/event-1 {
/useRulersIn1stQuadrant 0
/internalName (adobe_saveDocumentAs)
/localizedName [ 15
53706569636865726e20756e746572
]
/isOpen 1
/isOn 1
/hasDialog 1
/showDialog 0
/parameterCount 41
/parameter-1 {
/key 1766223220
/showInPalette -1
/type (enumerated)
/name [ 14
4149496d616765466f726d617473
]
/value 1
}
/parameter-2 {
/key 1349673843
/showInPalette -1
/type (enumerated)
/name [ 24
4149535647436f6f7264696e617465507265636973696f6e
]
/value 2
}
/parameter-3 {
/key 1382966386
/showInPalette -1
/type (enumerated)
/name [ 14
414953564752656e646572696e67
]
/value 1
}
/parameter-4 {
/key 1517252429
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-5 {
/key 1398359668
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-6 {
/key 1179869811
/showInPalette -1
/type (enumerated)
/name [ 19
4149535647466f6e7453756273657474696e67
]
/value 1
}
/parameter-7 {
/key 1179411316
/showInPalette -1
/type (enumerated)
/name [ 17
414953564746696c654c6f636174696f6e
]
/value 1
}
/parameter-8 {
/key 1164862308
/showInPalette -1
/type (enumerated)
/name [ 21
4149535647446f63756d656e74456e636f64696e67
]
/value 2
}
/parameter-9 {
/key 1131248238
/showInPalette -1
/type (enumerated)
/name [ 20
414953564746696c65436f6d7072657373696f6e
]
/value 1
}
/parameter-10 {
/key 1400132720
/showInPalette -1
/type (enumerated)
/name [ 10
41495356475374796c65
]
/value 3
}
/parameter-11 {
/key 1715891572
/showInPalette -1
/type (enumerated)
/name [ 15
4149535647466f6e74466f726d6174
]
/value 1
}
/parameter-12 {
/key 1131376761
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-13 {
/key 1467313748
/showInPalette -1
/type (enumerated)
/name [ 10
4149535647556e697473
]
/value 0
}
/parameter-14 {
/key 1215655508
/showInPalette -1
/type (enumerated)
/name [ 10
4149535647556e697473
]
/value 0
}
/parameter-15 {
/key 1383748980
/showInPalette -1
/type (enumerated)
/name [ 15
41495356475265736f6c7574696f6e
]
/value 0
}
/parameter-16 {
/key 1162233460
/showInPalette -1
/type (enumerated)
/name [ 21
4149535647456d626564466f6e74466f726d617473
]
/value 0
}
/parameter-17 {
/key 1146373236
/showInPalette -1
/type (enumerated)
/name [ 8
4149535647445444
]
/value 0
}
/parameter-18 {
/key 1380740963
/showInPalette -1
/type (enumerated)
/name [ 19
41495356475261737465724c6f636174696f6e
]
/value 1
}
/parameter-19 {
/key 1383289452
/showInPalette -1
/type (integer)
/value 72
}
/parameter-20 {
/key 1198675052
/showInPalette -1
/type (real)
/value 0.25
}
/parameter-21 {
/key 1416581236
/showInPalette -1
/type (enumerated)
/name [ 15
4149535647546578744f6e50617468
]
/value 0
}
/parameter-22 {
/key 1179929460
/showInPalette -1
/type (enumerated)
/name [ 13
4149535647466f6e7454797065
]
/value 1
}
/parameter-23 {
/key 1131639920
/showInPalette -1
/type (boolean)
/value 1
}
/parameter-24 {
/key 1129603426
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-25 {
/key 1383232626
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-26 {
/key 1097758832
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-27 {
/key 1415933300
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-28 {
/key 1449747799
/showInPalette 0
/type (raw)
/value < 16
00000000000000000000000000000000
>
/size 16
}
/parameter-29 {
/key 1232103270
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-30 {
/key 1230520656
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-31 {
/key 1230204003
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-32 {
/key 1229209931
/showInPalette -1
/type (boolean)
/value 1
}
/parameter-33 {
/key 1230262096
/showInPalette -1
/type (boolean)
/value 1
}
/parameter-34 {
/key 1230328692
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-35 {
/key 1196577654
/showInPalette -1
/type (boolean)
/value 1
}
/parameter-36 {
/key 1851878757
/showInPalette -1
/type (ustring)
/value [ 28
433a5c55736572735c6b6e617562765c4465736b746f705c74657374
]
}
/parameter-37 {
/key 1718775156
/showInPalette -1
/type (ustring)
/value [ 15
7376672066696c6520666f726d6174
]
}
/parameter-38 {
/key 1702392942
/showInPalette -1
/type (ustring)
/value [ 3
737667
]
}
/parameter-39 {
/key 1936548194
/showInPalette -1
/type (boolean)
/value 0
}
/parameter-40 {
/key 1935764588
/showInPalette -1
/type (boolean)
/value 1
}
/parameter-41 {
/key 1936875886
/showInPalette -1
/type (ustring)
/value [ 1
31
]
}
}
}
Would you have any idea where does this infinite loop come from ?
Many thanks in advance !
Kind regards,
Vincent.
I don't have time to go about testing it. but i have some quick recommendations just from taking a look.
clean out your for loop. the only things that should happen in a for loop should be things pertaining to that exact loop iteration. You have an include directive and a call to app.loadAction() inside the loop. since there's nothing unique about those lines, it's best to pull them outside the loop to increase efficiency and use less memory.
wrap your script in a container function to help avoid
...Copy link to clipboard
Copied
No idea ? I know that the message is quite long, but I can explain the problem more in details if needed. 🙂
Copy link to clipboard
Copied
I don't have time to go about testing it. but i have some quick recommendations just from taking a look.
clean out your for loop. the only things that should happen in a for loop should be things pertaining to that exact loop iteration. You have an include directive and a call to app.loadAction() inside the loop. since there's nothing unique about those lines, it's best to pull them outside the loop to increase efficiency and use less memory.
wrap your script in a container function to help avoid creating persistent global variables.
when you're writing your for loops, use 'var' when declaring the loop variable, otherwise you create a global variable that could be altered elsewhere and mess up the continuity of your loop. there's a decent chance this is where your infinite loop is happening. In fact, i just looked back at the function that you include, and that function also contains a for loop that redefines your global "i" variable at the beginning of the loop. your two for loops are stepping on each other, that's why you're getting an infinite loop.
try this out.
function container()
{
var sourceFolder = Folder.selectDialog();
// filesToProcess = sourceFolder.getFiles("*.ai");
var TypeList = prompt("Enter file types to act on","ai,eps,pdf,jpg,png","File Types");
var reg = new RegExp("\.(" + TypeList.replace(/,/g, '|') + ")$", 'i');
var filesToProcess = sourceFolder.getFiles(reg);
var x = 400;
var y = 300;
var w = 800;
var h = 600;
var userDesktop = Folder.desktop;
var f = new File(userDesktop+'/Satz 2.aia'); // make a file object first, using a string
function fitObjectToArtboardBounds()
{
var idoc = app.activeDocument;
var layers = idoc.layers;
var scriptID = "Random Select v0.2";
var selec = idoc.selection;
////
//always be careful looping elements at
//the document scope. this can lead to
//lots of problems
////
// if (idoc.selection.length == 0)
// {
// for (var i = 0; i < idoc.pageItems.length; i++)
// {
// idoc.pageItems.selected = true;
// }
// }
//try this for a little more reliability
for(var x=0,len=layers.length;x<len;x++)
{
layers
.hasSelectedArtwork = true; }
selec = idoc.selection;
if (selec.length == 1)
{
// get document bounds
var docw = idoc.width;
var doch = idoc.height;
var activeAB = idoc.artboards[idoc.artboards.getActiveArtboardIndex()]; // get active AB
docLeft = activeAB.artboardRect[0];
docTop = activeAB.artboardRect[1];
// get selection bounds
var sel = idoc.selection[0];
var selVB = sel.visibleBounds;
var selVw = selVB[2] - selVB[0];
var selVh = selVB[1] - selVB[3];
var selGB = sel.geometricBounds;
var selGw = selGB[2] - selGB[0];
var selGh = selGB[1] - selGB[3];
// get the difference between Visible & Geometric Bounds
var deltaX = selVw - selGw;
var deltaY = selVh - selGh;
if (sel.width > sel.height)
{
var newHeight = doch - deltaY;
var ratio = sel.height / newHeight;
sel.height = newHeight;
sel.width = sel.width / ratio;
//var newWidth = docw-deltaX;
//var ratio = sel.width / newWidth;
//sel.width = newWidth; // width is Geometric width, so we need to make it smaller...to accomodate the visible portion.
//sel.height = sel.height / ratio;
}
else
{
var newHeight = doch - deltaY;
var ratio = sel.height / newHeight;
sel.height = newHeight;
sel.width = sel.width / ratio;
}
sel.top = (doch / 2) - (sel.height / 2);
sel.left = (docw / 2) - (sel.width / 2);
app.doScript('Aktion1', 'Satz 3');
app.executeMenuCommand('fitall');
}
else
{
alert("select ONE object before running");
}
}
var userDesktop = Folder.desktop;
var g = new File(userDesktop+'/Satz 4.aia'); // make a file object first, using a string
app.loadAction (g); // the argument here is a file object
g = new File(userDesktop+'/Satz 3.aia'); // make a file object first, using a string
app.loadAction (g); // the argument here is a file object
// Create progress bar
var win = new Window("palette", "ProgressBar", [300, 150, 750, 280]);
win.pnl = win.add("panel", [10, 10, 440, 120], "Script Progress");
win.pnl.progBar = win.pnl.add("progressbar", [20, 35, 410, 60], 0, 100);
win.pnl.progBarLabel = win.pnl.add("statictext", [20, 20, 320, 35], "0%");
win.pnl.fileLabel = win.pnl.add("statictext", [20, 65, 410, 80], "File processed: none");
win.show();
// Increment through the files
for (var i=0; i < filesToProcess.length; i++) {
app.open(filesToProcess);
app.activeDocument.artboards[0].artboardRect = [x, -y, (x + w), -(y + h)];
// Update open file info
win.pnl.fileLabel.text = "File: " + app.activeDocument.name;
// win.pnl.fileLabel = "File: " + doc.path; // Show full path
win.update();
app.doScript ('Aktion3', 'Satz 4');
app.activeDocument.close();
// Update progress bar
win.pnl.progBar.value = parseInt( (i/filesToProcess.length)*100 );
win.pnl.progBarLabel.text = win.pnl.progBar.value+"%";
win.update();
}
win.pnl.progBar.value = 100;
win.pnl.progBarLabel.text = win.pnl.progBar.value+"%";
win.update();
alert('Done!');
// Close progress bar
win.close();
// Update progress bar
win.pnl.progBar.value = parseInt( (i/filesToProcess.length)*100 );
win.pnl.progBarLabel.text = win.pnl.progBar.value+"%";
win.update();
win.pnl.progBar.value = 100;
win.pnl.progBarLabel.text = win.pnl.progBar.value+"%";
win.update();
alert('Done!');
// Close progress bar
win.close();
}
container();
Copy link to clipboard
Copied
Hello williamadowling and thanks a lot for your answer 🙂 I tried your code and it indeed there is no more infinite loop, but now the picture is not resized and placed correctly on the artboard (the artboard is resized correctly though).
I have attached two screenshots, one showing the current result and the other one showing what I get when I run my script on a single file.
Thanks again in advance for your help (I just assembled scripts that I found here and there, but have no knowledge in JS, hence the big disorder and all the inclusions).
Copy link to clipboard
Copied
woops. i never made a call to the fitObjectToArtboardBounds function. just add this on line 119:
fitObjectToArtboardBounds();
Copy link to clipboard
Copied
Great, it works ! Thank you so much for your help !
Copy link to clipboard
Copied
Oh one more question now. I worked on Illustrator 2019, but my colleagues use the CS6 version. When I launch the script, I get two consecutive error messages saying "Could not load the actions because the file is not compatible" and "Error 1201: a memory error occured. Line: 110 -> app.loadAction (g); // the argument here is a file object". What would that mean ? CS6 is in German while 2019 is in English, but I recorded the actions again and changed the calls to the .aia in the script accordingly, but it did not solve the problem. Would there be a page showing the compatibility for scripts for different Illustrator versions ? Thank you !
Copy link to clipboard
Copied
running actions is supported in CS6 Cloud version, not in the non-cloudy and older versions.
Copy link to clipboard
Copied
Oh ok, that's not good news for me 😄 Now I guess I need to find out how to "convert" these actions into JS. I might come back on this thread (or in a new one). Thanks for the info Carlos !
Copy link to clipboard
Copied
no problem, you might not be able to convert to JS
but there's a glimpse of hope, applescript and vbscript support running actions in older versions of illustrator. So a possible convoluted workaround might involve Javascript-AS/VBS-SomeSortOfChecksAndBalances-Javascript
Copy link to clipboard
Copied
Hello again !
I finally could get a license for Illustrator CC 2018, but now I would need to reduce the output size.
At the moment it is around 5 MB, but I would need to lower it to around 100 kB. In my SVG file, when I click on the picture, it is indeed 800x600 px (actually 900x600 but the artboard cuts the 100px more), but when I click on the linked image properties, it still shows the original JPG size (5472x3648 px).
I have thought of changing DPI (minimum should be 96 DPI) in order to get an acceptable SVG size like this maybe ?
jpegOpt.horizontalScale = ( 300 / 72 ) * 100;
jpegOpt.verticalScale = ( 300 / 72 ) * 100;
But I don't know where I should include these lines in my script. Otherwise, would there be another way to reduce the SVG size ?