14 Replies Latest reply on Jun 22, 2015 6:53 AM by c.pfaffenbichler

    Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?

    pharmon_ Level 1

      With the end result being either the diffed output to a log or image, possibly outputting a list of the individual elements (channels, layers, etc.) and whether the histograms of each element match.

       

      Example:

      1. Document A is a TIF or PSD with multiple channels (RGB or CMYK/Spot color), multiple layers, text layers, etc.

      2. Document B is expected to be an exact copy of Document A, but may have been slightly tweaked/adjusted.

      3. Compare/Diff Doc A and Doc B down to the various elements:

      - Color Channels, Alpha Channels, Spot Color

      Or

      - Layers, Text Layers, Etc.

      4. Logging whether Doc A and Doc B are exact matches or have differences, and where the differences were found (channels, layers, etc.)

      (I have written a jsx to diff Doc A and Doc B, but only if they have been flattened and diffed (blend mode) and then can either stop/alert or after running through a group of compared documents, logging which one are not exact matches.)

       

        • 1. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
          c.pfaffenbichler Level 9

          I am not sure a comparison in Photoshop would be the best solution but I would not know how to evaluate the data outside of it.

           

          Difficulties come to mind regarding the comparison in Photoshop itself:

          • The evaluation of Layers via bounds, histogram or even loaded transparency may result in false positives

          compareLayeredFileScr.jpg

          • Type Layers are fairly difficult to evaluate when it comes to multiple settings for fonts, tracking, kerning etc. within one Type Layer

          • The possibilities for Blend Mode, Fill, Blend If settings etc. might make a very comprehensive evaluation of any individual Layer and Group necessary

           

          Ultimately it may practically be necessary to compare each pair of Layers against some background (preferably in a separate new file) with Blend Mode Difference but this might result in fairly bad performance speed-wise.

          And this may introduce possibilities for false positives again (a multiplying Layer of black at Fill 80% and one of 80% black at Fill 100% for example).

           

          Hopefully someone else will chime in.

          • 2. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
            pharmon_ Level 1

            c.pfaffenbichler,

             

            Currently this is all done in ImageMagick, but there have been some hiccups when updating versions and other things.

             

            I have been using a jsx to compare a baseline directory to a secondary directory, taking each matched file name, flattening the psd/tif and then using BlendMode.Difference to say whether there are any differences in the overall image data.  I then added some really bad looking selection options to highlight to the operator where the differences are.  However, I need to take this down to a by-channel and by-layer level for the operator to see more clearly where the differences lie.

             

            I have been working on the comparing every individual layer and channel against each other, but I have only been doing this for a couple of weeks in the evenings and was hoping someone else has had to go through this before.

             

            -Cheers

            • 3. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
              c.pfaffenbichler Level 9

              Comparing Spot Color and Alpha Channels should not be very difficult and basically your using of Blend Mode Difference (employing Image > Calculations maybe) seems a good approach (maybe the only valid one).

              But the time it takes may be considerable.

               

              With Layers I am afraid the number off possible problems could be huge …

              Name, itemID, bounds, histogram, … may all be good for a superficial check but could provide erroneous assessments.

               

              Will the Script ultimately be run by people individually on each file one at a time or do you intend to have it run on bunches of files and possibly a computer that is not being used for anything else at the time?

               

              was hoping someone else has had to go through this before

              Possibly, but unfortunately another relevant Photoshop Scripting site (ps-scripts.com) is currently offline.

              • 4. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                pharmon_ Level 1

                I'm trying to simply things by just trying to compare each channel from 2 images, but sadly, my js-foo is not working.

                 

                Specifically "Illegal Operation at line 76: var idCyn = charIDToTypeID( "channelNames[i]" ); // Trying to iterate through the Channels

                 

                 

                //---------------------------------------------------------------------------------------- ---------

                // enable double clicking from the Macintosh Finder or the Windows Explorer

                //#target photoshop (If you only have instance of PS)

                //#target "Photoshop-90.064" // For Adobe® Photoshop® CC 2015 - Windows x64

                #target "Photoshop-80.064" // For Adobe® Photoshop® CC 2014 - Windows x64

                 

                 

                function getProperty( psClass, psKey, index ){// integer:Class, integer:key

                    var ref = new ActionReference();

                    if( psKey != undefined ) ref.putProperty( charIDToTypeID( "Prpr" ), psKey );

                    if(index != undefined ){

                        ref.putIndex( psClass, index );

                    }else{

                        ref.putEnumerated( psClass , charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );

                    }

                    try{

                        var desc = executeActionGet(ref);

                    }catch(e){ return; }// return on error

                    if(desc.count == 0) return;// return undefined if property doesn't exists

                    var dataType = desc.getType(psKey);

                    switch(dataType){// not all types supported - returns undefined if not supported

                        case DescValueType.INTEGERTYPE:

                            return desc.getInteger(psKey);

                            break;

                        case DescValueType.ALIASTYPE:

                            return desc.getPath(psKey);

                            break;

                        case DescValueType.BOOLEANTYPE:

                            return desc.getBoolean(psKey);

                            break;

                        case DescValueType.BOOLEANTYPE:

                            return desc.getBoolean(psKey);

                            break;

                        case DescValueType.UNITDOUBLE:

                            return desc.getUnitDoubleValue(psKey);

                            break;

                        case DescValueType.STRINGTYPE:

                            return desc.getString(psKey);

                            break;

                        case  DescValueType.OBJECTTYPE:

                            return desc.getObjectValue(psKey);

                            break;

                        case  DescValueType.LISTTYPE:

                            return desc.getList(psKey);

                            break;

                        case  DescValueType.ENUMERATEDTYPE:

                            return desc.getEnumerationValue(psKey);

                            break;

                    }

                };

                 

                 

                var mySelectFile1 = File.openDialog("Selection prompt");

                if(mySelectFile1 != null) app.open(mySelectFile1);

                 

                 

                var mySelectFile2 = File.openDialog("Selection prompt");

                if(mySelectFile2 != null) app.open(mySelectFile2);

                 

                 

                  var doc1 = app.open(mySelectFile1);

                  var doc2 = app.open(mySelectFile2);

                 

                 

                var channelCount = app.activeDocument.channels.length;

                var channelNames = [];

                for(var channelIndex=1;channelIndex<=channelCount;channelIndex++){ 

                    var channelNames =getProperty(charIDToTypeID("Chnl"),charIDToTypeID("ChnN"),channelIndex);

                 

                 

                // =======================================================

                var idMk = charIDToTypeID( "Mk  " );

                    var desc5 = new ActionDescriptor();

                    var idNw = charIDToTypeID( "Nw  " );

                    var idDcmn = charIDToTypeID( "Dcmn" );

                    desc5.putClass( idNw, idDcmn );

                    var idUsng = charIDToTypeID( "Usng" );

                        var desc6 = new ActionDescriptor();

                        var idT = charIDToTypeID( "T   " );

                            var ref3 = new ActionReference();

                            var idChnl = charIDToTypeID( "Chnl" );

                //            var idCyn = charIDToTypeID( "Cyn " ); // Cyan was the example when I ran the ScriptListener

                            var idCyn = charIDToTypeID( "channelNames[i]" ); // Trying to iterate through the Channels

                            ref3.putEnumerated( idChnl, idCyn );

                            var idLyr = charIDToTypeID( "Lyr " );

                            var idBckg = charIDToTypeID( "Bckg" );

                            ref3.putProperty( idLyr, idBckg );

                            var idDcmn = charIDToTypeID( "Dcmn" );

                            ref3.putName( idDcmn, "mySelectFile1" );

                        desc6.putReference( idT, ref3 );

                        var idClcl = charIDToTypeID( "Clcl" );

                        var idClcn = charIDToTypeID( "Clcn" );

                        var idDfrn = charIDToTypeID( "Dfrn" );

                        desc6.putEnumerated( idClcl, idClcn, idDfrn );

                        var idSrctwo = charIDToTypeID( "Src2" );

                            var ref4 = new ActionReference();

                            var idChnl = charIDToTypeID( "Chnl" );

                //            var idCyn = charIDToTypeID( "Cyn " ); // Cyan was the example when I ran the ScriptListener

                            var idCyn = charIDToTypeID( "channelNames[i]" );  // Trying to iterate through the Channels

                            ref4.putEnumerated( idChnl, idCyn );

                            var idLyr = charIDToTypeID( "Lyr " );

                            var idBckg = charIDToTypeID( "Bckg" );

                            ref4.putProperty( idLyr, idBckg );

                            var idDcmn = charIDToTypeID( "Dcmn" );

                            ref4.putName( idDcmn, "mySelectFile2" );

                        desc6.putReference( idSrctwo, ref4 );

                    var idClcl = charIDToTypeID( "Clcl" );

                    desc5.putObject( idUsng, idClcl, desc6 );

                executeAction( idMk, desc5, DialogModes.NO );

                }   

                • 5. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                  pharmon_ Level 1

                  sorry, change this:

                   

                  var channelCount = app.activeDocument.channels.length; 

                  var channelNames = []; 

                  for(var channelIndex=1;channelIndex<=channelCount;channelIndex++){ 

                      channelNames.push(getProperty(charIDToTypeID("Chnl"),charIDToTypeID("ChnN"),channelIndex) ); 

                   

                  to this:

                  var channelCount = app.activeDocument.channels.length;

                  var channelNames = [];

                  for(var channelIndex=1;channelIndex<=channelCount;channelIndex++){

                      var channelNames =getProperty(charIDToTypeID("Chnl"),charIDToTypeID("ChnN"),channelIndex);

                  • 6. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                    c.pfaffenbichler Level 9

                    You can just use the index of the Channels.

                    You misidentified the documents with the Strings in the lines

                                ref3.putName( idDcmn, "mySelectFile1" );

                    and

                                ref4.putName( idDcmn, "mySelectFile2" );

                    instead of the documents’ names.

                    function getProperty( psClass, psKey, index ){// integer:Class, integer:key
                        var ref = new ActionReference();
                        if( psKey != undefined ) ref.putProperty( charIDToTypeID( "Prpr" ), psKey );
                        if(index != undefined ){
                            ref.putIndex( psClass, index );
                        }else{
                            ref.putEnumerated( psClass , charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
                        }
                        try{
                            var desc = executeActionGet(ref);
                        }catch(e){ return; }// return on error
                        if(desc.count == 0) return;// return undefined if property doesn't exists
                        var dataType = desc.getType(psKey);
                        switch(dataType){// not all types supported - returns undefined if not supported
                            case DescValueType.INTEGERTYPE:
                                return desc.getInteger(psKey);
                                break;
                            case DescValueType.ALIASTYPE:
                                return desc.getPath(psKey);
                                break;
                            case DescValueType.BOOLEANTYPE:
                                return desc.getBoolean(psKey);
                                break;
                            case DescValueType.BOOLEANTYPE:
                                return desc.getBoolean(psKey);
                                break;
                            case DescValueType.UNITDOUBLE:
                                return desc.getUnitDoubleValue(psKey);
                                break;
                            case DescValueType.STRINGTYPE:
                                return desc.getString(psKey);
                                break;
                            case  DescValueType.OBJECTTYPE:
                                return desc.getObjectValue(psKey);
                                break;
                            case  DescValueType.LISTTYPE:
                                return desc.getList(psKey);
                                break;
                            case  DescValueType.ENUMERATEDTYPE:
                                return desc.getEnumerationValue(psKey);
                                break;
                        }
                    };
                    
                    
                    var mySelectFile1 = File.openDialog("Selection prompt");
                    if(mySelectFile1 != null) app.open(mySelectFile1);
                    
                    
                    var mySelectFile2 = File.openDialog("Selection prompt");
                    if(mySelectFile2 != null) app.open(mySelectFile2);
                    
                    
                      var doc1 = app.open(mySelectFile1);
                      var doc2 = app.open(mySelectFile2);
                    
                    
                    var channelCount = app.activeDocument.channels.length;
                    var channelNames = [];
                    for(var channelIndex=4; channelIndex<=channelCount; channelIndex++){
                        channelNames.push(getProperty(charIDToTypeID("Chnl"),charIDToTypeID("ChnN"),channelIndex) );
                    
                    
                    // =======================================================
                    var idMk = charIDToTypeID( "Mk  " );
                        var desc5 = new ActionDescriptor();
                        var idNw = charIDToTypeID( "Nw  " );
                        var idDcmn = charIDToTypeID( "Dcmn" );
                        desc5.putClass( idNw, idDcmn );
                        var idUsng = charIDToTypeID( "Usng" );
                            var desc6 = new ActionDescriptor();
                            var idT = charIDToTypeID( "T  " );
                                var ref3 = new ActionReference();
                                var idChnl = charIDToTypeID( "Chnl" );
                                ref3.putIndex( idChnl, channelIndex );
                                var idLyr = charIDToTypeID( "Lyr " );
                                var idBckg = charIDToTypeID( "Bckg" );
                                ref3.putProperty( idLyr, idBckg );
                                var idDcmn = charIDToTypeID( "Dcmn" );
                                ref3.putName( idDcmn, doc1.name );
                            desc6.putReference( idT, ref3 );
                            var idClcl = charIDToTypeID( "Clcl" );
                            var idClcn = charIDToTypeID( "Clcn" );
                            var idDfrn = charIDToTypeID( "Dfrn" );
                            desc6.putEnumerated( idClcl, idClcn, idDfrn );
                            var idSrctwo = charIDToTypeID( "Src2" );
                                var ref4 = new ActionReference();
                                var idChnl = charIDToTypeID( "Chnl" );
                                ref4.putIndex( idChnl, channelIndex );
                                var idLyr = charIDToTypeID( "Lyr " );
                                var idBckg = charIDToTypeID( "Bckg" );
                                ref4.putProperty( idLyr, idBckg );
                                var idDcmn = charIDToTypeID( "Dcmn" );
                                ref4.putName( idDcmn, doc2.name );
                            desc6.putReference( idSrctwo, ref4 );
                        var idClcl = charIDToTypeID( "Clcl" );
                        desc5.putObject( idUsng, idClcl, desc6 );
                    executeAction( idMk, desc5, DialogModes.NO );
                    };
                    
                    • 7. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                      c.pfaffenbichler Level 9

                      Ideally you should probably also include a check to see if both images have the same number of Channels, if they are the same kinds of Channels and whether they have identical names.

                      • 8. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                        pharmon_ Level 1

                        Thank you for your help.  I have been rutting through online tutorials and hidden pockets where I can in my spare time.

                         

                        I have a question about how to get the channel name "ChnN" from the: channelNames.push(getProperty(charIDToTypeID("Chnl"),charIDToTypeID("ChnN"),channelIndex) );

                         

                        In your code snippet above (I don't know if I should paste in my entire script), how can I take the "ChnN" as it is iterating through so that I may use the channel name in logging output and file naming?

                         

                        When I attempt to look at the histogram of each diffed channel:

                         

                            found=0

                            var histogram = doc1.histogram;

                            for (var i = 1; i < histogram.length; ++i) {

                                if (histogram[i] > 0)

                                found=1

                            }

                         

                        And then attempt to log whether the channel(s) have differences, when I try to reference (in various manners) what I think should be in the channelIndex, I either see Cyan/ Cyan,, / Cyan,,, or undefined or 1,2,3,4

                         

                                log.writeln( doc1.name + doc2.name + "," + channelName? + ",Differences" );

                        • 9. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                          c.pfaffenbichler Level 9

                          I don't know if I should paste in my entire script

                          If you want people to understand what you are talking about then what is unclear about this?

                           

                          In your code snippet above (I don't know if I should paste in my entire script), how can I take the "ChnN" as it is iterating through so that I may use the channel name in logging output and file naming?

                          In the example the property is added to an Array, you can instead use it however you see fit.

                          • 10. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                            pharmon_ Level 1

                            #target photoshop

                             

                            function SavePNG(saveFile){

                                pngSaveOptions = new PNGSaveOptions();

                                activeDocument.saveAs(saveFile, pngSaveOptions, true, Extension.LOWERCASE);   

                            }

                             

                            function getProperty( psClass, psKey, index ) {// integer:Class, integer:key 

                                var ref = new ActionReference(); 

                                if( psKey != undefined ) ref.putProperty( charIDToTypeID( "Prpr" ), psKey ); 

                                if(index != undefined ){ 

                                    ref.putIndex( psClass, index ); 

                                }else{ 

                                    ref.putEnumerated( psClass , charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) ); 

                                } 

                                try{ 

                                    var desc = executeActionGet(ref); 

                                }catch(e){ return; }

                                if(desc.count == 0) return;

                                var dataType = desc.getType(psKey); 

                                switch(dataType){

                                    case DescValueType.INTEGERTYPE: 

                                        return desc.getInteger(psKey); 

                                        break; 

                                    case DescValueType.ALIASTYPE: 

                                        return desc.getPath(psKey); 

                                        break; 

                                    case DescValueType.BOOLEANTYPE: 

                                        return desc.getBoolean(psKey); 

                                        break; 

                                    case DescValueType.BOOLEANTYPE: 

                                        return desc.getBoolean(psKey); 

                                        break; 

                                    case DescValueType.UNITDOUBLE: 

                                        return desc.getUnitDoubleValue(psKey); 

                                        break; 

                                    case DescValueType.STRINGTYPE: 

                                        return desc.getString(psKey); 

                                        break; 

                                    case  DescValueType.OBJECTTYPE: 

                                        return desc.getObjectValue(psKey); 

                                        break; 

                                    case  DescValueType.LISTTYPE: 

                                        return desc.getList(psKey); 

                                        break; 

                                    case  DescValueType.ENUMERATEDTYPE: 

                                        return desc.getEnumerationValue(psKey); 

                                        break; 

                                } 

                            }; 

                             

                            function main() {

                             

                                var errorlog = File(Folder.desktop + "/Test_Log.txt");

                                var d =new Date;

                                errorlog.open('w');

                                errorlog.writeln(d);

                             

                                var mySelectFile1 = File.openDialog("Selection prompt"); 

                                if(mySelectFile1 != null) app.open(mySelectFile1);

                             

                                var mySelectFile2 = File.openDialog("Selection prompt"); 

                                if(mySelectFile2 != null) app.open(mySelectFile2); 

                             

                                var doc1 = app.open(mySelectFile1); 

                                var doc2 = app.open(mySelectFile2);

                               

                                doc2.selection.selectAll();

                                doc2.selection.copy();

                             

                             

                                app.activeDocument = doc1;

                                var newLayer = doc1.paste();

                                newLayer.blendMode = BlendMode.DIFFERENCE;

                             

                                found=0

                                var histogram = doc1.histogram;

                                for (var i = 1; i < histogram.length; ++i) {

                                    if (histogram[i] > 0)

                                    found=1

                                }

                             

                            activeDocument.activeLayer.remove();

                             

                            if (found){

                                var channelCount = app.activeDocument.channels.length; 

                                var channelNames = []; 

                                for(var channelIndex=1; channelIndex<=channelCount; channelIndex++){ 

                                    channelNames.push(getProperty(charIDToTypeID("Chnl"),charIDToTypeID("ChnN"),channelIndex) );

                             

                            // ======================================================= 

                                    var idMk = charIDToTypeID( "Mk  " ); 

                                    var desc5 = new ActionDescriptor();

                                    var idNw = charIDToTypeID( "Nw  " ); 

                                    var idDcmn = charIDToTypeID( "Dcmn" ); 

                                    desc5.putClass( idNw, idDcmn ); 

                                    var idUsng = charIDToTypeID( "Usng" ); 

                                    var desc6 = new ActionDescriptor();

                                    var idT = charIDToTypeID( "T   " );

                                    var ref3 = new ActionReference(); 

                                    var idChnl = charIDToTypeID( "Chnl" ); 

                                    ref3.putIndex( idChnl, channelIndex ); 

                                    var idLyr = charIDToTypeID( "Lyr " ); 

                                    var idBckg = charIDToTypeID( "Bckg" ); 

                                    ref3.putProperty( idLyr, idBckg ); 

                                    var idDcmn = charIDToTypeID( "Dcmn" ); 

                                    ref3.putName( idDcmn, doc1.name ); 

                                    desc6.putReference( idT, ref3 ); 

                                    var idClcl = charIDToTypeID( "Clcl" ); 

                                    var idClcn = charIDToTypeID( "Clcn" ); 

                                    var idDfrn = charIDToTypeID( "Dfrn" ); 

                                    desc6.putEnumerated( idClcl, idClcn, idDfrn ); 

                                    var idSrctwo = charIDToTypeID( "Src2" ); 

                                    var ref4 = new ActionReference(); 

                                    var idChnl = charIDToTypeID( "Chnl" ); 

                                    ref4.putIndex( idChnl, channelIndex ); 

                                    var idLyr = charIDToTypeID( "Lyr " ); 

                                    var idBckg = charIDToTypeID( "Bckg" ); 

                                    ref4.putProperty( idLyr, idBckg ); 

                                    var idDcmn = charIDToTypeID( "Dcmn" ); 

                                    ref4.putName( idDcmn, doc2.name ); 

                                    desc6.putReference( idSrctwo, ref4 ); 

                                    var idClcl = charIDToTypeID( "Clcl" ); 

                                    desc5.putObject( idUsng, idClcl, desc6 ); 

                                    executeAction( idMk, desc5, DialogModes.NO );

                             

                                    if (app.documents.length > 0 && app.activeDocument.mode = DocumentMode.GRAYSCALE) { 

                                    myDocument = app.activeDocument; 

                                    var originalRulerUnits = app.preferences.rulerUnits; 

                                    app.preferences.rulerUnits = Units.PIXELS; 

                                    var totalPixels = myDocument.width * myDocument.height; 

                                    myDocument.activeChannels = [myDocument.channels[0]]; 

                                    myDocument.selection.deselect(); 

                                    var theHistogram = myDocument.channels[0].histogram; 

                                    var blackAndWhite = theHistogram[0] + theHistogram[255]; 

                                    var blackPercentage = theHistogram[0]/totalPixels*100; 

                            //       var whitePercentage = theHistogram[255]/totalPixels*100; 

                                    if (blackAndWhite == totalPixels) {var theText = "100% Pixel Match"} 

                                    else {var theText = "has a difference of "}; 

                            //       alert (channelName? + " channel" + theText+(100-blackPercentage)+" %\r"+(totalPixels-theHistogram[0])+" out of "+totalPixels+ " total pixels."); 

                                    app.preferences.rulerUnits = originalRulerUnits; 

                             

                                    var idCnvM = charIDToTypeID( "CnvM" );

                                    var desc12 = new ActionDescriptor();

                                    var idT = charIDToTypeID( "T   " );

                                    var idGrys = charIDToTypeID( "Grys" );

                                    desc12.putClass( idT, idGrys );

                                    executeAction( idCnvM, desc12, DialogModes.NO );

                             

                                    var doc = mySelectFile1;

                                    var Path = File(Folder.desktop);

                                    var Name = doc.name.replace(/\.[^\.]+$/, '');

                                    var saveFile = File(Path + "/" + Name + channelName? + ".png");

                                    SavePNG(saveFile);

                             

                                    errorlog.writeln( doc1.name + doc2.name + "," + channelName? + ",Differences" );

                             

                                    }

                                }

                            }

                            • 11. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                              c.pfaffenbichler Level 9

                              The function "main" is not even being called, it seems, so this hardly seems to be the complete Script.

                               

                              The line

                              var theName = getProperty(charIDToTypeID("Chnl"),charIDToTypeID("ChnN"),channelIndex);

                              can not produce a meaningful result (the Channel’s name) after the first iteration of the for-clause as the active Document is a newly created grayscale image, I suppose you could either close the document or reselect the original image.

                              • 12. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                                c.pfaffenbichler Level 9

                                Why

                                        var blackAndWhite = theHistogram[0] + theHistogram[255];

                                        if (blackAndWhite == totalPixels) {var theText = "100% Pixel Match"}

                                ?

                                Wouldn’t white pixels would indicate a difference?

                                • 13. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                                  pharmon_ Level 1

                                  Sorry my paste was not complete. Also, I added context/comments for clarity:

                                   

                                  #target photoshop

                                   

                                  function SavePNG(saveFile){

                                      pngSaveOptions = new PNGSaveOptions();

                                      activeDocument.saveAs(saveFile, pngSaveOptions, true, Extension.LOWERCASE);   

                                  }

                                   

                                  function getProperty( psClass, psKey, index ) {// integer:Class, integer:key 

                                      var ref = new ActionReference(); 

                                      if( psKey != undefined ) ref.putProperty( charIDToTypeID( "Prpr" ), psKey ); 

                                      if(index != undefined ){ 

                                          ref.putIndex( psClass, index ); 

                                      }else{ 

                                          ref.putEnumerated( psClass , charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) ); 

                                      } 

                                      try{ 

                                          var desc = executeActionGet(ref); 

                                      }catch(e){ return; }

                                      if(desc.count == 0) return;

                                      var dataType = desc.getType(psKey); 

                                      switch(dataType){

                                          case DescValueType.INTEGERTYPE: 

                                              return desc.getInteger(psKey); 

                                              break; 

                                          case DescValueType.ALIASTYPE: 

                                              return desc.getPath(psKey); 

                                              break; 

                                          case DescValueType.BOOLEANTYPE: 

                                              return desc.getBoolean(psKey); 

                                              break; 

                                          case DescValueType.BOOLEANTYPE: 

                                              return desc.getBoolean(psKey); 

                                              break; 

                                          case DescValueType.UNITDOUBLE: 

                                              return desc.getUnitDoubleValue(psKey); 

                                              break; 

                                          case DescValueType.STRINGTYPE: 

                                              return desc.getString(psKey); 

                                              break; 

                                          case  DescValueType.OBJECTTYPE: 

                                              return desc.getObjectValue(psKey); 

                                              break; 

                                          case  DescValueType.LISTTYPE: 

                                              return desc.getList(psKey); 

                                              break; 

                                          case  DescValueType.ENUMERATEDTYPE: 

                                              return desc.getEnumerationValue(psKey); 

                                              break; 

                                      } 

                                  }; 

                                   

                                  function main() {

                                   

                                      var errorlog = File(Folder.desktop + "/Test_Log.txt");

                                      var d =new Date;

                                      errorlog.open('w');

                                      errorlog.writeln(d);

                                   

                                      var mySelectFile1 = File.openDialog("Selection prompt"); 

                                      if(mySelectFile1 != null) app.open(mySelectFile1);

                                   

                                      var mySelectFile2 = File.openDialog("Selection prompt"); 

                                      if(mySelectFile2 != null) app.open(mySelectFile2); 

                                   

                                      var doc1 = app.open(mySelectFile1); 

                                      var doc2 = app.open(mySelectFile2);

                                     

                                      doc2.selection.selectAll();

                                      doc2.selection.copy();

                                   

                                      app.activeDocument = doc1;

                                      var newLayer = doc1.paste();

                                      newLayer.blendMode = BlendMode.DIFFERENCE;

                                   

                                  // Compare images to see if there are any pixel differences - within the entirety of the images

                                   

                                      found=0

                                      var histogram = doc1.histogram;

                                      for (var i = 1; i < histogram.length; ++i) {

                                          if (histogram[i] > 0)

                                          found=1

                                      }

                                   

                                  // Delete the pasted layer from doc2 (maybe I should revert doc1 to it's original state.)

                                   

                                  activeDocument.activeLayer.remove();

                                   

                                  // If there is a difference between doc1 and doc2 - Compare channels to see if there are any pixel differences - within the individual channels

                                   

                                  if (found){

                                      var channelCount = app.activeDocument.channels.length; 

                                      var channelNames = []; 

                                      for(var channelIndex=1; channelIndex<=channelCount; channelIndex++){ 

                                          channelNames.push(getProperty(charIDToTypeID("Chnl"),charIDToTypeID("ChnN"),channelIndex) );

                                   

                                  // ======================================================= 

                                          var idMk = charIDToTypeID( "Mk  " ); 

                                          var desc5 = new ActionDescriptor();

                                          var idNw = charIDToTypeID( "Nw  " ); 

                                          var idDcmn = charIDToTypeID( "Dcmn" ); 

                                          desc5.putClass( idNw, idDcmn ); 

                                          var idUsng = charIDToTypeID( "Usng" ); 

                                          var desc6 = new ActionDescriptor();

                                          var idT = charIDToTypeID( "T   " );

                                          var ref3 = new ActionReference(); 

                                          var idChnl = charIDToTypeID( "Chnl" ); 

                                          ref3.putIndex( idChnl, channelIndex ); 

                                          var idLyr = charIDToTypeID( "Lyr " ); 

                                          var idBckg = charIDToTypeID( "Bckg" ); 

                                          ref3.putProperty( idLyr, idBckg ); 

                                          var idDcmn = charIDToTypeID( "Dcmn" ); 

                                          ref3.putName( idDcmn, doc1.name ); 

                                          desc6.putReference( idT, ref3 ); 

                                          var idClcl = charIDToTypeID( "Clcl" ); 

                                          var idClcn = charIDToTypeID( "Clcn" ); 

                                          var idDfrn = charIDToTypeID( "Dfrn" ); 

                                          desc6.putEnumerated( idClcl, idClcn, idDfrn ); 

                                          var idSrctwo = charIDToTypeID( "Src2" ); 

                                          var ref4 = new ActionReference(); 

                                          var idChnl = charIDToTypeID( "Chnl" ); 

                                          ref4.putIndex( idChnl, channelIndex ); 

                                          var idLyr = charIDToTypeID( "Lyr " ); 

                                          var idBckg = charIDToTypeID( "Bckg" ); 

                                          ref4.putProperty( idLyr, idBckg ); 

                                          var idDcmn = charIDToTypeID( "Dcmn" ); 

                                          ref4.putName( idDcmn, doc2.name ); 

                                          desc6.putReference( idSrctwo, ref4 ); 

                                          var idClcl = charIDToTypeID( "Clcl" ); 

                                          desc5.putObject( idUsng, idClcl, desc6 ); 

                                          executeAction( idMk, desc5, DialogModes.NO );

                                   

                                  // Once a channel has been compared, the New Document contains an Alpha Channel that is the diff, with the histogram channel composite

                                  // True, the below snippet I grabbed/borrowed/stole for temporary use and had not taken the time to clean it up.

                                  // I needed to be able to see how many pixels were different (rounding difference or if the result was something larger.

                                  // I eventually need to add in something that will tell me the max value/depth difference for each channel. If I can see in the csv/log that a baseline/original image and second version (that should exactly match) and see the difference is in only a few pixels, occurring in all channels, differing by 1-2 levels - that would be classified as something different than almost every pixel being different.

                                   

                                          if (app.documents.length > 0 && app.activeDocument.mode = DocumentMode.GRAYSCALE) { 

                                          myDocument = app.activeDocument; 

                                          var originalRulerUnits = app.preferences.rulerUnits; 

                                          app.preferences.rulerUnits = Units.PIXELS; 

                                          var totalPixels = myDocument.width * myDocument.height; 

                                          myDocument.activeChannels = [myDocument.channels[0]]; 

                                          myDocument.selection.deselect(); 

                                          var theHistogram = myDocument.channels[0].histogram; 

                                          var blackAndWhite = theHistogram[0] + theHistogram[255]; 

                                          var blackPercentage = theHistogram[0]/totalPixels*100; 

                                  //       var whitePercentage = theHistogram[255]/totalPixels*100; 

                                          if (blackAndWhite == totalPixels) {var theText = "100% Pixel Match"} 

                                          else {var theText = "has a difference of "}; 

                                  //       alert (channelName? + " channel" + theText+(100-blackPercentage)+" %\r"+(totalPixels-theHistogram[0])+" out of "+totalPixels+ " total pixels."); 

                                          app.preferences.rulerUnits = originalRulerUnits; 

                                   

                                  // If there channel comparison contains a difference, I want to convert to GS, so I can save out the png easier.

                                   

                                          var idCnvM = charIDToTypeID( "CnvM" );

                                          var desc12 = new ActionDescriptor();

                                          var idT = charIDToTypeID( "T   " );

                                          var idGrys = charIDToTypeID( "Grys" );

                                          desc12.putClass( idT, idGrys );

                                          executeAction( idCnvM, desc12, DialogModes.NO );

                                   

                                  // I want to name the png with the doc1 name, appended with the channel name.

                                   

                                          var doc = mySelectFile1;

                                          var Path = File(Folder.desktop);

                                          var Name = doc.name.replace(/\.[^\.]+$/, '');

                                          var saveFile = File(Path + "/" + Name + channelName? + ".png");

                                          SavePNG(saveFile);

                                   

                                  // I want to log the doc1-doc2 file names along with channels that are different,along with the differences. Haven't figured out best order yet, because I've been trying to make the above work.

                                   

                                          errorlog.writeln( doc1.name + doc2.name + "," + channelName? + ",Differences" );

                                   

                                          };

                                      }

                                  }

                                   

                                  else  {

                                          errorlog.writeln(doc1.name + "," + doc2.name +",Match");

                                          }

                                   

                                          while (documents.length > 0) {

                                          activeDocument.close(SaveOptions.DONOTSAVECHANGES);

                                          }

                                          errorlog.close();

                                          errorlog.execute();

                                          return;

                                  }

                                   

                                  main();

                                  • 14. Re: Is it possible to compare/diff all the elements between 2 documents (TIFFs/PSDs/Etc.) with javascript?
                                    c.pfaffenbichler Level 9

                                    I already told you that you need to

                                    • make the original document active if you want to get the Channels’ names or

                                    • close the newly created "difference" image.

                                     

                                    The way you try to evaluate the histogram does not seem to make sense yet.