retouch_3B = function() {
   // Радиус размытия слоя НЧ
var lowR;

//вычисляется по формуле lowR = bigD / lowK, где bigD - бОльшая сторона выделенной области
var lowK = 120; 

// Радиус размытия слоя СЧ
var midR;

//вычисляется по формуле midR = bigD / midK, где bigD - бОльшая сторона выделенной области
var midK = 350; 

// имя группы (битность добавится автоматически)
var groupName = '3 Band'

// Имена слоев:
var midBoostName = 'Mid Boost';
var txtrBoostName = 'Texture Boost';
var highRetName = 'High Retouch'
var highLayerName = 'High';
var midRetName = 'Mid Retouch'
var midLayerName = 'Mid';
var lowRetName = 'Retouch Low';
var lowLayerName = 'Low';
var baseName = 'Base';

var tempName = 'temp';
var invName = 'Inversion';

// что прописывается в историю (автоматически добавится битность)
var historyState = 'FS 3 Band'; 

if (app.documents.length > 0) {
    if ((getDocumentBits() == 8)||(getDocumentBits() == 16)){
        if (faceSelected()){
            ErrStrs = {};
            ErrStrs.USER_CANCELED = localize("$$$/ScriptingSupport/Errors/UserCancelled");
            var historyStateNow = -1;
            do historyStateNow++;
            while (app.activeDocument.activeHistoryState != app.activeDocument.historyStates[historyStateNow])
            
            try { 
                historyState = historyState+' '+getDocumentBits()+' bits';
                app.activeDocument.suspendHistory(historyState, "main()");
                //main();
            } catch(e) { 
                if (e.number != 8007) {
                    alert(e + " : " + e.line);
                    //throw e;
                } else {
                    app.activeDocument.activeHistoryState = app.activeDocument.historyStates[historyStateNow];
                    app.activeDocument.suspendHistory(historyState + " [cancelled]", "");
                    app.activeDocument.activeHistoryState = app.activeDocument.historyStates[historyStateNow];
                }
            }
        } else {
            alert("Select the face");
        }
    } else {
        alert("Active document must be 8-bit or 16-bit");
    }
} else {
    alert("At least one file must be opened");
}

function main(){  
    var oldUnits = app.preferences.rulerUnits; 
    app.preferences.rulerUnits = Units.PIXELS;
    
    var bigD = Math.max(app.activeDocument.selection.bounds[2]-app.activeDocument.selection.bounds[0], app.activeDocument.selection.bounds[3]-app.activeDocument.selection.bounds[1]);
    lowR = bigD / lowK;
    midR = bigD / midK;
    
    //lowR = 10;
    //midR = 30;
    
    app.activeDocument.selection.deselect();
    
    var setOfLayers = app.activeDocument.layerSets.add();
    setOfLayers.name = groupName+' ('+getDocumentBits()+' bits)';
    
    var baseLayer = app.activeDocument.artLayers.add();
    baseLayer.name = baseName;
    baseLayer.move(setOfLayers, ElementPlacement.PLACEATBEGINNING);
    
    app.activeDocument.activeLayer = baseLayer;
    applyImageMerged();
    
    var lowLayer = baseLayer.duplicate();
    lowLayer.name = lowLayerName;
    lowLayer.move(setOfLayers, ElementPlacement.PLACEATBEGINNING);
    
    var lowRetLayer = app.activeDocument.artLayers.add();
    lowRetLayer.name =lowRetName;
    lowRetLayer.move(setOfLayers, ElementPlacement.PLACEATBEGINNING);
    
    var midLayer = lowLayer.duplicate();
    midLayer.name = midLayerName;
    midLayer.move(setOfLayers, ElementPlacement.PLACEATBEGINNING);
    
    var midRetLayer = app.activeDocument.artLayers.add();
    midRetLayer.name =midRetName;
    midRetLayer.move(setOfLayers, ElementPlacement.PLACEATBEGINNING);
    
    var highLayer = midLayer.duplicate();
    highLayer.name = highLayerName;
    highLayer.move(setOfLayers, ElementPlacement.PLACEATBEGINNING);
    
    highLayer.opacity = 0;
    midLayer.opacity = 0;
    
    lowLayer.applyGaussianBlur(lowR);
    
    app.activeDocument.activeLayer = midLayer;
    applyImage816();
    
    midLayer.opacity = 100;
    
    midLayer.blendMode = BlendMode.LINEARLIGHT;
    
    var tempLayer = highLayer.duplicate();
    tempLayer.name = tempName;
    tempLayer.move(setOfLayers, ElementPlacement.PLACEATBEGINNING);
    
    tempLayer.opacity = 50;
    tempLayer.invert();
    
    app.activeDocument.activeLayer = tempLayer;
    makeInv();
    
    midLayer.applyGaussianBlur(midR);
    
    app.activeDocument.activeLayer.remove();
    tempLayer.remove();
    
    app.activeDocument.activeLayer = highLayer;
    applyImage816();
    
    highLayer.opacity = 100;
    
    highLayer.blendMode = BlendMode.LINEARLIGHT;
    
    var highRetLayer = highLayer.duplicate();
    highRetLayer.name = highRetName;
    highRetLayer.move(setOfLayers, ElementPlacement.PLACEATBEGINNING);
    
    app.activeDocument.activeLayer = highRetLayer;
    clippingMask();
    
    highRetLayer.blendMode = BlendMode.NORMAL;
    
    makeAjLayer(txtrBoostName);
    clippingMask();
    setAjLayer();
    app.activeDocument.activeLayer.visible = false;
    
    makeAjLayer(midBoostName);
    setAjLayer();
    app.activeDocument.activeLayer.visible = false;
    
    app.activeDocument.activeLayer = midRetLayer;
    clippingMask();
    
    app.activeDocument.activeLayer = lowRetLayer;
    
    app.preferences.rulerUnits = oldUnits;
}

function faceSelected() {
    var sel = true;
    try {var forgetIt = app.activeDocument.selection.bounds}
    catch (a) {sel = false};
    return sel;
}

function getDocumentBits(){
    var bits = 0;
    if (app.activeDocument.bitsPerChannel == BitsPerChannelType.ONE) bits = 1;
    if (app.activeDocument.bitsPerChannel == BitsPerChannelType.EIGHT) bits = 8;
    if (app.activeDocument.bitsPerChannel == BitsPerChannelType.SIXTEEN) bits = 16;
    if (app.activeDocument.bitsPerChannel == BitsPerChannelType.THIRTYTWO) bits = 32;
    return bits;
}

function applyImageMerged(){
    var idAppI = charIDToTypeID( "AppI" );
        var desc342 = new ActionDescriptor();
        var idWith = charIDToTypeID( "With" );
            var desc343 = new ActionDescriptor();
            var idT = charIDToTypeID( "T   " );
                var ref282 = new ActionReference();
                var idChnl = charIDToTypeID( "Chnl" );
                var idChnl = charIDToTypeID( "Chnl" );
                var idRGB = charIDToTypeID( "RGB " );
                ref282.putEnumerated( idChnl, idChnl, idRGB );
                var idLyr = charIDToTypeID( "Lyr " );
                var idOrdn = charIDToTypeID( "Ordn" );
                var idMrgd = charIDToTypeID( "Mrgd" );
                ref282.putEnumerated( idLyr, idOrdn, idMrgd );
            desc343.putReference( idT, ref282 );
        var idClcl = charIDToTypeID( "Clcl" );
        desc342.putObject( idWith, idClcl, desc343 );
    executeAction( idAppI, desc342, DialogModes.NO );
}

function applyImage816(){
    if (getDocumentBits() == 8) {
        var idAppI = charIDToTypeID( "AppI" );
            var desc484 = new ActionDescriptor();
            var idWith = charIDToTypeID( "With" );
                var desc485 = new ActionDescriptor();
                var idT = charIDToTypeID( "T   " );
                    var ref405 = new ActionReference();
                    var idChnl = charIDToTypeID( "Chnl" );
                    var idChnl = charIDToTypeID( "Chnl" );
                    var idRGB = charIDToTypeID( "RGB " );
                    ref405.putEnumerated( idChnl, idChnl, idRGB );
                    var idLyr = charIDToTypeID( "Lyr " );
                    var idOrdn = charIDToTypeID( "Ordn" );
                    var idMrgd = charIDToTypeID( "Mrgd" );
                    ref405.putEnumerated( idLyr, idOrdn, idMrgd );
                desc485.putReference( idT, ref405 );
                var idClcl = charIDToTypeID( "Clcl" );
                var idClcn = charIDToTypeID( "Clcn" );
                var idSbtr = charIDToTypeID( "Sbtr" );
                desc485.putEnumerated( idClcl, idClcn, idSbtr );
                var idScl = charIDToTypeID( "Scl " );
                desc485.putDouble( idScl, 2.000000 );
                var idOfst = charIDToTypeID( "Ofst" );
                desc485.putInteger( idOfst, 128 );
            var idClcl = charIDToTypeID( "Clcl" );
            desc484.putObject( idWith, idClcl, desc485 );
        executeAction( idAppI, desc484, DialogModes.NO );
    }
    
    if (getDocumentBits() == 16) {
        var idAppI = charIDToTypeID( "AppI" );
            var desc568 = new ActionDescriptor();
            var idWith = charIDToTypeID( "With" );
                var desc569 = new ActionDescriptor();
                var idT = charIDToTypeID( "T   " );
                    var ref469 = new ActionReference();
                    var idChnl = charIDToTypeID( "Chnl" );
                    var idChnl = charIDToTypeID( "Chnl" );
                    var idRGB = charIDToTypeID( "RGB " );
                    ref469.putEnumerated( idChnl, idChnl, idRGB );
                    var idLyr = charIDToTypeID( "Lyr " );
                    var idOrdn = charIDToTypeID( "Ordn" );
                    var idMrgd = charIDToTypeID( "Mrgd" );
                    ref469.putEnumerated( idLyr, idOrdn, idMrgd );
                desc569.putReference( idT, ref469 );
                var idInvr = charIDToTypeID( "Invr" );
                desc569.putBoolean( idInvr, true );
                var idClcl = charIDToTypeID( "Clcl" );
                var idClcn = charIDToTypeID( "Clcn" );
                var idAdd = charIDToTypeID( "Add " );
                desc569.putEnumerated( idClcl, idClcn, idAdd );
                var idScl = charIDToTypeID( "Scl " );
                desc569.putDouble( idScl, 2.000000 );
                var idOfst = charIDToTypeID( "Ofst" );
                desc569.putInteger( idOfst, 0 );
            var idClcl = charIDToTypeID( "Clcl" );
            desc568.putObject( idWith, idClcl, desc569 );
        executeAction( idAppI, desc568, DialogModes.NO );
    }
}

function clippingMask() {
    var idGrpL = charIDToTypeID( "GrpL" );
        var desc502 = new ActionDescriptor();
        var idnull = charIDToTypeID( "null" );
            var ref419 = new ActionReference();
            var idLyr = charIDToTypeID( "Lyr " );
            var idOrdn = charIDToTypeID( "Ordn" );
            var idTrgt = charIDToTypeID( "Trgt" );
            ref419.putEnumerated( idLyr, idOrdn, idTrgt );
        desc502.putReference( idnull, ref419 );
    executeAction( idGrpL, desc502, DialogModes.NO );
}

function makeAjLayer(layerName) {
    var idMk = charIDToTypeID( "Mk  " );
        var desc321 = new ActionDescriptor();
        var idnull = charIDToTypeID( "null" );
            var ref275 = new ActionReference();
            var idAdjL = charIDToTypeID( "AdjL" );
            ref275.putClass( idAdjL );
        desc321.putReference( idnull, ref275 );
        var idUsng = charIDToTypeID( "Usng" );
            var desc322 = new ActionDescriptor();
            var idType = charIDToTypeID( "Type" );
                var desc323 = new ActionDescriptor();
                var idpresetKind = stringIDToTypeID( "presetKind" );
                var idpresetKindType = stringIDToTypeID( "presetKindType" );
                var idpresetKindDefault = stringIDToTypeID( "presetKindDefault" );
                desc323.putEnumerated( idpresetKind, idpresetKindType, idpresetKindDefault );
            var idCrvs = charIDToTypeID( "Crvs" );
            desc322.putObject( idType, idCrvs, desc323 );
            var idNm = charIDToTypeID( "Nm  " );
            desc322.putString( idNm, layerName );
        var idAdjL = charIDToTypeID( "AdjL" );
        desc321.putObject( idUsng, idAdjL, desc322 );
    executeAction( idMk, desc321, DialogModes.NO );
}

function setAjLayer(){
    var idsetd = charIDToTypeID( "setd" );
        var desc1190 = new ActionDescriptor();
        var idnull = charIDToTypeID( "null" );
            var ref609 = new ActionReference();
            var idAdjL = charIDToTypeID( "AdjL" );
            var idOrdn = charIDToTypeID( "Ordn" );
            var idTrgt = charIDToTypeID( "Trgt" );
            ref609.putEnumerated( idAdjL, idOrdn, idTrgt );
        desc1190.putReference( idnull, ref609 );
        var idT = charIDToTypeID( "T   " );
            var desc1191 = new ActionDescriptor();
            var idpresetKind = stringIDToTypeID( "presetKind" );
            var idpresetKindType = stringIDToTypeID( "presetKindType" );
            var idpresetKindCustom = stringIDToTypeID( "presetKindCustom" );
            desc1191.putEnumerated( idpresetKind, idpresetKindType, idpresetKindCustom );
            var idAdjs = charIDToTypeID( "Adjs" );
                var list193 = new ActionList();
                    var desc1192 = new ActionDescriptor();
                    var idChnl = charIDToTypeID( "Chnl" );
                        var ref610 = new ActionReference();
                        var idChnl = charIDToTypeID( "Chnl" );
                        var idChnl = charIDToTypeID( "Chnl" );
                        var idCmps = charIDToTypeID( "Cmps" );
                        ref610.putEnumerated( idChnl, idChnl, idCmps );
                    desc1192.putReference( idChnl, ref610 );
                    var idCrv = charIDToTypeID( "Crv " );
                        var list194 = new ActionList();
                            var desc1193 = new ActionDescriptor();
                            var idHrzn = charIDToTypeID( "Hrzn" );
                            desc1193.putDouble( idHrzn, 64.000000 );
                            var idVrtc = charIDToTypeID( "Vrtc" );
                            desc1193.putDouble( idVrtc, 0.000000 );
                        var idPnt = charIDToTypeID( "Pnt " );
                        list194.putObject( idPnt, desc1193 );
                            var desc1194 = new ActionDescriptor();
                            var idHrzn = charIDToTypeID( "Hrzn" );
                            desc1194.putDouble( idHrzn, 192.000000 );
                            var idVrtc = charIDToTypeID( "Vrtc" );
                            desc1194.putDouble( idVrtc, 255.000000 );
                        var idPnt = charIDToTypeID( "Pnt " );
                        list194.putObject( idPnt, desc1194 );
                    desc1192.putList( idCrv, list194 );
                var idCrvA = charIDToTypeID( "CrvA" );
                list193.putObject( idCrvA, desc1192 );
            desc1191.putList( idAdjs, list193 );
        var idCrvs = charIDToTypeID( "Crvs" );
        desc1190.putObject( idT, idCrvs, desc1191 );
    executeAction( idsetd, desc1190, DialogModes.NO );
}

function makeInv(){
    var idMk = charIDToTypeID( "Mk  " );
        var desc743 = new ActionDescriptor();
        var idnull = charIDToTypeID( "null" );
            var ref610 = new ActionReference();
            var idAdjL = charIDToTypeID( "AdjL" );
            ref610.putClass( idAdjL );
        desc743.putReference( idnull, ref610 );
        var idUsng = charIDToTypeID( "Usng" );
            var desc744 = new ActionDescriptor();
            var idType = charIDToTypeID( "Type" );
            var idInvr = charIDToTypeID( "Invr" );
            desc744.putClass( idType, idInvr );
            var idNm = charIDToTypeID( "Nm  " );
            desc744.putString( idNm, invName );
        var idAdjL = charIDToTypeID( "AdjL" );
        desc743.putObject( idUsng, idAdjL, desc744 );
    executeAction( idMk, desc743, DialogModes.NO ); 
}

    };
retouch_3B();