// ============================================================ // Auto color correction based on Filter - Blur - Average // www.timon.ru // ============================================================ var docRef = app.activeDocument; var mainLayer = docRef.activeLayer; //сделаем дубликат слоя var filterLayer = mainLayer.duplicate (); docRef.activeLayer = filterLayer; //применим фильтр Average filterLayer.applyAverage(); //получим цвет слоя, пипетку отключаем она не у всех работает //var color = eyedropper(docRef , 1, 1); //получим цвет слоя var re = RegExp( '[123456789]+' ); var red = re.exec( docRef.channels[0].histogram.toString() ).index/2; var green = re.exec( docRef.channels[1].histogram.toString() ).index/2; var blue = re.exec( docRef.channels[2].histogram.toString() ).index/2; //слой нам больше не нужен, удалим docRef.activeLayer.remove(); // найдем среднюю яркость var middle = ( red + green + blue ) / 3 ; //пересчитаем новые корректирующие точки по каналам red = red * 127 / middle; green = green * 127 / middle; blue = blue * 127 / middle; //создадим корректирующий слой кривых для автоББ adjCurve(); /* * пипетка, на вход отдаем документ и координаты точки, на выходе цвет */ function eyedropper(doc,x,y) { Stdlib = function() {}; Stdlib.selectBounds = function(doc, b, type, feather, antialias) { doc.selection.select([[ b[0], b[1] ], [ b[2], b[1] ], [ b[2], b[3] ], [ b[0], b[3] ]], type, feather, antialias); }; // make new 1 pixel selection x = Math.floor(x); y = Math.floor(y); Stdlib.selectBounds(doc, [x, y, x+1, y+1]); try { function findPV(h) { for (var i = 0; i <= 255; i++ ) { if (h[i]) { return i; } } return 0; } var pColour = new SolidColor(); pColour.rgb.red = findPV(doc.channels["Red"].histogram); pColour.rgb.green = findPV(doc.channels["Green"].histogram); pColour.rgb.blue = findPV(doc.channels["Blue"].histogram); } finally { doc.selection.deselect(); } return pColour; }; function adjCurve(){ var c_ADJ_LAYER = charIDToTypeID( "AdjL" ); var c_ADJUSTMENT = charIDToTypeID( "Adjs" ); var c_CHANNEL = charIDToTypeID( "Chnl" ); var c_COMPOSITE = charIDToTypeID( "Cmps" ); var c_Rd = charIDToTypeID( "Rd " ); var c_Gr = charIDToTypeID( "Grn " ); var c_Bl = charIDToTypeID( "Bl " ); var c_CURVE = charIDToTypeID( "Crv " ); var c_CURVE_A = charIDToTypeID( "CrvA" ); var c_CURVES = charIDToTypeID( "Crvs" ); var c_HORIZONTAL = charIDToTypeID( "Hrzn" ); var c_MAKE = charIDToTypeID( "Mk " ); var c_NULL = charIDToTypeID( "null" ); var c_POINT = charIDToTypeID( "Pnt " ); var c_TYPE = charIDToTypeID( "Type" ); var c_USING = charIDToTypeID( "Usng" ); var c_VERTICAL = charIDToTypeID( "Vrtc" ); var d_CURVES_LAYER = new ActionDescriptor(); // Contains all the information necessary to perform the "MAKE" action var r_CLASS = new ActionReference(); r_CLASS.putClass( c_ADJ_LAYER ); d_CURVES_LAYER.putReference( c_NULL, r_CLASS ); // Class of make action is of an ajdustment layer var d_TYPE_CURVES = new ActionDescriptor(); // Contains all the information about all the curves var d_CHANNEL_CURVES = new ActionDescriptor(); var l_CHANNEL_CURVES = new ActionList(); // Contains a list of channel curves var d_CHANNEL_CURVE = new ActionDescriptor(); // Information for 1 channel curve var r_CHANNEL = new ActionReference(); r_CHANNEL.putEnumerated( c_CHANNEL, c_CHANNEL, c_Bl ); // This curve is for the composite channel - VARIES d_CHANNEL_CURVE.putReference( c_CHANNEL, r_CHANNEL ); // Contains the point list var l_POINTS = new ActionList(); // List of points for this channel - LENGTH VARIES var d_POINT = new ActionDescriptor(); // One point on the curve, has INPUT and OUTPUT value d_POINT.putDouble( c_HORIZONTAL, 0.000000 ); d_POINT.putDouble( c_VERTICAL, 0.000000 ); l_POINTS.putObject( c_POINT, d_POINT ); //var d_POINT2 = new ActionDescriptor(); d_POINT.putDouble( c_HORIZONTAL, blue ); d_POINT.putDouble( c_VERTICAL, 127.000000 ); l_POINTS.putObject( c_POINT, d_POINT ); //var d_POINT3 = new ActionDescriptor(); d_POINT.putDouble( c_HORIZONTAL, 255.000000 ); d_POINT.putDouble( c_VERTICAL, 255.000000 ); l_POINTS.putObject( c_POINT, d_POINT ); // Made the list of points d_CHANNEL_CURVE.putList( c_CURVE, l_POINTS ); // Now have a list of points for a specific channel l_CHANNEL_CURVES.putObject( c_CURVE_A, d_CHANNEL_CURVE ); var r_CHANNEL = new ActionReference(); r_CHANNEL.putEnumerated( c_CHANNEL, c_CHANNEL, c_Rd ); // This curve is for the composite channel - VARIES d_CHANNEL_CURVE.putReference( c_CHANNEL, r_CHANNEL ); // Contains the point list var l_POINTS = new ActionList(); // List of points for this channel - LENGTH VARIES var d_POINT = new ActionDescriptor(); // One point on the curve, has INPUT and OUTPUT value d_POINT.putDouble( c_HORIZONTAL, 0.000000 ); d_POINT.putDouble( c_VERTICAL, 0.000000 ); l_POINTS.putObject( c_POINT, d_POINT ); //var d_POINT2 = new ActionDescriptor(); d_POINT.putDouble( c_HORIZONTAL, red ); d_POINT.putDouble( c_VERTICAL, 127.000000 ); l_POINTS.putObject( c_POINT, d_POINT ); //var d_POINT3 = new ActionDescriptor(); d_POINT.putDouble( c_HORIZONTAL, 255.000000 ); d_POINT.putDouble( c_VERTICAL, 255.000000 ); l_POINTS.putObject( c_POINT, d_POINT ); // Made the list of points d_CHANNEL_CURVE.putList( c_CURVE, l_POINTS ); // Now have a list of points for a specific channel l_CHANNEL_CURVES.putObject( c_CURVE_A, d_CHANNEL_CURVE ); var r_CHANNEL = new ActionReference(); r_CHANNEL.putEnumerated( c_CHANNEL, c_CHANNEL, c_Gr ); // This curve is for the composite channel - VARIES d_CHANNEL_CURVE.putReference( c_CHANNEL, r_CHANNEL ); // Contains the point list var l_POINTS = new ActionList(); // List of points for this channel - LENGTH VARIES var d_POINT = new ActionDescriptor(); // One point on the curve, has INPUT and OUTPUT value d_POINT.putDouble( c_HORIZONTAL, 0.000000 ); d_POINT.putDouble( c_VERTICAL, 0.000000 ); l_POINTS.putObject( c_POINT, d_POINT ); //var d_POINT2 = new ActionDescriptor(); d_POINT.putDouble( c_HORIZONTAL, green ); d_POINT.putDouble( c_VERTICAL, 127.000000 ); l_POINTS.putObject( c_POINT, d_POINT ); //var d_POINT3 = new ActionDescriptor(); d_POINT.putDouble( c_HORIZONTAL, 255.000000 ); d_POINT.putDouble( c_VERTICAL, 255.000000 ); l_POINTS.putObject( c_POINT, d_POINT ); // Made the list of points d_CHANNEL_CURVE.putList( c_CURVE, l_POINTS ); // Now have a list of points for a specific channel l_CHANNEL_CURVES.putObject( c_CURVE_A, d_CHANNEL_CURVE ); // Add to the list of channel curves d_CHANNEL_CURVES.putList( c_ADJUSTMENT, l_CHANNEL_CURVES ); // All the channel curves are inside here d_TYPE_CURVES.putObject( c_TYPE, c_CURVES, d_CHANNEL_CURVES ); // ..... d_CURVES_LAYER.putObject( c_USING, c_ADJ_LAYER, d_TYPE_CURVES ); // package the curves and definition of the adjustment layer type executeAction( c_MAKE, d_CURVES_LAYER, DialogModes.NO ); }