Skip to content

Instantly share code, notes, and snippets.

@Yamonov
Last active April 17, 2026 06:06
Show Gist options
  • Select an option

  • Save Yamonov/fd886cedadccdbde7ca72423f7e86534 to your computer and use it in GitHub Desktop.

Select an option

Save Yamonov/fd886cedadccdbde7ca72423f7e86534 to your computer and use it in GitHub Desktop.
PhotoshopScripts

Photoshopスクリプトつめあわせ

/*
<javascriptresource>
<name>マスクカラー変更</name>
<category>YPresets</category>
</javascriptresource>
SCRIPTMETA-BEGIN
Script-ID=org.iwashi.Photoshop_ChangeMaskColor
Version=1
Release-Date=2026-03-23
Meta-URL=https://gist.github.com/Yamonov/fd886cedadccdbde7ca72423f7e86534
Target-App=Photoshop
Description-BEGIN
マスクのオーバーレイ表示カラーを、実行する度に色相環で60度ごとに切り替えます。
Description-END
SCRIPTMETA-END
*/
var regKey = "myMaskColor"; // 実行内容を記録するキー
// カラー設定
var defaultSaturation = 80; // 彩度(0〜100)
var defaultBrightness = 80; // 輝度(0〜100)
var defaultOpacity = 90; // 不透明度(0〜100)
var hueStep = 60; // 前回から加算するH(例: 120=RGB, 60=CMY)
// 前回記録の取得 or 初回記録
var currentHue;
try {
var desc = app.getCustomOptions(regKey);
currentHue = parseInt(desc.getString(1001), 10);
} catch (e) {
currentHue = saveHue(0); // 初回は0で記録
}
// 新しい色相の計算と保存
currentHue += hueStep;
if (currentHue >= 360) currentHue = 0;
saveHue(currentHue);
// 実行
try {
applyMaskColor(currentHue);
} catch (e) {}
// 関数:H値を保存
function saveHue(hue) {
var desc = new ActionDescriptor();
desc.putString(1001, String(hue));
app.putCustomOptions(regKey, desc, true);
return hue;
}
// 関数:マスクカラーを変更
function applyMaskColor(hue) {
var idSet = charIDToTypeID("setd");
var descSet = new ActionDescriptor();
var idNull = charIDToTypeID("null");
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Chnl"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
descSet.putReference(idNull, ref);
var idTo = charIDToTypeID("T ");
var descChannel = new ActionDescriptor();
var idColor = charIDToTypeID("Clr ");
var descHSB = new ActionDescriptor();
descHSB.putUnitDouble(charIDToTypeID("H "), charIDToTypeID("#Ang"), hue);
descHSB.putDouble(charIDToTypeID("Strt"), defaultSaturation);
descHSB.putDouble(charIDToTypeID("Brgh"), defaultBrightness);
descChannel.putObject(idColor, charIDToTypeID("HSBC"), descHSB);
// 不透明度を設定(不要ならこのブロック削除)
descChannel.putUnitDouble(
charIDToTypeID("Opct"),
charIDToTypeID("#Prc"),
defaultOpacity
);
descSet.putObject(idTo, charIDToTypeID("Chnl"), descChannel);
executeAction(idSet, descSet, DialogModes.NO);
}
/*
<javascriptresource>
<name>クリッピング表示</name>
<category>YPresets</category>
</javascriptresource>
SCRIPTMETA-BEGIN
Script-ID=org.iwashi.Photoshop_ClippingView
Version=1
Release-Date=2026-03-23
Meta-URL=https://gist.github.com/Yamonov/fd886cedadccdbde7ca72423f7e86534
Target-App=Photoshop
Description-BEGIN
RGBドキュメントとCMYKドキュメントで実行すると、潰れるところを青、飛ぶところを赤で表示するレイヤーグループを最上部に作成します。
もう一度実行すると非表示に、再度実行すると最上部に移動した上で表示状態になります。
CMYKドキュメントでは総インキ量を指定できます。システム側にインストールされる「TotalInkPreview.icc」を使用します。
Description-END
SCRIPTMETA-END
*/
if(app.documents.length){
app.activeDocument.suspendHistory("クリッピング表示","main()");
}
// ===========================================
// メイン処理
// ===========================================
function main() {
if (toggleAllClippingViewGroups()) {return;}
var colorMode = getDocumentColorMode();
if (colorMode === "CMYK") {
processCMYK();
} else if (colorMode === "RGB") {
processRGB();
} else {
alert("RGBまたはCMYKドキュメントで実行してください。");
}
}
// ===========================================
// CMYKモード用の処理
// ===========================================
function processCMYK() {
moveActiveLayerSelection(0);
createGroup("TEMP");
createColorLookupLayerWithICC(getICCPath(),"TAC2Gary");
setLayerBlendRangeGrayFull([0,0,254,254],[0,0,255,255]);
createThresholdLayer();
setThresholdByTAC();
applySolidFillEffect("CMYK",[100,50,0,0],"lighterColor");
createClippingMask();
createSolidColorLayer("CMYK",[0,100,100,0],"Highlight");
setLayerBlendRangeGrayFull([0,0,255,255],[255,255,255,255]);
moveActiveLayerSelection(0);
ungroupSelectedLayers();
selectLayerIDsFromTop(3);
makeLayerGroup("Clipping_View_CMYK","orange");
}
// ===========================================
// RGBモード用の処理
// ===========================================
function processRGB() {
moveActiveLayerSelection(0);
createGroup("TEMP");
createSolidColorLayer("RGB",[0,0,255],"Shadow");
setLayerBlendRangeGrayFull([0,0,255,255],[0,0,0,0]);
createSolidColorLayer("RGB",[255,0,0],"Highlight");
setLayerBlendRangeGrayFull([0,0,255,255],[255,255,255,255]);
moveActiveLayerSelection(0);
ungroupSelectedLayers();
selectLayerIDsFromTop(2);
makeLayerGroup("Clipping_View_RGB","orange");
}
// ===========================================
// OSに応じてICCファイルのパスを返す
// ===========================================
function getICCPath() {
var iccPath;
if ($.os.toLowerCase().indexOf("mac") >= 0) {
// Macの場合
iccPath = "/Library/Application Support/Adobe/Color Profiles/TotalInkPreview.icc";
} else {
// Windowsの場合
iccPath = "C:\\Program Files (x86)\\Common Files\\Adobe\\Color Profiles\\TotalInkPreview.icc";
}
var iccFile = new File(iccPath);
if (!iccFile.exists) {
alert(
"ICCプロファイルが見つかりません:\n" +
iccPath +
"\n付近を探して、見つかったパスを script71行目あたりで書き換えてください"
);
throw new Error("ICCプロファイルが存在しません。");
}
return iccPath;
}
// ===========================================
// ドキュメント直下の「Clipping_View_」で始まるすべてのレイヤーグループを
// 最上位に移動し、表示/非表示をトグル
// ===========================================
function toggleAllClippingViewGroups() {
if (app.documents.length === 0) return false;
var doc = app.activeDocument;
var targetPrefix = "Clipping_View_";
var targetGroups = [];
for (var i = 0; i < doc.layers.length; i++) {
var layer = doc.layers[i];
if (layer.typename === "LayerSet" && layer.name.indexOf(targetPrefix) === 0) {
targetGroups.push(layer);
}
}
if (targetGroups.length === 0) return false;
for (var j = targetGroups.length - 1; j >= 0; j--) {
var group = targetGroups[j];
if (doc.layers[0] !== group) {
group.move(doc.layers[0], ElementPlacement.PLACEBEFORE);
}
}
for (var k = 0; k < targetGroups.length; k++) {
targetGroups[k].visible = !targetGroups[k].visible;
}
return true;
}
// ===========================================
// 選択中の2階調化レイヤーの閾値を、総インキ量(TAC)入力から再設定する
// ===========================================
function setThresholdByTAC() {
if (app.documents.length && app.activeDocument.activeLayer.kind === LayerKind.THRESHOLD) {
var layer = app.activeDocument.activeLayer;
var match = layer.name.match(/TAC値[::]\s*(\d+(?:\.\d+)?)%?/);
var defaultValue = match ? match[1] : "350";
var x = null;
while (true) {
var input = prompt("総インキ量を入力してください(1〜400%)", defaultValue);
if (input === null) break;
x = parseFloat(input);
if (!isNaN(x) && x >= 1 && x <= 400) break;
alert("1〜400 の数値を入力してください。");
}
if (x !== null) {
var level = Math.round(255 * (1 - x / 400));
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(stringIDToTypeID("adjustmentLayer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
desc.putReference(stringIDToTypeID("null"), ref);
var toDesc = new ActionDescriptor();
toDesc.putInteger(stringIDToTypeID("level"), level);
desc.putObject(stringIDToTypeID("to"), stringIDToTypeID("thresholdClassEvent"), toDesc);
executeAction(stringIDToTypeID("set"), desc, DialogModes.NO);
layer.name = "TAC値:" + x + "%";
}
} else {
alert("2階調化調整レイヤーを選択してください。");
}
}
// ===========================================
// アクティブレイヤーの選択を指定位置に移動する
// 引数:0 = 最上部を選択、正数 = 上へ(前面側)選択移動、負数 = 下へ(背面側)選択移動
// ===========================================
function moveActiveLayerSelection(position) {
var doc = app.activeDocument;
var layers = getAllLayers(doc);
var currentLayer = doc.activeLayer;
var index = findLayerIndex(currentLayer, layers);
if (index === -1) {
alert("レイヤー位置を特定できません。");
return;
}
if (position === 0) {
doc.activeLayer = layers[0];
} else {
var targetIndex = index - position;
if (targetIndex < 0) {
targetIndex = 0;
}
if (targetIndex >= layers.length) {
targetIndex = layers.length - 1;
}
doc.activeLayer = layers[targetIndex];
}
}
// ===========================================
// 指定した名前と色でレイヤーグループを作成
// ===========================================
function makeLayerGroup(groupName, groupColorName) {
var idMake = stringIDToTypeID("make");
var desc = new ActionDescriptor();
var refClass = new ActionReference();
refClass.putClass(stringIDToTypeID("layerSection"));
desc.putReference(stringIDToTypeID("null"), refClass);
var refFrom = new ActionReference();
refFrom.putEnumerated(
stringIDToTypeID("layer"),
stringIDToTypeID("ordinal"),
stringIDToTypeID("targetEnum")
);
desc.putReference(stringIDToTypeID("from"), refFrom);
var usingDesc = new ActionDescriptor();
usingDesc.putString(stringIDToTypeID("name"), groupName);
usingDesc.putEnumerated(
stringIDToTypeID("color"),
stringIDToTypeID("color"),
stringIDToTypeID(groupColorName)
);
desc.putObject(stringIDToTypeID("using"), stringIDToTypeID("layerSection"), usingDesc);
desc.putString(stringIDToTypeID("name"), groupName);
executeAction(idMake, desc, DialogModes.NO);
}
// ===========================================
// 選択中のレイヤーグループを解除(ungroup)
// ===========================================
function ungroupSelectedLayers() {
// var idUngroup = stringIDToTypeID("ungroupLayersEvent");
// var desc = new ActionDescriptor();
// var ref = new ActionReference();
// ref.putEnumerated(
// stringIDToTypeID("layer"),
// stringIDToTypeID("ordinal"),
// stringIDToTypeID("targetEnum")
// );
// desc.putReference(stringIDToTypeID("null"), ref);
// executeAction(idUngroup, desc, DialogModes.NO);
var idungroupLayersEvent = stringIDToTypeID( "ungroupLayersEvent" );
var desc308 = new ActionDescriptor();
var idnull = stringIDToTypeID( "null" );
var ref48 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
ref48.putEnumerated( idlayer, idordinal, idtargetEnum );
desc308.putReference( idnull, ref48 );
executeAction( idungroupLayersEvent, desc308, DialogModes.NO );
}
// ===========================================
// 全レイヤーリスト内でレイヤーのインデックスを見つける
// ===========================================
function findLayerIndex(targetLayer, layers) {
for (var i = 0; i < layers.length; i++) {
if (layers[i] === targetLayer) {
return i;
}
}
return -1;
}
// ===========================================
// 上から順に指定数の layerID を選択
// ===========================================
function selectLayerIDsFromTop(count) {
var ids = getAllLayerIDs(app.activeDocument).slice(0, count);
if (!(ids instanceof Array)) ids = [ids];
var selectDesc = new ActionDescriptor();
var selectRef = new ActionReference();
for (var i = 0; i < ids.length; i++) {
selectRef.putIdentifier(charIDToTypeID("Lyr "), ids[i]);
}
selectDesc.putReference(charIDToTypeID("null"), selectRef);
selectDesc.putBoolean(charIDToTypeID("MkVs"), false);
executeAction(charIDToTypeID("slct"), selectDesc, DialogModes.NO);
}
// ===========================================
// 単一レイヤーからlayerIDを取得
// ===========================================
function getLayerID(layer) {
try {
var ref = new ActionReference();
ref.putIndex(charIDToTypeID("Lyr "), layer.itemIndex);
var desc = executeActionGet(ref);
return desc.getInteger(stringIDToTypeID("layerID"));
} catch (e) {
return -1;
}
}
// ===========================================
// ドキュメント内の全レイヤーの layerID を上から順に返す
// ===========================================
function getAllLayerIDs(doc) {
var ids = [];
function collect(container) {
for (var i = 0; i < container.layers.length; i++) {
var layer = container.layers[i];
if (layer.typename === "ArtLayer" || layer.typename === "LayerSet") {
var id = getLayerID(layer);
if (id !== -1) ids.push(id);
if (layer.typename === "LayerSet") collect(layer);
}
}
}
collect(doc);
return ids;
}
// ===========================================
// ドキュメント内の全レイヤーをフラットに取得する
// ===========================================
function getAllLayers(doc) {
var layers = [];
function collect(layerContainer) {
for (var i = 0; i < layerContainer.layers.length; i++) {
var layer = layerContainer.layers[i];
if (layer.typename === "ArtLayer") {
layers.push(layer);
} else if (layer.typename === "LayerSet") {
layers.push(layer);
collect(layer);
}
}
}
collect(doc);
return layers;
}
// ===========================================
// 指定した名前で新しいフォルダ(レイヤーグループ)を作成する
// ===========================================
function createGroup(name) {
var doc = app.activeDocument;
var group = doc.layerSets.add();
group.name = name;
}
// ===========================================
// アクティブなレイヤーをクリッピングマスクにする
// ===========================================
function createClippingMask() {
app.activeDocument.activeLayer.grouped = true;
}
// ===========================================
// 現在のドキュメントのカラーモードを判定して返す
// ("RGB" / "CMYK" / "Other" を返す)
// ===========================================
function getDocumentColorMode() {
var mode = app.activeDocument.mode;
if (mode == DocumentMode.RGB) {
return "RGB";
} else if (mode == DocumentMode.CMYK) {
return "CMYK";
} else {
return "Other";
}
}
// ===========================================
// 2階調化(Threshold)レイヤーを作成する
// ===========================================
function createThresholdLayer(level) {
var idmake = stringIDToTypeID("make");
var desc = new ActionDescriptor();
var idnull = stringIDToTypeID("null");
var ref = new ActionReference();
var idadjustmentLayer = stringIDToTypeID("adjustmentLayer");
ref.putClass(idadjustmentLayer);
desc.putReference(idnull, ref);
var idusing = stringIDToTypeID("using");
var descUsing = new ActionDescriptor();
var idtype = stringIDToTypeID("type");
var descType = new ActionDescriptor();
var idlevel = stringIDToTypeID("level");
descType.putInteger(idlevel, (level !== undefined) ? level : 128);
var idthresholdClassEvent = stringIDToTypeID("thresholdClassEvent");
descUsing.putObject(idtype, idthresholdClassEvent, descType);
desc.putObject(idusing, idadjustmentLayer, descUsing);
executeAction(idmake, desc, DialogModes.NO);
}
// ===========================================
// Color Lookup調整レイヤーを作成し、ICCプロファイルを適用、レイヤー名を設定する
// ===========================================
function createColorLookupLayerWithICC(filePath, layerName) {
try {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putClass(stringIDToTypeID("adjustmentLayer"));
desc.putReference(stringIDToTypeID("null"), ref);
var descInner = new ActionDescriptor();
descInner.putClass(stringIDToTypeID("type"), stringIDToTypeID("colorLookup"));
desc.putObject(stringIDToTypeID("using"), stringIDToTypeID("adjustmentLayer"), descInner);
executeAction(stringIDToTypeID("make"), desc, DialogModes.NO);
var iccFile = new File(filePath);
if (!iccFile.exists) {
alert("指定されたICCファイルが存在しません: " + filePath);
return;
}
var refSet = new ActionReference();
refSet.putEnumerated(
charIDToTypeID("AdjL"),
charIDToTypeID("Ordn"),
charIDToTypeID("Trgt")
);
var descSet = new ActionDescriptor();
descSet.putReference(charIDToTypeID("null"), refSet);
var descLookup = new ActionDescriptor();
descLookup.putEnumerated(
stringIDToTypeID("lookupType"),
stringIDToTypeID("colorLookupType"),
stringIDToTypeID("deviceLinkProfile")
);
descLookup.putString(charIDToTypeID("Nm "), iccFile.name);
iccFile.open("r");
iccFile.encoding = "BINARY";
var binData = iccFile.read();
iccFile.close();
descLookup.putData(stringIDToTypeID("profile"), binData);
descSet.putObject(
charIDToTypeID("T "),
stringIDToTypeID("colorLookup"),
descLookup
);
executeAction(charIDToTypeID("setd"), descSet, DialogModes.NO);
if (layerName) {
app.activeDocument.activeLayer.name = layerName;
}
} catch (e) {
alert("エラー: " + e);
}
}
// ===========================================
// 選択レイヤーのブレンド条件(グレー)を設定する
// 引数: srcRangeArray, destRangeArray
// - srcRangeArray = [srcBlackMin, srcBlackMax, srcWhiteMin, srcWhiteMax]
// - destRangeArray = [destBlackMin, destBlackMax, destWhiteMin, destWhiteMax]
// ===========================================
function setLayerBlendRangeGrayFull(srcRangeArray, destRangeArray) {
if (!srcRangeArray || !destRangeArray || srcRangeArray.length !== 4 || destRangeArray.length !== 4) {
throw new Error("srcRangeArrayとdestRangeArrayにはそれぞれ4つの数値を指定してください。");
}
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
desc.putReference(stringIDToTypeID("null"), ref);
var layerDesc = new ActionDescriptor();
var blendRangeList = new ActionList();
var grayChannelDesc = new ActionDescriptor();
var channelRef = new ActionReference();
channelRef.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("gray"));
grayChannelDesc.putReference(stringIDToTypeID("channel"), channelRef);
// 現在のレイヤー
grayChannelDesc.putInteger(stringIDToTypeID("srcBlackMin"), srcRangeArray[0]);
grayChannelDesc.putInteger(stringIDToTypeID("srcBlackMax"), srcRangeArray[1]);
grayChannelDesc.putInteger(stringIDToTypeID("srcWhiteMin"), srcRangeArray[2]);
grayChannelDesc.putInteger(stringIDToTypeID("srcWhiteMax"), srcRangeArray[3]);
// 下になっているレイヤー
grayChannelDesc.putInteger(stringIDToTypeID("destBlackMin"), destRangeArray[0]);
grayChannelDesc.putInteger(stringIDToTypeID("destBlackMax"), destRangeArray[1]);
grayChannelDesc.putInteger(stringIDToTypeID("destWhiteMin"), destRangeArray[2]);
grayChannelDesc.putInteger(stringIDToTypeID("destWhiteMax"), destRangeArray[3]);
blendRangeList.putObject(stringIDToTypeID("blendRange"), grayChannelDesc);
layerDesc.putList(stringIDToTypeID("blendRange"), blendRangeList);
desc.putObject(stringIDToTypeID("to"), stringIDToTypeID("layer"), layerDesc);
executeAction(stringIDToTypeID("set"), desc, DialogModes.NO);
}
// ===========================================
// アクティブレイヤーに単色塗りレイヤースタイルを適用する
// 引数:
// - colorMode: "RGB" または "CMYK"
// - colorArray: [R,G,B] または [C,M,Y,K]
// - blendMode: ブレンドモード(省略時は"normal")
// ===========================================
function applySolidFillEffect(colorMode, colorArray, blendMode) {
if (!colorMode || !colorArray || !(colorArray instanceof Array)) {
throw new Error("colorMode と colorArray を正しく指定してください。");
}
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("layerEffects"));
ref.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
desc.putReference(stringIDToTypeID("null"), ref);
var layerEffectsDesc = new ActionDescriptor();
layerEffectsDesc.putUnitDouble(stringIDToTypeID("scale"), stringIDToTypeID("percentUnit"), 100.0);
var solidFillDesc = new ActionDescriptor();
solidFillDesc.putBoolean(stringIDToTypeID("enabled"), true);
solidFillDesc.putBoolean(stringIDToTypeID("present"), true);
solidFillDesc.putBoolean(stringIDToTypeID("showInDialog"), true);
solidFillDesc.putEnumerated(
stringIDToTypeID("mode"),
stringIDToTypeID("blendMode"),
stringIDToTypeID(blendMode || "normal")
);
// buildColorDescriptor関数を使用
var colorResult = buildColorDescriptor(colorMode, colorArray);
solidFillDesc.putObject(stringIDToTypeID("color"), stringIDToTypeID(colorResult.colorType), colorResult.colorDesc);
solidFillDesc.putUnitDouble(stringIDToTypeID("opacity"), stringIDToTypeID("percentUnit"), 100.0);
layerEffectsDesc.putObject(stringIDToTypeID("solidFill"), stringIDToTypeID("solidFill"), solidFillDesc);
desc.putObject(stringIDToTypeID("to"), stringIDToTypeID("layerEffects"), layerEffectsDesc);
executeAction(stringIDToTypeID("set"), desc, DialogModes.NO);
}
// ===========================================
// ベタ塗りレイヤー(Solid Color Fill Layer)を作成する(RGB/CMYK対応)
// 引数:
// - colorMode: "RGB" または "CMYK"
// - colorArray: [R,G,B] または [C,M,Y,K]
// - name: レイヤー名(省略可)
// ===========================================
function createSolidColorLayer(colorMode, colorArray, name) {
if (!colorMode || !colorArray || !(colorArray instanceof Array)) {
throw new Error("colorMode と colorArray を正しく指定してください。");
}
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putClass(stringIDToTypeID("contentLayer"));
desc.putReference(stringIDToTypeID("null"), ref);
var usingDesc = new ActionDescriptor();
var typeDesc = new ActionDescriptor();
// buildColorDescriptor関数を使用
var colorResult = buildColorDescriptor(colorMode, colorArray);
typeDesc.putObject(stringIDToTypeID("color"), stringIDToTypeID(colorResult.colorType), colorResult.colorDesc);
usingDesc.putObject(stringIDToTypeID("type"), stringIDToTypeID("solidColorLayer"), typeDesc);
desc.putObject(stringIDToTypeID("using"), stringIDToTypeID("contentLayer"), usingDesc);
executeAction(stringIDToTypeID("make"), desc, DialogModes.NO);
if (name) {
app.activeDocument.activeLayer.name = name;
}
}
// ===========================================
// colorModeとcolorArrayに応じたColor Descriptorを生成する
// 戻り値: { colorDesc: ActionDescriptor, colorType: "RGBColor" or "CMYKColorClass" }
// ===========================================
function buildColorDescriptor(colorMode, colorArray) {
var colorDesc = new ActionDescriptor();
if (colorMode === "RGB") {
colorDesc.putDouble(stringIDToTypeID("red"), colorArray[0] || 0);
colorDesc.putDouble(stringIDToTypeID("green"), colorArray[1] || 0);
colorDesc.putDouble(stringIDToTypeID("blue"), colorArray[2] || 0);
return { colorDesc: colorDesc, colorType: "RGBColor" };
} else if (colorMode === "CMYK") {
colorDesc.putDouble(stringIDToTypeID("cyan"), colorArray[0] || 0);
colorDesc.putDouble(stringIDToTypeID("magenta"), colorArray[1] || 0);
colorDesc.putDouble(stringIDToTypeID("yellowColor"), colorArray[2] || 0);
colorDesc.putDouble(stringIDToTypeID("black"), colorArray[3] || 0);
return { colorDesc: colorDesc, colorType: "CMYKColorClass" };
} else {
throw new Error("colorModeには 'RGB' または 'CMYK' を指定してください。");
}
}
/*
SCRIPTMETA-BEGIN
Script-ID=org.iwashi.Photoshop_OpacityFlowExposure
Version=1
Release-Date=2026-03-23
Meta-URL=https://gist.github.com/Yamonov/fd886cedadccdbde7ca72423f7e86534
Target-App=Photoshop
Description-BEGIN
ブラシの不透明度と流量を変更する、本体スクリプトです。
$.evalFile(File(File($.fileName).parent + "/opacityFlowExposure.jsxinc")); r($.fileName);
を書き込んだ、ファイル名「OFE_xxx.jsx」を複数作成し、同じフォルダ内に置いて、そちらを実行してください。
ファイル名のxxx部分を読み取って動作を変更します。
F:flow(流量)、O:opacity(不透明度)
に続けて、0〜100、または-、+を付けてください。
例:
OFE_F-.jsx (Flowをいい感じに一段階下げます)
OFE_O100.jsx (Opacityを最大値に設定します)
Description-END
SCRIPTMETA-END
*/
function r(f) {
var b = File(f).name;
var p = "OFE_";
var d = b.lastIndexOf(".");
var c;
var m = { O: "opacity", F: "flow" };
var k;
var u;
var a = [2, 4, 6, 8, 10, 12, 14, 16, 20, 30, 40, 50, 60, 70, 80, 90, 100];
var t = app.currentTool;
var iu = stringIDToTypeID("percentUnit");
var inull = charIDToTypeID("null");
var iT = charIDToTypeID("T ");
var iO = charIDToTypeID("Ordn");
var iP = stringIDToTypeID("property");
var iTool = stringIDToTypeID("tool");
var iC = charIDToTypeID("capp");
var iG = charIDToTypeID("Trgt");
var iS = stringIDToTypeID("set");
var iE = stringIDToTypeID("exposure");
if (b.indexOf(p) !== 0 || d <= p.length) {
throw new Error("Unexpected file name: " + b);
}
c = b.substring(p.length, d);
k = m[c.charAt(0)];
u = c.substring(1);
if (!k || !u) {
throw new Error("Unexpected command: " + c);
}
function n(v, x) {
var l = 0;
var h = a.length - 1;
var r = v;
var q;
while (l <= h) {
q = Math.floor((l + h) / 2);
if ((x > 0 && a[q] > v) || (x < 0 && a[q] < v)) {
r = a[q];
if (x > 0) {
h = q - 1;
} else {
l = q + 1;
}
} else if (x > 0) {
l = q + 1;
} else {
h = q - 1;
}
}
return r;
}
function v(x) {
var y;
if (u === "+") {
return n(x, 1);
}
if (u === "-") {
return n(x, -1);
}
y = parseFloat(u);
if (isNaN(y)) {
throw new Error("Unexpected value: " + u);
}
return y;
}
function s(tr, o, id, val) {
var ad = new ActionDescriptor();
var ar = new ActionReference();
ar.putClass(tr);
ad.putReference(inull, ar);
o.putUnitDouble(id, iu, val);
ad.putObject(iT, iO, o);
executeAction(iS, ad, DialogModes.NO);
}
try {
var ar = new ActionReference();
var g;
var o;
var tr;
var id;
var x;
ar.putProperty(iP, iTool);
ar.putEnumerated(iC, iO, iG);
g = executeActionGet(ar);
o = g.getObjectValue(stringIDToTypeID("currentToolOptions"));
tr = g.getEnumerationType(iTool);
id = (t === "dodgeTool" || t === "burnInTool") ? iE : stringIDToTypeID(k);
x = o.getUnitDoubleValue(id);
s(tr, o, id, v(x));
} catch (e) {
$.writeln("Error: " + e.message);
}
}
#target photoshop
/*
<javascriptresource>
<name>ブラシサイズを画面上の指定pxに変更</name>
<category>YPresets</category>
</javascriptresource>
SCRIPTMETA-BEGIN
Script-ID=org.iwashi.Photoshop_ResetBrushSize
Version=1
Release-Date=2026-03-23
Meta-URL=https://gist.github.com/Yamonov/fd886cedadccdbde7ca72423f7e86534
Target-App=Photoshop
Description-BEGIN
ブラシサイズをズームレベルに合わせてリセットします。大きすぎる・小さすぎるサイズからショートカットキーで一発で使いやすいサイズにします。
Description-END
SCRIPTMETA-END
*/
(function () {
// 画面上で見えるブラシサイズ(px)
var TARGET_SCREEN_SIZE = 150;
// ブラシ未対応ツールの場合は終了
if (!app.toolSupportsBrushes(app.currentTool)) return;
// ズームレベルを取得し、直径を計算(最大5000pxに制限)
var zoom = getZoomLevel();
var newDiameter = Math.min(5000, Math.round(TARGET_SCREEN_SIZE / (zoom / 100)));
// 計算したサイズを、ブラシの masterDiameter に直接設定
setBrushDiameter(newDiameter);
// ズームレベルを取得
function getZoomLevel() {
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("zoom"));
ref.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var desc = executeActionGet(ref);
return desc.getDouble(stringIDToTypeID("zoom")) * 100;
}
// masterDiameter を直接設定(他のブラシ設定は変更しない)
function setBrushDiameter(diameter) {
var idSet = stringIDToTypeID("set");
var desc = new ActionDescriptor();
var ref = new ActionReference();
var idBrush = stringIDToTypeID("brush");
var idOrdinal = stringIDToTypeID("ordinal");
var idTargetEnum = stringIDToTypeID("targetEnum");
ref.putEnumerated(idBrush, idOrdinal, idTargetEnum);
desc.putReference(stringIDToTypeID("null"), ref);
var brushDesc = new ActionDescriptor();
brushDesc.putUnitDouble(stringIDToTypeID("masterDiameter"), stringIDToTypeID("pixelsUnit"), diameter);
desc.putObject(stringIDToTypeID("to"), idBrush, brushDesc);
executeAction(idSet, desc, DialogModes.NO);
}
})();
#target photoshop
/*
<javascriptresource>
<name>ブラシサイズ変更と初期ブラシに戻す</name>
<category>YPresets</category>
</javascriptresource>
SCRIPTMETA-BEGIN
Script-ID=org.iwashi.Photoshop_ResetBrushSizeType
Version=1
Release-Date=2026-03-23
Meta-URL=https://gist.github.com/Yamonov/fd886cedadccdbde7ca72423f7e86534
Target-App=Photoshop
Description-BEGIN
ブラシをブラシパネルの最初のプリセットにし、ブラシサイズをズームレベルに合わせてリセットします。大きすぎる・小さすぎるサイズからショートカットキーで一発で使いやすいサイズにします。
初期設定の円形ブラシをブラシパネルの最初においてください。
Description-END
SCRIPTMETA-END
*/
(function () {
// 画面上で見えるブラシサイズ(px)
var TARGET_SCREEN_SIZE = 150;
var originalTool = app.currentTool;
// ブラシ未対応ツールの場合は終了
if (!app.toolSupportsBrushes(app.currentTool)) return;
// 最初のブラシプリセットに戻す
selectFirstBrush();
// ズームレベルを取得し、直径を計算(最大5000pxに制限)
var zoom = getZoomLevel();
var newDiameter = Math.min(5000, Math.round(TARGET_SCREEN_SIZE / (zoom / 100)));
// masterDiameter を直接設定(他のブラシ設定は変更しない)
setBrushDiameter(newDiameter);
// --- 関数定義 ---
// ズームレベル取得関数
function getZoomLevel() {
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("zoom"));
ref.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var desc = executeActionGet(ref);
return desc.getDouble(stringIDToTypeID("zoom")) * 100;
}
// masterDiameter を直接設定する関数
function setBrushDiameter(diameter) {
var idSet = stringIDToTypeID("set");
var desc = new ActionDescriptor();
var ref = new ActionReference();
var idBrush = stringIDToTypeID("brush");
var idOrdinal = stringIDToTypeID("ordinal");
var idTargetEnum = stringIDToTypeID("targetEnum");
ref.putEnumerated(idBrush, idOrdinal, idTargetEnum);
desc.putReference(stringIDToTypeID("null"), ref);
var brushDesc = new ActionDescriptor();
brushDesc.putUnitDouble(stringIDToTypeID("masterDiameter"), stringIDToTypeID("pixelsUnit"), diameter);
desc.putObject(stringIDToTypeID("to"), idBrush, brushDesc);
executeAction(idSet, desc, DialogModes.NO);
}
// 最初のブラシプリセットを選択する関数
function selectFirstBrush() {
var ref = new ActionReference();
ref.putIndex(stringIDToTypeID("brush"), 1);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref);
executeAction(stringIDToTypeID("select"), desc, DialogModes.NO);
}
if (app.currentTool !== originalTool) {
app.currentTool = originalTool;
}
})();
SCRIPTMETA-DIST-BEGIN
Script-ID=org.iwashi.Photoshop_ResetBrushSize
Version=1
Release-Date=2026-03-23
Script-ID=org.iwashi.Photoshop_ResetBrushSizeType
Version=1
Release-Date=2026-03-23
Script-ID=org.iwashi.Photoshop_OpacityFlowExposure
Version=1
Release-Date=2026-03-23
Script-ID=org.iwashi.Photoshop_toggle_mask
Version=1
Release-Date=2026-03-23
Script-ID=org.iwashi.Photoshop_ClippingView
Version=1
Release-Date=2026-03-23
Script-ID=org.iwashi.Photoshop_ToggleAllButBottom
Version=1
Release-Date=2026-03-23
Script-ID=org.iwashi.Photoshop_ChangeMaskColor
Version=1
Release-Date=2026-03-23
SCRIPTMETA-DIST-END
/*
<javascriptresource>
<name>マスクトグル表示v3</name>
<category>YPresets</category>
</javascriptresource>
SCRIPTMETA-BEGIN
Script-ID=org.iwashi.Photoshop_toggle_mask
Version=1
Release-Date=2026-03-23
Meta-URL=https://gist.github.com/Yamonov/fd886cedadccdbde7ca72423f7e86534
Target-App=Photoshop
Description-BEGIN
レイヤーマスクやクイックマスクの表示を、実行するたびに
通常表示→オーバーレイ表示→マスクのみ表示
と順に切り替えます。
Description-END
SCRIPTMETA-END
*/
if (app.documents.length) {
main();
}
//実行部分
function main() {
var myDoc = app.activeDocument;
var myCh = myDoc.channels;
var myVisibleCh = getChannel();
var myChID = [];
//モード判別
try {
switch (myDoc.mode) {
case DocumentMode.LAB:
var myMode = 3;
myChID = ['Lght', 'A ', 'B '];
break;
case DocumentMode.GRAYSCALE:
var myMode = 1;
myChID = ['Blck'];
break;
case DocumentMode.RGB:
var myMode = 3;
myChID = ['Rd ', 'Grn ', 'Bl '];
break;
case DocumentMode.CMYK:
var myMode = 4;
myChID = ['Cyn ', 'Mgnt', 'Yllw', 'Blck'];
break;
case DocumentMode.INDEXCOLOR:
var myMode = 1;
myChID = ['RGB '];
break;
case DocumentMode.MULTICHANNEL:
case DocumentMode.BITMAP:
alert('このモードは未対応です');
return;
break;
}
} catch (e) {
return
};
//var myChVis=getVisible ();
//クイックマスクモード
if (myDoc.quickMaskMode) {
if (getVisible()) {
SwHdComponents(myChID, 'Hd ');
} else {
SwHdComponents(myChID, 'Shw ');
};
return;
};
//レイヤーマスクの有無
if (!hasLayerMask()) {
return;
};
//レイヤーマスク表示・非表示
if (myVisibleCh > myMode) {
ShowMask();
return;
};
if (myVisibleCh == myMode && myMode != 1) {
ShowwithMask();
return;
};
if (myMode == 1) {
if (myVisibleCh == 1 && getVisible() == 1) {
ShowwithMask();
} else {
HideMask();
};
} else {
HideMask()
};
} //mainここまで
//コンポーネントチャンネルが表示されているか Buliarca Cristian http://buliarcatools.blog.fc2.com/blog-entry-5.html
function getVisible() {
var map = {}
map[DocumentMode.GRAYSCALE] = charIDToTypeID('Blck');
map[DocumentMode.RGB] = charIDToTypeID('RGB ');
map[DocumentMode.CMYK] = charIDToTypeID('CMYK');
map[DocumentMode.LAB] = charIDToTypeID('Lab ');
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID('Chnl'), charIDToTypeID('Chnl'), map[app.activeDocument.mode]);
var vis = executeActionGet(ref).getInteger(stringIDToTypeID('visible'));
return vis;
}
//コンポーネントチャンネルを表示・非表示
function SwHdComponents(myQMID, mySH) {
var myQMIDLength = myQMID.length;
var myADSwHd = charIDToTypeID(mySH);
var myADDesc = new ActionDescriptor();
var idnull = charIDToTypeID('null');
var myADList = new ActionList();
for (i = 0; i < myQMIDLength; i++) {
var myADRef = new ActionReference();
var idChnl = charIDToTypeID('Chnl');
var idRd = charIDToTypeID(myQMID[i]);
myADRef.putEnumerated(idChnl, idChnl, idRd);
myADList.putReference(myADRef);
}
myADDesc.putList(idnull, myADList);
executeAction(myADSwHd, myADDesc, DialogModes.NO);
}
//マスク非表示
function HideMask() {
var idSlct = charIDToTypeID('slct');
var idNull = charIDToTypeID('null');
var idChnl = charIDToTypeID('Chnl');
var idMsk = charIDToTypeID('Msk ');
var idMkVs = charIDToTypeID('MkVs');
var switchToMaskDescriptor = new ActionDescriptor();
var actionRef = new ActionReference();
actionRef.putEnumerated(idChnl, idChnl, idMsk);
switchToMaskDescriptor.putReference(idNull, actionRef);
switchToMaskDescriptor.putBoolean(idMkVs, false);
executeAction(idSlct, switchToMaskDescriptor, DialogModes.NO);
}
//マスクのみ表示
function ShowMask() {
var idSlct = charIDToTypeID('slct');
var idNull = charIDToTypeID('null');
var idChnl = charIDToTypeID('Chnl');
var idMsk = charIDToTypeID('Msk ');
var idMkVs = charIDToTypeID('MkVs');
var switchToMaskDescriptor = new ActionDescriptor();
var actionRef = new ActionReference();
actionRef.putEnumerated(idChnl, idChnl, idMsk);
switchToMaskDescriptor.putReference(idNull, actionRef);
switchToMaskDescriptor.putBoolean(idMkVs, true);
executeAction(idSlct, switchToMaskDescriptor, DialogModes.NO);
}
//マスクオーバーレイ
function ShowwithMask() {
var idShw = charIDToTypeID('Shw ');
var desc = new ActionDescriptor();
var idnull = charIDToTypeID('null');
var list = new ActionList();
var ref = new ActionReference();
var idChnl = charIDToTypeID('Chnl');
var idMsk = charIDToTypeID('Msk ');
ref.putEnumerated(idChnl, idChnl, idMsk);
list.putReference(ref);
desc.putList(idnull, list);
executeAction(idShw, desc, DialogModes.NO);
}
//レイヤーマスクの有無判定 Paul Riggott https://forums.adobe.com/thread/909630
function hasLayerMask() {
var hasLayerMask = false;
try {
var ref = new ActionReference();
var keyUserMaskEnabled = app.charIDToTypeID('UsrM');
ref.putProperty(app.charIDToTypeID('Prpr'), keyUserMaskEnabled);
ref.putEnumerated(app.charIDToTypeID('Lyr '), app.charIDToTypeID('Ordn'), app.charIDToTypeID('Trgt'));
var desc = executeActionGet(ref);
if (desc.hasKey(keyUserMaskEnabled)) {
hasLayerMask = true;
}
} catch (e) {
hasLayerMask = false;
}
return hasLayerMask;
}
//表示されているチャンネル数取得 Buliarca Cristian http://buliarcatools.blog.fc2.com/blog-entry-5.html
function getChannel() {
var ref = new ActionReference();
var keyVisChannels = app.stringIDToTypeID('visibleChannels');
ref.putEnumerated(app.charIDToTypeID('Lyr '), app.charIDToTypeID('Ordn'), app.charIDToTypeID('Trgt'));
var desc = executeActionGet(ref);
return desc.getList(keyVisChannels).count;
}
/*
<javascriptresource>
<name>最下レイヤー以外の表示トグル</name>
<category>YPresets</category>
</javascriptresource>
SCRIPTMETA-BEGIN
Script-ID=org.iwashi.Photoshop_ToggleAllButBottom
Version=1
Release-Date=2026-03-23
Meta-URL=https://gist.github.com/Yamonov/fd886cedadccdbde7ca72423f7e86534
Target-App=Photoshop
Description-BEGIN
ドキュメントの最下レイヤーまたはレイヤーグループ以外の表示を切り替えます。レイヤーの目玉マークをoption(alt)クリックした動作と同じです。
Description-END
SCRIPTMETA-END
*/
// --- IDs & helpers (hoisted once) ---
var cid = charIDToTypeID;
var ID_SHOW = cid("Shw ");
var ID_NULL = cid("null");
var ID_LAYER = cid("Lyr ");
var ID_BKG = cid("Bckg");
var ID_TOGGLE = cid("TglO");
function bottomLayerOf(doc) {
// レイヤーが無い or 非対応なら null
if (!doc || !doc.layers || doc.layers.length === 0) return null;
return doc.layers[doc.layers.length - 1];
}
function toggleLayerVisibility() {
try {
var doc = app.activeDocument;
var targetLayer = bottomLayerOf(doc);
if (!targetLayer) return; // レイヤー無しなら終了
var ref = new ActionReference();
if (targetLayer.isBackgroundLayer) {
ref.putProperty(ID_LAYER, ID_BKG);
} else {
ref.putIndex(ID_LAYER, targetLayer.itemIndex);
}
var list = new ActionList();
list.putReference(ref);
var desc = new ActionDescriptor();
desc.putList(ID_NULL, list);
desc.putBoolean(ID_TOGGLE, true);
executeAction(ID_SHOW, desc, DialogModes.NO);
} catch (e) {
// no-op(Photoshopの一時状態で失敗する場合に備える)
}
}
toggleLayerVisibility();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment