3

Is it possible to show the same photoshop file in two separate windows, each with a different layer comp?

11
  • 1
    Only if you duplicate the psd file and open it twice. What's the scenario? Why do you want that? There could be a workaround or an alternative.
    – Joonas
    Commented Mar 27, 2019 at 14:48
  • i like showing different layer comps side by side - it's often 70-90% the same file with different variations
    – ina
    Commented Mar 28, 2019 at 2:03
  • I don't know if I'm immediately thinking too complicated, but I think it would be possible to make a script that duplicates the full document for each layer comp or just the selected comps and merges them all into a separate document with all the chosen layer comps side by side.
    – Joonas
    Commented Mar 28, 2019 at 6:34
  • You could use File > Export > Layer Comps to files (or to PDF) Doesn't make it as easy as a new window for the same document, but may be easier than duplicating the entire document.
    – Scott
    Commented Mar 28, 2019 at 16:06
  • That requires creating new files each time though... Would there be a better totally different way to do this to compare side by side different versions (saved as layer comps or otherwise) of a similar file?
    – ina
    Commented Mar 31, 2019 at 1:26

1 Answer 1

3

So I wrote a script that should get pretty close to what you are after.

If you're not familiar with using scripts, I'm sure there are many sources if you google: "how to run scripts in photoshop" or something. Though it may be good to know that you can: 1. set a shortcut to run a script 2. run a script from an Action 3. run it from the File > Scripts... menu 4. run it using third party applications (like I'm doing in the gif). The script was tested in Photoshop CC 2019, so there is a chance it won't work in anything older...

What you don't see in the gif is that this comparison image is actually a new document. I just keep closing it and running the script again. The gif is a bit hectic, I know, but I had to make sure the filesize is small enough to upload here.

enter image description here

// Version 1.1.
// Compare Selected Comps.jsx
// https://gist.github.com/joonaspaakko/adbe208a867f8681afa86032f91f5099?ts=2

// #########
// Changelog
// #########

// v.1.1.
// - Tested in Photoshop CC 2019
// - Added a fallback for when less than 2 layer comps are selected, in which case all layer comps are pushed to the comparison document.
// - Fixed the border issue.
// - Fixed the issue where comp gets fused with the comparison document background.

// v.1.0.
// - First Version
// - Tested in Photoshop CC 2019
// - Known issues:
//      - The script adds a border around the final comp layer in order to divide the comp layers a bit. If the comp doesn't have a solid background, the stroke will do weird things.
//      - The first comp gets fused with the background of the comparison document in some situations...

#target photoshop

var startCompare = false;
var maxHorizontal = 1;

if ( app.documents.length > 0 ) init();

function init() {

    var rulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;

    var doc = app.activeDocument;

    // Duplicate current document
    var tempDoc = doc.duplicate( (doc.name + ' (Comparison)') );

    // Check layer comp selection.length
    // Get layer comps
    var layerComps = tempDoc.layerComps;
    var selectedComps = [];
    var leftOverComps = [];
    // Go through every comp
    for ( var i=0; i < layerComps.length; i++ ) {
        var comp = layerComps[ i ];
        // If comp is selected...
        if ( comp.selected ) {
            selectedComps.push( comp );
        }
        else {
            leftOverComps.push( comp );
        }
    }

    // If more than one comp is selected...
    // Remove all leftover layer comps
    if ( selectedComps.length > 1 ) {

        // Go through every comp
        for ( var i=0; i < leftOverComps.length; i++ ) {
            var comp = leftOverComps[ i ];
            comp.remove();
        }

    }

    dialog( tempDoc.layerComps.length );

    if ( !startCompare ) {
    // tempDoc.close( SaveOptions.DONOTSAVECHANGES );
    }
    else if ( startCompare ) {

        var tempDocsCollection = [];
        // Get layer comps again...
        var layerComps = tempDoc.layerComps;
        var selectedCompsLength = layerComps.length;
        // Go through every comp
        for ( var i=0; i < selectedCompsLength; i++ ) {

            var comp = layerComps[ i ];
            comp.apply();
            var thisCompDoc = tempDoc.duplicate( comp.name, true);
            thisCompDoc.flatten();
            addBlackBorder();
            tempDocsCollection.push( thisCompDoc );
            app.activeDocument = tempDoc;

        }

        // Get ready to receive compsies
        // Scrub the temp document clean...
        tempDoc.flatten();
        whiteFill();

        // New size to fit the border
        tempDoc.resizeCanvas( (tempDoc.width + 1), (tempDoc.height + 1), AnchorPosition.TOPLEFT );

        var tempDocWidth = tempDoc.width;
        var tempDocHeight = tempDoc.height;

        // Find out how many rows are needed
        var columns = maxHorizontal;
        var rows = 0;
        var equalizer = 1;
        for ( var i = 0; i < selectedCompsLength; i++ ) {
            if ( equalizer == 1 ) {
                rows = rows+1;
            }
            equalizer = equalizer == columns ? 1 : equalizer + 1;
        }

        var newWidth = tempDocWidth * columns;
        var newHeight = tempDocHeight * rows;
        tempDoc.resizeCanvas( newWidth, newHeight, AnchorPosition.TOPLEFT );

        // Go through every comp document
        var cumulativeWidth = 0;
        var cumulativeHeight = 0;
        var equalizer = 1;
        for ( var i=0; i < tempDocsCollection.length; i++ ) {

            var compDoc = tempDocsCollection[ i ];
            app.activeDocument = compDoc;
            compLayerName = compDoc.name;

            // Duplicate comp document back to the tempdoc as a single layer...
            var compLayer = compDoc.activeLayer.duplicate( tempDoc, ElementPlacement.PLACEATEND );
            compDoc.close( SaveOptions.DONOTSAVECHANGES );
            app.activeDocument = tempDoc;
            compLayer.name = compLayerName;

            // Move comp layers side by side
            compLayer.translate( cumulativeWidth, cumulativeHeight );

            cumulativeWidth  = ( equalizer == columns ) ? 0 : cumulativeWidth  + tempDocWidth;
            cumulativeHeight = ( equalizer == columns ) ? (cumulativeHeight + tempDocHeight) : cumulativeHeight;
            equalizer = equalizer == columns ? 1 : equalizer + 1;
        }

    }

  app.preferences.rulerUnits = rulerUnits;

}

function whiteFill() {

  function cTID(s) { return app.charIDToTypeID(s); };
  function sTID(s) { return app.stringIDToTypeID(s); };

  var desc419 = new ActionDescriptor();
  desc419.putEnumerated( cTID('Usng'), cTID('FlCn'), cTID('Wht ') );
  desc419.putUnitDouble( cTID('Opct'), cTID('#Prc'), 100.000000 );
  desc419.putEnumerated( cTID('Md  '), cTID('BlnM'), cTID('Nrml') );
  executeAction( cTID('Fl  '), desc419, DialogModes.NO );

}

function selectAllLayers() {

    // Makes background layer a normal layer.
    // Otherwise it wouldn't be selected in the next step.
    var firstLayer = app.activeDocument.layers[ app.activeDocument.layers.length - 1 ];
    if ( firstLayer.isBackgroundLayer ) firstLayer.isBackgroundLayer = false;

    // Select all layers...
    var actionDescriptor = new ActionDescriptor();
    var actionReference = new ActionReference();
    actionReference.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
    actionDescriptor.putReference( charIDToTypeID( "null" ), actionReference );
    executeAction( stringIDToTypeID( "selectAllLayers" ), actionDescriptor, DialogModes.NO );

}

function addBlackBorder() {

  function cTID(s) { return app.charIDToTypeID(s); };
  function sTID(s) { return app.stringIDToTypeID(s); };

  var desc97 = new ActionDescriptor();
  desc97.putBoolean( cTID('Rltv'), true );
  desc97.putUnitDouble( cTID('Wdth'), cTID('#Pxl'), 2.000000 );
  desc97.putUnitDouble( cTID('Hght'), cTID('#Pxl'), 2.000000 );
  desc97.putEnumerated( cTID('Hrzn'), cTID('HrzL'), cTID('Cntr') );
  desc97.putEnumerated( cTID('Vrtc'), cTID('VrtL'), cTID('Cntr') );
  desc97.putEnumerated( sTID('canvasExtensionColorType'), sTID('canvasExtensionColorType'), cTID('Clr ') );
      var desc98 = new ActionDescriptor();
      desc98.putUnitDouble( cTID('H   '), cTID('#Ang'), 0.000000 );
      desc98.putDouble( cTID('Strt'), 0.000000 );
      desc98.putDouble( cTID('Brgh'), 0.000000 );
  desc97.putObject( sTID('canvasExtensionColor'), cTID('HSBC'), desc98 );
  executeAction( cTID('CnvS'), desc97, DialogModes.NO );

}

function dialog( compsLength ) {

    /*
    Code for Import https://scriptui.joonas.me — (Triple click to select):
    {"activeId":0,"items":{"item-0":{"id":0,"type":"Dialog","parentId":false,"style":{"varName":null,"text":"Compare Selected Comps.jsx","preferredSize":[0,0],"margins":29,"orientation":"row","spacing":10,"alignChildren":["right","center"]}},"item-1":{"id":1,"type":"EditText","parentId":0,"style":{"varName":null,"text":"4","preferredSize":[52,0],"alignment":null,"helpTip":null}},"item-2":{"id":2,"type":"StaticText","parentId":0,"style":{"varName":null,"text":"Max comps side by side:","justify":"left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-5":{"id":5,"type":"Button","parentId":0,"style":{"varName":null,"text":"Cancel","justify":"center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-6":{"id":6,"type":"Button","parentId":0,"style":{"varName":null,"text":"Compare","justify":"center","preferredSize":[0,0],"alignment":null,"helpTip":null}}},"order":[0,2,1,6,5]}
    */

    // DIALOG
    // ======
    var dialog = new Window("dialog");
        dialog.text = "Compare Selected Comps.jsx";
        dialog.orientation = "row";
        dialog.alignChildren = ["right","center"];
        dialog.spacing = 10;
        dialog.margins = 29;

    var statictext1 = dialog.add("statictext");
        statictext1.text = "Max comps side by side:";

    var edittext1 = dialog.add("edittext");
        edittext1.text = "4";
        edittext1.preferredSize.width = 52;

    var button1 = dialog.add("button", undefined, undefined, {name:"ok"});
            button1.text = "Compare";
            button1.justify = "center";

    var button2 = dialog.add("button", undefined, undefined, {name:"cancel"});
            button2.text = "Cancel";
            button2.justify = "center";

    // Customization

    edittext1.text = compsLength;
    edittext1.active = true;

  button1.onClick = function() {
     startCompare = true;
     maxHorizontal = parseInt( edittext1.text, 10);
     dlg.close();
  }

  button2.onClick = function() {
    dlg.close();
  }

  dialog.show();


}
17
  • 1
    @ina, Definitely Alfred. It's great for managing lots of scripts of any amount really... Especially its File Filter. I have a file filter set for both PS and AI where when I open the Alfred launcher Ctrl+Space and write .ps or .ai any following characters I write does a fuzzy search for either PS or AI scripts in specific folders I have in Dropbox. So if I download a PS script, I put it in that Dropbox folder and I can immediately search for it using .ps ...
    – Joonas
    Commented Apr 9, 2019 at 6:52
  • 1
    Oh and I almost forgot... I got these file filters setup to open the file in PS or AI when I press enter with a file selected, like you see in the gif. You do need the Powerpack license for Alfred to use that or pretty much any of its custom automation related features. It does have keywords too if you want to give a script or anything a specific keyword to find it via the Alfred launcher or you can also give shortcut triggers too. I only give shortcuts for scripts I use a lot or where it makes sense. The file filter is excellent for those scripts you use rarely.
    – Joonas
    Commented Apr 9, 2019 at 6:53
  • 1
    Just as a neat example on how amazing alfred/dropbox sync combo is... I'm on a different computer right now and didn't do anything except start the computer and if I wanted to, I could search and run that script with: Ctrl+Space.ps compareEnter. Same thing if I ever format my computer or something... I just install Dropbox and Alfred and I'm back to using the same keywords and shortcut keys...
    – Joonas
    Commented Apr 9, 2019 at 7:27
  • 1
    I can't talk so much about Alfred and not mention Packal. It's a third party site for packal workflows and is well known among Alfred users. Obviously you can make your own Workflows too, and you should, but there are many good workflows out there, like this one I've made and shared in packal. You can also find some Workflows in the official Alfred forums, github and generally from Google.
    – Joonas
    Commented Apr 10, 2019 at 17:31
  • 1
    @ina, I bumped into this question again and this is a little late, but just thought I'd link the file filter workflow I talked about above: github.com/joonaspaakko/…
    – Joonas
    Commented Feb 19, 2021 at 12:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.