Copy link to clipboard
Copied
I recently wrote a script that samples 4 points the the upper lefthand corner of an image, and then uses their RGB values to color select the entire background. The purpose of this is so that later in an action (but not in this script) the selection can be inverted and made into a new layer.
Taken as a whole the process essentially removes that background of an image. But, it only works if the colors in the upper left corner are representative of the entire background and the background is fairly uniform.
I am posting this for 3 reasons:
1) in case anyone finds it or any snippets of it useful
2) in case anyone has suggestions about ways the script could be improved...specifically I feel like the arrays could have been assembled a more concise fashion....?
3) because every time I play the script is causing my (usually closed) info panel to open as it creates the color samples and it's driving me crazy. Is there any type of .dialogsNO option I can put somewhere in here to keep this from happening? Or if not is there something I can add to the end of the script to close it?
#target photoshop
var doc = app.activeDocument
doc.colorSamplers.removeAll();
var samp1 = doc.colorSamplers.add([1,1]);
var samp1R = samp1.color.rgb.red;
var samp1G = samp1.color.rgb.green;
var samp1B = samp1.color.rgb.blue;
var samp2 = doc.colorSamplers.add([15,1]);
var samp2R = samp2.color.rgb.red;
var samp2G = samp2.color.rgb.green;
var samp2B = samp2.color.rgb.blue;
var samp3 = doc.colorSamplers.add([1,15]);
var samp3R = samp3.color.rgb.red;
var samp3G = samp3.color.rgb.green;
var samp3B = samp3.color.rgb.blue;
var samp4 = doc.colorSamplers.add([15,15]);
var samp4R = samp4.color.rgb.red;
var samp4G = samp4.color.rgb.green;
var samp4B = samp4.color.rgb.blue;
var reds = new Array;
var greens = new Array;
var blues = new Array;
reds.push([samp1R],[samp2R],[samp3R],[samp4R]);
greens.push([samp1G],[samp2G],[samp3B],[samp4G]);
blues.push([samp1B],[samp2B],[samp3B],[samp4B]);
redsMax = Math.max.apply(Math, reds);
greensMax = Math.max.apply(Math, greens);
bluesMax = Math.max.apply(Math, blues);
redsMin = Math.min.apply(Math, reds);
greensMin = Math.min.apply(Math, greens);
bluesMin = Math.min.apply(Math, blues);
//-----------KEY ADUSTMENTS----------//
tolerance = 25;
fuziness = 40;
//-----------KEY ADUSTMENTS----------//
redsMaxAdjusted = redsMax - (tolerance/5);
greensMaxAdjusted = greensMax- (tolerance/5);
bluesMaxAdjusted = bluesMax- (tolerance/5);
redsMinAdjusted = redsMin - tolerance;
greensMinAdjusted = greensMin - tolerance;
bluesMinAdjusted = bluesMin- tolerance;
app.activeDocument.suspendHistory ("autoSelect", "selectColorRange( redsMinAdjusted, greensMinAdjusted, bluesMinAdjusted, redsMaxAdjusted, greensMaxAdjusted, bluesMaxAdjusted, fuziness )");
function selectColorRange (minR, minG, minB, maxR, maxG, maxB, fuzz) {
var idClrR = charIDToTypeID( "ClrR" );
var desc4 = new ActionDescriptor();
var idFzns = charIDToTypeID( "Fzns" );
desc4.putInteger( idFzns, fuzz );
var idMnm = charIDToTypeID( "Mnm " );
var desc5 = new ActionDescriptor();
var idR = charIDToTypeID( "Rd " );
desc5.putDouble( idR, minR );
var idG = charIDToTypeID( "Grn " );
desc5.putDouble( idG, minG );
var idB = charIDToTypeID( "Bl " );
desc5.putDouble( idB, minB );
var idRGCl = charIDToTypeID( "RGBC" );
desc4.putObject( idMnm, idRGCl, desc5 );
var idMxm = charIDToTypeID( "Mxm " );
var desc6 = new ActionDescriptor();
var idR = charIDToTypeID( "Rd " );
desc6.putDouble( idR, maxR );
var idG = charIDToTypeID( "Grn " );
desc6.putDouble( idG, maxG );
var idB = charIDToTypeID( "Bl " );
desc6.putDouble( idB, maxB );
var idRGCl = charIDToTypeID( "RGBC" );
desc4.putObject( idMxm, idRGCl, desc6 );
var idcolorModel = stringIDToTypeID( "colorModel" );
desc4.putInteger( idcolorModel, 0 );
executeAction( idClrR, desc4, DialogModes.NO );
};
You could add...
app.runMenuItem (stringIDToTypeID ("closeInfoPanel"));
This should then close the Info panel.
Copy link to clipboard
Copied
You could add...
app.runMenuItem (stringIDToTypeID ("closeInfoPanel"));
This should then close the Info panel.
Copy link to clipboard
Copied
Perfect, thanks.
Copy link to clipboard
Copied
You seem to be using Action Manager code to do a Select Color Range. The IMO that would not only select the background it would also select areas in the image that have color in the same color range as the background. You may be better off using the magic want set to contiguous and sampling a few areas near the canvas left and right bounds. You could also do that for a layer stack to try to clear each layers background to trim to the layers object.
This script does that for normal layers above the background layer
try { if(app.documents.length>0){ app.activeDocument.suspendHistory ('Trim Layers', 'TrimLayers();') } }
catch(e) { alert( e + ': on line ' + e.line );}
function TrimLayers() {
var orig_ruler_units = app.preferences.rulerUnits; // save user ruler units
var orig_display_dialogs = app.displayDialogs; // Save users Display Doalogs
app.preferences.rulerUnits = Units.PIXELS; // set the ruler units to PIXELS
app.displayDialogs = DialogModes.NO; // Set Dialogs off
var doc = app.activeDocument; // get current document
var saveactiveLayer = doc.activeLayer; // save activeLayer
doc.selection.deselect(); // make sure ther is no active selection
try {processArtLayers(doc);} // Process all Layers
catch(e) { alert( e + ': on line ' + e.line );} // some unexpected error
doc.selection.deselect(); // make sure ther is no active selection
try { doc.activeLayer = saveactiveLayer;} // restore activeLayer
catch(e) { } // may have been deleted
app.displayDialogs = orig_display_dialogs; // Reset display dialogs
app.preferences.rulerUnits = orig_ruler_units; // reset units to original settings
}
///////////////////////////////////////////////////////////////////////////////
// Function: processsArtLayers
// Input: document or layer set
///////////////////////////////////////////////////////////////////////////////
function processArtLayers(obj) {
for(var i = obj.artLayers.length-1;0<= i; i--) { // for Layers
try {TrimLayer(obj.artLayers); } // process Art Layer
catch(e) {} // don't stop on errors
}
for(var i=obj.layerSets.length-1;0<=i;i--) { // for Layer sets
try {processArtLayers(obj.layerSets);} // process Layer Set
catch(e) {} // don't stop on errors
}
}
function TrimLayer(layer) {
// do nothing if layer is background or locked
if(layer.isBackgroundLayer || layer.allLocked || layer.pixelsLocked || layer.positionLocked || layer.transparentPixelsLocked ) return;
//if(layer.protectArtboardAutonest ) return;
if( layer.kind != LayerKind.NORMAL) return; // do nothing if not normal layer
app.activeDocument.activeLayer = layer; // target layer
var bounds = layer.bounds; // layer bounds
var LWidth = bounds[2]-bounds[0]; // layer width
var LHeight = bounds[3]-bounds[1]; // layer height
var Lleft = bounds[0]; // layer left x
var Lright = bounds[2]; // layer right x
var Ltop = bounds[1]; // layer top y
var Lbottom = bounds[3]; // layer bottom y
var tlrnc = 20; // tolerance
i=0.6; // fudge factor
try {
MagicWand((Lleft+i), (Ltop+i), tlrnc); // top left
app.activeDocument.selection.clear(); // clear
}
catch(e) {}; // do nothing
try {
MagicWand((Lleft+LWidth/2), (Ltop+i), tlrnc); // top middle
app.activeDocument.selection.clear(); // clear
}
catch(e) {}; // do nothing
try {
MagicWand((Lright-i), (Ltop+i), tlrnc); // top right
app.activeDocument.selection.clear(); // clear
}
catch(e) {}; // do nothing
try {
MagicWand((Lleft+i), (Ltop+LHeight/2), tlrnc); // middle left
app.activeDocument.selection.clear(); // clear
}
catch(e) {}; // do nothing
try {
MagicWand((Lright-i), (Ltop+LHeight/2), tlrnc); // middle right
app.activeDocument.selection.clear(); // clear
}
catch(e) {}; // do nothing
try {
MagicWand((Lleft+i), (Lbottom-i), tlrnc); // bottom left
app.activeDocument.selection.clear(); // clear
}
catch(e) {}; // do nothing
try {
MagicWand((Lleft+LWidth/2), (Lbottom-i), tlrnc); // bottom middle
app.activeDocument.selection.clear(); // clear
}
catch(e) {}; // do nothing
try {
MagicWand((Lright-i), (Lbottom-i), tlrnc); // bottom right
app.activeDocument.selection.clear(); // clear
}
catch(e) {}; // do nothing
}
function MagicWand(x,y,tolerance) {
var idsetd = charIDToTypeID( "setd" );
var desc106 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref60 = new ActionReference();
var idChnl = charIDToTypeID( "Chnl" );
var idfsel = charIDToTypeID( "fsel" );
ref60.putProperty( idChnl, idfsel );
desc106.putReference( idnull, ref60 );
var idT = charIDToTypeID( "T " );
var desc107 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc107.putUnitDouble( idHrzn, idPxl, x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc107.putUnitDouble( idVrtc, idPxl, y );
var idPnt = charIDToTypeID( "Pnt " );
desc106.putObject( idT, idPnt, desc107 );
var idTlrn = charIDToTypeID( "Tlrn" );
desc106.putInteger( idTlrn, tolerance );
var idAntA = charIDToTypeID( "AntA" );
desc106.putBoolean( idAntA, true );
executeAction( idsetd, desc106, DialogModes.NO );
}
Copy link to clipboard
Copied
Due to the files I'm working with, the color selection works well for me, but this is an interesting technique that I'll have to play around with. Thanks.