PS是一款栅格图像编辑软件,模块众多。提供了脚本,动态连接库等多种扩展机制,本文演示如何通过脚本实现增加细节相关功能,展示从互联网收集而来的一个小插件,供大家学习交流,请勿用于商业用途。
1.插件界面本文界面是一系列功能的一部分,将逐步展示,但是功能界面是共同的,如下图所示:
2.关键代码-增加细节大家可通过源代码阅读,来掌握相关技巧,源代码如下:
// jamEngine.jsxinc v4.4 (minified)
if (typeof jamEngine !== 'object') {
var jamEngine = {};
(function () {
var that;
jamEngine.meaningfulIds = false;
jamEngine.parseFriendly = false;
var conflictingStringIdStrs = {
"'Algn'": ["align", "alignment"],
"'AntA'": ["antiAlias", "antiAliasedPICTAcquire"],
"'BckL'": ["backgroundLayer", "backgroundLevel"],
"'BlcG'": ["blackGenerationType", "blackGenerationCurve"],
"'BlcL'": ["blackLevel", "blackLimit"],
"'Blks'": ["blacks", "blocks"],
"'BlrM'": ["blurMethod", "blurMore"],
"'BrgC'": ["brightnessEvent", "brightnessContrast"],
"'BrsD'": ["brushDetail", "brushesDefine"],
"'Brsh'": ["brush", "brushes"],
"'Clcl'": ["calculation", "calculations"],
"'ClrP'": ["colorPalette", "coloredPencil"],
"'Cnst'": ["constant", "constrain"],
"'CntC'": ["centerCropMarks", "conteCrayon"],
"'Cntr'": ["center", "contrast"],
"'CrtD'": ["createDroplet", "createDuplicate"],
"'CstP'": ["customPalette", "customPhosphors"],
"'Cstm'": ["custom", "customPattern"],
"'Drkn'": ["darken", "darkness"],
"'Dstr'": ["distort", "distortion", "distribute", "distribution"],
"'Dstt'": ["desaturate", "destWhiteMax"],
"'FlIn'": ["FileInfo", "fillInverse"],
"'Gd '": ["good", "guide"],
"'GnrP'": ["generalPreferences", "generalPrefs", "preferencesClass"],
"'GrSt'": ["grainStippled", "graySetup"],
"'Grdn'": ["gradientClassEvent", "gridMinor"],
"'Grn '": ["grain", "green"],
"'Grns'": ["graininess", "greens"],
"'HstP'": ["historyPreferences", "historyPrefs"],
"'HstS'": ["historyState", "historyStateSourceType"],
"'ImgP'": ["imageCachePreferences", "imagePoint"],
"'In '": ["in", "stampIn"],
"'IntW'": ["interfaceWhite", "intersectWith"],
"'Intr'": ["interfaceIconFrameDimmed", "interlace", "interpolation", "intersect"],
"'JPEG'": ["JPEG", "JPEGFormat"],
"'LghD'": ["lightDirection", "lightDirectional"],
"'LghO'": ["lightOmni", "lightenOnly"],
"'LghS'": ["lightSource", "lightSpot"],
"'Lns '": ["lens", "lines"],
"'Mgnt'": ["magenta", "magentas"],
"'MrgL'": ["mergeLayers", "mergedLayers"],
"'Mxm '": ["maximum", "maximumQuality"],
"'NTSC'": ["NTSC", "NTSCColors"],
"'NmbL'": ["numberOfLayers", "numberOfLevels"],
"'PlgP'": ["pluginPicker", "pluginPrefs"],
"'Pncl'": ["pencilEraser", "pencilWidth"],
"'Pnt '": ["paint", "point"],
"'Prsp'": ["perspective", "perspectiveIndex"],
"'PrvM'": ["previewMacThumbnail", "previewMagenta"],
"'Pstr'": ["posterization", "posterize"],
"'RGBS'": ["RGBSetup", "RGBSetupSource"],
"'Rds '": ["radius", "reds"],
"'ScrD'": ["scratchDisks", "screenDot"],
"'ShdI'": ["shadingIntensity", "shadowIntensity"],
"'ShpC'": ["shapeCurveType", "shapingCurve"],
"'ShrE'": ["sharpenEdges", "shearEd"],
"'Shrp'": ["sharpen", "sharpness"],
"'SplC'": ["splitChannels", "supplementalCategories"],
"'Spot'": ["spot", "spotColor"],
"'SprS'": ["separationSetup", "sprayedStrokes"],
"'StrL'": ["strokeLength", "strokeLocation"],
"'Strt'": ["saturation", "start"],
"'TEXT'": ["char", "textType"],
"'TIFF'": ["TIFF", "TIFFFormat"],
"'TglO'": ["toggleOptionsPalette", "toggleOthers"],
"'TrnG'": ["transparencyGamutPreferences", "transparencyGrid", "transparencyGridSize"],
"'TrnS'": ["transferSpec", "transparencyShape", "transparencyStop"],
"'Trns'": ["transparency", "transparent"],
"'TxtC'": ["textClickPoint", "textureCoverage"],
"'TxtF'": ["textureFile", "textureFill"],
"'UsrM'": ["userMaskEnabled", "userMaskOptions"],
"'c@#^'": ["inherits", "pInherits"],
"'comp'": ["comp", "sInt64"],
"'doub'": ["floatType", "IEEE64BitFloatingPoint", "longFloat"],
"'long'": ["integer", "longInteger", "sInt32"],
"'magn'": ["magnitude", "uInt32"],
"'null'": ["null", "target"],
"'shor'": ["sInt16", "sMInt", "shortInteger"],
"'sing'": ["IEEE32BitFloatingPoint", "sMFloat", "shortFloat"]
};
jamEngine.getConflictingStringIdStrs = function (charIdStr) {
return conflictingStringIdStrs[charIdStr] || null;
};
jamEngine.uniIdStrToId = function (uniIdStr) {
var id = 0;
if (typeof uniIdStr === 'string') {
if ((uniIdStr.length === (1 4 1)) && (uniIdStr.charAt(0) === "'") && (uniIdStr.charAt(5) === "'")) {
id = app.charIDToTypeID(uniIdStr.substring(1, 5));
} else {
id = app.stringIDToTypeID(uniIdStr);
}
}
return id;
};
var smallestHashValue = app.charIDToTypeID(" ");
jamEngine.idToUniIdStrs = function (id) {
var charIdStr = "";
var stringIdStr = app.typeIDToStringID(id);
if (id >= smallestHashValue) {
charIdStr = "'" app.typeIDToCharID(id) "'";
if (stringIdStr !== "") {
if (charIdStr in conflictingStringIdStrs) {
stringIdStr = conflictingStringIdStrs[charIdStr];
}
}
}
return [charIdStr, stringIdStr];
};
jamEngine.equivalentUniIdStrs = function (uniIdStr1, uniIdStr2) {
return this.uniIdStrToId(uniIdStr1) === this.uniIdStrToId(uniIdStr2);
};
function putInReference(ref, containers) {
if (containers.constructor === Array) {
var count = containers.length;
for (var i = 0; i < count; i ) {
var container = that.parseCompact(containers[i]);
var desiredClassId = that.uniIdStrToId(container[0]);
var typedValue = that.parseCompact(container[1]);
var form = typedValue[0];
var value = typedValue[1];
switch (form) {
case"<class>":
ref.putClass(desiredClassId);
break;
case"<enumerated>":
var enumerated = that.parseCompact(value);
ref.putEnumerated(desiredClassId, that.uniIdStrToId(enumerated[0]), that.uniIdStrToId(enumerated[1]));
break;
case"<identifier>":
ref.putIdentifier(desiredClassId, value);
break;
case"<index>":
ref.putIndex(desiredClassId, value);
break;
case"<name>":
ref.putName(desiredClassId, value);
break;
case"<offset>":
ref.putOffset(desiredClassId, value);
break;
case"<property>":
ref.putProperty(desiredClassId, that.uniIdStrToId(value));
break;
default:
throw new Error("[jamEngine putInReference] Unknown reference form: " form);
break;
}
}
} else {
throw new Error("[jamEngine putInReference] JavaScript array expected");
}
}
function putInList(list, items) {
if (items.constructor === Array) {
var count = items.length;
for (var i = 0; i < count; i ) {
var item = that.parseCompact(items[i]);
var type = item[0];
var value = item[1];
switch (type) {
case"<Boolean>":
list.putBoolean(value);
break;
case"<class>":
list.putClass(that.uniIdStrToId(value));
break;
case"<data>":
list.putData(value);
break;
case"<double>":
list.putDouble(value);
break;
case"<enumerated>":
var enumerated = that.parseCompact(value);
list.putEnumerated(that.uniIdStrToId(enumerated[0]), that.uniIdStrToId(enumerated[1]));
break;
case"<integer>":
list.putInteger(value);
break;
case"<largeInteger>":
list.putLargeInteger(value);
break;
case"<list>":
var actionList = new ActionList();
putInList(actionList, value);
list.putList(actionList);
break;
case"<object>":
var object = that.parseCompact(value);
if (object[1]) {
var actionDescriptor = new ActionDescriptor();
putInDescriptor(actionDescriptor, object[1]);
list.putObject(that.uniIdStrToId(object[0]), actionDescriptor);
} else {
list.putClass(that.uniIdStrToId(object[0]));
}
break;
case"<path>":
var fileRef = new File(value);
list.putPath(fileRef);
break;
case"<reference>":
var actionReference = new ActionReference();
putInReference(actionReference, value);
list.putReference(actionReference);
break;
case"<string>":
list.putString(value);
break;
case"<unitDouble>":
var unitDouble = that.parseCompact(value);
list.putUnitDouble(that.uniIdStrToId(unitDouble[0]), unitDouble[1]);
break;
default:
throw new Error("[jamEngine putInList] Unknown list type: " type);
break;
}
}
} else {
throw new Error("[jamEngine putInList] JavaScript array expected");
}
}
function putInDescriptor(desc, members) {
if (members.constructor === Object) {
for (var key in members) {
if (members.hasOwnProperty(key)) {
var keyID = that.uniIdStrToId(key);
var member = that.parseCompact(members[key]);
var type = member[0];
var value = member[1];
switch (type) {
case"<boolean>":
desc.putBoolean(keyID, value);
break;
case"<class>":
desc.putClass(keyID, that.uniIdStrToId(value));
break;
case"<data>":
desc.putData(keyID, value);
break;
case"<double>":
desc.putDouble(keyID, value);
break;
case"<enumerated>":
var enumerated = that.parseCompact(value);
desc.putEnumerated(keyID, that.uniIdStrToId(enumerated[0]), that.uniIdStrToId(enumerated[1]));
break;
case"<integer>":
desc.putInteger(keyID, value);
break;
case"<largeInteger>":
desc.putLargeInteger(keyID, value);
break;
case"<list>":
var actionList = new ActionList();
putInList(actionList, value);
desc.putList(keyID, actionList);
break;
case"<object>":
var object = that.parseCompact(value);
if (object[1]) {
var actionDescriptor = new ActionDescriptor();
putInDescriptor(actionDescriptor, object[1]);
desc.putObject(keyID, that.uniIdStrToId(object[0]), actionDescriptor);
} else {
desc.putClass(keyID, that.uniIdStrToId(object[0]));
}
break;
case"<path>":
var fileRef = new File(value);
desc.putPath(keyID, fileRef);
break;
case"<reference>":
var actionReference = new ActionReference();
putInReference(actionReference, value);
desc.putReference(keyID, actionReference);
break;
case"<string>":
desc.putString(keyID, value);
break;
case"<unitDouble>":
var unitDouble = that.parseCompact(value);
desc.putUnitDouble(keyID, that.uniIdStrToId(unitDouble[0]), unitDouble[1]);
break;
default:
throw new Error("[jamEngine putInDescriptor] Unknown descriptor type: " type);
break;
}
}
}
} else {
throw new Error("[jamEngine putInDescriptor] JavaScript object expected");
}
}
var contextRules = {
"'Algn'": {
"<classKey>": {
"bevelEmboss": "align",
"frameFX": "align",
"gradientFill": "align",
"gradientLayer": "align",
"patternFill": "align",
"patternLayer": "align"
}, "<event>": "align", "<key>": "alignment"
},
"'AntA'": {"<class>": "antiAliasedPICTAcquire", "<key>": "antiAlias"},
"'BckL'": {"<class>": "backgroundLayer", "<key>": "backgroundLevel"},
"'BlcG'": {"<enumType>": "blackGenerationType", "<key>": "blackGenerationCurve"},
"'BlcL'": {
"<classKey>": {"'GEfc'": "blackLevel", "CMYKSetup": "blackLimit"},
"<eventKey>": {"reticulation": "blackLevel"}
},
"'Blks'": {"<typeValue>": {"colors": "blacks", "extrudeType": "blocks"}},
"'BlrM'": {"<enumType>": "blurMethod", "<event>": "blurMore", "<key>": "blurMethod"},
"'BrgC'": {"<class>": "brightnessContrast", "<event>": "brightnessContrast"},
"'BrsD'": {"<enumValue>": "brushesDefine", "<key>": "brushDetail"},
"'Brsh'": {"<class>": "brush", "<key>": "brushes"},
"'Clcl'": {"<class>": "calculation", "<enumValue>": "calculations", "<key>": "calculation"},
"'ClrP'": {
"<typeValue>": {"'GEft'": "coloredPencil"},
"<enumType>": "colorPalette",
"<event>": "coloredPencil"
},
"'Cnst'": {"<classKey>": {"channelMatrix": "constant"}, "<unknown>": "constrain"},
"'CntC'": {"<typeValue>": {"'GEft'": "conteCrayon"}, "<event>": "conteCrayon", "<key>": "centerCropMarks"},
"'Cntr'": {
"<classKey>": {
"'GEfc'": "contrast",
"brightnessContrast": "contrast",
"document": "center",
"polygon": "center",
"quadrilateral": "center"
},
"<eventKey>": {
"adaptCorrect": "contrast",
"brightnessEvent": "contrast",
"grain": "contrast",
"halftoneScreen": "contrast",
"sumie": "contrast",
"tornEdges": "contrast",
"waterPaper": "contrast"
},
"<enumValue>": "center"
},
"'CrtD'": {"<enumValue>": "createDuplicate", "<event>": "createDroplet"},
"'CstP'": {"<class>": "customPhosphors", "<key>": "customPalette"},
"'Cstm'": {"<enumValue>": "customPattern", "<event>": "custom", "<key>": "custom"},
"'Drkn'": {"<enumValue>": "darken", "<key>": "darkness"},
"'Dstr'": {
"<classKey>": {"'GEfc'": "distortion"},
"<eventKey>": {"glass": "distortion", "addNoise": "distribution"},
"<enumType>": "distribution",
"<enumValue>": "distort",
"<event>": "distribute"
},
"'Dstt'": {"<enumValue>": "desaturate", "<event>": "desaturate", "<key>": "destWhiteMax"},
"'FlIn'": {
"<typeValue>": {"fillColor": "fillInverse", "menuItemType": "fileInfo"},
"<class>": "fileInfo",
"<key>": "fileInfo"
},
"'Gd '": {"<class>": "guide", "<enumValue>": "good"},
"'GnrP'": {"<class>": "preferencesClass", "<enumValue>": "generalPreferences", "<key>": "generalPrefs"},
"'GrSt'": {"<class>": "graySetup", "<enumValue>": "grainStippled", "<key>": "graySetup"},
"'Grdn'": {"<class>": "gradientClassEvent", "<event>": "gradientClassEvent", "<key>": "gridMinor"},
"'Grn '": {
"<typeValue>": {"'GEft'": "grain"},
"<classKey>": {
"'GEfc'": "grain",
"RGBColor": "green",
"blackAndWhite": "green",
"channelMatrix": "green",
"channelMixer": "green"
},
"<eventKey>": {"blackAndWhite": "green", "channelMixer": "green", "filmGrain": "grain"},
"<enumValue>": "green",
"<event>": "grain"
},
"'Grns'": {"<enumValue>": "greens", "<key>": "graininess"},
"'HstP'": {"<enumValue>": "historyPreferences", "<key>": "historyPrefs"},
"'HstS'": {"<class>": "historyState", "<enumType>": "historyStateSourceType"},
"'ImgP'": {"<class>": "imagePoint", "<enumValue>": "imageCachePreferences"},
"'In '": {"<enumValue>": "stampIn", "<key>": "in"},
"'IntW'": {"<event>": "intersectWith", "<key>": "interfaceWhite"},
"'Intr'": {
"<typeValue>": {"shapeOperation": "intersect"},
"<classKey>": {
"GIFFormat": "interlace",
"SaveForWeb": "interlace",
"application": "interfaceIconFrameDimmed",
"computedBrush": "interpolation",
"gradientClassEvent": "interpolation",
"photoshopEPSFormat": "interpolation"
},
"<eventKey>": {
"convertMode": "interpolation",
"imageSize": "interpolation",
"transform": "interpolation"
},
"<event>": "intersect"
},
"'JPEG'": {"<class>": "JPEGFormat", "<enumValue>": "JPEG"},
"'LghD'": {"<enumType>": "lightDirection", "<enumValue>": "lightDirectional", "<key>": "lightDirection"},
"'LghO'": {"<typeValue>": {"diffuseMode": "lightenOnly", "lightType": "lightOmni"}},
"'LghS'": {"<class>": "lightSource", "<enumValue>": "lightSpot", "<key>": "lightSource"},
"'Lns '": {"<enumType>": "lens", "<enumValue>": "lines", "<key>": "lens"},
"'Mgnt'": {
"<typeValue>": {"channel": "magenta", "colors": "magentas", "guideGridColor": "magenta"},
"<key>": "magenta"
},
"'MrgL'": {"<enumValue>": "mergedLayers", "<event>": "mergeLayers"},
"'Mxm '": {"<enumValue>": "maximumQuality", "<event>": "maximum", "<key>": "maximum"},
"'NTSC'": {"<enumValue>": "NTSC", "<event>": "NTSCColors"},
"'NmbL'": {
"<classKey>": {"'GEfc'": "numberOfLevels", "document": "numberOfLayers"},
"<eventKey>": {"cutout": "numberOfLevels"}
},
"'PlgP'": {"<class>": "pluginPrefs", "<enumValue>": "pluginPicker", "<key>": "pluginPrefs"},
"'Pncl'": {"<enumValue>": "pencilEraser", "<key>": "pencilWidth"},
"'Pnt '": {"<typeValue>": {"textType": "point"}, "<class>": "point", "<event>": "paint"},
"'Prsp'": {"<enumValue>": "perspective", "<key>": "perspectiveIndex"},
"'PrvM'": {"<enumValue>": "previewMagenta", "<key>": "previewMacThumbnail"},
"'Pstr'": {"<class>": "posterize", "<event>": "posterize", "<key>": "posterization"},
"'RGBS'": {"<enumType>": "RGBSetupSource", "<key>": "RGBSetup"},
"'Rds '": {"<enumValue>": "reds", "<key>": "radius"},
"'ScrD'": {"<enumValue>": "screenDot", "<key>": "scratchDisks"},
"'ShdI'": {
"<classKey>": {"'GEfc'": "shadowIntensity"},
"<eventKey>": {"watercolor": "shadowIntensity"},
"<unknown>": "shadingIntensity"
},
"'ShpC'": {
"<classKey>": {"application": "shapingCurve"},
"<class>": "shapingCurve",
"<key>": "shapeCurveType"
},
"'ShrE'": {"<event>": "sharpenEdges", "<key>": "shearEd"},
"'Shrp'": {"<event>": "sharpen", "<key>": "sharpness"},
"'SplC'": {"<event>": "splitChannels", "<key>": "supplementalCategories"},
"'Spot'": {"<enumValue>": "spotColor", "<key>": "spot"},
"'SprS'": {
"<typeValue>": {"'GEft'": "sprayedStrokes"},
"<enumValue>": "separationSetup",
"<event>": "sprayedStrokes"
},
"'StrL'": {"<enumType>": "strokeLocation", "<key>": "strokeLength"},
"'Strt'": {
"<classKey>": {
"currentToolOptions": "saturation",
"fileNamingRules": "start",
"HSBColorClass": "saturation",
"hueSatAdjustment": "saturation",
"hueSatAdjustmentV2": "saturation",
"lineClass": "start",
"range": "start",
"vibrance": "saturation"
},
"<eventKey>": {"replaceColor": "saturation", "variations": "saturation", "vibrance": "saturation"},
"<enumValue>": "saturation"
},
"'TEXT'": {"<enumType>": "textType", "<key>": "textType"},
"'TIFF'": {"<class>": "TIFFFormat", "<enumValue>": "TIFF"},
"'TglO'": {"<enumValue>": "toggleOptionsPalette", "<key>": "toggleOthers"},
"'TrnG'": {
"<classKey>": {"application": "transparencyGrid", "transparencyPrefs": "transparencyGridSize"},
"<enumType>": "transparencyGridSize",
"<enumValue>": "transparencyGamutPreferences"
},
"'TrnS'": {
"<classKey>": {
"bevelEmboss": "transparencyShape",
"dropShadow": "transparencyShape",
"innerGlow": "transparencyShape",
"innerShadow": "transparencyShape",
"outerGlow": "transparencyShape"
}, "<class>": "transparencyStop", "<unknown>": "transferSpec"
},
"'Trns'": {"<enumValue>": "transparent", "<key>": "transparency"},
"'TxtC'": {
"<classKey>": {"'GEfc'": "textureCoverage", "textLayer": "textClickPoint"},
"<eventKey>": {"underpainting": "textureCoverage"}
},
"'TxtF'": {"<event>": "textureFill", "<key>": "textureFile"},
"'UsrM'": {"<enumType>": "userMaskOptions", "<key>": "userMaskEnabled"},
"'null'": {"<class>": "null", "<enumValue>": "null", "<event>": "null", "<key>": "target"}
};
function getFromId(context, parentContext) {
var uniIdStr;
var kind = context[0];
var id = context[1];
if (id < smallestHashValue) {
uniIdStr = app.typeIDToStringID(id);
} else {
uniIdStr = "'" app.typeIDToCharID(id) "'";
if (that.meaningfulIds) {
if (uniIdStr in contextRules) {
function resolveIdStr(candidates) {
var idStr = "";
for (var parentString in candidates) {
if (candidates.hasOwnProperty(parentString)) {
if (parentContext[1] === that.uniIdStrToId(parentString)) {
idStr = candidates[parentString];
break;
}
}
}
return idStr;
}
var resolvedIdStr = "";
var rule = contextRules[uniIdStr];
if (parentContext) {
switch (kind) {
case"<key>":
if ((parentContext[0] === "<class>") && ("<classKey>" in rule)) {
resolvedIdStr = resolveIdStr(rule["<classKey>"]);
} else if ((parentContext[0] === "<event>") && ("<eventKey>" in rule)) {
resolvedIdStr = resolveIdStr(rule["<eventKey>"]);
}
break;
case"<enumValue>":
if ((parentContext[0] === "<enumType>") && ("<typeValue>" in rule)) {
resolvedIdStr = resolveIdStr(rule["<typeValue>"]);
}
break;
}
}
if (resolvedIdStr !== "") {
uniIdStr = resolvedIdStr;
} else if (kind in rule) {
uniIdStr = rule[kind];
}
} else {
var stringIDStr = app.typeIDToStringID(id);
if (stringIDStr !== "") {
uniIdStr = stringIDStr;
}
}
}
}
return uniIdStr;
}
3.代码转执行
使用记事本或者notepad 等文本编辑器,将代码拷贝至文本文件,然后修改后缀名为js或者jsx,最后再PS软件菜单文件》脚本》浏览,点执行即可,也可以将脚本放在预设文件夹内,会显示再脚本下的二级子菜单。如下图所示:
4.作者答疑代码长度过长,如需全部项目或有疑问,请留言。
提示:
提示: