Copy link to clipboard
Copied
Current workflow( When retouching is required on a background copy (patch etc) (obviously increasing file size))
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:
Im almost certain than small changes do not load in selection.. any thoughts or improvements to the accuracy would be greatly appreciated.
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!
Copy link to clipboard
Copied
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!
Copy link to clipboard
Copied
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 )
}
Copy link to clipboard
Copied
I found my old action... 2003, yikes! If I remember correctly, this was made after the healing tools were introduced in v7, back when it was not possible to heal to a transparent layer, as was possible with the clone stamp tool. I don't miss the days of dust-busting scans!
Copy link to clipboard
Copied
Thank you that's useful. Out of interest, what did you set the threshold and levels to?
I mainly want to use it to slim down a merged layer from Frequency separtion.
Copy link to clipboard
Copied
Threshold was 128, levels was auto contrast.
Out of curiosity I ran the action through xtools:
#target photoshop
//
// HealingProv1_0APS5.jsx
//
//
// Generated Wed May 26 2021 18:48:30 GMT+1000
//
cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };
//
//==================== Healing Pro v1.0 APS5 ==============
//
function HealingProv1_0APS5() {
// Stop
function step1(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
desc1.putString(cTID('Msge'), "Healing Pro v1.0 APS5\r\rStephen Marsh\r\rhttp://members.ozemail.com.au/~binaryfx");
desc1.putBoolean(cTID('Cntn'), true);
executeAction(cTID('Stop'), desc1, dialogMode);
};
// Stop
function step2(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
desc1.putString(cTID('Msge'), "Run on a targeted, healed layer - do not apply to flat background data. \r\rThis action presumes a two layer document, with the upper duplicate layer holding the cloned or healed data.\r\rContinue or Stop?");
desc1.putBoolean(cTID('Cntn'), true);
executeAction(cTID('Stop'), desc1, dialogMode);
};
// Duplicate
function step3(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated(cTID('Dcmn'), cTID('Ordn'), cTID('Frst'));
desc1.putReference(cTID('null'), ref1);
desc1.putString(cTID('Nm '), "HealingPro Temp");
executeAction(cTID('Dplc'), desc1, dialogMode);
};
// Set
function step4(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated(cTID('Lyr '), cTID('Ordn'), cTID('Trgt'));
desc1.putReference(cTID('null'), ref1);
var desc2 = new ActionDescriptor();
desc2.putEnumerated(cTID('Md '), cTID('BlnM'), cTID('Dfrn'));
desc1.putObject(cTID('T '), cTID('Lyr '), desc2);
executeAction(cTID('setd'), desc1, dialogMode);
};
// Flatten Image
function step5(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
executeAction(sTID('flattenImage'), undefined, dialogMode);
};
// Convert Mode
function step6(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
desc1.putClass(cTID('T '), cTID('Grys'));
executeAction(sTID('convertMode'), desc1, dialogMode);
};
// Equalize
function step7(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
executeAction(cTID('Eqlz'), undefined, dialogMode);
};
// Maximum
function step8(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
desc1.putInteger(cTID('Rds '), 3);
executeAction(cTID('Mxm '), desc1, dialogMode);
};
// Threshold
function step9(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
desc1.putInteger(cTID('Lvl '), 128);
executeAction(cTID('Thrs'), desc1, dialogMode);
};
// Gaussian Blur
function step10(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
desc1.putDouble(cTID('Rds '), 2);
executeAction(sTID('gaussianBlur'), desc1, dialogMode);
};
// Levels
function step11(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
desc1.putBoolean(cTID('AuCo'), true);
executeAction(cTID('Lvls'), desc1, dialogMode);
};
// Set
function step12(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putProperty(cTID('Chnl'), sTID("selection"));
desc1.putReference(cTID('null'), ref1);
desc1.putEnumerated(cTID('T '), cTID('Ordn'), cTID('Al '));
executeAction(cTID('setd'), desc1, dialogMode);
};
// Copy
function step13(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
executeAction(cTID('copy'), undefined, dialogMode);
};
// Close
function step14(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
desc1.putEnumerated(cTID('Svng'), cTID('YsN '), cTID('N '));
executeAction(cTID('Cls '), desc1, dialogMode);
};
// Make
function step15(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var desc2 = new ActionDescriptor();
desc2.putString(cTID('Nm '), "HealingPro Alpha");
desc2.putEnumerated(cTID('ClrI'), cTID('MskI'), cTID('MskA'));
var desc3 = new ActionDescriptor();
desc3.putDouble(cTID('Rd '), 255);
desc3.putDouble(cTID('Grn '), 0);
desc3.putDouble(cTID('Bl '), 0);
desc2.putObject(cTID('Clr '), sTID("RGBColor"), desc3);
desc2.putInteger(cTID('Opct'), 50);
desc1.putObject(cTID('Nw '), cTID('Chnl'), desc2);
executeAction(cTID('Mk '), desc1, dialogMode);
};
// Set
function step16(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putProperty(cTID('Chnl'), sTID("selection"));
desc1.putReference(cTID('null'), ref1);
desc1.putEnumerated(cTID('T '), cTID('Ordn'), cTID('Al '));
executeAction(cTID('setd'), desc1, dialogMode);
};
// Paste
function step17(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
executeAction(cTID('past'), undefined, dialogMode);
};
// Set
function step18(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putProperty(cTID('Chnl'), sTID("selection"));
desc1.putReference(cTID('null'), ref1);
desc1.putEnumerated(cTID('T '), cTID('Ordn'), cTID('None'));
executeAction(cTID('setd'), desc1, dialogMode);
};
// Set
function step19(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putProperty(cTID('Chnl'), sTID("selection"));
desc1.putReference(cTID('null'), ref1);
var ref2 = new ActionReference();
ref2.putEnumerated(cTID('Chnl'), cTID('Ordn'), cTID('Trgt'));
desc1.putReference(cTID('T '), ref2);
executeAction(cTID('setd'), desc1, dialogMode);
};
// Select
function step20(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated(cTID('Chnl'), cTID('Chnl'), sTID("CMYK"));
desc1.putReference(cTID('null'), ref1);
executeAction(cTID('slct'), desc1, dialogMode);
};
// Make
function step21(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
desc1.putClass(cTID('Nw '), cTID('Chnl'));
var ref1 = new ActionReference();
ref1.putEnumerated(cTID('Chnl'), cTID('Chnl'), cTID('Msk '));
desc1.putReference(cTID('At '), ref1);
desc1.putEnumerated(cTID('Usng'), cTID('UsrM'), cTID('RvlS'));
executeAction(cTID('Mk '), desc1, dialogMode);
};
// Delete
function step22(enabled, withDialog) {
if (enabled != undefined && !enabled)
return;
var dialogMode = (withDialog ? DialogModes.ALL : DialogModes.NO);
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated(cTID('Chnl'), cTID('Ordn'), cTID('Trgt'));
desc1.putReference(cTID('null'), ref1);
desc1.putBoolean(cTID('Aply'), true);
executeAction(cTID('Dlt '), desc1, dialogMode);
};
step1(false, true); // Stop
step2(true, true); // Stop
step3(); // Duplicate
step4(); // Set
step5(); // Flatten Image
step6(); // Convert Mode
step7(); // Equalize
step8(); // Maximum
step9(); // Threshold
step10(); // Gaussian Blur
step11(); // Levels
step12(); // Set
step13(); // Copy
step14(); // Close
step15(); // Make
step16(); // Set
step17(); // Paste
step18(); // Set
step19(); // Set
step20(); // Select
step21(); // Make
step22(); // Delete
};
//=========================================
// HealingProv1_0APS5.main
//=========================================
//
HealingProv1_0APS5.main = function () {
HealingProv1_0APS5();
};
HealingProv1_0APS5.main();
// EOF
"HealingProv1_0APS5.jsx"
// EOF
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
With your script, you will only spoil your work. Moreover, his work depends on the channel settings.
See video.
upd.
Copy link to clipboard
Copied
Thanks for demo, I guess merging down is safest
Copy link to clipboard
Copied
clear selected areas (unchanged areas removed)
By @Gibson Editions
Your script deletes just the changed parts from me.