Skip navigation
BobH3
Currently Being Moderated

Restart illustrator through script (or eliminate PARM error)

Aug 10, 2012 12:00 PM

Tags: #javascript #batch #batch_actions #rasterize #illustrator_cs5 #jsx #parm

I'm working on a javascript that goes through a folder, rasterizes the paths inside each file, and saves the results as separate files in another folder. My script works fine on individual files as well as for several simple files. However, once it gets going on some of the big ones, it starts to give me PARM errors.

 

What I'm working with:

  • Illustrator CS5.1
  • Windows XP, SP3 (work computer)
  • Javascript
  • The CAD export that created the pdf and eps files broke any curves into tons of tiny straight lines. As a result, these drawings can have 15-35 thousand paths per image.

 

Summary of my code:

  • Get the source and destination directories
  • Open a file from the source directory
  • Go to the first layer of the file
  • Loop through all text items to move them to their own layer
  • Loop through all path and compound paths to move them to a group
  • Rasterize the group of path items
  • Repeat for the next layer and so on
  • Save the file to the destination directory
  • Repeat the process for the next file and so on

 

The scripting guide suggests it could be from conflicting functions or global variables overwriting each other. However, my script is now entirely contained within its own function, and all variables are declared locally. Running from a clean illustrator and ESTK startup, it will still produce a PARM error after a few large files.

 

The guide also suggests having the script quit and re-launch Illustrator after working on many files. Since I assume these huge diagrams are probably several "normal" files' worth of objects each, I figured it probably just needs to restart Illustrator after x amount of stuff goes through. So I look in the guide's section on launching Illustrator through javascript. That basically says "Why would you ever need to do that?" Gee, thanks. I tried looking it up in the tools guide, but that document isn't very clear at all.

 

 

So, onto my actual questions:

 

1. What would I have to do so Illustrator doesn't throw a PARM error on the line marked below? (besides just putting it in a try/catch and pretending it didn't happen) It doesn't consistently happen on the same file or even at the same point in the file, but always at that line.

 

This is just a tiny part of the script. objectClass is a placeholder for PathItems, CompoundPathItems, etc. Looping backwards and setting the group to null at the end were just experiments, neither of which had any effect on the error.

 

if(objectClass.length > 0){
    var objectGroup = myLayer.groupItems.add();
    for(var i = objectClass.length; i > 0; i--){
        objectClass[i-1].move(objectGroup, ElementPlacement.PLACEATBEGINNING); //This one keeps breaking stuff.
    }
    sourceDoc.rasterize(objectGroup, rastBounds, rastOptions);
    objectGroup = null;
}

 

 

 

2. Failing that, how can I relaunch Illustrator through javascript? Or a limited amount of VBScript, though my knowledge of that is limited too.

 
Replies
  • Currently Being Moderated
    Aug 10, 2012 11:42 PM   in reply to BobH3

    "#target estoolkit" and use BridgeTalk to run your script function.

    a basic example: https://gist.github.com/3321845

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 13, 2012 12:16 PM   in reply to BobH3

    Does it make any difference if you use  for(var i = objectClass.length-1; i => 0; i--)

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 13, 2012 2:08 PM   in reply to BobH3

    I have not had the time to test your script… After a quick overview… Question what is the visiible reason for moving before rasterizing files? Could you not have just opened in Photoshop and rasterize the file? Sorry just trying to justify what you are doing here…? While you can pass complex objects ( array, function, object etc.  ) through bridgetalk using toSource() you will need to eval on the other side…

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 13, 2012 7:55 PM   in reply to BobH3

    Sorry for the "single-line comments" part. I should have advise you to use "toString()" to convert function to massage string, then there will be no problem.

    So let's re-write the function:

     

    function AIrasterize(fileList, destinationFolder, itemsProcessed, itemsToReset) {
        var bt = new BridgeTalk();
        bt.target = 'illustrator';
        bt.body = rasterizeDoc.toString() + ";rasterizeDoc(" + fileList[j].toSource() + "," + destinationFolder.toSource() + "," + itemsProcessed + "," + itemsToReset + ");";
        bt.onResult = function(resultMsg) {
            //~                 while (BridgeTalk.getStatus('illustrator') != 'ISNOTRUNNING') $.sleep(20);
            //~                 ++j < fileList.length && AIrasterize(fileList[j], destinationFolder, itemsProcessed, itemsToReset);
        }
        // tell you where error occur
        bt.onError = function(a) {
            alert(a.body + "(" + a.headers["Error-Code"] + ")")
        }
        bt.send();
        $.writeln(bt.body); // also you can use this code to debug, you will see you made some mistake in your code
    }
    

    Two major mistake in your code:

     

    app.open(myDoc);
    sourceDoc = myDoc;

     

    myDoc is a File object here, not document!

    Second, due to bridgeTalk, "filetype" should be an argument of AIrasterize and rasterizeDoc function.

     

    As for the time count, you should get the end time within the BridgeTalk, either send start time to BT or send BT result back to calculate.

    Hopeful with some debug, you can finally get you code work.

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 14, 2012 7:59 PM   in reply to BobH3

    What's your whole code looks like now?

     

    PS:

    After read more explanation of you purpose, I think you'd better use other method: record an action is more powerful, the action can be like this image

     

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 15, 2012 11:17 PM   in reply to BobH3

    There are a couple files even in my test batch that take 5 minutes to process.

    Therefore I think you'd better re-write your function. What if you group all non-text-object and rasterize them in one go?

    And if break the process into two parts: first group all and save/close file, second reopen and rasterize groupItem. Can this method aovid the 'PARM' error?

     

    Any way, I have modified your code, and it should work. See code comments for my logic. https://gist.github.com/3321845#file_a%20realworld%20example.jsx

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 16, 2012 8:29 PM   in reply to BobH3

    Try my suggestion in last reply:

    1. Collect textFrames, group all others(I think you do not need ungroup groupItems first at all), save, close;

    2. Re-open, rasterize the groupItem, save, close;

    3. Repeat for the next file.

    If this method work, then you don't need BridgeTalk at all.

     

    For above script's problem, I think I have no idea without your testing files. Could you upload some sample files?

    Also with sample files I can check if it is possible to combine action with script(a litter VBScript code).

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 18, 2012 12:19 AM   in reply to BobH3

    Glad it finally works.

     

    On the group issue, what I mean is loop through all pageItems, not each type separately.

    Here is the main function follow my logic:

    function layersCheck(doc) {
        var oLayers = doc.layers,
            len = oLayers.length,
            oLayer;
        for (; len-- > 0;) {
            oLayer = oLayers[len];
            oLayer.locked && oLayer.locked = false; // if locked, unlock it
            !oLayer.visible && (oLayer.visible = true, oLayer.remove()); // if not visible, delete it
        }
    }
     
    function extractText_RasterizeAll(doc) {
        var t = (doc.legacyTextItems.convertToNative(), doc.textFrames),
            l = t.length,
            layer = doc.layers.add(),
            group = layer.groupItems.add(),
            i = -1,
            rastOptions = new RasterizeOptions,
            len, p, oLayer;
        // collect text objects, legacyTextItems have been converted to native textItems
        for (; ++i < l; t[i].move(layer, ElementPlacement.PLACEATBEGINNING));
        // group all other objects, remove empty layers
        while (doc.layers.length > 1) {
            oLayer = doc.layers[doc.layers.length - 1];
            for (p = oLayer.pageItems.length; p-- > 0; oLayer.pageItems[p].move(group, ElementPlacement.PLACEATBEGINNING));
            oLayer.remove();
        }
        // rasterize the group
        rastOptions.antiAliasingMethod = AntiAliasingMethod.None;
        rastOptions.clippingMask = false;
        rastOptions.resolution = 300;
        rastOptions.convertSpotColors = false;
        rastOptions.transparency = true;
        doc.rasterize(group, group.visibleBounds, rastOptions);
    }
     
    layersCheck(activeDocument);
    extractText_RasterizeAll(activeDocument);
     
    

    The result: a single raster image object and all text objects in one layer.

     

    Note: Above code does not handle sublayers.

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points