Skip to main content
Gibson Editions
Inspiring
May 25, 2021
Answered

Slimming layers with Difference

  • May 25, 2021
  • 3 replies
  • 2310 views

Current workflow( When retouching is required on a background copy (patch etc) (obviously increasing file size))

  • compare retouched layer with background via difference (with background layer below)
  • load as as selection and invert selection
  • clear selected areas (unchanged areas removed)
doc = app.activeDocument

CalcDiff()
ChanNme ("Difference")
var diffChan = doc.channels.getByName ("Difference")
loadChannelSelection ()
doc.selection.invert()
selectRGB ()
doc.selection.clear()
executeAction(s2t("delete"), undefined, DialogModes.NO)
doc.selection.deselect()
diffChan.remove()





function c2t(s) {return charIDToTypeID(s)}
function s2t(s){return stringIDToTypeID(s)}

function selectRGB(){
    var d1 = new ActionDescriptor();
    var r1 = new ActionReference();
    r1.putEnumerated(s2t("channel"),s2t("channel"),s2t("RGB"))
    d1.putReference(s2t("null"), r1)
   executeAction(s2t("select"), d1, DialogModes.NO)
   }


function CalcDiff(){
var d1 = new ActionDescriptor();
    d1.putClass( s2t( "new" ), s2t( "channel" ) );
        var d2 = new ActionDescriptor();
            var r1 = new ActionReference();
             r1.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "gray" ));
   r1.putEnumerated( s2t( "layer" ), s2t( "ordinal" ), s2t( "targetEnum" ));   
//            r1.putName(s2t( "layer" ), "Layer 1" );
        d2.putReference( s2t( "to" ), r1 );
        d2.putEnumerated( s2t( "calculation" ), s2t( "calculationType" ),s2t( "difference" ) );
            var r2 = new ActionReference();
            r2.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "gray" ));
            r2.putProperty(s2t( "layer" ), s2t( "background" ));
        d2.putReference( s2t( "source2" ), r2 );
    var idcalculation = s2t( "calculation" );
    d1.putObject( s2t( "using" ), s2t( "calculation" ), d2 );
executeAction( s2t( "make" ), d1, DialogModes.NO );
}



function ChanNme(name) {

var r1 = new ActionReference();
var d1 = new ActionDescriptor();
var d2 = new ActionDescriptor();
r1.putEnumerated(s2t("channel"),s2t("ordinal"),s2t("targetEnum"));
d1.putReference( s2t("target"), r1 );
d2.putString(s2t("name"), name);
d1.putObject(s2t("to"), s2t("channel"), d2 );
executeAction(s2t("set"), d1, DialogModes.NO );

}


function loadChannelSelection(){
    var d1 = new ActionDescriptor()
        var r1 = new ActionReference()
        r1.putProperty(c2t( "Chnl" ), c2t( "fsel" ) )
    d1.putReference( c2t( "null" ), r1 )
        var r2 = new ActionReference()
        r2.putEnumerated(  c2t( "Chnl" ),c2t( "Ordn" ),c2t( "Trgt" ) )
    d1.putReference( c2t( "T   " ), r2 )
executeAction( c2t( "setd" ), d1, DialogModes.NO )

}

 

My questions are:

  1. is this an accurate way of removing unchanged parts of a layer? 
  2. is difference the best comparision blend mode math to use?

 

Im almost certain than small changes do not load in selection.. any thoughts or improvements to the accuracy would be greatly appreciated. 

 

 

This topic has been closed for replies.
Correct answer Stephen Marsh

I used to do this many years ago with an action.

 

I would suggest that you add an equalize step to amplify the differences, then a threshold step to unify. Possibly expand these areas and blur slightly so that there is a minimum edge of unchanged pixels when the mask is applied. 

Hope this helps!

 

3 replies

Legend
May 25, 2021
quoteclear selected areas (unchanged areas removed)

By @Gibson Editions

 

Your script deletes just the changed parts from me.

Legend
May 25, 2021

What are you supposed to do with the resulting layer?

 

Note: the result of the calculation can be not only the channel, but also the selection.

Gibson Editions
Inspiring
May 26, 2021

The resulting layer is just any pixel retouching that has been done, so it stays in the stack. The channel gives more flexibility, in terms of amplifing it as Stephen_A_Marsh suggested

