[ごはんとFlash] 背景差分でホームページ素材メーカー
ごはんとFlashのライブコーディングしたやつ(要Webカメラ)
*
* こういうことになります
* http://lab.alumican.net/wonderfl/rice/
* 照明条件が悪かったのでうまく抜けてませんが、
* ちゃんとした背景のところでやればそれなりにうまくいくはず
*
* capture background : 背景画像の取り込み
* ready to capture : 押すと、次にマイクから大きな音が録音されたときに現在の画面をダウンロード可能な状態へキャプチャする
* load background : 背景部分に好きな画像を敷ける
* テキスト入力(大きい方): 某ホームPジビルD風のテキストを挿入できる
* テキスト入力(小さい方): フォントサイズの指定
* save : キャプチャ画像の保存(まずready to captureしたあとにキャプチャしないとダメ)
* delete : キャプチャ画像の消去
/**
* Copyright alumican_net ( http://wonderfl.net/user/alumican_net )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/pCoa
*/
// forked from alumican_net's 使いそうなもの詰め合わせセットお徳用
/**
* ごはんとFlashのライブコーディングしたやつ(要Webカメラ)
*
* こういうことになります
* http://lab.alumican.net/wonderfl/rice/
* 照明条件が悪かったのでうまく抜けてませんが、
* ちゃんとした背景のところでやればそれなりにうまくいくはず
*
* capture background : 背景画像の取り込み
* ready to capture : 押すと、次にマイクから大きな音が録音されたときに現在の画面をダウンロード可能な状態へキャプチャする
* load background : 背景部分に好きな画像を敷ける
* テキスト入力(大きい方): 某ホームPジビルD風のテキストを挿入できる
* テキスト入力(小さい方): フォントサイズの指定
* save : キャプチャ画像の保存(まずready to captureしたあとにキャプチャしないとダメ)
* delete : キャプチャ画像の消去
*/
package {
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.media.*;
import flash.text.*;
import flash.ui.*;
import flash.utils.*;
import com.bit101.components.*;
public class FlashTest extends Sprite {
public function FlashTest():void {
// write as3 code here..
Wonderfl.disable_capture();
var W:uint = 320;
var H:uint = 240;
var container:Sprite = addChild(new Sprite()) as Sprite;
container.x = 10;
container.y = 100;
var mirror:Matrix = new Matrix();
mirror.scale(-1, 1);
mirror.translate(W, 0);
var bmd:BitmapData = new BitmapData(W, H, true, 0x0);
var blend:Sprite = new Sprite();
var blendBg:Bitmap = blend.addChild(new Bitmap(bmd.clone())) as Bitmap;
var blendSrc:Bitmap = blend.addChild(new Bitmap(bmd.clone())) as Bitmap;
blendSrc.blendShader = new BackgroundDifferencingShader();
var background:Bitmap = container.addChild(new Bitmap(bmd.clone())) as Bitmap;
var blendResult:Bitmap = container.addChild(new Bitmap(bmd.clone())) as Bitmap;
var capture:Bitmap = addChild(new Bitmap(bmd.clone())) as Bitmap;
capture.x = container.x;
capture.y = container.y;
var camera:Camera = Camera.getCamera();
var video:Video = new Video(W, H);
video.attachCamera(camera);
var mic:Microphone = Microphone.getMicrophone();
mic.setLoopBack(true);
var waiting:Boolean = false;
var file:ImageFileReference = new ImageFileReference();
file.onImageLoadComplete = function(bmd:BitmapData):void
{
background.bitmapData = bmd;
}
file.onImageSaveComplete = function():void
{
capture.visible = false;
container.visible = true;
}
var deco:DecoratedText;
function createText():void
{
if (deco) container.removeChild(deco);
deco = container.addChild(new DecoratedText(inputField.text, parseInt(sizeField.text))) as DecoratedText;
deco.x = W / 2;
deco.y = H - 30;
}
var inputField:TextField = addChild(new TextField()) as TextField;
inputField.x = 10;
inputField.y = 50;
inputField.width = 320;
inputField.height = 20;
inputField.border = true;
inputField.type = TextFieldType.INPUT;
inputField.addEventListener(Event.CHANGE, function(e:*):void
{
createText();
});
var sizeField:InputText = new InputText(this, 360, 50, "", function(e:*):void
{
createText();
});
new PushButton(this, 10, 10, "capture background", function(e:Event):void
{
blendBg.bitmapData.draw(video, mirror);
});
new PushButton(this, 120, 10, "ready to capture", function(e:Event):void
{
waiting = true;
});
new PushButton(this, 230, 10, "load background", function(e:Event):void
{
file.loadImage();
});
new PushButton(this, 360, 100, "save", function(e:Event):void
{
file.saveAsPng(capture.bitmapData);
});
new PushButton(this, 360, 130, "delete", function(e:Event):void
{
capture.visible = false;
container.visible = true;
});
addEventListener(Event.ENTER_FRAME, function(e:*):void
{
blendSrc.bitmapData.draw(video, mirror);
blendResult.bitmapData.draw(blend);
if (waiting && mic.activityLevel > 13)
{
waiting = false;
capture.bitmapData.draw(container);
capture.visible = true;
container.visible = false;
}
});
}
}
}
import flash.display.Shader;
import flash.utils.ByteArray;
class BackgroundDifferencingShader extends Shader
{
private static var _data:Vector.<int> = Vector.<int>([ -91, 1, 0, 0, 0, -92, 22, 0, 66, 97, 99, 107, 103, 114, 111, 117, 110, 100, 68, 105, 102, 102, 101, 114, 101, 110, 99, 105, 110, 103, -96, 12, 110, 97, 109, 101, 115, 112, 97, 99, 101, 0, 110, 101, 116, 46, 97, 108, 117, 109, 105, 99, 97, 110, 0, -96, 12, 118, 101, 110, 100, 111, 114, 0, 97, 108, 117, 109, 105, 99, 97, 110, 0, -96, 8, 118, 101, 114, 115, 105, 111, 110, 0, 1, 0, -96, 12, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 0, 66, 97, 99, 107, 103, 114, 111, 117, 110, 100, 32, 68, 105, 102, 102, 101, 114, 101, 110, 99, 105, 110, 103, 0, -95, 1, 2, 0, 0, 12, 95, 79, 117, 116, 67, 111, 111, 114, 100, 0, -93, 0, 4, 98, 97, 99, 107, 103, 114, 111, 117, 110, 100, 0, -93, 1, 4, 102, 111, 114, 101, 103, 114, 111, 117, 110, 100, 0, -95, 2, 4, 1, 0, 15, 100, 115, 116, 0, -95, 1, 1, 0, 0, 2, 114, 97, 110, 103, 101, 0, -94, 1, 109, 105, 110, 86, 97, 108, 117, 101, 0, 0, 0, 0, 0, -94, 1, 109, 97, 120, 86, 97, 108, 117, 101, 0, 63, -128, 0, 0, -94, 1, 100, 101, 102, 97, 117, 108, 116, 86, 97, 108, 117, 101, 0, 61, -52, -52, -51, 48, 2, 0, -15, 0, 0, 16, 1, 29, 3, 0, -13, 2, 0, 27, 0, 48, 2, 0, -15, 0, 0, 16, 0, 29, 4, 0, -13, 2, 0, 27, 0, 29, 0, 0, 16, 3, 0, 0, 0, 2, 0, 0, 16, 4, 0, 0, 0, 24, 2, 0, -128, 0, 0, -64, 0, 43, 2, 0, -128, 0, 0, -128, 0, 29, 1, -128, -128, 0, -128, 0, 0, 29, 0, 0, 16, 3, 0, 64, 0, 2, 0, 0, 16, 4, 0, 64, 0, 24, 2, 0, -128, 0, 0, -64, 0, 43, 2, 0, -128, 0, 0, -128, 0, 29, 1, -128, 64, 0, -128, 0, 0, 45, 1, -128, -128, 1, -128, 64, 0, 29, 0, 0, 16, 3, 0, -128, 0, 2, 0, 0, 16, 4, 0, -128, 0, 24, 2, 0, -128, 0, 0, -64, 0, 43, 2, 0, -128, 0, 0, -128, 0, 29, 1, -128, 64, 0, -128, 0, 0, 45, 1, -128, -128, 1, -128, 64, 0, 52, 0, 0, 0, 1, -128, 0, 0, 50, 1, 0, -128, 0, 0, 0, 0, 50, 1, 0, 64, 0, 0, 0, 0, 50, 1, 0, 32, 63, -128, 0, 0, 50, 1, 0, 16, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 29, 1, 0, -128, 3, 0, 0, 0, 29, 1, 0, 64, 3, 0, 64, 0, 29, 1, 0, 32, 3, 0, -128, 0, 50, 1, 0, 16, 63, -128, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0]);
private static var _byteCode:ByteArray;
public function get range():Number { return _range; }
public function set range(value:Number):void { data.range.value = [_range = value]; }
private var _range:Number;
public function BackgroundDifferencingShader(range:Number = 0.1):void
{
if (_byteCode == null)
{
_byteCode = new ByteArray();
for (var i:uint = 0, l:uint = _data.length; i < l; ++i)
{
_byteCode.writeByte(_data[i]);
}
}
super(_byteCode);
this.range = range;
}
}
import flash.display.Sprite;
import flash.filters.*;
import flash.text.engine.*;
import flash.text.*;
class DecoratedText extends Sprite
{
public function DecoratedText(text:String, size:uint = 0):void
{
super();
var txtColor:uint = Math.random() * 0xffffff;
var fontSize:uint = (size != 0 ) ? size :
(text.length > 8) ? 24 :
(text.length > 6) ? 36 :
(text.length > 5) ? 48 : 64;
var font:FontDescription = new FontDescription("メイリオ,ヒラギノ角ゴ Pro W3,MS Pゴシック,_ゴシック,_等幅", FontWeight.NORMAL, FontPosture.NORMAL, FontLookup.DEVICE, RenderingMode.NORMAL);
var format:ElementFormat = new ElementFormat(font, fontSize, txtColor);
format.locale = "ja";
var textBlock:TextBlock = new TextBlock();
textBlock.lineRotation = TextRotation.ROTATE_0;
textBlock.textJustifier = new EastAsianJustifier("ja", LineJustification.UNJUSTIFIED);
textBlock.content = new TextElement(text, format);
var i:uint = 0;
var textLine:TextLine = textBlock.createTextLine(null, 500);
while (textLine)
{
addChild(textLine);
textLine.x = -textLine.width / 2;
textLine = textBlock.createTextLine(textLine, 500);
}
var glow:GlowFilter = new GlowFilter(Math.random() * 0xffffff, 1, 8, 8, 1000, 1);
var bevel:BevelFilter = new BevelFilter();
bevel.shadowAlpha = 0.3;
filters = [bevel, glow, bevel];
}
}
/**
* 画像を保存したり読み込んだりする
*/
import flash.display.Bitmap;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.errors.IllegalOperationError;
import flash.errors.MemoryError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.net.FileFilter;
import flash.net.FileReference;
class ImageFileReference
{
//コールバック
public var onImageLoadOpen:Function;
public var onImageLoadProgress:Function;
public var onImageLoadComplete:Function;
public var onImageLoadCancel:Function;
public var onImageLoadIOError:Function;
public var onImageLoadException:Function;
public var onImageSaveComplete:Function;
//デバッグ出力
private function _trace(m:*):void { if (_useTrace) trace(m); }
private var _useTrace:Boolean;
//読み込んだ画像
public function get bmd():BitmapData { return _bmd ? _bmd.clone() : null; }
private var _bmd:BitmapData;
private var _file:FileReference;
//Constructor
public function ImageFileReference(useTrace:Boolean = false):void
{
_useTrace = useTrace;
}
//画像の保存
public function saveAsPng(bmd:BitmapData, filename:String = "image.png"):void
{
var png:ByteArray = PNGEnc.encode(bmd);
_file = new FileReference();
_file.addEventListener(Event.SELECT, _fileSaveSelectHandler);
_file.save(png, filename);
}
private function _fileSaveSelectHandler(e:Event):void
{
_trace("save");
if (onImageSaveComplete != null) onImageSaveComplete();
}
//画像の読み込み
public function loadImage(filter:String = "*.jpg;*.png;.*gif"):void
{
_file = new FileReference();
_file.addEventListener(Event.SELECT, _fileLoadSelectHandler);
_file.addEventListener(Event.CANCEL, _fileLoadCancelHandler);
_file.browse();
}
private function _fileLoadCancelHandler(e:Event):void
{
_file.removeEventListener(Event.SELECT, _fileLoadSelectHandler);
_file.removeEventListener(Event.CANCEL, _fileLoadCancelHandler);
_trace("user canceled");
if (onImageLoadCancel != null) onImageLoadCancel();
}
private function _fileLoadSelectHandler(e:Event):void
{
_file.removeEventListener(Event.SELECT, _fileLoadSelectHandler);
_file.removeEventListener(Event.CANCEL, _fileLoadCancelHandler);
_file.addEventListener(Event.OPEN, _fileLoadOpenHandler);
_file.addEventListener(ProgressEvent.PROGRESS, _fileLoadProgressHandler);
_file.addEventListener(Event.COMPLETE, _fileLoadCompleteHandler);
_file.addEventListener(IOErrorEvent.IO_ERROR, _fileLoadIOErrorHandler);
try
{
_file.load();
}
catch(error:IllegalOperationError)
{
_trace("illegal operation error");
_file.removeEventListener(Event.OPEN, _fileLoadOpenHandler);
_file.removeEventListener(ProgressEvent.PROGRESS, _fileLoadProgressHandler);
_file.removeEventListener(Event.COMPLETE, _fileLoadCompleteHandler);
_file.removeEventListener(IOErrorEvent.IO_ERROR, _fileLoadIOErrorHandler);
if (onImageLoadException != null) onImageLoadException(error);
return;
}
catch(error:MemoryError)
{
_trace("memory error");
_file.removeEventListener(Event.OPEN, _fileLoadOpenHandler);
_file.removeEventListener(ProgressEvent.PROGRESS, _fileLoadProgressHandler);
_file.removeEventListener(Event.COMPLETE, _fileLoadCompleteHandler);
_file.removeEventListener(IOErrorEvent.IO_ERROR, _fileLoadIOErrorHandler);
if (onImageLoadException != null) onImageLoadException(error);
return;
}
catch(error:Error)
{
_trace("error");
_file.removeEventListener(Event.OPEN, _fileLoadOpenHandler);
_file.removeEventListener(ProgressEvent.PROGRESS, _fileLoadProgressHandler);
_file.removeEventListener(Event.COMPLETE, _fileLoadCompleteHandler);
_file.removeEventListener(IOErrorEvent.IO_ERROR, _fileLoadIOErrorHandler);
if (onImageLoadException != null) onImageLoadException(error);
return;
}
_trace("load");
}
private function _fileLoadIOErrorHandler(e:IOErrorEvent):void
{
_file.removeEventListener(Event.OPEN, _fileLoadOpenHandler);
_file.removeEventListener(ProgressEvent.PROGRESS, _fileLoadProgressHandler);
_file.removeEventListener(Event.COMPLETE, _fileLoadCompleteHandler);
_file.removeEventListener(IOErrorEvent.IO_ERROR, _fileLoadIOErrorHandler);
_trace("io error");
if (onImageLoadIOError != null) onImageLoadIOError(e);
}
private function _fileLoadOpenHandler(e:Event):void
{
_file.removeEventListener(Event.OPEN, _fileLoadOpenHandler);
_trace("open");
if (onImageLoadOpen != null) onImageLoadOpen(e);
}
private function _fileLoadProgressHandler(e:ProgressEvent):void
{
_trace("progress " + e.bytesLoaded + "bytes / " + e.bytesTotal + "bytes");
if (onImageLoadProgress != null) onImageLoadProgress(e.bytesLoaded, e.bytesTotal);
}
private function _fileLoadCompleteHandler(e:Event):void
{
_file.removeEventListener(ProgressEvent.PROGRESS, _fileLoadProgressHandler);
_file.removeEventListener(Event.COMPLETE, _fileLoadCompleteHandler);
_file.removeEventListener(IOErrorEvent.IO_ERROR, _fileLoadIOErrorHandler);
_trace("complete");
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, _fileLoadInitHandler);
loader.loadBytes(_file.data);
}
private function _fileLoadInitHandler(e:Event):void
{
e.target.removeEventListener(e.type, arguments.callee);
if (_bmd) _bmd.dispose();
_bmd = Bitmap(LoaderInfo(e.target).content).bitmapData;
_trace("init");
if (onImageLoadComplete != null) onImageLoadComplete(bmd);
}
}
/**
* PNGエンコーダ
* http://www.5etdemi.com/blog/archives/2006/12/as3-png-encoder-faster-better/
*/
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
import flash.utils.getTimer;
class PNGEnc {
public static function encode(img:BitmapData, type:uint = 0):ByteArray {
// Create output byte array
var png:ByteArray = new ByteArray();
// Write PNG signature
png.writeUnsignedInt(0x89504e47);
png.writeUnsignedInt(0x0D0A1A0A);
// Build IHDR chunk
var IHDR:ByteArray = new ByteArray();
IHDR.writeInt(img.width);
IHDR.writeInt(img.height);
if(img.transparent || type == 0)
{
IHDR.writeUnsignedInt(0x08060000); // 32bit RGBA
}
else
{
IHDR.writeUnsignedInt(0x08020000); //24bit RGB
}
IHDR.writeByte(0);
writeChunk(png,0x49484452,IHDR);
// Build IDAT chunk
var IDAT:ByteArray= new ByteArray();
switch(type)
{
case 0:
writeRaw(img, IDAT);
break;
case 1:
writeSub(img, IDAT);
break;
}
IDAT.compress();
writeChunk(png,0x49444154,IDAT);
// Build IEND chunk
writeChunk(png,0x49454E44,null);
// return PNG
return png;
}
private static function writeRaw(img:BitmapData, IDAT:ByteArray):void
{
var h:int = img.height;
var w:int = img.width;
var transparent:Boolean = img.transparent;
for(var i:int=0;i < h;i++) {
// no filter
if ( !transparent ) {
var subImage:ByteArray = img.getPixels(
new Rectangle(0, i, w, 1));
//Here we overwrite the alpha value of the first pixel
//to be the filter 0 flag
subImage[0] = 0;
IDAT.writeBytes(subImage);
//And we add a byte at the end to wrap the alpha values
IDAT.writeByte(0xff);
} else {
IDAT.writeByte(0);
var p:uint;
for(var j:int=0;j < w;j++) {
p = img.getPixel32(j,i);
IDAT.writeUnsignedInt(
uint(((p&0xFFFFFF) << 8)|
(p>>>24)));
}
}
}
}
private static function writeSub(img:BitmapData, IDAT:ByteArray):void
{
var r1:uint;
var g1:uint;
var b1:uint;
var a1:uint;
var r2:uint;
var g2:uint;
var b2:uint;
var a2:uint;
var r3:uint;
var g3:uint;
var b3:uint;
var a3:uint;
var p:uint;
var h:int = img.height;
var w:int = img.width;
for(var i:int=0;i < h;i++) {
// no filter
IDAT.writeByte(1);
if ( !img.transparent ) {
r1 = 0;
g1 = 0;
b1 = 0;
a1 = 0xff;
for(var j:int=0;j < w;j++) {
p = img.getPixel(j,i);
r2 = p >> 16 & 0xff;
g2 = p >> 8 & 0xff;
b2 = p & 0xff;
r3 = (r2 - r1 + 256) & 0xff;
g3 = (g2 - g1 + 256) & 0xff;
b3 = (b2 - b1 + 256) & 0xff;
IDAT.writeByte(r3);
IDAT.writeByte(g3);
IDAT.writeByte(b3);
r1 = r2;
g1 = g2;
b1 = b2;
a1 = 0;
}
} else {
r1 = 0;
g1 = 0;
b1 = 0;
a1 = 0;
for(j=0;j < w;j++) {
p = img.getPixel32(j,i);
a2 = p >> 24 & 0xff;
r2 = p >> 16 & 0xff;
g2 = p >> 8 & 0xff;
b2 = p & 0xff;
r3 = (r2 - r1 + 256) & 0xff;
g3 = (g2 - g1 + 256) & 0xff;
b3 = (b2 - b1 + 256) & 0xff;
a3 = (a2 - a1 + 256) & 0xff;
IDAT.writeByte(r3);
IDAT.writeByte(g3);
IDAT.writeByte(b3);
IDAT.writeByte(a3);
r1 = r2;
g1 = g2;
b1 = b2;
a1 = a2;
}
}
}
}
private static var crcTable:Array;
private static var crcTableComputed:Boolean = false;
private static function writeChunk(png:ByteArray,
type:uint, data:ByteArray):void {
var c:uint;
if (!crcTableComputed) {
crcTableComputed = true;
crcTable = [];
for (var n:uint = 0; n < 256; n++) {
c = n;
for (var k:uint = 0; k < 8; k++) {
if (c & 1) {
c = uint(uint(0xedb88320) ^
uint(c >>> 1));
} else {
c = uint(c >>> 1);
}
}
crcTable[n] = c;
}
}
var len:uint = 0;
if (data != null) {
len = data.length;
}
png.writeUnsignedInt(len);
var p:uint = png.position;
png.writeUnsignedInt(type);
if ( data != null ) {
png.writeBytes(data);
}
var e:uint = png.position;
png.position = p;
c = 0xffffffff;
for (var i:int = 0; i < (e-p); i++) {
c = uint(crcTable[
(c ^ png.readUnsignedByte()) &
0xff] ^ (c >>> 8));
}
c = uint(c^uint(0xffffffff));
png.position = e;
png.writeUnsignedInt(c);
}
}