Skip to main content
Inspiring
March 7, 2024
Answered

Updated Frequency Separation Action for PS 2024?

  • March 7, 2024
  • 5 replies
  • 17616 views

The better existing FS Actions need to be updated. From what I know, the best FS actions offer the option of FS for 8Bit or 16bit -and they will not have the same structure.

FS can work better with Median Filter applied instead of Gauss Blur. And there shuld be a built in PAUSE to allow user to set the level of Median applied. Fully automatic FS actions won't work on every image.

There are plenty of free FS actions that really are either too basic or not full featured.

THe better FS actions also create preview toggle layers that allow quick before/after comparison.

I'm an experienced retoucher, but not the uptimate expert on FS Actions, so there may well be features that I'm not aware of. 

I'd be OK payong for a quality FS action, but not a big proprietary plugin.

Of course Free is always best if anyone has a link to a quality FS action with the above features.

Any other FS wisdom to share with experiened retouchers?

Correct answer davescm

There is no need to buy anything. The steps for frequency separation are simple and you can record an action for each of 8 bit and 16 bit and a version to use either median and gaussian blur.

https://helpx.adobe.com/uk/photoshop/using/creating-actions.html

 

The steps in manual frequency separation are:

1. Make 2 duplicates of your image layer (Ctrl+J twice)
Name the lower - "Low frequency"
Name the Higher - "High Frequency"

2. Select the Low frequency layer and use Filter Gaussian Blur (around 6.0) or use Median if you prefer

3. Select the High frequency layer
Go to menu Image > Apply Image
Set the source layer to Low Frequency
Set the blending mode to Subtract
Set Scale to 2 *
Set offset to 128 *
Click OK
4. Change the blending mode of the high frequency layer to Linear Light






* Note - the above steps are for 8 bit/channel images. For 16 bit/channel step 3 changes slightly

3. Select the High frequency layer
Go to menu Image > Apply Image
Set the source layer to Low Frequency
Check "Invert" next to channel

Set the blending mode to Add
Set Scale to 2
Set Offset to 0
Click OK

Now carry on with step 4 above

 

That is it - just take a few minutes to record those steps into an action, or set of actions, and you are ready to click and  go.

 

Dave

 

5 replies

Stephen Marsh
Community Expert
March 10, 2024

The following script may also be of interest:

 

// MultiDecomp
// ver. 0.5
// Decomposes an image into as many layer slices as the user would like, based on the techniques in the 'HighPass Sucks' thread.
// by *THAT* HP Guy.

// *** USE AT YOUR OWN RISK ***

// Version Changes:
// 0.2 --
//    Introduced sanity checks
//    Check bit depth and use modes as appropriate
//    Verify # of layers at outset and copy / copy merged as appropriate
// 0.3 --
//    Improved layout
// 0.4 --
//	Included Clipped Curves adjustment layers option
// 0.5 --
//	Fixed Curves bug
//	Round display values for layer names

// To Do:
// 1.0 --
//    Improve accuracy / investigate multilayer recomposition from source in 8bit
//    Ideas?



var startRulerUnits = app.preferences.rulerUnits;
var startTypeUnits = app.preferences.typeUnits;
var startDisplayDialogs = app.displayDialogs;
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
app.displayDialogs = DialogModes.NO;

var sep = new Window("dialog { \
			alignChildren:'fill', \
			text:'Frequency Separator', \
			vals: Panel { text: 'Values', orientation: 'column', alignChildren:'right', \
				sm: Group { orientation: 'row',\
					smLabel:StaticText { text:'Starting radius:'},\
					smallest:EditText {text:'1', characters: 6}\
				},\
				lg: Group { orientation: 'row',\
					lgLabel:StaticText { text:'Ending radius:'},\
					largest:EditText{text:'100', characters: 6,}\
				},\
				stps: Group { orientation: 'row',\
					stepsLabel:StaticText { text:'Steps between:'},\
					steps:EditText{text:'4', characters: 6}\
				}\
			}, \
			curves: Checkbox { alignment:'right', text:'Clipped Curves Adjustments?', value:false},\
			buttons: Group {orientation: 'row', \
				okButton:Button{text:'OK' },\
				cancelButton:Button{text:'Cancel' }\
			} \
	}");

sep.buttons.okButton.onClick = function(){
	goAhead = true;
	sep.close();
};

sep.buttons.cancelButton.onClick = function(){
	sep.close();
};

sep.vals.lg.largest.onChange = function(){
	if ((Number(sep.vals.lg.largest.text) < 0.1) || (Number(sep.vals.lg.largest.text) > 250)) {
		sep.vals.lg.largest.text = "1.0";
		alert ("Radii must fall between 0.1 and 250.0 pixels.");
	}
}

