写真に青いレイヤーを乗算してみる
こないだ本屋で見た上野樹里が表紙の雑誌「Levi’s book ROCKS」がえらいかっこ良かったのでFlashで真似てみる。透明度0.9くらいの青いベタ塗りを写真の上に引いて、ブレンドモードを乗算にして写真の彩度とコントラストを少々弄るとそれっぽくなった。
うーん、何かに使えないかなー。
こないだ本屋で見た上野樹里が表紙の雑誌「Levi’s book ROCKS」がえらいかっこ良かったのでFlashで真似てみる。透明度0.9くらいの青いベタ塗りを写真の上に引いて、ブレンドモードを乗算にして写真の彩度とコントラストを少々弄るとそれっぽくなった。
うーん、何かに使えないかなー。
技術的なエントリーは久しぶりだなー。CBCNETで連載されているtrick7のteraさんの記事が面白かったので、自分なりにやってみる。この表現って素敵ですよね。記事にもあるようにPhotoshopでの参考サイトがあるので、これに忠実にActionScript3で再現してみる。元画像はこちら。
まずは画像をムービークリップに内包してステージにインスタンス名を「photo」にして配置。Tweenerでコントラストと彩度と明度を調整する。次にこのmcをBitmapDataでキャプチャしてコピー。コピーにも色を同じように調整して、ブラーをかける。新たにに円形グラデーション用のmcを作ってscaleYを半分にして楕円型にする。マスクするmcとマスクされるmcの両方にcacheAsBitmapをtrueに設定。最後にマスクをかけて完成と。
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.display.GradientType;
import flash.geom.Matrix;
import caurina.transitions.Tweener;
import caurina.transitions.properties.ColorShortcuts;
import caurina.transitions.properties.FilterShortcuts;
public class Main extends Sprite
{
public function Main():void
{
ColorShortcuts.init();
FilterShortcuts.init();
setToyFilter();
}
private function setToyFilter():void
{
//-----[色調整 ボケなし]
Tweener.addTween(photo, { _contrast:0.6, _saturation:1.6, _brightness:0.2 } );
//-----[キャプチャしてコピー]
var bmd:BitmapData = new BitmapData(photo.width, photo.height);
bmd.draw(photo);
var bm:Bitmap = new Bitmap(bmd);
var sp:Sprite = new Sprite();
sp.addChild(bm);
addChild(sp);
sp.x = photo.x;
sp.y = photo.y;
swapChildren(photo, sp);
//-----[色調整 ボケあり]
Tweener.addTween(sp, { _contrast:0.6, _saturation:1.6, _brightness:0.2, _Blur_blurX:5, _Blur_blurY:5, _Blur_quality:2 } );
//-----[グラデーションマスクの設定]
var gmask:Sprite = new Sprite();
var radius:uint = photo.width / 1.5;
var scale:Number = 1.0 / 1638.4 * radius * 2;
var m:Matrix = new Matrix();
m.identity();
m.scale(scale , scale);
addChild(gmask);
gmask.x = photo.x + photo.width / 2;
gmask.y = photo.y + photo.height / 2;
gmask.scaleY = 0.5;
gmask.graphics.lineStyle();
gmask.graphics.beginGradientFill(
GradientType.RADIAL,
[0x000000, 0x818181, 0xFFFFFF],
[1.0, 0.4, 0],
[120, 200, 255],
m
);
gmask.graphics.drawCircle(0, 0 , radius);
gmask.cacheAsBitmap = true;
photo.cacheAsBitmap = true;
photo.mask = gmask;
}
}
}
参考サイトでは被写体をパスで切り抜いて輪郭を強調してるけどFlashではそこまで出来ないのでピンのゆるさはご愛敬。写真素材をそれっぽいの使えば、擬似的に似せることは出来そうだなー。
追記
northprintさんがwonderflでPixel Bender版を公開されてます。こちらも勉強になります。
画像処理の勉強としてRGBとCMYの色分解をやってみた。色々試したけどCMYKの4色に分解する方法がまだ良く分かんない。という事で画像処理入門の本をamazonで購入した。明日届いたらもうちょいやってみる。
うねうねと有機的に動く円を作ってみた。katamariさんのサイトを見よう見真似で模写。なんか違う気がするなぁ。うねり具合がしっくりこない。
最近ビットマップフォントの常套モーションになっているランダムテキストを自作してみた。最初のモーションですべての文字を「アンダーバー」に変えてからランダムに1文字づつシャッフルしてます。TimerEventで動かしてるんだけど、シャッフルのスピードがブラウザで見るとやや遅い。デバッグプレイヤーだと思い通りのスピードなのに。ENTER_FRAMEで動かすほうが良いの?。誰か教えてください。
コードは以下参照。シャッフル時間を任意に調整できるようにしてます。
package info.five.filters
{
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class RandomText
{
const _replaceWord:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789=+-*/!?";
private var _content:TextField;
private var _word:String;
private var _timer:Timer;
private var _randomCnt:uint;
private var _randomArr:Array = new Array();
private var _shuffleArr:Array = new Array();
private var _speed:Number = 1;
private var _time:uint = 30;
private var _cnt1:uint = 0;
private var _cnt2:uint = 0;
//------------------------------
// ランダムテキストクラス
//------------------------------
public function RandomText(content:TextField)
{
this._content = content;
this._word = content.text;
_timer = new Timer(_speed, 0);
_timer.addEventListener(TimerEvent.TIMER, onTick, false, 0, true);
}
//------------------------------
// テキストの再設定
//------------------------------
public function setText(newText:String):void
{
this._word = newText;
}
//------------------------------
// モーションスタート
//------------------------------
public function start():void
{
//-----[変数の初期化]
_content.text = "";
_randomCnt = 0;
_randomArr = [];
_shuffleArr = [];
_cnt1 = 0;
_cnt2 = 0;
_content.wordWrap = false;
_content.autoSize = TextFieldAutoSize.LEFT;
//-----[文字番号を配列に取得]
for(var i:uint=0; i<_word .length; i++)
{
_randomArr.push(i);
_content.appendText("_");
}
//-----[文字番号をシャッフル]
_shuffleArr = shuffle(_randomArr);
_timer.start();
}
//------------------------------
// 配列のシャッフル
//------------------------------
private function shuffle(arr:Array):Array
{
var l = arr.length;
var newArr = arr;
while(l)
{
var m = Math.floor(Math.random()*l);
var n = newArr[--l];
newArr[l] = newArr[m];
newArr[m] = n;
}
return newArr;
}
//------------------------------
// シャッフルモーション
//------------------------------
private function onTick(e:TimerEvent):void
{
if(_randomCnt < _time)
{
var randomNo:uint = Math.round(Math.random() * _replaceWord.length);
var s1:uint = _shuffleArr[_cnt1];
var s2:uint = _shuffleArr[_cnt1] + 1;
var s3:String = _replaceWord.charAt(randomNo);
_content.replaceText(s1, s2, s3);
if(_cnt1 >= _word.length - 1) _cnt1 = 0;
else _cnt1++;
}
else
{
var s4:uint = _shuffleArr[_cnt2];
var s5:uint = _shuffleArr[_cnt2] + 1;
var s6:String = _word.charAt(_shuffleArr[_cnt2]);
_content.replaceText(s4, s5, s6);
_cnt2++;
if(_cnt2 >= _word.length)
{
_timer.stop();
}
}
_randomCnt++;
}
//------------------------------
// getter
//------------------------------
public function get time():uint
{
return _time;
}
//------------------------------
// setter
//------------------------------
public function set time(t:uint):void
{
_time = t;
}
}
}
使い方はテキストフィールドを引数にインスタンスを作ってstart()メソッドを呼ぶだけ。
import info.five.filters.RandomText; var randomText1:RandomText = new RandomText(myText1); randomText1.start();
シャッフルスピードを変えるにはtimeプロパティを変える。(デフォルトは30)
randomText1.time = 100;
テキストを変更するには、setText()メソッドの引数に文字列を与える。
randomText1.setText("HOGE")
randomText1.start();
ロシアのトイカメラLOMOで撮影したような効果を与えるフィルターを作ってみた。全体的にハイコントラストにして四隅が暗くなるように調整。勝手にロモフィルターと命名することに。
LomoFilter.as
import flash.geom.Matrix;
class info.five.as2.filters.LomoFilter
{
function LomoFilter()
{
trace("LomoFilterクラスの読込完了");
}
//------------------------------
// LomoFilterセット関数
// mc:ムービークリップ
// vol:ボリューム(1.0~2.0)
//------------------------------
function setLomoFilter(mc:MovieClip, vol:Number)
{
mc.createEmptyMovieClip("lomo", mc.getNextHighestDepth());
mc.lomo.blendMode = "overlay";
with(mc.lomo)
{
fillType = "radial";
colors = [0x000000, 0x000000, 0x000000];
alphas = [0, 100, 100];
ratios = [0, 150, 255];
spreadMethod = "pad";
interpolationMethod = "RGB";
focalPointRatio = 0;
matrix = new Matrix();
matrix.createGradientBox(mc._width*vol, mc._height*vol, 0, (mc._width-mc._width*vol)/2, (mc._height-mc._height*vol)/2);
beginGradientFill(fillType, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPointRatio);
moveTo(0, 0);
lineTo(0, mc._height);
lineTo(mc._width, mc._height);
lineTo(mc._width, 0);
lineTo(0, 0);
endFill();
}
}
}
flaの1フレーム目に以下のコードを書く。
import info.five.as2.filters.LomoFilter; var lomo:LomoFilter = new LomoFilter(); lomo.setLomoFilter(thumb1, 1.4); lomo.setLomoFilter(thumb2, 1.4); lomo.setLomoFilter(thumb3, 1.4); lomo.setLomoFilter(thumb4, 1.4);
setLomoFilter()の第1引数はmcのインスタンス名。第2引数はフィルター量になってます。(1.0~2.0くらいで)もうちょっとぼけ具合とかピンホールとか色々弄りたかったけど、やりすぎない程度にしてみました。
ダイナミックテキストにビットマップ塗りでマスクをかけて網掛け状態にしてみる。
上記のような斜線のpngを用意してライブラリに読み込んでおく。リンケージ名を「bg04.png」にして、「ActionScriptに書き出し」、「最初のフレームに書き出し」にチェックを入れる。あとは1フレーム目にコードをコピペ。フォントの埋め込みはしていません。
import flash.display.*;
import flash.geom.*;
//-----[初期設定]
var textW:Number = lineText._width;
var textH:Number = lineText._height;
var theMatrix:Matrix = new Matrix();
var theColTrans:ColorTransform = new ColorTransform();
var bmd:BitmapData = BitmapData.loadBitmap("bg04.png");
//-----[マスクの作成]
_root.createEmptyMovieClip("mask", 0);
mask._x = lineText._x;
mask._y = lineText._y;
mask.cacheAsBitmap = true;
lineText.cacheAsBitmap = true;
mask.clear();
mask.lineStyle();
mask.beginBitmapFill(bmd, theMatrix, true, true);
mask.moveTo(0, 0);
mask.lineTo(textW, 0);
mask.lineTo(textW, textH);
mask.lineTo(0, textH);
mask.lineTo(0, 0);
mask.endFill();
mask.setMask(lineText);
※macで見るとマスクが吹っ飛んで、何も表示されないみたい。cacheAsBitmapを両方ともtrueにしてるんだけどこれが表示されない原因ぽい?winとmacで仕様が違うのか?何でじゃー!?