// BridgeEnfuse.jsx // // Copyright 2009 Dmitriy Mayorov // All Rights Reserved // /** @fileoverview Allows to enfuse selected images in Bridge. @class Add a custom menu element to a context menu in Bridge.

Usage

  1. Execute the snippet in the ExtendScript Toolkit with Adobe Bridge as the target.
  2. In Bridge, select thumbnails
  3. Right click in Windows, Ctrl-click in Mac OS to invoke context menu
  4. Select "Enfuse".

Description

Add a custom menu element to a context menu in Bridge, when the user selects files or a folder.

Add a command to the context menu for thumbnails using a handler for the onDisplay event, and defines behavior for it using a handler for the onSelect event.

The script can only be run once within a Bridge session; you must restart Bridge to run it again. This avoids the creation of duplicate menu elements with slightly different behavior.

Uses the following command-line tools: align_image_stack, enfuse, exiftool.

Script location

@constructor Constructor. */ function BridgeEnfuse() { /** The context in which this snippet can run; Bridge must be running. @type String */ this.requiredContext = "\tAdobe Bridge must be running.\n\tExecute against Bridge as the Target.\n"; $.level = 1; // Debugging level /** The unique identifier for the new menu item command @type String */ this.menuID = "idBridgeEnfuse"; } /** Add a command to the context menu that is displayed when there is a multiple selection in the Bridge content pane, and defines the behavior using an event handler for the onSelect event.

Can only run once in a session. You must restart Bridge to test any change you make in the code. @return True if the snippet ran as expected, false otherwise. @type Boolean */ BridgeEnfuse.prototype.run = function() { var retval = true; var uid = 1; // Static counter that is incremented each time we enfuse. Used in prefix to avoid filename conflicts. if (!this.canRun()) { retval = false; return retval; } var cntCommand = new MenuElement("command", "Enfuse", "at the end of Thumbnail", this.menuID); // What to do when the menu item is selected cntCommand.onSelect = function(m) { var prefix = 'bridge-enfuse-' + uid; uid++; var bin = '/Users/dmitrym/bin/'; var target; var dcraw = ''; var converted = ''; var aligned = ''; for (var i = 0; i < app.document.selections.length; i++) { if (i == 0) { // Target filename is the same as first merged file, but with underscore at the end. target = '' + app.document.selections[i].spec; var lastdot = target.lastIndexOf('.'); if (lastdot > 0) { target = target.substring(0, lastdot) + '_.tif'; } else { target += '_'; } } dcraw += bin + 'dcraw -v -c -T -4 ' + app.document.selections[i].spec + ' >' + prefix + '-' + i + '.tif 2>>' + prefix + ".log;\n"; converted += ' ' + prefix + '-' + i + '.tif'; aligned += ' ' + prefix + '-000' + i + '.tif'; } var command_line = "(cd /tmp;\n"; // Step 1 - Create an empty file to indicate to the user that enfusing is underway command_line += 'touch ' + target + ";\n"; // Step 2 - Convert to TIFF. command_line += dcraw; // Step 3 - Align. EXIF data will be lost, but we'll copy it over later. command_line += bin + 'align_image_stack -l -a ' + prefix + '-' + converted + ";\n"; // Step 4 - No longer need converted files, remove them. command_line += 'rm' + converted + ";\n"; // Step 5 - Enfuse aligned files. command_line += bin + 'enfuse -v -o ' + target + aligned + '>>' + prefix + ".log 2>&1;\n"; // Step 6 - Copy EXIF from the first original. command_line += '/usr/bin/exiftool -overwrite_original -tagsFromFile ' + app.document.selections[0].spec + ' ' + target + '>>' + prefix + ".log 2>&1;\n"; // Step 7 - Remove aligned files. command_line += 'rm' + aligned + ')&'; // & at the end means Bridge won't wait for the operation to finish. //alert(command_line); app.system(command_line); }; // When to display the menu item cntCommand.onDisplay = function() { try { if (app.document.selections.length > 1 && !app.document.selections[0].container) { cntCommand.enabled = true; cntCommand.text = "Enfuse " + app.document.selections.length + " files"; } else { cntCommand.enabled = false; cntCommand.text = "Enfuse"; } } catch(error){ $.writeln(error); } }; return retval; } /** Determines whether snippet can be run given current context. @return True is this snippet can run, false otherwise @type boolean */ BridgeEnfuse.prototype.canRun = function() { // Must run in Bridge if (BridgeTalk.appName == "bridge") { // Stop the menu element from being added again if the snippet has already run if (MenuElement.find(this.menuID)) { $.writeln("ERROR:: Menu element from BridgeEnfuse already exists!\nRestart Bridge to run this snippet again."); return false; } return true; } $.writeln("ERROR:: Cannot run BridgeEnfuse"); $.writeln(this.requiredContext); return false; } /** "main program": construct an anonymous instance and run it as long as we are not unit-testing this snippet. */ if (typeof(BridgeEnfuse_unitTest) == "undefined") { new BridgeEnfuse().run(); }