sep.vals.sm.smallest.onChange = function(){
	if ((Number(sep.vals.sm.smallest.text) < 0.1) || (Number(sep.vals.sm.smallest.text) > 250)) {
		sep.vals.sm.smallest.text = "1.0";
		alert ("Radii must fall between 0.1 and 250.0 pixels.");
	}
}

addCurves = function() {
	var id29 = charIDToTypeID( "Mk  " );
	    var desc6 = new ActionDescriptor();
	    var id30 = charIDToTypeID( "null" );
	        var ref2 = new ActionReference();
	        var id31 = charIDToTypeID( "AdjL" );
	        ref2.putClass( id31 );
	    desc6.putReference( id30, ref2 );
	    var id32 = charIDToTypeID( "Usng" );
	        var desc7 = new ActionDescriptor();
	        var id33 = charIDToTypeID( "Grup" );
	        desc7.putBoolean( id33, true );
	        var id34 = charIDToTypeID( "Type" );
	            var desc8 = new ActionDescriptor();
	            var id35 = stringIDToTypeID( "presetKind" );
	            var id36 = stringIDToTypeID( "presetKindType" );
	            var id37 = stringIDToTypeID( "presetKindDefault" );
	            desc8.putEnumerated( id35, id36, id37 );
      	  var id38 = charIDToTypeID( "Crvs" );
	        desc7.putObject( id34, id38, desc8 );
	    var id39 = charIDToTypeID( "AdjL" );
	    desc6.putObject( id32, id39, desc7 );
	executeAction( id29, desc6, DialogModes.NO );
}

apply16 = function() {
	var id39 = charIDToTypeID( "AppI" );
    	var desc11 = new ActionDescriptor();
	    var id40 = charIDToTypeID( "With" );
      	  var desc12 = new ActionDescriptor();
      	  var id41 = charIDToTypeID( "T   " );
      	      var ref6 = new ActionReference();
      	      var id42 = charIDToTypeID( "Chnl" );
      	      var id43 = charIDToTypeID( "Chnl" );
      	      var id44 = charIDToTypeID( "RGB " );
      	      ref6.putEnumerated( id42, id43, id44 );
      	      var id45 = charIDToTypeID( "Lyr " );
        	      ref6.putName( id45, LFRef.name );
	        desc12.putReference( id41, ref6 );
	        var id46 = charIDToTypeID( "Invr" );
	        desc12.putBoolean( id46, true );
	        var id47 = charIDToTypeID( "Clcl" );
	        var id48 = charIDToTypeID( "Clcn" );
	        var id49 = charIDToTypeID( "Add " );
	        desc12.putEnumerated( id47, id48, id49 );
	        var id50 = charIDToTypeID( "Scl " );
	        desc12.putDouble( id50, 2.000000 );
	        var id51 = charIDToTypeID( "Ofst" );
	        desc12.putInteger( id51, 0 );
	    var id52 = charIDToTypeID( "Clcl" );
	    desc11.putObject( id40, id52, desc12 );
	executeAction( id39, desc11, DialogModes.NO );
}

round = function( num, decs ) {
	return Math.round(num*Math.pow(10,decs))/10;
}

apply8 = function() {
	var id94 = charIDToTypeID( "AppI" );
	    var desc20 = new ActionDescriptor();
	    var id95 = charIDToTypeID( "With" );
	        var desc21 = new ActionDescriptor();
	        var id96 = charIDToTypeID( "T   " );
	            var ref10 = new ActionReference();
	            var id97 = charIDToTypeID( "Chnl" );
	            var id98 = charIDToTypeID( "Chnl" );
	            var id99 = charIDToTypeID( "RGB " );
	            ref10.putEnumerated( id97, id98, id99 );
	            var id100 = charIDToTypeID( "Lyr " );
	            ref10.putName( id100, LFRef.name );
	        desc21.putReference( id96, ref10 );
	        var id101 = charIDToTypeID( "Clcl" );
	        var id102 = charIDToTypeID( "Clcn" );
	        var id103 = charIDToTypeID( "Sbtr" );
	        desc21.putEnumerated( id101, id102, id103 );
	        var id104 = charIDToTypeID( "Scl " );
	        desc21.putDouble( id104, 2.000000 );
	        var id105 = charIDToTypeID( "Ofst" );
	        desc21.putInteger( id105, 128 );
	    var id106 = charIDToTypeID( "Clcl" );
	    desc20.putObject( id95, id106, desc21 );
	executeAction( id94, desc20, DialogModes.NO );
}

goAhead=false;
sep.center();
sep.show();

