Buglet in Image Processor.jsx

I'm not sure how to report this, but there's a bug in the Image Processor script that was driving me nuts so I figured out how to patch it. This may be a Windows-only bug (I'm not sure).
The problem is that the when you bring up either of the directory pickers for changing the directories in the Image Processor dialog, they both default to the Windows desktop rather than the path that the dialog shows. Since the Windows desktop is a long ways away from where I keep my images, tihs is a lot of mouse clicks to set this directory everytime I want to use it. There is an attempt to pass the directory picker a starting directory, but that code is just wrong. This occurs in two places in the Image Processor. To fix it, I replace this line:
var selFolder = Folder.selectDialog( strPickDest, this.parent.parent.destLongText );
with this line:
var selFolder = Folder.selectDialog( strPickDest, d.destLongText);
and now the directory picker starts out where it's supposed to and it's a lot quicker to set it to what I want.
If this has been bugging you, you can patch your own Image Processor.jsx file. Just find the two lines that look like the first line and replace them with the second line.
And Robert, do you have any idea how to get the real one fixed at Adobe?
I wonder if this actually works on the Mac. On windows, it takes a chain of 5 parents up (this.parent.parent.parent.parent.parent.destLongText) to make the original way work, but I could imagine that this would be difference on Windows/Mac. Since the real parent has already been resolved with FindWindow right in this same function, I found a safer way to accomplish the goal.
--John

>>>I'm not sure how to report this, but there's a bug in the Image Processor script that was driving me nuts so I figured out how to patch it. This may be a Windows-only bug (I'm not sure).
var selFolder = Folder.selectDialog( strPickDest, this.parent.parent.destLongText );
with this line:
var selFolder = Folder.selectDialog( strPickDest, d.destLongText); <<<<br />
John I did your bugfix, but it did not work in my CS2. I'm still taken to the Desktop. Have you done any further work on this "bug"?
Thanks,
Dennis Jacobsen

Similar Messages

  • Photoshop Image Processor.jsx could not be found. CS5

    I like to use Bridge to export groups of photos and with past versions I've been able to select photos, go to Tools>Photoshop>Image Process and select one of my custom actions.  Now I get this error: Photoshop Image Processor.jsx could not be found.
    Any thoughts?
    Thanks

    By default the image processor script should be placed in the Application
    folder (on root level, not in the user
    account)/AdobePhotoshop/presets/scripts/ image Processor.jsx
    Also by default in Bridge preferences Start up Scripts Adobe Photoshop
    should have a checkmark in front of it.
    If you changed any of these there lies your fault, if it happened to fail
    out of the blue you first should try restart Bridge holding down option key
    and choose refresh preferences.
    First check if it works now and if it does again set preferences to your
    wishes. (obvious not deselecting the PS script... )
    Now I get this error: Photoshop Image Processor.jsx could not be found.

  • I am trying to batch convert cr2 to jpg. in bridge i go tools ps image processor and it returns a message "Image Processor.jsx could not be found." I updated cc to no avail. i am on mac 10.7.5

    I am trying to batch convert cr2 to jpg. in bridge i go tools>ps>image processor and it returns a message "Image Processor.jsx could not be found." I updated cc to no avail. i am on mac 10.7.5

    I go to file scripts but there is no option there for Image Processor

  • Help needed: Image Processor.jsx missing in CS4

    The Image Processor.jsx is missing from my Photoshop CS4 scripts folder and when I search I don't find it anywhere. (I get "Image Processor.jsx cannot be found" error when I try to do Image Processing in Bridge CS4.) I guess it never loaded. Can someone send it to me so I can load it. Also please tell me exactly where I should put it.

    never loaded. Can someone send it to me so I can load it. Also please tell me
    exactly where I should put it.
    After default install the script should be present in the application it
    self:
    On root level (not user account) :
    Application folder/AdobePhotoshopCS4/Presets/Scripts/ Image Processor.jsx
    Here is a link for the download of the script from the Adobe Site, if it
    does not work for you (the site is often country specific) perform a search
    on the Adobe Site for the Image Processor
    https://www.adobe.com/cfusion/exchange/index.cfm?searchfield=Image+Processor
    &search_exchange=16&search_category=-1&search_license=&search_rating=&search
    platform=0&searchpubdate=&num=25&startnum=1&event=search&sticky=true&sort=
    0&rnav_dummy_tmpfield=&Submit=

  • Image Processor.jsx bug (CS3, 10.0.1): fail to restore history item sometimes

    I have very limited history depth (5 items) to conserve my RAM.
    When I run "Image Processor" script, which calls some complex Action, "Image Processor" fails to restore history item (because it was dropped already) in this lines (tere is same line for every save file type):
    app.activeDocument.activeHistoryState = historyState;
    This line(s) throw exception (file was saved, really!), and file remains open and after processing 10-15 files computer starts to thrash.
    I've surrounded all these lines with try { ... } catch(e) {} and it works for me.
    IMHO, it here are two bad ideas in this script:
    (1) Consider every and any exception as error. In this case, history is not a thing I care about
    (2) Don't close files in case of error. It can fill up RAM & scratch disk very quickly.

    Update Server
    Try:
    - Powering off and then back on your router.
    - iTunes for Windows: iTunes cannot contact the iPhone, iPad, or iPod software update server
    - Change the DNS to either Google's or Open DNS servers
    Public DNS — Google Developers
    OpenDNS IP Addresses
    - For one user uninstalling/reinstalling iTunes resolved the problem
    - Try on another computer/network
    - Wait if it is an Apple problem

  • Bridge Image Processor always creates JPEG or TIFF folder, how do I change that behavior?

    I have searched the web, Bridge forums, and Photoshop forums, and come up empty-handed. (The strange thing is, I know there used to be a post that answered this question a few years ago.) Anyway, I use Image Processor quite a bit, and it works great except for the annoying behavior of always creating a new folder to store the newly-created images.
    I remember the solution is to change some line in a (XML?) file from "JPEG" to "". For the life of me, I can't find which file that is! I think it used to located down inside Application Support. I think.
    Thanks for help on this, it's driving me crazy!
    Jeff

    Thanks for replying! I'm running CS 5.1. Oh, now I see...I've never run Image Processor from within Photoshop, just from Bridge. You're right, it does offer different options than Bridge.
    Anyway, I found it what I was looking for.
    Open up (don't run!) the Image Processor.jsx file. I opened it up in ExtendScript Toolkit. The path is /Applications/Adobe Photoshop CS5.1/Presets/Scripts/Image Processor.jsx
    I'm on line 1574 (in other versions, the line number may vary)
    This is what the line says:
    var subFolderText = inFolderLocation + "/JPEG/";
    Change to:
    var subFolderText = inFolderLocation + "//";
    Problem solved. Repeat as necessary for other folders you don't want created (TIFF, PSD)
    Back to work!

  • Add Functions to Image Processor

    Can someone assist me or point me in the right direction, to information on how to add functions to the default Photoshop Image Processor script. I do not know javascript but can follow along fairly well if someone has good sirections.
    What I need to add,
    Renaming files like PSE's 'Process Multiple Files' feature, output as .png in adition to jpg, psd and tiff.
    I would basically like to bring PSE's multiple image processor into Photoshop.
    I found the image processor script, but dont know java. If someone could assist with this I would appreciate it.
    I have attached an image of what I need from PSE. The default image processor in PS CS4 almost does it, but a couple of areas are lacking.
    Any info, greatly appreciated.

    I don’t want to sound condescending, especially as I also have often had to to rely on some of this forum’s contributor’s help myself, but maybe You should start with working through »Adobe Intro To Scripting.pdf« and then read up on »User-Interface Tools« in »JavaScript Tools Guide CS4.pdf«.
    Both pdfs should be located in Your ExtendScript Toolkit-folder (ESTK is installed with Photoshop CS4).
    Starting Photoshop-Scripting with adapting a Script as voluminous as »Image Processor.jsx« might be a bit of a challenge.

  • Issue with Image Processor starting

    When I go to start Image Processor in CS5, I get "Image Processor.jsx could not be found".  Please help.  Thanks.

    Search your machine for that file "Image Processor.jsx"   make sure it in Photoshop's folder Presets\Scripts\   I would think it would be if its listed in menu File>Script>Image Processor... .

  • When does the Image Processor perform actions?

    Let's say I use the image processor to convert a bunch of .psd files into JPEGs while also using the resize to fit (and convert to sRGB) option. I also want it to run an action which sharpens the image. When does that action/sharpening happen? Before or after the resize?
    Can it be that this behavior was changed in CS5 (compared to CS3)?

    I would appear that the srgb-conversion, the resizing and the Action are applied in this order.
    See lines 1584 to 1592 of »Image Processor.jsx«.
    If you wanted to change the sequence you could edit the Script (after making a backup of it in another location, duplicating the Script in the Scripts-folder would seem inadvisable).

  • Wish Image Processor always came up.

    Not most innovative request, but gotta let you know. Lot of times I select the image processor (from within Bridge) and it just does not come up. So far----thankfully, it comes up after a quit and relaunch. But hoping not have to do that down the road. appreciate it.

    Thanks for replying! I'm running CS 5.1. Oh, now I see...I've never run Image Processor from within Photoshop, just from Bridge. You're right, it does offer different options than Bridge.
    Anyway, I found it what I was looking for.
    Open up (don't run!) the Image Processor.jsx file. I opened it up in ExtendScript Toolkit. The path is /Applications/Adobe Photoshop CS5.1/Presets/Scripts/Image Processor.jsx
    I'm on line 1574 (in other versions, the line number may vary)
    This is what the line says:
    var subFolderText = inFolderLocation + "/JPEG/";
    Change to:
    var subFolderText = inFolderLocation + "//";
    Problem solved. Repeat as necessary for other folders you don't want created (TIFF, PSD)
    Back to work!

  • I can't get Dr Browns Image Processor Pro to work from Bridge with Photoshop CC 2014

    We use the wonderful DR Browns Image Processor Pro script a lot, but cannot get it to work from Bridge with PS CC 2014. When I select files in Bridge CC and then go to Tools> Dr Browns Services 2.3.1 > Image Processor Pro it just pops up an error message that says ReferenceError: photoshop is undefined.
    The actual script works fine if I launch it from Photoshop CC 2014 - just not if I load it from Bridge CC.
    I have unistalled it and re installed a few times, both manually and through the Extension Manager CC.
    I am using a Win 7 64bit computer.
    I assume there is some change in the scripting part that loads Photoshop from bridge but not sure. It worked fine in CC. Just not CC 2014.
    I opened the Dr Browns Services .jsx file but don't see anything obvious. This is the section related to the Image Processor Pro part:
      // This routine takes an array of files. If called by Photoshop,
      // it will invoke Dr. Brown's Process 1-2-3 with the files. If called by
      // any other app, it will send a BridgeTalk message to Photoshop
      // to invoke this routine with the same arguments.
    drbrownserv.process123 = function (files) {
    // Bring Photoshop to the foreground.
      BridgeTalk.bringToFront ("photoshop");
      // Create a new BridgeTalk message for Photoshop to invoke
      // Image Processor with the selected files
      var btMessage = new BridgeTalk;
    btMessage.target = "photoshop";
      btMessage.body = "drbrownserv.process123 (" + files.toSource () + ");";
      btMessage.send ();
      } else {
    photoshop.runActionCommand ('611736f0-9c46-11e0-aa82-0800200c9a66', files);
      catch (error) {
      if (error.number != 8007) // Don't report user cancelled errors.
      drbrownserv.alert (error);

    I copied that .jsx file to a new name "Xbytor Image Processor Pro.jsx" edit that file changed the string Dr Browns services to "Xbytor Image Processor Pro" then commented out all the code that added tools menu items but "Image Processor Pro" and I put that file into
    "C:\Program Files (x86)\Common Files\Adobe\Startup Scripts CC\Adobe Bridge" even though Bridge CC is 64Bit seems to use theat location.
    Bridge CC was updated by the creative clouds update and opens Photoshop CC 2014 now

  • Image Processor Pro and Picture Processor load eps files without rasterizing them

    Hi. My name is Lucas. Im from Argentina, now living in Brazil. I have the problem that is in the title. Im new doing this stuff but reading a lot i discovered that both scripts open eps files and because they dont get reasterized, then saved files looks preety bad.
    I know that there are some parameters to open eps, ex:
    var epsOpenOptions = new EPSOpenOptions();
       epsOpenOptions.antiAlias = true;
       epsOpenOptions.mode = OpenDocumentMode.RGB;
       epsOpenOptions.resolution = 72;
       epsOpenOptions.constrainProportions = true;
    I have to say that looking for a solution a found a script and modified to suit partially my needs. I said partially because i need the script to look folders and save output files with same structure. Here is the script that manage one folder at a time:
    #target photoshop
    // Asks user for input folder
    var inputFolder = Folder.selectDialog("Select a folder to process");
    // Asks user for output folder
    var OutputFolder = Folder.selectDialog("Select a folder to save your Tiffs");
    if ( inputFolder != null && OutputFolder  != null ) {
       // Makes list of all files located in that folder
       var fileList = inputFolder.getFiles( "*.eps" );
       // Create a EPS option object [height & width are doc size]
       var epsOpenOptions = new EPSOpenOptions();
       epsOpenOptions.antiAlias = true;
       epsOpenOptions.mode = OpenDocumentMode.RGB;
       epsOpenOptions.resolution = 72;
       epsOpenOptions.constrainProportions = true;
       // Open each file in turn
       for (var i = 0; i < fileList.length; i++) {
          // open the file
          app.open( fileList[i], epsOpenOptions );
          var baseName = activeDocument.name.slice( 0,-4 );
          // put your code to 'save as' the file here
          var saveFile = new File ( OutputFolder + "/" + baseName + ".jpg" );
       SaveForWeb(saveFile,60); // set quality to suit
    function SaveForWeb(saveFile,jpegQuality) {
      var sfwOptions = new ExportOptionsSaveForWeb();
      sfwOptions.format = SaveDocumentType.JPEG;
      sfwOptions.includeProfile = false;
      sfwOptions.interlaced = 0;
      sfwOptions.optimized = true;
      sfwOptions.quality = jpegQuality;
    activeDocument.exportDocument(saveFile, ExportType.SAVEFORWEB, sfwOptions);
    activeDocument.close( SaveOptions.DONOTSAVECHANGES ); 
    So, if you know some way modify image processor pro or picture processor i will be very pleased.
    Because i will only use the script to manage eps files and save them as jpg (save for web) i dont need an special button to activate that option. Keep it simple. Thanx!!

    You can tweak ImageProcessorPro.jsx by make the following edit.
    Search for code that looks like this:
    ImageProcessor.prototype.openDocument = function(file) {
      var self = this;
      var settings = self.settings;
      var mode = DialogModes.NO;
      var ext = file.strf("%e").toLowerCase();
      var isRaw = ImageProcessor.CAMERA_RAW_FILES.contains(ext);
      if (isRaw) {
    and insert this code right after it:
      if (ext == "eps") {
        var epsOpenOptions = new EPSOpenOptions();
        epsOpenOptions.antiAlias = true;
        epsOpenOptions.mode = OpenDocumentMode.RGB;
        epsOpenOptions.resolution = 72;
        epsOpenOptions.constrainProportions = true;
        try {
          var doc = app.open(file, epsOpenOptions);
        } catch (e) {
          Error.runtimeError(9002, ZStrings.UnableToOpenErr);
        return doc;
    I haven't tested this at all but it looks good from here.

  • Help needed to enhance Image Processor Pro Script to save transparency in TIF

    Hi everyone,
    this is my first post in this community.
    We have a droplet which reduces the resolution of tif images to 72dpi and save the tif image with transparency. This works fine, but it took to long for the whole process of many picture in different folders. That's the reason why we searched for another script which can preserve the folder structure and set the resolution of every tif image to 72dpi.
    We found Image Processor Pro, which does exactly what we needed. The script works perfectly in CS5 and CS5.5 as it saves the tif with the transparency. Those saved tif images could be used in InDesign with the transparency.
    BUT Image Processor Pro script works not so perfectly in CS6 as it seems that this option to save a tif with transparency is not implemented or does not work in the script. The result is that those converted tif images are w/o transparency in InDesign. That's a huge problem for us.
    This is the point where I need your help. Neither I have experience yet with jsx-files nor with the right syntax of it.
    Is there a way for anybody of you to implement / enhance Image Processor Pro so it will save tif with transparency?
    We used the latest German Version of Image Processor Pro: 2.3.1 (link: http://www.russellbrown.com/scripts.html)
    (The German version contains only german on screen texts!)
    I am very thankful for every help you can give.
    Thanks in advance for your help.

    Possible causes:
    1) It probably has nothing to do with your image files, but you won't know until someone else tests one of them. You could create a small 50% gray TIFF file with transparency and post it, assuming you know it exhibits the issue with IPP.
    2) At the download link you provided:
    http://www.russellbrown.com/scripts.html
    There are two installers for Image Processor (CS5 and CS6). Did you download and install the CS6 Version Installer?
    3) Another possible solution other than modifying the script is to reset the PS Preferences file. When strange things happen in PS with no explanation this usually fixes them. My PS CS6 was inflating  all new files by 1.4MB. After examining one of the files it turned out PS was inserting a Costco printer profile into every new file. So don't automatically assume your PS image files are not somehow being corrupted and causing loss of transparency in IPP. Creating a new Preferences file resolved my issue:
    http://forums.adobe.com/thread/375776
    You may want to record your old Preferences settings prior to creating a new one, but test it first with the default settings.

  • Image processor always on top?

    When I use image processor (launched by Photoshop or Bridge) Photoshop  go in front (top window) each new picture processed, means every  seconds.
    It's pretty annoying cause I can't even keep a browser in front...
    Does anybody have the same problem?
    It comes with CS4 and CS5, on 2 different machines.
    How can I fix that?

    The Image Processor resize is a fit image type resize not an Image Size dialog type resize.  Let say you have a 3:2 aspect ratio camera. Landscale image have 3:2 aspect ratio and portrait have 2:3  aspect ratio. You want the resize your large camera images for the web. You want the longest side to be 600 px. You would set the width and height values 600 px. Your image would be resize constraine to retain their aspect ratios. So landscape images would resize to 600px by 400 px and Portraits would resize to 400 px by 600 px. You can also resize Image fot a device like your 4:3 UXGA display set 1600 in for the width and 1200 for the height Portrait would still be 2:3 with a 1200 px height and Landscape will still be 3:2 with a 1600 px width. When displayed on you 4:3 display the whole images would fit on your display and fil the width or hight depending in the images orientation ther woul be a border on two sides.
    Photoshop also shipts with a FitImage Plug-in so you can record using the plug-in in as action. When you do the values you set in the fitimage dialog while recording the action are recorded into the action step. When the action plays back the values are passed to fitimage and the dialog for the step is not diaplayed. Unless you thurn on that steps dialog. If you do you will see the recorded values are set into the dialog. So you don't need to write a script to handle resize for different orientations.   It just so happens to be that since CS3 FitImage is a script.  So if you want to pass some values to a script. Write the script as a plugin and record as action to pass recorded values.  Plug-in scripting support was added in CS3.   The script needs to record its dialog setting into the action step and also not display it dialog if it being run from a recorded action step.  To learn more read FitImage.jsx in Photoshop's Presets\Scripts folder.

  • Photoshop Cs 4 Image Processor

    Unable to use image processor feature in CS 4. Error message indicates "Cannot find javascript plug-in. This feature was working just fine until a few weeks ago. Nothing unusual has changed. Thanks

    the folder must have moved or something...
    here it is for now copy it to ... applications/adobe photoshop cs4/presets/scripts : and it will be a good time to see if that folder is even there.
    Regards
    G
    // (c) Copyright 2006-2007.  Adobe Systems, Incorporated.  All rights reserved.
    // Photomerge in ExtendScript.
    // Translated from the original C++ automation & filter plugins
    // John Peterson, Adobe Systems, 2006
    // Adobe Patent or Adobe Patent Pending Invention Included Within this File
    @@@BUILDINFO@@@ Photomerge.jsx 3.0.0.1
    // BEGIN__HARVEST_EXCEPTION_ZSTRING
    <javascriptresource>
    <name>$$$/JavaScripts/Photomerge/Menu=Photomerge...</name>
    <about>$$$/JavaScripts/Photomerge/About=Photomerge^r^rCopyright 2006-2008 Adobe Systems Incorporated. All rights reserved.^r^rCombines several photographs into one continuous image.</about>
    <menu>automate</menu>
    </javascriptresource>
    // END__HARVEST_EXCEPTION_ZSTRING
    // on localized builds we pull the $$$/Strings from a .dat file
    $.localize = true;
    // Put header files in a "Stack Scripts Only" folder.  The "...Only" tells
    // PS not to place it in the menu.  For that reason, we do -not- localize that
    // portion of the folder name.
    var g_StackScriptFolderPath = app.path + "/"+ localize("$$$/ScriptingSupport/InstalledScripts=Presets/Scripts") + "/"
                                            + localize("$$$/Private/Exposuremerge/StackScriptOnly=Stack Scripts Only/");
    $.evalFile(g_StackScriptFolderPath + "LatteUI.jsx");
    $.evalFile(g_StackScriptFolderPath + "StackSupport.jsx");
    $.evalFile(g_StackScriptFolderPath + "CreateImageStack.jsx");
    $.evalFile(g_StackScriptFolderPath + "Geometry.jsx");
    $.evalFile(g_StackScriptFolderPath + "PolyClip.jsx");
    // debug level: 0-2 (0:disable, 1:break on error, 2:break at beginning)
    // Must leave at zero, otherwise trapping gFileFromBridge fails on QA's debug builds.
    $.level = 0; // (Window.version.search("d") != -1) ? 1 : 0;
    // debugger; // launch debugger on next line
    if (typeof(PMDebug) == 'undefined')
        var PMDebug = false;
    // photomerge routines
    // Debug - write the trapezoid in Matlab format
    function dumpTrap( name, corners )
        var i;
        if (! PMDebug) return;
        $.write( name + "= [" );
        for (i in corners)
            $.write( ((i > 0) ? "; " : "" ) + corners[i].fX + " " + corners[i].fY );
        $.writeln( "];");
    StackElement.prototype.dumpMLCorners = function()
        // Weed out file suffix (chokes matlab)
        dumpTrap( this.fName.match(/([^.]+)/)[1], this.fCorners );
    // Set the fCorners of the layer to the bounds of the Photoshop layer.
    StackElement.prototype.setCornersToLayerBounds = function( stackDoc )
        if (typeof(stackDoc) == "undefined")
            stackDoc = app.activeDocument;
        var bounds = stackDoc.layers[this.fName].bounds;
        this.fCorners = new Array();
        this.fCorners[0] = new TPoint( bounds[0].as("px"), bounds[1].as("px") );
        this.fCorners[2] = new TPoint( bounds[2].as("px"), bounds[3].as("px") );
        this.fCorners[1] = new TPoint( this.fCorners[2].fX, this.fCorners[0].fY );
        this.fCorners[3] = new TPoint( this.fCorners[0].fX, this.fCorners[2].fY );
    // Add the corner data to the string of per-stackElement information
    // that gets passed to the filter plugin
    StackElement.prototype.addPieceData = function()
        if (typeof(this.fCorners) != "undefined")
            // Add corners in place of trailing '\n'
            this.fString = this.fString.slice(0,-1) + "fCorners=";
            for (j = 0; j < 4; j++)
                this.fString += " " + this.fCorners[j].fX.toString() + " " + this.fCorners[j].fY.toString();
            this.fString += "\t";
            if (typeof(this.fScale) != "undefined")
                this.fString += ("fScale=" + this.fScale.toString() + "\t");
            if ((typeof(this.fConnectedTo) != "undefined") && this.fConnectedTo)
                this.fString += "fConnectedTo=" + this.fConnectedTo.fLayerID + "\t";
            if (typeof(this.fLayerID) != "undefined")
                this.fString += "fLayerID=" + this.fLayerID.toString() + "\t";
            this.fString += "\n";
        else
            debugger;    // Corner data missing!
    StackElement.prototype.overlapArea = function( other )
        if (other == this)
            return TPoint.polygonArea( this.fCorners );
        var overlapBounds = TRect.intersection( this.fBoundsCache, other.fBoundsCache );
        if (overlapBounds.isEmpty())
            return 0.0;
        var clipPoly = TPoint.intersectConvexPolygons( this.fCorners, other.fCorners );
        if (! clipPoly)
            return 0.0;
        else return TPoint.polygonArea( clipPoly );
    // Find the points where the two quadrilaterals intersect (yes, eight is a theoretical max)
    // Note situations where one piece intersects the same edge twice - special
    // case handled by SoftEdgeBlend
    StackElement.prototype.findQuadIntersections = function( other, intersections )
        var i, j;
        var curIntersections, numIntersections = 0;
        var innerEdgeIntersections = [ 0, 0, 0, 0 ];
        var outerEdgeIntersections = [ 0, 0, 0, 0 ];
        var thisEdge = false;
        var otherEdge = false;
        for (i = 0; i < 4; i++)
            var eb0 = other.fCorners[i];
            var eb1 = other.fCorners[(i + 1) > 3 ? 0 : i + 1];
            curIntersections = numIntersections;
            for (j = 0; j < 4; j++)
                var ed0 = this.fCorners[j];
                var ed1 = this.fCorners[(j + 1) > 3 ? 0 : j + 1];
                var cross = TPoint.lineSegmentIntersect( eb0, eb1, ed0, ed1 );
                if (cross != TPoint.kInfinite)
                    intersections[numIntersections++] = cross;
                    innerEdgeIntersections[j]++;
            outerEdgeIntersections[i] = numIntersections - curIntersections;
        if (numIntersections == 2)
            for (i = 0; i < 4; i++)
                if (innerEdgeIntersections[i] == 2) thisEdge = true;
                if (outerEdgeIntersections[i] == 2) otherEdge = true;
        return {"numIntersections":numIntersections, "thisEdge":thisEdge, "otherEdge":otherEdge};
    // Look for a point of this that's inside the corners of other.
    StackElement.prototype.findSingleInsidePoint = function( other )
        var i;
        var result = new Object();
        result.numFound = 0;
        for (i = 0; i < 4; i++)
            if (this.fCorners[i].pointInQuad( other.fCorners ))
                result.numFound++;
                result.insidePt = this.fCorners[i];
        return result;
    // "Adobe patent application tracking # B349, entitled 'Method and apparatus for Layer-based Panorama Adjustment and Editing', inventor: John Peterson"
    // Because we're dealing with quads, we can't use the simple scheme
    // to generate blend rects that the rectangles use - black stuff
    // from the rects will seep in. So instead, we use various heuristics to
    // figure out how the quads themselves intersect.  This isn't too hard
    // when there's just two intersection points (usual case), but there are
    // some pathological cases where there are many more intersections (the octogon
    // from one square 45 deg. off from another is the classic example).          
    StackElement.prototype.softEdgeBlend = function( other, blendRad )
        var i, j;
        var intersections = new Array();    // Worst case is a square inside a 45 degree rot square
        // If there's no distortion, do the blend strictly on the rectangles
    /*    if ((!IsQuadMapped() && !other->IsQuadMapped())
            || (IsRectilinear() && other->IsRectilinear()))
            Assert_( other->fWarpedRaster );
            fWarpedRaster->SoftEdgeBlendRasters( *(other->fWarpedRaster), blendRad );
            return;
        var bounds = this.getBounds();
        // Find the points where the two quadrilaterals intersect
        var intResult = this.findQuadIntersections( other, intersections );
        var numIntersections = intResult.numIntersections;
        var thisEdgeTwice = intResult.thisEdge;
        var otherEdgeTwice = intResult.otherEdge;
        var thisInsidePt = this.findSingleInsidePoint( other );
        var otherInsidePt = other.findSingleInsidePoint( this );
        // If quads don't overlap, just bail
        if (numIntersections == 0)
            return;
        // Handle cases where just one point overlaps the other piece
        var insidePoint;
        if (otherEdgeTwice || ((numIntersections == 2) && (thisInsidePt.numFound == 1)))
            insidePoint = thisInsidePt.insidePt;
            this.makeBlendTrapezoid( intersections[0], intersections[1], insidePoint, blendRad, false );
            return;
        if (thisEdgeTwice /*|| ((numIntersections == 2) && (otherInsidePt.numFound == 1))*/)
            insidePoint = otherInsidePt.insidePt;
            this.makeBlendTrapezoid( intersections[0], intersections[1], insidePoint, blendRad, false );
            return;
        // ...More than two corners overlap, apply heuristics to find reasonable blending
        $.bp( numIntersections > 8 );
        // If we got more than two points, pick the two furthest apart
        if (numIntersections > 2)
            var max0, max1;
            var maxDist = -1.0;
            for (i = 0; i < numIntersections - 1; i++)
                for (j = i + 1; j < numIntersections; j++)
                    var dist = (intersections[i] - intersections[j]).vectorLength();
                    if (dist > maxDist)
                        max0 = intersections[i];
                        max1 = intersections[j];
                        maxDist = dist;
            $.bp( maxDist <= -1.0 );
            intersections[0] = max0;
            intersections[1] = max1;
            numIntersections = 2;
        TPoint.clipLineToRect( bounds, intersections[0], intersections[1] );
        // The point furthest away from the cut line on the "other" image
        // is the one that we blend toward (the "dark" corner).
        var maxPoint = 0, maxDist = -1;
        for (i = 0; i < 4; i++)
            var dist = Math.abs( other.fCorners[i].distanceToLine( intersections[0], intersections[1] ) );
            if (dist > maxDist)
                maxDist = dist;
                maxPoint = i;
        this.makeBlendTrapezoid( intersections[0], intersections[1], other.fCorners[maxPoint], blendRad, true );
    // "Adobe patent application tracking # B349, entitled 'Method and apparatus for Layer-based Panorama Adjustment and Editing', inventor: John Peterson"
    // Create a layer mask that fades out from the edge0,edge1 cutline towards "insidePt"
    // If two points are inside, construct the mask fade from the edge of the image.
    //                       insidePt
    //             |            *           |
    //             |           / \          |
    //             |          /   \         |
    // insetLine-> |       +-/-----\-+      |  --
    //             |       |/       \|      |   | radius
    // baseLine->  +-------*---------*------+  --
    //                    /edge0      \edge1
    StackElement.prototype.makeBlendTrapezoid = function( edge0, edge1, insidePt, radius, useCorners )
        function sgn(x) { if (x < 0) return -1; if (x > 0) return 1; return 0; }
        function wrap4(i, next)
            i += next;
            if (i > 3) return i % 4;
            if (i < 0) return 3;
            return i;
        // Create a layer mask
        selectOneLayer( app.activeDocument, this.fName );
    //    app.activeDocument.activeLayer = app.activeDocument.layers[this.fName];    // Broken if multiple layers selected.
        createLayerMask();    // Does nothing if the layer already has a mask
        // Create vector perpendicular to edge towards insidePt
        var edgeDir = edge1 - edge0;
        var blendDir = new TPoint( -edgeDir.fY, edgeDir.fX );
        blendDir /= blendDir.vectorLength();    // Make unit length
        // Make a polygonal selection covering the area
        var dist = insidePt.distanceToLine( edge0, edge1 );
        var blendOffset = blendDir * dist;
        var blendBox;
        if (! useCorners)
            blendBox = [edge0, edge0+blendOffset, edge1+blendOffset, edge1, edge0];
        else
            // If the cutline slices across the image (two points on each side), then
            //        - Look for the edge edge0 is on
            //        - Figure out which corner is on the same side as "insdePt"
            //        - Construct the blendBox from that.
            var i, nextPtInd;
            for (i = 0; i < 4; i++)
                if (edge0.distanceToLine( this.fCorners[i], this.fCorners[wrap4(i,1)] ) < 0.0001 )
                    if (this.fCorners[i].sideOf( edge0, edge1 ) == sgn( dist ))
                        nextPtInd = -1;
                    else
                        nextPtInd = 1;
                    blendBox = new Array();
                    blendBox[0] = edge0;
                    blendBox[1] = (nextPtInd < 0) ? this.fCorners[i] : this.fCorners[i+1];
                    blendBox[2] = (nextPtInd < 0) ? this.fCorners[wrap4(i, -1)] : this.fCorners[wrap4(i, 2)];
                    blendBox[3] = edge1;
                    break;
            $.bp( i == 4 );    // Never found edge0?
        createPolygonSelection( blendBox );
        // Fill it.
        var midPoint = (edge0 + edge1) * 0.5;
        gradientFillLayerMask( midPoint, midPoint + blendDir * radius * sgn(dist) );
        app.activeDocument.selection.deselect();
    // Photomerge base class
    const kPhotomergeAdvancedBlendingFlag = app.stringIDToTypeID( "PhotomergeAdvancedBlendingFlag" );  
    photomerge = new ImageStackCreator( localize("$$$/AdobePlugin/Shared/Photomerge/Process/Name=Photomerge"),
                                              localize('$$$/AdobePlugin/Shared/Photomerge/Auto/untitled=Untitled_Panorama' ), null );
    // For now, alignment is turned OFF, because we want to
    // invoke it independantly.             
    photomerge.useAlignment            = false;    // We do the alignment, not PS
    photomerge.hideAlignment        = true;
    photomerge.mustBeSameSize        = false;
    photomerge.mustBeUnmodifiedRaw = false;
    photomerge.mustNotBe32Bit        = ! app.featureEnabled(localize("$$$/private/32BitLayersFeature=32-Bit Layers"));
    photomerge.radioButtons = ["_LOauto", "_LOperspective", "_LOcylindrical", "_LOspherical", "_LOcollage", "_LOnormal", "_LOinteractive"];
    photomerge.interactiveFlag        = false;
    photomerge.alignmentKey            = "Auto";    // Defaults to perspective
    photomerge.compositionFile        = null;
    photomerge.advancedBlending        = true;
    photomerge.lensCorrection        = false;
    photomerge.removeVignette        = false;
    try {
    // We want to steer people to the advanced blending option,
    // so have it be on by default, rather than sticky.
    //    var desc = app.getCustomOptions("PhotomergeFlags001");
    //    photomerge.advancedBlending = desc.getBoolean( kPhotomergeAdvancedBlendingFlag );
    catch (e)
    // Get the bounds of all of the stackElements.
    photomerge.getBounds = function()
        var i;
        for (i in this.stackElements)
            if (i == 0)
                this.fBounds = this.stackElements[i].getBounds();
            else
                this.fBounds.extendTo( this.stackElements[i].getBounds() );
        return this.fBounds;
    // Align selected layers by content (uses SIFT registration in Photoshop core)
    // This just returns the alignment data, it does not actually transform the layers
    // unless doTransform is true
    photomerge.getAlignmentInfo = function( stackDoc, doTransform )
        selectAllLayers(stackDoc, 1);
        const kMargin = 10;
        function offsetGroup( delta, group )
            group.bounds.offset( delta );
            var k;
            for (k = 0; k < group.layers.length; ++k)
                group.layers[k].offset( delta );
                if (doTransform)
                    selectOneLayer( stackDoc, group.layers[k].fName );
                    // Translate gets broken when document DPI isn't 72 DPI...(PR 1417264)
    //                activeDocument.activeLayer.translate( UnitValue( delta.fX, "px" ), UnitValue( delta.fY, "px" ) );   
                    translateActiveLayer( delta.fX, delta.fY );
        var i, j, alignInfo;
        var alignmentFlags = [];
        if (this.lensCorrection) alignmentFlags.push(kradialDistortStr);
        if (this.removeVignette) alignmentFlags.push(kvignetteStr);
        alignInfo = getActiveDocAlignmentInfo( this.alignmentKey, doTransform, alignmentFlags );
        // If the alignment fails completely, fake up a plan B...
        // For now, just set the images side by side.
        if (! alignInfo)
            alert(localize("$$$/AdobePlugin/Shared/Photomerge/alignbad=Some images could not be automatically aligned"));
            var xpos = 0;
            for (i in this.stackElements)
                this.stackElements[i].setCornersToSize();
                this.stackElements[i].offset( new TPoint( xpos, 0 ) );
                xpos += this.stackElements[i].getBounds().getWidth() + kMargin;
            this.fGroups = null;
        else
            var layerList = alignInfo.layerInfo;
            this.fGroups = new Array();
            for (i = 0; i < layerList.length; ++i)
                // Note we depend on stackElement's order matching
                // the document's sheet list!
                var curGroup = layerList[i].groupNum;
                if (!doTransform && (layerList[i].corners.length > 0))
                    this.stackElements[i].fCorners = layerList[i].corners;
                else
                    this.stackElements[i].setCornersToLayerBounds( stackDoc );
                this.stackElements[i].fAlignGroup = curGroup;
                this.stackElements[i].fBaseFlag = layerList[i].baseFlag;
                if (typeof(this.fGroups[curGroup]) == "undefined")
                    this.fGroups[curGroup] = new Object();
                    this.fGroups[curGroup].hasCorners = layerList[i].corners.length > 0;
                    this.fGroups[curGroup].bounds = this.stackElements[i].getBounds();
                    this.fGroups[curGroup].layers = new Array();
                    this.fGroups[curGroup].xformType = layerList[i].xformType;
                else
                    this.fGroups[curGroup].bounds.extendTo( this.stackElements[i].getBounds() );
                this.fGroups[curGroup].layers.push( this.stackElements[i] );
            // Now move the groups into  place
            // Note carefully: if the corners were given, then the group is already
            // transformed into the proper spot, and we just need to move the corners to
            // match.  So shut off moving the layer pixels around from here on out.
            offsetGroup( -this.fGroups[0].bounds.getTopLeft(), this.fGroups[0] );
            for (i = 1; i < alignInfo.numGroups; ++i)
                var spacing = Math.round(this.fGroups[i-1].bounds.getHeight() / 10.0);
                offsetGroup( -this.fGroups[i].bounds.getTopLeft() + new TPoint(0, spacing + Math.round(this.fGroups[i-1].bounds.fBottom)),
                               this.fGroups[i] );
        this.getBounds();
    // The original Photomerge plugin needs to have the "connectivity" of the
    // pieces when in perspective mode, i.e., a pieces distortion is based
    // on the distortion of the one it overlaps most.  This takes the
    // "base" piece information from the PS core and uses overlap area to
    // determine this.
    photomerge.setupConnectivity = function()
        var i;
        // See if stackElem is connected to the "base".  If "without"
        // is given, then the path to the base must not use "without"
        function isConnectedToBase( stackElem, without, dbg_count )
            if (typeof(dbg_count) == "undefined")
                dbg_count = 0;
            if (typeof(without) == "undefined")
                without = null;
            $.bp( dbg_count > 150 );    // oops, got stuck in a loop...
            if (stackElem == null)
                return false;
            if (stackElem == without)
                return false;
            if (stackElem.fConnectedTo == stackElem)
                return true;        // Already at base
            return isConnectedToBase( stackElem.fConnectedTo, without, dbg_count + 1 );
        // Initialize
        for (i in this.stackElements)
            this.stackElements[i].fBoundsCache = this.stackElements[i].getBounds();
            this.stackElements[i].fLayerID = i;
            // Bases connect to themselves.
            this.stackElements[i].fConnectedTo = this.stackElements[i].fBaseFlag ? this.stackElements[i] : null;
            this.stackElements[i].fNeighborOverlap = 0;
        // Create a connection table based on the overlap of the pieces
        var g, i, j, baseInd = -1;
        if (this.fGroups)
            for (g in this.fGroups)
                var group = this.fGroups[g];
                var connections = new Array();
                var numLayers = group.layers.length;
                // Ignore orphan images
                if (numLayers < 2)
                    group.layers[0].fBaseFlag = false;
                    group.layers[0].fConnectedTo = null;
                    continue;
                // If there's no perspective, there's no connections ("0" is kProjective in UAlignment.h)
                if (group.xformType != 0)
                    for (i = 0; i < numLayers; ++i)
                        group.layers[i].fBaseFlag = false;
                        group.layers[i].fConnectedTo = group.layers[i];
                    continue;
                for (i = 0; i < numLayers; ++i)
                    if (group.layers[i].fBaseFlag)
                        baseInd = i;
                    connections[i] = new Array();
                    group.layers[i].fGroupIndex = i;
                    if (i > 0)
                        for (j = 0; j < i; ++j)
                            connections[i][j] = group.layers[i].overlapArea( group.layers[j] );
                            connections[j][i] = connections[i][j];    // table is symentric
                $.bp( baseInd == -1 );    // Never found the base?
                // Debug - dump the connection table
        /*        for (i = 0; i < numLayers; ++i)
                    var s = "";
                    for (j = 0; j < numLayers; ++j)
                        s += ", " + Math.floor(connections[i][j]);
                    $.writeln(s);
                // Connect everything to the base that's connected.
                for (i = 0; i < numLayers; ++i)
                    if ((i != baseInd) && (connections[baseInd][i] > 0))
                        group.layers[i].fConnectedTo = group.layers[baseInd];
                        group.layers[i].fNeighborOverlap = connections[baseInd][i];
                // Walk the cconnectivity table and make sure everything is
                // "optimally" connected.
                var changes = false;
                do {
                    changes = false;
                    for (i = 0; i < numLayers; ++i)
                        if (i != baseInd)
                            var curLayer = group.layers[i];
                            for (j = 0; j < numLayers; ++j)
                                if (((j != baseInd) && (j != i))
                                    && (((connections[i][j] > curLayer.fNeighborOverlap)
                                            && isConnectedToBase( group.layers[j], curLayer ))))
                                    curLayer.fConnectedTo = group.layers[j];
                                    curLayer.fNeighborOverlap = connections[i][j];
                                    changes = true;
                } while (changes);
        //        for (i = 0; i < numLayers; ++i)
        //            $.writeln( group.layers[i].fName + " is connected to " + (group.layers[i].fConnectedTo ? group.layers[i].fConnectedTo.fName : "??") );
    photomerge.offsetStack = function( delta )
        for (i in this.stackElements)
            this.stackElements[i].offset( delta );
        this.fBounds.offset( delta );
    photomerge.scaleStack = function( s )
        for (i in this.stackElements)
            this.stackElements[i].scale( s );
        this.getBounds();
    // This gets executed before a filter plugin is invoked.  "desc"
    // allows passing parameters to the filter.
    photomerge.customPluginArguments = function( desc )
        var f = new File(this.stackElements[0].fFullName);
        var path = File.encode( f.parent.fsName ) + (File.fs == "Windows" ? "\\" : "/");
        desc.putString( app.charIDToTypeID('PMfp'), path );
        if (this.compositionFile)
            desc.putString( app.charIDToTypeID('PMrf'), this.compositionFile.fsName );
            desc.putString( app.charIDToTypeID('PMcf'), File.encode( this.compositionFile.fsName ) );
    photomerge.callInteractivePlugin = function( stackDoc )
        // Scale the results to fit the screen
    /*        var scaleFactor = 1.0, screenSize = primaryScreenDimensions() * 0.75;
        if (this.fBounds.getHeight() > this.fBounds.getWidth())
            if (this.fBounds.getHeight() > screenSize.fY)
                scaleFactor = screenSize.fY / this.fBounds.getHeight();
        else
            if (this.fBounds.getWidth() > screenSize.fX)
                scaleFactor = screenSize.fX / this.fBounds.getWidth();
        const kMaxPieceSize = 1024;        // Must match value in PhotomergeUI.cpp
        var i;
        // The old plugin insists on eight bit data.
        if (stackDoc.bitsPerChannel != BitsPerChannelType.EIGHT)
            stackDoc.bitsPerChannel = BitsPerChannelType.EIGHT;
            this.stackDepthChanged = true;
        if (this.compositionFile == null)
            // Make sure the quad coordinates coorespond to the scale used by the UI plugin
            var maxPieceSize = 0;
            for (i in this.stackElements)
                maxPieceSize = Math.max( Math.max( this.stackElements[i].fWidth, this.stackElements[i].fHeight ), maxPieceSize );
            var mipLevel = 0;
            while (maxPieceSize >> mipLevel > kMaxPieceSize)
                mipLevel++;
            var imageReduction = 1.0 / (1 << mipLevel);
            this.offsetStack( -this.fBounds.getCenter() );
            this.scaleStack( imageReduction );
            this.offsetStack( -this.fBounds.getTopLeft() );
            this.setupConnectivity();
            // Add the additional per-piece metadata to pass to the filter plugin
            for (i in this.stackElements)
                this.stackElements[i].addPieceData();
        // Make the result layer active
        app.activeDocument.activeLayer = app.activeDocument.layers[app.activeDocument.layers.length -1];
        // Note: we need an "unmodified" flag, so if no
        // changes are made we skip the data recovery step...
        var result, err;
        try {
            result = this.invokeFilterPlugin( "AdobePhotomergeUI4SCRIPT", DialogModes.ALL );
        catch (err)
            result = null;
        if (result == null)        // Cancelled / bombed out
            stackDoc.close(SaveOptions.DONOTSAVECHANGES);
            return null;
        // Extract the data from the plugin
        var modifiedPieceInfo = result.getString( app.charIDToTypeID('PSpc') ).split('\n');
        for (i in modifiedPieceInfo)
            // If we loaded a composition (.pmg) file, we won't have corners yet.
            if (typeof(this.stackElements[i].fCorners) == "undefined")
                this.stackElements[i].fCorners = new Array();
            var j, pieceData = modifiedPieceInfo[i].split('\t');
            for (j in pieceData)
                var k, pair = pieceData[j].split('=');
                if (pair[0] == 'fUsed')
                    this.stackElements[i].fUsed = eval(pair[1]);
                if (pair[0] == 'fCorners')
                    var coords = pair[1].split(/\s+/).slice(1);
                    for (k = 0; k < 4; k++)
                        this.stackElements[i].fCorners[k] = new TPoint( Number(coords[k*2]), Number(coords[k*2+1]) );
        // Remove unused photos
        for (i = 0; i < this.stackElements.length; ++i)
            if (! this.stackElements[i].fUsed)
                stackDoc.layers[(this.stackElements.length-1)-i].remove();
                this.stackElements.splice(i,1);
                i--;
        // Hey...it could happen.
        if (this.stackElements.length < 2)
            return null;
        // If we run the UI, we're restricted to an eight bit stack.
        // If the source images were higher, we need to reload the image stack.
        if (this.stackDepthChanged)
            stackDoc.close(SaveOptions.DONOTSAVECHANGES);
            stackDoc = this.loadStackLayers();
        this.getBounds();        // Update w/new corner data
        return stackDoc;
    // "Adobe patent application tracking # B349, entitled 'Method and apparatus for Layer-based Panorama Adjustment and Editing', inventor: John Peterson"
    // Use the geometry of the overlapping pieces to create
    // simple rectangular blend masks.
    photomerge.quickBlend = function()
        var i, j;
        var blendRadius = Math.round(Math.min(this.stackElements[0].fWidth, this.stackElements[0].fHeight) / 10.0);
        if (PMDebug)
            for (i in this.stackElements)
                this.stackElements[i].dumpMLCorners();
        // Set up progress bar for blending
        // The progress bar doesn't work - there's know way in ScriptUI to force it to update.
    /*    var progressWindow = latteUI( g_StackScriptFolderPath + "PMBlendingProgress.exv" );
        var num = this.stackElements.length;
        var progressBar = progressWindow.findControl('_progress');
        progressBar.maxvalue = (num * (num + 1)) / 2;
        num = 0;
        progressWindow.center();
        progressWindow.show();
        // Blend the i'th piece against the 0..i-1 pieces below it
        for (i = this.stackElements.length-1; i > 0; --i)
            for (j = i-1; j >= 0; j--)
    //            num++;
    //            progressBar.value = num; // ScriptUI bug - there's no way to force this to update.
                this.stackElements[i].softEdgeBlend( this.stackElements[j], blendRadius );
    //    progressWindow.close();
    // Wrap the advancedBlend in a try/catch so errors (i.e., user cancel)
    // just stop the blend process.
    photomerge.advancedBlend = function( stackDoc )
        try {
            selectAllLayers(stackDoc, 1);
            advancedMergeLayers();
        catch (err)
    // With the stack elements specified, this
    // portion actually creates the Panorama.
    // Returns boolean indicating success/failure
    photomerge.doPanorama = function()
        var i, stackDoc = null;
        function primaryScreenDimensions()
            var i;
            for (i in $.screens)
                if ($.screens[i].primary)
                    return new TPoint( $.screens[i].right - $.screens[i].left,
                                          $.screens[i].bottom - $.screens[i].top );
        function resizeCanvasToFitPano()
            // Extend the canvas to hold the panorama
            var w = UnitValue( photomerge.getBounds().getWidth(), "px" );
            var h = UnitValue( photomerge.getBounds().getHeight(), "px" );
            app.activeDocument.resizeCanvas( w, h, AnchorPosition.TOPLEFT );
        if (this.interactiveFlag)
            // Filter must have eight bit depth and RGB color space
            stackDoc = this.loadStackLayers( BitsPerChannelType.EIGHT );
            stackDoc.changeMode(ChangeMode.RGB);
        else
            stackDoc = this.loadStackLayers();
        if (! stackDoc)
            return false;
        // Remove spurious last layer (not needed by Photomerge)
        if (app.activeDocument.layers[app.activeDocument.layers.length-1].name == this.pluginName)
            app.activeDocument.layers[app.activeDocument.layers.length-1].remove();
        // The UI needs everything in the top left corner
        if (this.interactiveFlag)
            for (i = 0; i < stackDoc.layers.length; ++i)
                var xoff = stackDoc.layers[i].bounds[0].as("px");
                var yoff = stackDoc.layers[i].bounds[1].as("px");
                if ((xoff != 0) || (yoff != 0))
                    stackDoc.layers[i].translate( UnitValue( -xoff, "px" ), UnitValue( -yoff, "px" ) );
        // Sort out exactly what operations we want to do.
        if (! this.interactiveFlag)
            selectAllLayers(stackDoc, 1);
            this.getAlignmentInfo( stackDoc, true );
            resizeCanvasToFitPano();
            if (this.advancedBlending)
                stackDoc.changeMode( ChangeMode.RGB );    // Auto-blend requires  RGB
                this.advancedBlend( stackDoc );
    // The Advanced blending works so well that there's little point
    // in having the rectangular gradient blends anymore.  Uncomment the
    // following two lines if you still want them (see similar code below
    // for the interactive case).
    //        else
    //            this.quickBlend();
            purgeHistoryStates();
            return true;
        // Interactive happens here
        if (this.compositionFile == null)
            this.getAlignmentInfo( stackDoc, false );   
            // With the corners computed by getAlignmentInfo,
            // find the bounds and use that to slide the images
            // over so their bounds has origin 0,0 (top left)
            this.offsetStack( -this.fBounds.getTopLeft() );
        if (this.interactiveFlag)
            stackDoc = this.callInteractivePlugin( stackDoc );
        if (stackDoc == null)
            return false;
        resizeCanvasToFitPano();
        // Now apply the transformation to the pieces
        for (i in this.stackElements)
            this.stackElements[i].transform();
        if (this.advancedBlending)
            selectAllLayers( stackDoc, 1 );
            stackDoc.changeMode( ChangeMode.RGB );    // Auto-blend requires  RGB
            advancedMergeLayers();
    // The new "advanced blending" works well enough that there's
    // little point in invoking the rectangular gradient blends anymore.
    // If you really want them, you can uncomment the two lines below.
    //    else
    //        this.quickBlend();
        purgeHistoryStates();
        return true;
    // Extra group breaks the main dialog's radio buttons,
    // so we manually implement it here (ScriptUI lossage)
    // NOTE: When called, this is a member function of radioControl,
    // -not- photomerge.  JavaScript voodoo.
    photomerge.radioClick = function()
        var w = this.window;
        var i;
        // Some of the transforms don't allow lens correction...
        var allowLensCor = ((this.button_id != '_LOnormal')
                            && (this.button_id != '_LOcollage')
                            && (this.button_id != '_LOinteractive'));
        w.findControl('_useLensCorrection').enabled = allowLensCor;
        w.findControl('_removeVignette').enabled = allowLensCor;
        // Be aggressive about it...
        if (! allowLensCor)
            w.findControl('_useLensCorrection').value = false;
            w.findControl('_removeVignette').value = false;
        for (i in photomerge.radioButtons)
            var b = w.findControl(photomerge.radioButtons[i]);
            if (b != this)
                b.value = false;
    // Callback when "Load Composition" is clicked.
    // NOTE: When called, this is a member function of buttonControl,
    // -not- photomerge.  JavaScript voodoo.
    photomerge.loadCompositionClick = function()
        function MacPMGType( f )
            if (f.type == 'PhMg')
                return true;
            var match = f.name.match(/.*[.](.+)$/);
            var suffix = match != null ? match[1].toLowerCase() : "";
            if (suffix == "pmg")
                return true;
            if (f instanceof Folder)
                // If the item is an app or a bundle it will be an
                // instance of folder. If we return true it will
                // appear as an enabled item. While the OS will not
                // let the user navigate into it, it is better to
                // have it appear as disabled.
                if (suffix.match(/app|bundle/i) != null)
                    // Do not navigate folders that end in .app or .bundle
                    return false;
                // navigate any other folder
                return true;
            // some unknown file type/suffix
            return false;
        var fileType = File.fs == "Windows" ? localize("$$$/AdobePlugin/Shared/Photomerge/Auto/Win=Photomerge Compositions:*.pmg")
                                        : MacPMGType;
        photomerge.compositionFile = File.openDialog( localize("$$$/AdobePlugin/Photomerge/LoadComp=Load Photomerge Composition"), fileType );
        if (photomerge.compositionFile == null || !photomerge.compositionFile.open("r"))
            return;
        var line = photomerge.compositionFile.readln();
        if (! line.match(/^VIS/))
            alert( this.pluginName + localize("$$$/AdobePlugin/Photomerge/BadComp=The Composition file is corrupt"), this.pluginName, true );
            return;
        // Read through the composition file and extract the file paths in it.
        var mergeFiles = new Array();
        while (! photomerge.compositionFile.eof)
            line = photomerge.compositionFile.readln();
            var f = line.match(/^\s*PATH\s+<([^>]+)/);
            if (f)
                // If no file path delimiters, image paths are assumed relative to the composition file
                var relPath = (f[1].indexOf( (File.fs == "Windows") ? "\\" : "/" ) < 0);
                f = (relPath ? photomerge.compositionFile.path + "/" : "") + f[1];
                mergeFiles.push( new StackElement( new File(f) ) );
        if (mergeFiles.length < 2)
            alert( this.pluginName + localize("$$$/AdobePlugin/Photomerge/BadComp=The Composition file is corrupt"), this.pluginName, true );
            return;
        photomerge.stackElements = mergeFiles;
        photomerge.interactiveFlag = true;
        this.window.close(kFilesFromPMLoad);
    // Set up the radio buttons
    photomerge.customDialogSetup = function( w )
        var i, button;
        for (i in this.radioButtons)
            button = w.findControl(this.radioButtons[i]);
            button.onClick = this.radioClick;
            // Flag with name so we can identify it in radioClick
            button.button_id = this.radioButtons[i];
        // Missing feature: We should query the selected file's metadata and
        // automatically turn on the '_useLensCorrection' checkbox if the
        // file has the proper support for it.
        w.findControl("_loadcomp").onClick = this.loadCompositionClick;
        // Julie didn't like the intro line; nuke it here because stackDialog looks for it.
        w.findControl("_intro").parent.remove(['_intro']);
        var size = w.findControl("_fileList").size;
        size[1] += 20;
        w.findControl("_LOauto").value = true;        // Set default
        w.findControl("_advancedBlend").value = this.advancedBlending;
        // If the PhotomergeUI or ADM plugins aren't there, don't display the option for it.
        if ((app.systemInformation.search(/PhotomergeUI/) < 0) || (app.systemInformation.search(/ADM /) < 0))
           w.findControl("_PMInteractive").hide();
           w.findControl("_loadcomp").hide();
    // Called by the dialog on closing to collect the results
    photomerge.customDialogFunction = function( w )
        if (w.findControl("_LOinteractive").value)
            this.interactiveFlag = true;
            this.alignmentKey = 'interactive';
        else
            var i, d = [{k:"_LOauto",v:"Auto"},{k:"_LOnormal",v:"translation"},{k:"_LOperspective",v:"Prsp"},{k: "_LOcylindrical",v:"cylindrical"},{k:"_LOspherical",v:"spherical"},{k:"_LOcollage",v:"scen eCollage"}];
            for (i in d)
                if (w.findControl(d[i].k).value)
                    this.alignmentKey = d[i].v;
                    break;
        this.advancedBlending = w.findControl("_advancedBlend").value;
        this.lensCorrection = w.findControl("_useLensCorrection").value;
        this.removeVignette = w.findControl("_removeVignette").value;
    // "Main" execution of Photomerge from the menu
    photomerge.doInteractivePano = function ()
        // Because of the ",true", the dialog is pre-loaded with any bridge files.
        this.getFilesFromBridgeOrDialog( localize("$$$/Private/Photomerge/PMDialogexv=PMDialog.exv"), true );
        try {
            if (this.stackElements && this.doPanorama())
                fitViewOnScreen();
                var flagDesc = new ActionDescriptor();
                flagDesc.putBoolean( kPhotomergeAdvancedBlendingFlag, photomerge.advancedBlending );
                app.putCustomOptions( "PhotomergeFlags001", flagDesc, true );
        catch (err)
            if (this.stackDoc)
                this.stackDoc.close(SaveOptions.DONOTSAVECHANGES)
    // Use this version to call Photomerge from a script.
    photomerge.createPanorama = function(filelist, displayDialog)
        this.interactiveFlag = (typeof(displayDialog) == 'boolean') ? displayDialog : false;
        if (filelist.length < 2)
            alert(localize("$$$/AdobePlugin/Shared/Photomerge/AtLeast2=Photomerge needs at least two files selected."), this.pluginName, true );
            return;
        var j;
        this.stackElements = new Array();
        for (j in filelist)
            var f = filelist[j];
            this.stackElements.push( new StackElement( (typeof(f) == 'string') ? File(f) : f ) );
        if (this.stackElements.length > 1)
            this.doPanorama();
    if ((typeof(runphotomergeFromScript) == 'undefined')
        || (runphotomergeFromScript==false))
        photomerge.doInteractivePano();

Maybe you are looking for

  • How to restrict the selection of other nodes when we minimize previous node

    Hi , I have requirement where i am displaying the data in tree view as result list. Here in the tree view i have  i base under that iobject and under that contract when i expand ibase node and select some iobjects and when i minimize the ibase now au

  • How do I move my iPad to a new computer without losing all my game settings?

    I installed a fresh Lion system on a new HD and moved all my data there, but my iPad (running ios5) is synced to iCloud. I'd now like to install some movies onto the iPad, so I apparently have to synch to iTunes to do this. But syncing to iTunes woul

  • Can't install Oracle 8i Ent Ed on Windows XP

    My colleagues have told me that they were able to install Oracle 8i Ent Ed(8.1.7) on Windows XP even though the site's saying it's only for Win NT/2000. Howcome i can't install it in my pc? Are there any requirements before you could install Oracle 8

  • How do I change the default location for iPhoto media?

    On my MacBook Pro, I have a 250 GB solid state drive. More than 140 GB of that space is taken up by images and video in my iPhoto folder. I want to purchase an external hard drive to store my iPhoto media so I can free up space on my Mac's hard drive

  • Change Currency in Document Flow

    SD Experts, I am noticing that when I display document flow under invoice the amount is displayed in EUR, however all documents are created in USD. Where can I change the currency so that when I display it document flow everythign shows USD. We only