Files
hcie-rust-v3.05/_tools/photoshop/generate_inner_shadow_dataset.jsx
2026-07-09 02:59:53 +03:00

186 lines
6.3 KiB
React

/**
* generate_inner_shadow_dataset.jsx
*
* Purpose:
* Generate a systematic Inner Shadow effect dataset in Adobe Photoshop.
*
* Logic & Workflow:
* 1. Creates a new transparent RGB document.
* 2. Adds a raster layer and fills a centered rectangle with black.
* 3. Applies one Inner Shadow effect via Photoshop ActionDescriptor.
* 4. Saves the result as a transparent PNG.
*
* Arguments:
* None (interactive). The user selects an output folder via dialog.
*
* Side Effects:
* - Creates and closes many temporary Photoshop documents.
* - Writes PNG files to the selected folder.
*/
var outFolder = Folder.selectDialog("Select output folder for Inner Shadow dataset");
if (!outFolder) {
alert("No output folder selected. Exiting.");
throw new Error("No output folder");
}
var angles = [0, 90, 180, 270];
var distances = [5, 15, 30];
var sizes = [10, 30];
var chokes = [0, 20];
var fxOpacities = [75, 100];
var fxBlendModes = [
{ key: "Nrml", name: "normal" },
{ key: "Mltp", name: "multiply" }
];
function pxValue(v) {
if (v === undefined || v === null) return 0;
if (typeof v === "number") return v;
if (typeof v.as === "function") return v.as("px");
if (typeof v.value !== "undefined") return v.value;
return Number(v);
}
function createDocument(name, width, height) {
try {
return app.documents.add(width, height, 72, name, NewDocumentMode.RGB, DocumentFill.TRANSPARENT);
} catch (e) {
return app.documents.add(width, height, 72, name, NewDocumentMode.RGB);
}
}
function addBlackRectangle(doc) {
var w = pxValue(doc.width);
var h = pxValue(doc.height);
var margin = Math.round(Math.min(w, h) * 0.25);
var layer = doc.artLayers.add();
layer.name = "shape";
var region = [
[margin, margin],
[w - margin, margin],
[w - margin, h - margin],
[margin, h - margin]
];
doc.selection.select(region);
var black = new SolidColor();
black.rgb.red = 0;
black.rgb.green = 0;
black.rgb.blue = 0;
doc.selection.fill(black);
doc.selection.deselect();
return layer;
}
function blendModeTypeID(mode) {
try { return charIDToTypeID(mode); }
catch (e) { return stringIDToTypeID(mode); }
}
function applyInnerShadow(params) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(charIDToTypeID("Prpr"), charIDToTypeID("Lefx"));
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
desc.putReference(charIDToTypeID("null"), ref);
var fxDesc = new ActionDescriptor();
var isDesc = new ActionDescriptor();
isDesc.putBoolean(charIDToTypeID("enab"), true);
isDesc.putBoolean(charIDToTypeID("present"), true);
isDesc.putBoolean(charIDToTypeID("showInDialog"), true);
isDesc.putEnumerated(charIDToTypeID("Blnd"), charIDToTypeID("BlnM"), blendModeTypeID(params.blendMode));
var clr = new ActionDescriptor();
clr.putDouble(charIDToTypeID("Rd "), 0);
clr.putDouble(charIDToTypeID("Grn "), 0);
clr.putDouble(charIDToTypeID("Bl "), 0);
isDesc.putObject(charIDToTypeID("Clr "), charIDToTypeID("RGBC"), clr);
isDesc.putInteger(charIDToTypeID("Opct"), params.opacity);
isDesc.putInteger(charIDToTypeID("lagl"), params.angle);
isDesc.putBoolean(charIDToTypeID("uglg"), false);
isDesc.putInteger(charIDToTypeID("Dstn"), params.distance);
isDesc.putInteger(charIDToTypeID("Ckmt"), params.choke);
isDesc.putInteger(charIDToTypeID("blur"), params.size);
isDesc.putInteger(charIDToTypeID("Nose"), 0);
fxDesc.putObject(charIDToTypeID("IrSh"), charIDToTypeID("IrSh"), isDesc);
desc.putObject(charIDToTypeID("T "), charIDToTypeID("Lefx"), fxDesc);
executeAction(charIDToTypeID("setd"), desc, DialogModes.NO);
}
function saveTransparentPng(doc, file) {
var pngOptions = new PNGSaveOptions();
pngOptions.compression = 6;
pngOptions.interlaced = false;
doc.saveAs(file, pngOptions, true, Extension.LOWERCASE);
}
var count = 0;
var errors = 0;
var total = angles.length * distances.length * sizes.length * chokes.length * fxOpacities.length * fxBlendModes.length;
for (var a = 0; a < angles.length; a++) {
for (var d = 0; d < distances.length; d++) {
for (var s = 0; s < sizes.length; s++) {
for (var c = 0; c < chokes.length; c++) {
for (var o = 0; o < fxOpacities.length; o++) {
for (var b = 0; b < fxBlendModes.length; b++) {
var params = {
angle: angles[a],
distance: distances[d],
size: sizes[s],
choke: chokes[c],
opacity: fxOpacities[o],
blendMode: fxBlendModes[b].key
};
var fileName = "is_" +
"a" + params.angle + "_" +
"d" + params.distance + "_" +
"s" + params.size + "_" +
"c" + params.choke + "_" +
"op" + params.opacity + "_" +
"bm" + fxBlendModes[b].name +
".png";
var file = new File(outFolder + "/" + fileName);
if (file.exists) { count++; continue; }
var doc = createDocument("inner_shadow_test", 256, 256);
var layer = addBlackRectangle(doc);
try {
applyInnerShadow(params);
saveTransparentPng(doc, file);
} catch (e) {
$.writeln("Error: " + fileName + " — " + e);
errors++;
} finally {
doc.close(SaveOptions.DONOTSAVECHANGES);
}
count++;
if (count % 10 === 0) {
$.writeln("Progress: " + count + " / " + total + " (errors: " + errors + ")");
}
}
}
}
}
}
}
alert("Done. Generated " + count + " images, " + errors + " errors.\n" + outFolder.fsName);