2007年09月13日
チャンネルごとに描画するドローイングソフト
BitmapData.copyChannel ネタの集大成として、チャンネルごとに描画するアプリケーションを作ってみました。
使い方
- 黒い4つの四角がキャンバスです。
- マウスでドラッグすると線が引けます。
- 左上が赤、右上が青、左下が緑、右下がα値を表しています。
- 右側のグラデーションをクリックすると描画の階調を変えられます。
- 希望する色を描くためには、それぞれのチャンネルに適切な階調で線を引く必要があります。
- CLEAR ボタンを押すと最初からやり直せます
コツ
運を天に任せて適当にマウスを動かすと、意外にきれいな絵が描けたりします。
実用性はあまりないので、偶然の産物を楽しみましょう。
作品例1
乱雑。適当にマウスを動かした例。

なんだか分からないけど、きれいに見えるような見えないような。
作品例2
「てっく煮」。

赤い「て」、青い「っ」、緑の「く」がうっすら見えるところがチャームポイント。
ソースコード
ソースコードは以下に(180行)
package
{
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.utils.*;
public class ChannelDrawer extends Sprite
{
[Embed(source='clear.png')]
private var ClearImage:Class;
// 画像のサイズ
private const MARGIN:int = 5;
private const SIZE:int = 100;
private const SIZE2:int = SIZE + MARGIN;
private const SIZE3:int = SIZE * 2 + MARGIN;
private const SIZE4:int = SIZE3 + SIZE3 + MARGIN + 10;
// 色
private var color:int = 0xffffff;
// チャンネルの順番
private var channels:Array = [BitmapDataChannel.RED, BitmapDataChannel.GREEN,
BitmapDataChannel.BLUE, BitmapDataChannel.ALPHA];
// BitmapData
private var bmpPreview:BitmapData = new BitmapData(SIZE, SIZE);
private var bmpCanvas:BitmapData = new BitmapData(SIZE3, SIZE3);
// Sprite
private var canvas:Sprite;
private var clearBtn:Sprite;
private var curColor:Shape;
// change flag
private var changed:Boolean = false;
// コンストラクタ
public function ChannelDrawer()
{
stage.scaleMode = "noScale";
stage.align = "TL";
// 左のプレビュー
var bmp:Bitmap = addChild(new Bitmap(bmpPreview)) as Bitmap;
bmp.scaleX = bmp.scaleY = 2;
// 描画領域
addChild(canvas = new Sprite()).x = SIZE3;
clear();
canvas.addEventListener("mouseDown", mouseDownHandler);
// 描画領域の枠
var mask:Sprite = new Sprite();
mask.graphics.beginFill(0xffffff);
mask.graphics.drawRect(SIZE3 + SIZE, 0 , MARGIN, SIZE3);
mask.graphics.drawRect(SIZE3 , SIZE, SIZE3 , MARGIN);
mask.graphics.endFill();
addChild(mask);
// CLEARボタン
clearBtn = new Sprite();
addChild(clearBtn);
clearBtn.addChild(new ClearImage());
clearBtn.buttonMode = true;
clearBtn.x = SIZE4;
clearBtn.y = SIZE3 - clearBtn.height;
clearBtn.addEventListener("click", clear);
// 色選択
var choiseColor:Sprite = new Sprite();
choiseColor.buttonMode = true;
var matrix:Matrix = new Matrix();
choiseColor.graphics.lineStyle(0x000000, 1);
matrix.createGradientBox(1, SIZE3 - clearBtn.height * 2 - MARGIN * 2, Math.PI / 2);
choiseColor.graphics.beginGradientFill("linear", [0xffffff, 0x000000], [100, 100], [0x00, 0xff], matrix);
choiseColor.graphics.drawRect(0, 0, clearBtn.width, SIZE3 - clearBtn.height * 2 - MARGIN * 2);
choiseColor.graphics.endFill();
choiseColor.x = SIZE4;
addChild(choiseColor);
choiseColor.addEventListener("click", function(event:MouseEvent):void
{
var c:int = 255 - (event.localY / choiseColor.height) * 255;
trace(c.toString(16));
color = (c << 16) + (c << 8) + c;
trace(color.toString(16));
updateCurColor();
});
// 色表示
curColor = new Shape();
curColor.x = SIZE4;
curColor.y = SIZE3 - clearBtn.height * 2 - MARGIN;
addChild(curColor);
updateCurColor();
// loop
var count:int = 0;
addEventListener("enterFrame", function(event:Event):void
{
count = (count + 1) % 5;
if(count == 0 && changed)
{
updatePreview();
}
});
}
private function mouseDownHandler(event:MouseEvent):void
{
canvas.graphics.beginFill(0, 0);
canvas.graphics.lineStyle(3, color);
canvas.graphics.moveTo(event.localX, event.localY);
canvas.graphics.lineTo(event.localX, event.localY);
stage.addEventListener("mouseMove", mouseMoveHandler);
stage.addEventListener("mouseUp", mouseUpHandler);
}
private function mouseMoveHandler(event:MouseEvent):void
{
if(event.target == canvas)
{
canvas.graphics.lineStyle(3, color);
canvas.graphics.lineTo(event.localX, event.localY);
canvas.graphics.lineStyle();
changed = true;
}
}
private function mouseUpHandler(event:MouseEvent):void
{
canvas.graphics.lineStyle();
canvas.graphics.endFill();
stage.removeEventListener("mouseMove", mouseMoveHandler);
stage.removeEventListener("mouseUp", mouseUpHandler);
}
// チャンネルを合成する
private function updatePreview():void
{
var rect:Rectangle = new Rectangle(0, 0, SIZE, SIZE);
var zeroPoint:Point = new Point(0, 0);
// init
bmpCanvas.fillRect(new Rectangle(0, 0, SIZE3, SIZE3), 0xff000000);
bmpCanvas.draw(canvas);
// copy channel
bmpPreview.lock();
for(var i:int = 0; i < 4; i++)
{
var channel:uint = channels[i];
var fromRect:Rectangle = new Rectangle(Math.floor(i / 2) * (SIZE + MARGIN), (i % 2) * (SIZE + MARGIN), SIZE, SIZE);
bmpPreview.copyChannel(bmpCanvas, fromRect, zeroPoint, BitmapDataChannel.RED, channel);
}
bmpPreview.unlock();
}
// 初期化
private function clear(event:* = null):void
{
canvas.graphics.clear();
canvas.graphics.beginFill(0);
canvas.graphics.drawRect(0, 0, SIZE3, SIZE3);
canvas.graphics.endFill();
updatePreview();
}
// 色変更
private function updateCurColor(event:* = null):void
{
curColor.graphics.lineStyle(0x000000, 1);
curColor.graphics.beginFill(color);
curColor.graphics.drawRect(0, 0, clearBtn.width, clearBtn.height);
curColor.graphics.endFill();
}
}
}