Legend
May 26, 2021

With your script, you will only spoil your work. Moreover, his work depends on the channel settings.

See video.

 

upd.

https://disk.yandex.ru/i/84AJAxrBKs2Lgw

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
May 25, 2021

I used to do this many years ago with an action.

 

I would suggest that you add an equalize step to amplify the differences, then a threshold step to unify. Possibly expand these areas and blur slightly so that there is a minimum edge of unchanged pixels when the mask is applied. 

Hope this helps!

 

Gibson Editions
Inspiring
May 26, 2021

come up with this, 

 

ive used diffuse instead of gaussian blur, its seems the equalize step obliterates any anti aliasing, thought diffuse might be a bit more subtle. 

 

doc = app.activeDocument

CalcDiff()
ChanNme ("Difference")
var diffChan = doc.channels.getByName ("Difference")
executeAction( s2t("equalize"), undefined, DialogModes.NO );
debugger
diffuse()

loadChannelSelection ()
doc.selection.invert()
selectRGB ()
doc.selection.clear()
executeAction(s2t("delete"), undefined, DialogModes.NO)
doc.selection.deselect()
diffChan.remove()





function c2t(s) {return charIDToTypeID(s)}
function s2t(s){return stringIDToTypeID(s)}

function selectRGB(){
    var d1 = new ActionDescriptor();
    var r1 = new ActionReference();
    r1.putEnumerated(s2t("channel"),s2t("channel"),s2t("RGB"))
    d1.putReference(s2t("null"), r1)
   executeAction(s2t("select"), d1, DialogModes.NO)
   }

function Gblur(){    var d1 = new ActionDescriptor();
    d1.putUnitDouble( s2t("radius"),s2t("pixelsUnit"), 1.000000 );
executeAction( s2t("gaussianBlur"), d1, DialogModes.NO );}

function diffuse(){    var d1 = new ActionDescriptor()
    d1.putEnumerated( c2t( "Md  " ), c2t( "DfsM" ), s2t( "anisotropic" ))
  d1.putInteger(  c2t( "FlRs" ), 3603398 )
executeAction( c2t( "Dfs " ), d1, DialogModes.NO )}



function CalcDiff(){
var d1 = new ActionDescriptor();
    d1.putClass( s2t( "new" ), s2t( "channel" ) );
        var d2 = new ActionDescriptor();
            var r1 = new ActionReference();
             r1.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "gray" ));
   r1.putEnumerated( s2t( "layer" ), s2t( "ordinal" ), s2t( "targetEnum" ));   
//            r1.putName(s2t( "layer" ), "Layer 1" );
        d2.putReference( s2t( "to" ), r1 );
        d2.putEnumerated( s2t( "calculation" ), s2t( "calculationType" ),s2t( "difference" ) );
            var r2 = new ActionReference();
            r2.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "gray" ));
            r2.putProperty(s2t( "layer" ), s2t( "background" ));
        d2.putReference( s2t( "source2" ), r2 );
    var idcalculation = s2t( "calculation" );
    d1.putObject( s2t( "using" ), s2t( "calculation" ), d2 );
executeAction( s2t( "make" ), d1, DialogModes.NO );
}



function ChanNme(name) {

var r1 = new ActionReference();
var d1 = new ActionDescriptor();
var d2 = new ActionDescriptor();
r1.putEnumerated(s2t("channel"),s2t("ordinal"),s2t("targetEnum"));
d1.putReference( s2t("target"), r1 );
d2.putString(s2t("name"), name);
d1.putObject(s2t("to"), s2t("channel"), d2 );
executeAction(s2t("set"), d1, DialogModes.NO );

}


function loadChannelSelection(){
    var d1 = new ActionDescriptor()
        var r1 = new ActionReference()
        r1.putProperty(c2t( "Chnl" ), c2t( "fsel" ) )
    d1.putReference( c2t( "null" ), r1 )
        var r2 = new ActionReference()
        r2.putEnumerated(  c2t( "Chnl" ),c2t( "Ordn" ),c2t( "Trgt" ) )
    d1.putReference( c2t( "T   " ), r2 )
executeAction( c2t( "setd" ), d1, DialogModes.NO )

}