if (goAhead) {
	var docRef = app.activeDocument;
	docRef.selection.selectAll();
	if (docRef.artLayers.length > 1)
		docRef.selection.copy(true);
	else
		docRef.selection.copy();

	var LFRef = docRef.paste();
	var nextRef = null;
	var smallest = Number(sep.vals.sm.smallest.text);
	var largest = Number(sep.vals.lg.largest.text);
	var steps = Number(sep.vals.stps.steps.text);
	var blurBy = smallest;
	var increment = (largest - blurBy) / steps;
	var i =0;

	while (i <= steps) {
		HFRef = LFRef.duplicate (LFRef, ElementPlacement.PLACEBEFORE);
		HFRef.blendMode = BlendMode.LINEARLIGHT;
		if (i > 0)
			HFRef.name = round(Number(blurBy - increment),1) + " - " + round(blurBy,1);
		else
			HFRef.name = " < " + round(smallest,1);
		LFRef.applyGaussianBlur(blurBy);
		docRef.activeLayer = HFRef;

		if (docRef.bitsPerChannel == BitsPerChannelType.EIGHT)
			apply8();
		else
			if (docRef.bitsPerChannel == BitsPerChannelType.SIXTEEN)
				apply16();

		if (sep.curves.value == true) {
			addCurves();
		}

		blurBy += increment;
		i=i+1;
	};
	LFRef.name = "> " + round(largest,1);

	docRef = null;
	HFRef = null;
	LFRef = null;
	nextRef = null;
};

app.preferences.rulerUnits = startRulerUnits;
app.preferences.typeUnits = startTypeUnits;
app.displayDialogs = startDisplayDialogs;

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

Inspiring
March 11, 2024

Stefano, can you get the action of these steps, I would like to see if I can create a small UXP panel.

thanks as always

 

davescm
davescmCorrect answer
Community Expert
March 9, 2024

There is no need to buy anything. The steps for frequency separation are simple and you can record an action for each of 8 bit and 16 bit and a version to use either median and gaussian blur.

https://helpx.adobe.com/uk/photoshop/using/creating-actions.html

 

The steps in manual frequency separation are:

1. Make 2 duplicates of your image layer (Ctrl+J twice)
Name the lower - "Low frequency"
Name the Higher - "High Frequency"

2. Select the Low frequency layer and use Filter Gaussian Blur (around 6.0) or use Median if you prefer

3. Select the High frequency layer
Go to menu Image > Apply Image
Set the source layer to Low Frequency
Set the blending mode to Subtract
Set Scale to 2 *
Set offset to 128 *
Click OK
4. Change the blending mode of the high frequency layer to Linear Light






* Note - the above steps are for 8 bit/channel images. For 16 bit/channel step 3 changes slightly

3. Select the High frequency layer
Go to menu Image > Apply Image
Set the source layer to Low Frequency
Check "Invert" next to channel

Set the blending mode to Add
Set Scale to 2
Set Offset to 0
Click OK

Now carry on with step 4 above

 

That is it - just take a few minutes to record those steps into an action, or set of actions, and you are ready to click and  go.

 

Dave

 

FauxtoGuyAuthor
Inspiring
March 10, 2024

Thanks davescm, very helpful. I would like to insert a stop in the recording process where I can enter the value for the Median filter based on the current image. The Adobe explanation for this step is a bit unclear to me. I know it's simple, I'm just not good at entering command sets. I assume the Stop (pause?) is added during the recording process?

 

Also, some FS actions add a "Solaraize" layer, high in the stack, for visualization. Not sure exactly how to do that, whether it's an adjustment layer, or a copy of the Low/High -?

 

One of the FS actions I have seen uses a Smart Layer for the low freq layer, which of course can't be "painted" on. But it allows the Median Filter to be adjusted later. So perhaps with that process, the Low Freq layer gets duplicated, and then raterized (during the reording process) so it can be used for painting, cloning etc?

Thanks again

 

Stephen Marsh
Community Expert
March 10, 2024

@FauxtoGuy 

 

I think that you are looking for the modal control, not a stop. A stop would be to disruptive to the flow. Look at the median step in the action that I made for you. It's the square icon that can be toggled on or off to provide interactivity, similar to the image below next to the tick box controls.

 


https://helpx.adobe.com/photoshop/using/creating-actions.html

Ivan Zajats
Inspiring
March 9, 2024

@FauxtoGuy, if you claim to be a pro, you should be able to write your own basic actions.

Search some articles and tutorials, there's a lot of information around.

FauxtoGuyAuthor
Inspiring
March 10, 2024

If I had ALL the answers, I wouldn't have posted the question here.

Stephen Marsh
Community Expert
March 8, 2024

@FauxtoGuy 

 

I have just made a Median-based version of the standard Gaussian Blur version of my Frequency Splitter action for you, see if it works and let me know.

 

Play the "Conditional Run" action in the set which will conditionally play the 8bpc or 16bpc action depending on the current file bit depth.

 

Inspiring
March 8, 2024