Files
tools/Mac工具/Yeomai-Toolbox-CEP/jsx/scripts/2.通道工具/RGBA通道工具.jsx
T
2026-08-20 11:58:15 +08:00

1131 lines
35 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#target photoshop
/*
Photoshop RGBA Channel Tools 5.7
使用方法:
1. 在 Photoshop 中打开一个 RGB 文档,并选中目标图层。
2. 选择“文件 > 脚本 > 浏览”,运行本 JSX 文件。
3. 在弹窗中选择需要执行的功能:
- 互换 R、G、B、A 中任意两个通道;
- 把当前图层的 R、G、B 或 A 复制为纯白透明图层。
通道交换:
- R/G/B 沿用 Photoshop 原生“通道混合器”算法;
- 与 A 组合时,输出透明度 = 所选 R/G/B 通道 × 当前图层 A;
- 结果像素为对应通道的纯色,其他通道区域及原透明区域保持透明;
- 只读取运行脚本时选中的图层,A 表示该图层自身透明度;
- 结果是当前文档、当前图层正上方的独立普通像素层;
- 最终结果层禁止使用剪切蒙版;无法确认时中止并删除结果层;
- 不修改原图层,也不建立图层蒙版或链接;
- 计算用的临时文档会自动关闭,不会留下新文档副本。
复制通道:
- 读取当前图层的指定通道;
- R/G/B 的输出透明度 = 对应通道 × 当前图层 A;
- A 的输出透明度 = 当前图层 A;
- 仅在结果非透明区域填充纯白像素;
- 不使用图层蒙版或剪切蒙版,也不链接其他图层;
- 名称为“原图层名称_R/G/B/A”。
窗口:
- “执行”和“取消”都会显式关闭 ScriptUI 对话框;
- 请求系统标题栏显示关闭按钮,并把 Esc 明确绑定到取消;
- 开始图像处理前再次安全释放窗口,避免留下空白窗口残影。
*/
(function () {
var SCRIPT_TITLE = "RGBA 通道工具";
var CHANNEL_LABELS = [
"R(红)",
"G(绿)",
"B(蓝)",
"A(透明度)"
];
var COPY_CHANNEL_LABELS = [
"R(红)",
"G(绿)",
"B(蓝)",
"A(当前图层透明度)"
];
var CHANNEL_NAMES = ["R", "G", "B", "A"];
if (app.documents.length === 0) {
alert("请先打开一个 RGB 图像文档。", SCRIPT_TITLE, true);
return;
}
var doc = app.activeDocument;
if (doc.mode !== DocumentMode.RGB) {
alert(
"当前文档不是 RGB 颜色模式。\n请先转换为 RGB 模式后再运行脚本。",
SCRIPT_TITLE,
true
);
return;
}
var dialog = new Window(
"dialog",
SCRIPT_TITLE,
undefined,
{ closeButton: true }
);
dialog.orientation = "column";
dialog.alignChildren = ["fill", "top"];
dialog.spacing = 12;
dialog.margins = 18;
var operationPanel = dialog.add("panel", undefined, "功能");
operationPanel.orientation = "column";
operationPanel.alignChildren = ["left", "center"];
operationPanel.margins = 14;
var swapRadio = operationPanel.add(
"radiobutton",
undefined,
"互换两个 R/G/B/A 通道(输出到当前文档)"
);
var copyRadio = operationPanel.add(
"radiobutton",
undefined,
"复制指定通道为纯白透明图层"
);
swapRadio.value = true;
var swapPanel = dialog.add("panel", undefined, "互换通道");
swapPanel.orientation = "column";
swapPanel.alignChildren = ["fill", "center"];
swapPanel.spacing = 10;
swapPanel.margins = 14;
var firstRow = swapPanel.add("group");
firstRow.orientation = "row";
firstRow.add("statictext", undefined, "第一个通道:");
var firstDropdown = firstRow.add(
"dropdownlist",
undefined,
CHANNEL_LABELS
);
firstDropdown.preferredSize.width = 180;
firstDropdown.selection = 0;
var secondRow = swapPanel.add("group");
secondRow.orientation = "row";
secondRow.add("statictext", undefined, "与此通道互换:");
var secondDropdown = secondRow.add(
"dropdownlist",
undefined,
CHANNEL_LABELS
);
secondDropdown.preferredSize.width = 180;
secondDropdown.selection = 1;
var modeText = swapPanel.add(
"statictext",
undefined,
"与 A 互换:透明度 = 所选颜色通道 × 当前图层 A。"
);
modeText.alignment = "fill";
var modeText2 = swapPanel.add(
"statictext",
undefined,
"只处理当前选中图层;结果为独立非剪切图层。"
);
modeText2.alignment = "fill";
var copyPanel = dialog.add("panel", undefined, "复制通道");
copyPanel.orientation = "column";
copyPanel.alignChildren = ["fill", "center"];
copyPanel.spacing = 10;
copyPanel.margins = 14;
var copyRow = copyPanel.add("group");
copyRow.orientation = "row";
copyRow.add("statictext", undefined, "要复制的通道:");
var copyDropdown = copyRow.add(
"dropdownlist",
undefined,
COPY_CHANNEL_LABELS
);
copyDropdown.preferredSize.width = 210;
copyDropdown.selection = 0;
var copyHint = copyPanel.add(
"statictext",
undefined,
"R/G/B 会与当前图层 A 相乘;黑色和原透明区域保持透明。"
);
copyHint.alignment = "fill";
var copyHint2 = copyPanel.add(
"statictext",
undefined,
"最终层禁止剪切蒙版;名称:原图层名称_R/G/B/A。"
);
copyHint2.alignment = "fill";
var buttons = dialog.add("group");
buttons.alignment = "right";
var cancelButton = buttons.add(
"button",
undefined,
"取消",
{ name: "cancel" }
);
var executeButton = buttons.add(
"button",
undefined,
"执行",
{ name: "ok" }
);
// 明确声明键盘与系统窗口按钮的默认行为。
dialog.cancelElement = cancelButton;
dialog.defaultElement = executeButton;
dialog.onClose = function () {
return true;
};
swapRadio.onClick = updateOperationUI;
copyRadio.onClick = updateOperationUI;
cancelButton.onClick = function () {
dialog.close(0);
};
executeButton.onClick = function () {
dialog.close(1);
};
updateOperationUI();
dialog.center();
var dialogResult = dialog.show();
if (dialogResult !== 1) {
disposeScriptUIDialog(dialog);
return;
}
function updateOperationUI() {
swapPanel.enabled = swapRadio.value;
copyPanel.enabled = copyRadio.value;
}
function disposeScriptUIDialog(dialogReference) {
if (dialogReference === null || dialogReference === undefined) {
return;
}
try {
dialogReference.hide();
} catch (hideDialogError) {
// 点击标准按钮后窗口通常已关闭;此处只负责兼容残留外壳。
}
try {
dialogReference.close();
} catch (closeDialogError) {
// 已关闭的 ScriptUI 对话框无需重复处理。
}
try {
app.refresh();
} catch (refreshUIError) {
// 某些旧版 Photoshop 没有公开 refresh;关闭窗口本身仍有效。
}
}
var operationIsSwap = swapRadio.value;
var firstIndex = firstDropdown.selection.index;
var secondIndex = secondDropdown.selection.index;
var copyIndex = copyDropdown.selection.index;
// 选项已保存为普通数值;切换文档和处理像素前彻底释放窗口。
disposeScriptUIDialog(dialog);
dialog = null;
if (operationIsSwap && firstIndex === secondIndex) {
alert("请选择两个不同的通道。", SCRIPT_TITLE, true);
return;
}
try {
app.activeDocument = doc;
var resultLayer;
if (operationIsSwap) {
resultLayer = swapChannelsToCurrentDocument(
doc,
firstIndex,
secondIndex
);
alert(
"已交换 " +
CHANNEL_NAMES[firstIndex] +
" 与 " +
CHANNEL_NAMES[secondIndex] +
" 通道,并放入当前文档的新图层:\n" +
resultLayer.name,
SCRIPT_TITLE
);
} else {
resultLayer = copyChannelToWhiteAlphaLayer(doc, copyIndex);
alert(
"已把 " +
CHANNEL_NAMES[copyIndex] +
" 通道写入纯白图层的透明度:\n" +
resultLayer.name,
SCRIPT_TITLE
);
}
} catch (error) {
try {
app.activeDocument = doc;
} catch (activateError) {
// 文档状态异常时保留原始错误信息。
}
var details = error.message;
if (error.number !== undefined) {
details += "\n错误编号:" + error.number;
}
if (error.line !== undefined) {
details += "\n脚本行号:" + error.line;
}
alert(
(operationIsSwap ? "通道交换失败。\n\n" : "通道复制失败。\n\n") +
details +
"\n\n临时文档已自动关闭,当前文档不会留下未完成的新图层。",
SCRIPT_TITLE,
true
);
}
function swapChannelsToCurrentDocument(
sourceDocument,
channelA,
channelB
) {
var anchorLayer = sourceDocument.activeLayer;
var temporaryDocument = null;
var placedLayer = null;
var outputLayer = null;
var outputName =
"交换_" +
CHANNEL_NAMES[channelA] +
"-" +
CHANNEL_NAMES[channelB];
try {
// 只把当前选中图层隔离为临时像素层;源文档及其他图层不参与。
temporaryDocument = createIsolatedLayerDocument(
sourceDocument,
makeTemporaryName("Swap")
);
app.activeDocument = temporaryDocument;
deselectSafely(temporaryDocument);
activateRGBComposite(temporaryDocument);
if (channelA < 3 && channelB < 3) {
// R/G/B 之间继续使用 Photoshop 原生通道混合器算法。
outputLayer = temporaryDocument.activeLayer;
applyRGBSwap(outputLayer, channelA, channelB);
} else {
// 涉及 A 时,仅提取“所选颜色通道 × 原图层 A”。
// 例如 G-A:只有 G × A 的部分显示纯绿色,其余透明。
var sourceLayer = temporaryDocument.activeLayer;
var storedChannels = captureRGBAChannels(
temporaryDocument,
sourceLayer,
"__RGBA_Tools_Swap_"
);
var colorChannelIndex =
channelA === 3 ? channelB : channelA;
var outputTransparencyChannel =
createCopyTransparencyChannel(
temporaryDocument,
storedChannels,
colorChannelIndex
);
outputLayer = createPrimaryColorAlphaLayer(
temporaryDocument,
outputTransparencyChannel,
colorChannelIndex
);
}
outputLayer.name = outputName;
placedLayer = placeStandaloneLayer(
outputLayer,
sourceDocument,
anchorLayer,
outputName
);
return placedLayer;
} catch (swapError) {
removeLayerSafely(placedLayer);
placedLayer = null;
throw swapError;
} finally {
closeDocumentSafely(temporaryDocument);
restoreTargetDocument(
sourceDocument,
placedLayer !== null ? placedLayer : anchorLayer
);
}
}
function copyChannelToWhiteAlphaLayer(documentReference, channelIndex) {
var anchorLayer = documentReference.activeLayer;
var sourceName = anchorLayer.name;
var temporaryDocument = null;
var placedLayer = null;
try {
temporaryDocument = createIsolatedLayerDocument(
documentReference,
makeTemporaryName("Copy")
);
app.activeDocument = temporaryDocument;
var sourcePixelLayer = temporaryDocument.activeLayer;
var storedChannels = captureRGBAChannels(
temporaryDocument,
sourcePixelLayer,
"__RGBA_Tools_Copy_"
);
var outputName = sourceName + "_" + CHANNEL_NAMES[channelIndex];
var outputTransparencyChannel = createCopyTransparencyChannel(
temporaryDocument,
storedChannels,
channelIndex
);
var outputLayer = createWhiteAlphaLayer(
temporaryDocument,
outputTransparencyChannel
);
outputLayer.name = outputName;
placedLayer = placeStandaloneLayer(
outputLayer,
documentReference,
anchorLayer,
outputName
);
return placedLayer;
} catch (copyError) {
removeLayerSafely(placedLayer);
placedLayer = null;
throw copyError;
} finally {
closeDocumentSafely(temporaryDocument);
restoreTargetDocument(
documentReference,
placedLayer !== null ? placedLayer : anchorLayer
);
}
}
function applyRGBSwap(pixelLayer, channelA, channelB) {
// 每一行表示输出 R、G、B 从输入 R、G、B 获取的百分比;
// 第四个数值是常数,交换通道时保持为 0。
var matrix = [
[100, 0, 0, 0],
[0, 100, 0, 0],
[0, 0, 100, 0]
];
var temporaryRow = matrix[channelA];
matrix[channelA] = matrix[channelB];
matrix[channelB] = temporaryRow;
pixelLayer.mixChannels(matrix, false);
}
function createIsolatedLayerDocument(sourceDocument, temporaryName) {
var temporaryDocument = sourceDocument.duplicate(temporaryName, false);
try {
app.activeDocument = temporaryDocument;
deselectSafely(temporaryDocument);
activateRGBComposite(temporaryDocument);
// 整个文档副本只用来保持尺寸、位深和颜色配置一致。
// 把镜像的当前图层复制进临时组并合并,可得到独立普通像素层。
var mirroredSourceLayer = temporaryDocument.activeLayer;
var wrapperGroup = temporaryDocument.layerSets.add();
wrapperGroup.name = "__RGBA_Tools_Isolate__";
wrapperGroup.visible = true;
wrapperGroup.opacity = 100;
wrapperGroup.blendMode = BlendMode.NORMAL;
var isolatedCopy = mirroredSourceLayer.duplicate();
prepareLayerForIsolation(isolatedCopy);
isolatedCopy.move(wrapperGroup, ElementPlacement.INSIDE);
temporaryDocument.activeLayer = wrapperGroup;
var pixelLayer = wrapperGroup.merge();
pixelLayer.name = "__RGBA_Tools_Source__";
// 合并结果位于最上方;移除其余镜像图层,只保留当前图层内容。
while (temporaryDocument.layers.length > 1) {
var lowerLayer = temporaryDocument.layers[
temporaryDocument.layers.length - 1
];
unlockLayerSafely(lowerLayer);
lowerLayer.remove();
}
prepareStandaloneArtLayer(pixelLayer);
temporaryDocument.activeLayer = pixelLayer;
activateRGBComposite(temporaryDocument);
return temporaryDocument;
} catch (isolateError) {
closeDocumentSafely(temporaryDocument);
throw isolateError;
}
}
function prepareLayerForIsolation(layerReference) {
unlockLayerSafely(layerReference);
layerReference.visible = true;
layerReference.opacity = 100;
try {
layerReference.blendMode = BlendMode.NORMAL;
} catch (blendModeError) {
// 合并临时组时仍会转换为普通像素层。
}
enforceNoClippingMask(layerReference);
}
function captureRGBAChannels(
documentReference,
sourceLayer,
channelNamePrefix
) {
var componentChannels = [
documentReference.channels[0],
documentReference.channels[1],
documentReference.channels[2]
];
var storedChannels = [];
var componentIndex;
for (componentIndex = 0; componentIndex < 3; componentIndex++) {
deselectSafely(documentReference);
activateRGBComposite(documentReference);
loadChannelSelectionSafely(
documentReference,
componentChannels[componentIndex]
);
storedChannels[componentIndex] = storeSelectionAsAlphaChannel(
documentReference,
channelNamePrefix + CHANNEL_NAMES[componentIndex]
);
}
deselectSafely(documentReference);
activateRGBComposite(documentReference);
documentReference.activeLayer = sourceLayer;
try {
loadActiveLayerTransparency();
} catch (emptyTransparencyError) {
// 完全透明图层可能报告“没有选中像素”,按空 A 通道处理。
deselectSafely(documentReference);
}
storedChannels[3] = storeSelectionAsAlphaChannel(
documentReference,
channelNamePrefix + "A"
);
deselectSafely(documentReference);
activateRGBComposite(documentReference);
documentReference.activeLayer = sourceLayer;
return storedChannels;
}
function storeSelectionAsAlphaChannel(documentReference, channelName) {
var storageChannel = documentReference.channels.add();
storageChannel.name = channelName;
try {
// 没有选区时 Photoshop 可能抛错;新建通道保持全黑即可。
documentReference.selection.store(
storageChannel,
SelectionType.REPLACE
);
} catch (emptySelectionError) {
deselectSafely(documentReference);
}
activateRGBComposite(documentReference);
return storageChannel;
}
function createCopyTransparencyChannel(
documentReference,
storedChannels,
channelIndex
) {
// 复制 A 时直接使用当前图层自身透明度。
if (channelIndex === 3) {
return storedChannels[3];
}
var colorChannel = storedChannels[channelIndex];
var alphaChannel = storedChannels[3];
var colorRange = inspectChannelRange(colorChannel);
var alphaRange = inspectChannelRange(alphaChannel);
var resultName =
"__RGBA_Tools_Copy_" +
CHANNEL_NAMES[channelIndex] +
"_x_A";
deselectSafely(documentReference);
activateRGBComposite(documentReference);
// 任一输入全黑,乘积必定全黑;直接建立空通道。
if (
(colorRange.known && colorRange.allBlack) ||
(alphaRange.known && alphaRange.allBlack)
) {
return storeSelectionAsAlphaChannel(
documentReference,
resultName
);
}
try {
if (colorRange.known && colorRange.allWhite) {
// 255 × A = A。
documentReference.selection.load(
alphaChannel,
SelectionType.REPLACE
);
} else if (alphaRange.known && alphaRange.allWhite) {
// 通道 × 255 = 通道。
documentReference.selection.load(
colorChannel,
SelectionType.REPLACE
);
} else {
documentReference.selection.load(
colorChannel,
SelectionType.REPLACE
);
// Photoshop 对灰度选区执行“交叉”,得到逐像素乘积:
// 输出 Alpha = 颜色通道 × 当前图层 Alpha。
documentReference.selection.load(
alphaChannel,
SelectionType.INTERSECT
);
}
} catch (intersectError) {
throw new Error(
"无法计算 " +
CHANNEL_NAMES[channelIndex] +
" 通道与当前图层透明度的交集:" +
intersectError.message
);
}
return storeSelectionAsAlphaChannel(
documentReference,
resultName
);
}
function buildLayerFromRGBAChannels(
documentReference,
storedChannels,
mapping
) {
var outputLayer = documentReference.artLayers.add();
prepareStandaloneArtLayer(outputLayer);
documentReference.activeLayer = outputLayer;
activateRGBComposite(documentReference);
// 先得到不透明黑底,再逐一写入三个颜色通道。
fillEntireLayer(documentReference, makeGrayColor(0));
var componentChannels = [
documentReference.channels[0],
documentReference.channels[1],
documentReference.channels[2]
];
var outputIndex;
for (outputIndex = 0; outputIndex < 3; outputIndex++) {
writeStoredChannelToComponent(
documentReference,
outputLayer,
componentChannels[outputIndex],
storedChannels[mapping[outputIndex]]
);
}
writeStoredChannelToLayerTransparency(
documentReference,
outputLayer,
storedChannels[mapping[3]]
);
prepareStandaloneArtLayer(outputLayer);
documentReference.activeLayer = outputLayer;
activateRGBComposite(documentReference);
deselectSafely(documentReference);
return outputLayer;
}
function writeStoredChannelToComponent(
documentReference,
outputLayer,
targetComponentChannel,
sourceStorageChannel
) {
var range = inspectChannelRange(sourceStorageChannel);
documentReference.activeLayer = outputLayer;
activateRGBComposite(documentReference);
deselectSafely(documentReference);
if (range.known && range.allBlack) {
return;
}
documentReference.activeChannels = [targetComponentChannel];
if (range.known && range.allWhite) {
documentReference.selection.selectAll();
} else {
activateRGBComposite(documentReference);
loadChannelSelectionSafely(
documentReference,
sourceStorageChannel
);
documentReference.activeChannels = [targetComponentChannel];
if (!range.known && !hasSelection(documentReference)) {
activateRGBComposite(documentReference);
deselectSafely(documentReference);
return;
}
}
documentReference.selection.fill(
makeGrayColor(255),
ColorBlendMode.NORMAL,
100,
false
);
deselectSafely(documentReference);
activateRGBComposite(documentReference);
}
function writeStoredChannelToLayerTransparency(
documentReference,
outputLayer,
sourceStorageChannel
) {
var range = inspectChannelRange(sourceStorageChannel);
documentReference.activeLayer = outputLayer;
activateRGBComposite(documentReference);
deselectSafely(documentReference);
if (range.known && range.allWhite) {
return;
}
if (range.known && range.allBlack) {
documentReference.selection.selectAll();
documentReference.selection.clear();
deselectSafely(documentReference);
return;
}
loadChannelSelectionSafely(documentReference, sourceStorageChannel);
if (!range.known && !hasSelection(documentReference)) {
documentReference.selection.selectAll();
documentReference.selection.clear();
deselectSafely(documentReference);
return;
}
documentReference.selection.invert();
if (range.known || hasSelection(documentReference)) {
documentReference.selection.clear();
}
deselectSafely(documentReference);
}
function createWhiteAlphaLayer(
documentReference,
sourceStorageChannel
) {
return createSolidColorAlphaLayer(
documentReference,
sourceStorageChannel,
makeGrayColor(255)
);
}
function createPrimaryColorAlphaLayer(
documentReference,
sourceStorageChannel,
colorChannelIndex
) {
return createSolidColorAlphaLayer(
documentReference,
sourceStorageChannel,
makePrimaryColor(colorChannelIndex)
);
}
function createSolidColorAlphaLayer(
documentReference,
sourceStorageChannel,
fillColor
) {
var outputLayer = documentReference.artLayers.add();
prepareStandaloneArtLayer(outputLayer);
documentReference.activeLayer = outputLayer;
activateRGBComposite(documentReference);
deselectSafely(documentReference);
var range = inspectChannelRange(sourceStorageChannel);
// 全黑结果保持为空图层:没有任何可见像素。
if (range.known && range.allBlack) {
return outputLayer;
}
if (range.known && range.allWhite) {
documentReference.selection.selectAll();
} else {
loadChannelSelectionSafely(
documentReference,
sourceStorageChannel
);
if (!range.known && !hasSelection(documentReference)) {
deselectSafely(documentReference);
return outputLayer;
}
}
// 从透明空层开始,使用来源通道的灰度作为输出透明度;
// 非透明像素只写入指定纯色,不创建蒙版或剪切关系。
documentReference.selection.fill(
fillColor,
ColorBlendMode.NORMAL,
100,
false
);
prepareStandaloneArtLayer(outputLayer);
documentReference.activeLayer = outputLayer;
deselectSafely(documentReference);
activateRGBComposite(documentReference);
return outputLayer;
}
function inspectChannelRange(channelReference) {
var result = {
known: false,
allBlack: false,
allWhite: false
};
try {
var histogram = channelReference.histogram;
if (histogram === undefined || histogram.length < 2) {
return result;
}
var hasNonBlackPixels = false;
var hasNonWhitePixels = false;
var lastIndex = histogram.length - 1;
var index;
for (index = 0; index < histogram.length; index++) {
if (histogram[index] > 0) {
if (index > 0) {
hasNonBlackPixels = true;
}
if (index < lastIndex) {
hasNonWhitePixels = true;
}
}
}
result.known = true;
result.allBlack = !hasNonBlackPixels;
result.allWhite = !hasNonWhitePixels;
} catch (histogramError) {
// 极少数旧版本无法读取 Alpha 直方图时,后续回退到选区检测。
}
return result;
}
function loadChannelSelectionSafely(
documentReference,
channelReference
) {
deselectSafely(documentReference);
activateRGBComposite(documentReference);
try {
documentReference.selection.load(
channelReference,
SelectionType.REPLACE
);
} catch (loadSelectionError) {
deselectSafely(documentReference);
}
}
function placeStandaloneLayer(
sourceLayer,
targetDocument,
anchorLayer,
layerName
) {
var placedLayer = null;
try {
placedLayer = sourceLayer.duplicate(targetDocument);
app.activeDocument = targetDocument;
placedLayer.move(anchorLayer, ElementPlacement.PLACEBEFORE);
prepareStandaloneArtLayer(placedLayer);
placedLayer.name = layerName;
enforceNoClippingMask(placedLayer);
targetDocument.activeLayer = placedLayer;
activateRGBComposite(targetDocument);
return placedLayer;
} catch (placeError) {
removeLayerSafely(placedLayer);
throw placeError;
}
}
function prepareStandaloneArtLayer(layerReference) {
unlockLayerSafely(layerReference);
layerReference.visible = true;
layerReference.opacity = 100;
try {
layerReference.fillOpacity = 100;
} catch (fillOpacityError) {
// 某些旧版本或图层类型没有 fillOpacity。
}
try {
layerReference.blendMode = BlendMode.NORMAL;
} catch (blendModeError) {
// 输出层最终为 ArtLayer;保留此兼容保护。
}
enforceNoClippingMask(layerReference);
}
function enforceNoClippingMask(layerReference) {
if (layerReference.typename !== "ArtLayer") {
return;
}
var isClippingLayer;
try {
// 对 grouped 已为 false 的普通图层再次赋值,在部分 Photoshop
// 版本中会触发“释放剪贴蒙版当前不可用”。必须先判断再执行。
isClippingLayer = layerReference.grouped;
} catch (readClippingError) {
throw new Error(
"无法确认结果图层是否为剪切蒙版,已取消生成。"
);
}
if (isClippingLayer === true) {
try {
layerReference.grouped = false;
} catch (releaseClippingError) {
throw new Error(
"无法解除结果图层的剪切蒙版,已取消生成。"
);
}
}
try {
isClippingLayer = layerReference.grouped;
} catch (verifyClippingError) {
throw new Error(
"无法验证结果图层的剪切状态,已取消生成。"
);
}
if (isClippingLayer === true) {
throw new Error(
"结果图层仍处于剪切蒙版状态,已取消生成。"
);
}
}
function unlockLayerSafely(layerReference) {
if (layerReference === null || layerReference === undefined) {
return;
}
try {
layerReference.allLocked = false;
} catch (allLockedError) {
// 继续尝试解除各项锁定。
}
try {
layerReference.pixelsLocked = false;
} catch (pixelsLockedError) {
// 图层组没有此属性。
}
try {
layerReference.positionLocked = false;
} catch (positionLockedError) {
// 旧版本可能不支持。
}
try {
layerReference.transparentPixelsLocked = false;
} catch (transparentPixelsLockedError) {
// 图层组没有此属性。
}
}
function activateRGBComposite(documentReference) {
documentReference.activeChannels = [
documentReference.channels[0],
documentReference.channels[1],
documentReference.channels[2]
];
}
function loadActiveLayerTransparency() {
var descriptor = new ActionDescriptor();
var selectionReference = new ActionReference();
selectionReference.putProperty(
charIDToTypeID("Chnl"),
charIDToTypeID("fsel")
);
descriptor.putReference(
charIDToTypeID("null"),
selectionReference
);
var transparencyReference = new ActionReference();
transparencyReference.putEnumerated(
charIDToTypeID("Chnl"),
charIDToTypeID("Chnl"),
charIDToTypeID("Trsp")
);
descriptor.putReference(
charIDToTypeID("T "),
transparencyReference
);
executeAction(
charIDToTypeID("setd"),
descriptor,
DialogModes.NO
);
}
function hasSelection(documentReference) {
try {
var bounds = documentReference.selection.bounds;
return bounds !== undefined && bounds !== null;
} catch (selectionError) {
return false;
}
}
function deselectSafely(documentReference) {
try {
documentReference.selection.deselect();
} catch (deselectError) {
// 没有选区时无需处理。
}
}
function fillEntireLayer(documentReference, color) {
documentReference.selection.selectAll();
documentReference.selection.fill(
color,
ColorBlendMode.NORMAL,
100,
false
);
deselectSafely(documentReference);
}
function makeGrayColor(value) {
var color = new SolidColor();
color.rgb.red = value;
color.rgb.green = value;
color.rgb.blue = value;
return color;
}
function makePrimaryColor(channelIndex) {
var color = new SolidColor();
color.rgb.red = channelIndex === 0 ? 255 : 0;
color.rgb.green = channelIndex === 1 ? 255 : 0;
color.rgb.blue = channelIndex === 2 ? 255 : 0;
return color;
}
function makeTemporaryName(operationName) {
return "__RGBA_Tools_" + operationName + "_" + new Date().getTime();
}
function restoreTargetDocument(documentReference, activeLayerReference) {
try {
app.activeDocument = documentReference;
activateRGBComposite(documentReference);
if (
activeLayerReference !== null &&
activeLayerReference !== undefined
) {
documentReference.activeLayer = activeLayerReference;
}
} catch (restoreError) {
// 清理阶段不覆盖原始结果或错误。
}
}
function closeDocumentSafely(documentReference) {
if (documentReference !== null && documentReference !== undefined) {
try {
documentReference.close(SaveOptions.DONOTSAVECHANGES);
} catch (closeError) {
// 清理阶段不覆盖原始结果或错误。
}
}
}
function removeLayerSafely(layerReference) {
if (layerReference !== null && layerReference !== undefined) {
try {
layerReference.remove();
} catch (removeLayerError) {
// 清理阶段不覆盖原始结果或错误。
}
}
}
})();