雨を描く(簡易フィルタ)

Photoshopには、数多くのフィルタ(プラグイン)が出ています。無料のものから有料のものまで様々です。今回はJavaScriptを使った簡単なフィルタスクリプトです。ただし、何でもできるわけではなく制限があります。この制限は

「点を描く事はできる。しかし、すでにある点の情報は読めない」

というものです。つまり一般的なフィルタのように、画像のデータを読み取って、それに応じて加工することはできないのです。このため、一方的に点を描くだけというフィルタ程度しか作成することができないわけです。
そうは言っても全くできないよりはマシということで作成したのが「雨を描く」スクリプトです。原理は簡単で選択範囲を作成して、そこを塗りつぶすだけです。ランダムに選択範囲を作成し、そこを塗りつぶしていくことで雨を描くわけです。以下のスクリプトがランダムな位置に雨を描くものです。

// x=X座標、y=Y座標、h=雨の長さ、opacity=明るさ
function rain(x,y,h,opacity)
{
var selReg = [[x,y],[x+1,y],[x+1,y+h],[x,y+h]];
activeDocument.selection.select(selReg);
activeDocument.selection.fill(RGBColor,ColorBlendMode.NORMAL, opacity, false);
}

activeDocument.activeLayer.isBackgroundLayer = false;
RGBColor = new SolidColor();
RGBColor.red = 0;
RGBColor.green = 0;
RGBColor.blue = 20;
rainNum = 60;

docW = parseFloat(activeDocument.width);
docH = parseFloat(activeDocument.height);

for (i=0; i<rainNum; i++)
{
X = Math.random() * docW;
Y = Math.random() * docH;
rain(X,Y,80,50);
}

雨の数を変えるには

rainNum = 60;

の60を変更してください。描いた後にぼかしフィルタを適用したい場合には一番最後に以下の行を入れてみてください。

activeDocument.activeLayer.applyBlur();

実際に描かせてみると、雨が偏って描画されてしまいます。なるべくならば全体的には均等に近いけど、ちょっとずれているような感じにしたいところです。このような場合は基準となる座標を決めておいて、そこから数ピクセル分ずらすようにして描きます。実際のスクリプトは以下のようになります。

// x=X座標、y=Y座標、h=雨の長さ、opacity=明るさ
function rain(x,y,h,opacity)
{
var selReg = [[x,y],[x+1,y],[x+1,y+h],[x,y+h]];
activeDocument.selection.select(selReg);
activeDocument.selection.fill(RGBColor,ColorBlendMode.NORMAL, opacity, false);
}

activeDocument.activeLayer.isBackgroundLayer = false;
RGBColor = new SolidColor();
RGBColor.red = 0; // 雨の色(赤の輝度)
RGBColor.green = 0; // 雨の色(緑の輝度)
RGBColor.blue = 20; // 雨の色(青の輝度)
rainNum = 60; // 雨の数
rainOffset = 10; // 雨の横のぶれ幅

docW = parseFloat(activeDocument.width);
docH = parseFloat(activeDocument.height);
rainX = 0;
rainDX = docW / rainNum;
for (i=0; i<rainNum; i++)
{
X = rainX + Math.random() * rainOffset;
Y = Math.random() * docH;
rain(X,Y,80,50);
rainX = rainX + rainDX;
}
activeDocument.activeLayer.applyBlur();

雨の長さが全部同じだと、これも気になります。雨の長さも基準の長さを決めておいてランダムに長くなったりすると少しは雨らしくなります。実際のスクリプトは以下のようになります。

// x=X座標、y=Y座標、h=雨の長さ、opacity=明るさ
function rain(x,y,h,opacity)
{
var selReg = [[x,y],[x+1,y],[x+1,y+h],[x,y+h]];
activeDocument.selection.select(selReg);
activeDocument.selection.fill(RGBColor,ColorBlendMode.NORMAL, opacity, false);
}

activeDocument.activeLayer.isBackgroundLayer = false;
RGBColor = new SolidColor();
RGBColor.red = 0; // 雨の色(赤の輝度)
RGBColor.green = 0; // 雨の色(緑の輝度)
RGBColor.blue = 20; // 雨の色(青の輝度)
rainNum = 60; // 雨の数
rainOffset = 10; // 雨の横のぶれ幅
rainLength = 80; // 雨の長さ
rainLOffset = 30; // 雨の長さのぶれ幅

docW = parseFloat(activeDocument.width);
docH = parseFloat(activeDocument.height);
rainX = 0;
rainDX = docW / rainNum;
for (i=0; i<rainNum; i++)
{
X = rainX + Math.random() * rainOffset;
Y = Math.random() * docH;
L = rainLength + Math.random() * rainLOffset;
rain(X,Y,L,50);
rainX = rainX + rainDX;
}

まあまあ、雨に近くなりました。が、実際の雨は斜めに降ってきたりしますので、もう一工夫して斜めにも降るようにしたものが以下のスクリプトになります。

// x=X座標、y=Y座標、d=傾き、h=雨の長さ、opacity=明るさ
function rain(x,y,d,h,opacity)
{
var selReg = [[x,y],[x+1,y],[x+d+1,y+h],[x+d,y+h]];
activeDocument.selection.select(selReg);
activeDocument.selection.fill(RGBColor,ColorBlendMode.NORMAL, opacity, false);
}

activeDocument.activeLayer.isBackgroundLayer = false;
RGBColor = new SolidColor();
RGBColor.red = 0; // 雨の色(赤の輝度)
RGBColor.green = 0; // 雨の色(緑の輝度)
RGBColor.blue = 20; // 雨の色(青の輝度)
rainNum = 60; // 雨の数
rainOffset = 10; // 雨の横のぶれ幅
rainLength = 80; // 雨の長さ
rainLOffset = 30; // 雨の長さのぶれ幅

docW = parseFloat(activeDocument.width);
docH = parseFloat(activeDocument.height);
rainX = 0;
rainDX = docW / rainNum;
for (i=0; i<rainNum; i++)
{
X = rainX + Math.random() * rainOffset;
Y = Math.random() * docH;
L = rainLength + Math.random() * rainLOffset;
rain(X,Y,10,L,50);
rainX = rainX + rainDX;
}

左上から右下に降るようになっていますが、右上から左下に降るようにしたい場合には

rain(X,Y,10,L,50);

rain(X,Y,-10,L,50);

のようにマイナスの数値にします。この数値を大きくすると雨が、より斜めになります。




[サンプルをダウンロード]