四分木モザイク
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.BlurFilter;
import flash.media.Camera;
import flash.media.Video;
[SWF(width="465",height="465",backgroundColor="0",frameRate="20")]
public class TestMosaic extends Sprite
{
private var cam:Camera;
private var vid:Video;
private var source:BitmapData;
private var qCell:QuarterCell;
private var bmd:BitmapData;
private var bmp:Bitmap;
public function TestMosaic()
{
cam = Camera.getCamera();
cam.setMode(465, 465, 20);
vid = new Video(cam.width, cam.height);
vid.attachCamera(cam);
source = new BitmapData(vid.width, vid.height);
//モザイクのセルをひとつ作ると連鎖的に子ノードのセルが作られる
qCell = new QuarterCell(source, 0, 0, source.width, source.height);
bmd = new BitmapData(vid.width, vid.height);
bmp = new Bitmap(bmd);
addChild(bmp);
addEventListener(Event.ENTER_FRAME, enter);
}
private function enter(e:Event):void {
source.draw(vid);
//親ノードセルの更新を行うと連鎖的に子ノードも更新される
qCell.updateColor();
//ターゲットBimapDataはsetPixelsで書き換えるのでロックする
bmd.lock();
qCell.putColor(bmd);
bmd.unlock();
}
}
}
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
class ColorCell
{
protected static var byteArray:ByteArray = new ByteArray();
protected var _color:uint;
protected var _x:uint;
protected var _y:uint;
protected var _width:uint;
protected var _height:uint;
protected var _rect:Rectangle;
protected var _numOfPixel:uint;
internal var colorAvailable:Boolean = true;
public function ColorCell(x:uint, y:uint, width:uint, height:uint)
{
_x = x;
_y = y;
_width = width;
_height = height;
_numOfPixel = width * height;
_rect = new Rectangle(x, y, width, height);
}
public function get color():uint {
return _color;
}
public function putColor(target:BitmapData):void {
var ba:ByteArray = byteArray;
ba.clear();
ba.writeUnsignedInt(_color);
for (var i:int = 1; i < _numOfPixel; i<<=1)
{
ba.writeBytes(ba);
}
ba.position = 0;
target.setPixels(_rect, ba);
}
}
class QuarterCell extends ColorCell
{
protected var _source:BitmapData;
private var cell_00:ColorCell;
private var cell_01:ColorCell;
private var cell_10:ColorCell;
private var cell_11:ColorCell;
public function QuarterCell(source:BitmapData, x:uint, y:uint, width:uint, height:uint)
{
_source = source;
super(x, y, width, height);
var w2:uint = width >>> 1;
var w2_1:uint = w2 + (width & 1);
var h2:uint = height >>> 1;
var h2_1:uint = h2 + (height & 1);
if (w2 == 1 || h2 == 1) {
cell_00 = new ColorPickCell(source, x, y, w2, h2);
cell_01 = new ColorPickCell(source, x + w2, y, w2_1, h2);
cell_10 = new ColorPickCell(source, x, y + h2, w2, h2_1);
cell_11 = new ColorPickCell(source, x + w2, y + h2, w2_1, h2_1);
} else {
cell_00 = new QuarterCell(source, x, y, w2, h2);
cell_01 = new QuarterCell(source, x + w2, y, w2_1, h2);
cell_10 = new QuarterCell(source, x, y + h2, w2, h2_1);
cell_11 = new QuarterCell(source, x + w2, y + h2, w2_1, h2_1);
}
}
public function updateColor() :uint{
return color;
}
override public function get color():uint {
var c00 :uint = cell_00.color;
var c01 :uint = cell_01.color;
var c10 :uint = cell_10.color;
var c11 :uint = cell_11.color;
if (!(cell_00.colorAvailable && cell_01.colorAvailable && cell_10.colorAvailable && cell_11.colorAvailable)) {
colorAvailable = false;
return 0;
}
if (judgeAverage(c00, c01, c10, c11, 0x80808080)) {
colorAvailable = true;
_color = average4Colors(c00, c01, c10, c11);
return _color;
} else {
colorAvailable = false;
return 0;
}
}
override public function putColor(target:BitmapData):void
{
if(colorAvailable){
super.putColor(target);
}else {
cell_00.putColor(target);
cell_01.putColor(target);
cell_10.putColor(target);
cell_11.putColor(target);
}
}
public static function average2Colors(c1:uint, c2:uint):uint {
var odd:uint = c1 & c2 & 0x01010101;
c1 &= 0xfefefefe;
c1 >>>= 1;
c2 &= 0xfefefefe;
c2 >>>= 1;
return c1 + c2 + odd;
}
public static function average4Colors(c1:uint, c2:uint, c3:uint, c4:uint):uint {
return average2Colors(average2Colors(c1, c2), average2Colors(c3, c4));
}
public static function judgeAverage(c1:uint, c2:uint, c3:uint, c4:uint, mask:uint = 0x80808080):Boolean {
return ((c1 ^ c2) & mask) == 0 && ((c2 ^ c3) & mask) == 0 && ((c3 ^ c4) & mask) == 0;
}
}
class ColorPickCell extends ColorCell
{
protected var _source:BitmapData;
public function ColorPickCell(source:BitmapData, x:uint, y:uint, width:uint, height:uint)
{
_source = source;
super(x, y, width, height);
}
override public function get color():uint {
_color = _source.getPixel32(_x, _y);
return _color;
}
override public function putColor(target:BitmapData):void
{
var ba:ByteArray = byteArray;
var r:Rectangle = _rect;
ba.clear();
ba = _source.getPixels(r);
ba.position = 0;
target.setPixels(r, ba);
}
}