(function () {
if (app.documents.length === 0)
{ alert("ドキュメントを開いてください。"); return; }
var doc = app.activeDocument;
if (!doc.selection || doc.selection.length === 0)
{ alert("オブジェクトを選択してください。"); return; }
var targetIsRGB = (doc.documentColorSpace ===
DocumentColorSpace.RGB);
var changed = 0, skipped = 0;
// ImageColorSpace 列挙の短縮
var ICS = ImageColorSpace;
function colorToArray(c) {
// 任意の Color を「その色が属する空間の配列値 + 空間種別」を返す
// 戻り値: {space: ICS.RGB|CMYK|GRAY|LAB, values:[...]}
if (c.typename === "RGBColor") return { space: ICS.RGB,
values: [c.red, c.green, c.blue] };
if (c.typename === "CMYKColor") return { space: ICS.CMYK,
values: [c.cyan, c.magenta, c.yellow, c.black] };
if (c.typename === "GrayColor")
return { space: ICS.Gray, values: [c.gray] };
if (c.typename === "LabColor")
return { space: ICS.LAB, values: [c.l, c.a, c.b] };
if (c.typename === "SpotColor")
return colorToArray(c.spot.color);
// 中身の実色で再帰
// その他(パターン/グラデ/なし)はここには来ない想定
throw new Error("未対応のカラータイプ: " + c.typename);
}
function convert(values, srcSpace, dstSpace) {
// app.convertSampleColor(src, srcArray, dst, purpose)
// purpose: ImageColorConvertPurpose.defaultpurpose
return app.convertSampleColor(srcSpace, values, dstSpace,
ImageColorConvertPurpose.defaultpurpose);
}
function makeSolidColorFromArray(arr, useRGB) {
if (useRGB) {
var rgb = new RGBColor();
rgb.red = arr[0]; rgb.green = arr[1]; rgb.blue = arr[2];
return rgb;
} else {
var cmyk = new CMYKColor();
cmyk.cyan = arr[0]; cmyk.magenta = arr[1];
cmyk.yellow = arr[2]; cmyk.black = arr[3];
return cmyk;
}
}
function getColorAt50Percent(gradient) {
// 0..100 の rampPoint を持つ gradientStops から、
// pos=50 に隣接する2ストップを見つけ補間
var stops = gradient.gradientStops;
if (stops.length === 0) return null;
if (stops.length === 1) return stops[0].color;
// ストップを rampPoint 昇順で収集
var list = [];
for (var i = 0; i < stops.length; i++) {
list.push({ p: stops[i].rampPoint, c: stops[i].color });
}
list.sort(function (a, b) { return a.p - b.p; });
var pos = 50;
// ちょうど一致
for (var j = 0; j < list.length; j++) {
if (Math.abs(list[j].p - pos) < 0.0001) return list[j].c;
}
// 区間を特定
var a = list[0], b = list[list.length - 1];
for (var k = 0; k < list.length - 1; k++) {
if (list[k].p <= pos && pos <= list[k + 1].p)
{ a = list[k]; b = list[k + 1]; break; }
}
var t = (pos - a.p) / Math.max(1e-6, (b.p - a.p)); // 0..1
// 両端色をドキュメント空間へ変換
var dst = targetIsRGB ? ICS.RGB : ICS.CMYK;
var A = colorToArray(a.c);
var B = colorToArray(b.c);
var aDst = (A.space === dst) ? A.values.slice(0) :
convert(A.values, A.space, dst);
var bDst = (B.space === dst) ? B.values.slice(0) :
convert(B.values, B.space, dst);
// 線形補間
var out = [];
var n = aDst.length;
for (var m = 0; m < n; m++) {
out[m] = aDst[m] + (bDst[m] - aDst[m]) * t;
}
return makeSolidColorFromArray(out, targetIsRGB);
}
function processItem(it) {
try {
// PathItem / CompoundPathItem の塗りを処理
if (it.typename === "PathItem") {
if (it.filled && it.fillColor && it.fillColor.typename ===
"GradientColor")
{var col = getColorAt50Percent(it.fillColor.gradient);
if (col) { it.fillColor = col; changed++; return; }
}
} else if (it.typename === "CompoundPathItem") {
// コンパウンドは子パスの塗りに依存
for (var i = 0; i < it.pathItems.length; i++) {
var p = it.pathItems[i];
if (p.filled && p.fillColor && p.fillColor.typename ===
"GradientColor") {
var col2 = getColorAt50Percent(p.fillColor.gradient);
if (col2) { p.fillColor = col2; changed++; }
}
}
return;
} else if ("pageItems" in it) {
// グループ/テキストアウトラインなど再帰
for (var j = 0; j < it.pageItems.length; j++)
processItem(it.pageItems[j]);
return;
}
skipped++;
} catch (e) {
// 個々のアイテムで失敗しても継続
$.writeln(e);
skipped++;
}
}
// 選択全体を処理
var sel = doc.selection;
for (var s = 0; s < sel.length; s++) processItem(sel[s]);
alert("完了: 中間色に変更 " + changed + " 件" +
(skipped ? "(対象外 " + skipped + " 件)" : ""));
})();