Skip to content

Instantly share code, notes, and snippets.

@shspage
Last active July 29, 2016 00:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save shspage/1fb61ff3c6b5466451d371e6666ccc0b to your computer and use it in GitHub Desktop.
Save shspage/1fb61ff3c6b5466451d371e6666ccc0b to your computer and use it in GitHub Desktop.
colorizing script for Illustrator (Commented in Japanese)
#target "illustrator"
// 選択パスのうち最前面のもののfillColor(CMYKグラデーション)をソースとして、
// その他の選択パスのfillColorを、選択パス(最前面を除く)を囲む
// 矩形範囲の対角線(左上→右下)を基準にした位置にあたるソース上の色の云々
// TODO: midPoint, opacity を考慮する
(function(){
function main(){
// selectionは全てpathItemとする
var sel = app.activeDocument.selection;
if(sel.length < 2) return;
// 最前面のパスのfillColor(CMYKグラデーション)をソースにする
var grad = sel[0].fillColor;
if(isGradInvalid(grad)) return;
var stops = grad.gradient.gradientStops;
// 選択範囲全体の矩形範囲(最前面を除く)を取得
var rect = getSelBounds(sel);
// 色作成用function
var getColorOnDiagonal = getColorOnDiagonalFunc(rect, stops);
if(!getColorOnDiagonal) return;
// 色を割り当て
for(var i = 1; i < sel.length; i++){
var center = getCenter(sel[i]);
sel[i].fillColor = getColorOnDiagonal(center);
}
}
// ---------------------------------------------------------------
// グラデーションが不適切な場合に true を返す。
// grad = GradientColor ?
function isGradInvalid(grad){
if(!grad || grad.typename != "GradientColor"){
alert("最前面パスの色がグラデーションではありません");
return true;
}
var stops = grad.gradient.gradientStops;
for(var i = 0; i < stops.length; i++){
if(stops[i].color.typename != "CMYKColor"
&& stops[i].color.typename != "GrayColor"){
alert("グラデーションにCMYK, グレースケール以外の色が含まれています");
return true;
}
}
return false;
}
// ---------------------------------------------------------------
function getSelBounds(sel){
var rect = { left:0, top:0, right:0, bottom:0, width:0, height:0 };
// 最前面は除く
var idx = 1;
var gb = sel[idx].geometricBounds;
rect.left = gb[0];
rect.top = gb[1];
rect.right = gb[2];
rect.bottom = gb[3];
for(var i = idx, iEnd = sel.length; i < iEnd; i++){
gb = sel[i].geometricBounds;
if(gb[0] < rect.left) rect.left = gb[0];
if(gb[1] > rect.top) rect.top = gb[1];
if(gb[2] > rect.right) rect.right = gb[2];
if(gb[3] < rect.bottom) rect.bottom = gb[3];
}
rect.width = rect.right - rect.left;
rect.height = rect.top - rect.bottom;
return rect;
}
// ---------------------------------------------------------------
var getCenter = function(p){
var gb = p.geometricBounds; // left, top, right, bottom
return [(gb[0] + gb[2]) / 2, (gb[1] + gb[3]) / 2];
}
// ---------------------------------------------------------------
function mix(c1, c2, p1, p2){
return Math.min(100, c1 * p1 + c2 * p2);
}
// ---------------------------------------------------------------
function getColorOfGradationAtPercent(stops, p){
// stops = grad.gradient.gradientStops
// p = 対角線左上=0, 右下=100 とした対角線上の位置
// TODO: midPoint, opacity
// midPoint, opacity は考慮されていません
if(p <= stops[0].rampPoint) return stops[0].color;
if(p >= stops[stops.length - 1].rampPoint) return stops[stops.length - 1].color;
var idx = 0;
for(var i = 1; i < stops.length; i++){
if(p < stops[i].rampPoint){
idx = i;
break;
}
}
var loc = p - stops[idx - 1].rampPoint;
var range = stops[idx].rampPoint - stops[idx - 1].rampPoint;
if(range == 0) return stops[idx].color;
var p1 = loc / range;
var p2 = 1 - p1;
var c1 = fixColor(stops[idx - 1].color);
var c2 = fixColor(stops[idx].color);
var c = new CMYKColor();
c.cyan = mix(c1.cyan, c2.cyan, p2, p1);
c.magenta = mix(c1.magenta, c2.magenta, p2, p1);
c.yellow = mix(c1.yellow, c2.yellow, p2, p1);
c.black = mix(c1.black, c2.black, p2, p1);
return c;
}
// ---------------------------------------------------------------
function fixColor(c){
if(c.typename == "CMYKColor") return c;
if(c.typename == "GrayColor"){
var c1 = new CMYKColor();
c1.cyan = 0;
c1.magenta = 0;
c1.yellow = 0;
c1.black = c.gray;
return c1;
}
}
// ---------------------------------------------------------------
function getColorOnDiagonalFunc(rect, stops){
var wh = rect.width * rect.height;
if(wh == 0) return;
var wh2 = 2 * wh;
var getColorOnDiagonal = function(point){
var x = point[0] - rect.left;
var y = point[1] - rect.bottom;
var p = 100 * (wh + rect.height * x - rect.width * y) / wh2; // wh2 != 0
var c = getColorOfGradationAtPercent(stops, p);
return c;
}
return getColorOnDiagonal;
}
main();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment