Forked from: undo's pngで保存 forked from: モザイク forked from: モザイクがうまくいかない.. diff:58 単位面積あたりの偏差が小さい場合は赤く塗りつぶす forked from: pngで保存 undo forked:1favorite:3lines:224license : MIT License modified : 2009-11-16 17:01:09 Embed Tweet <?xml version = "1.0" encoding = "utf-8"?> <!-- forked from undo's pngで保存 forked from: モザイク forked from: モザイクがうまくいかない --> <!-- forked from undo's モザイク forked from: モザイクがうまくいかない --> <!-- forked from undo's モザイクがうまくいかない --> <mx:Application xmlns:mx = "http://www.adobe.com/2006/mxml" layout = "absolute" applicationComplete = "init();"> <mx:Script> <![CDATA[ /* *モザイク単位あたりのアルファ、R、G、Bチャンネルで偏差を取り、 *すべてしきい値以下だった場合、つまり見た感じ同じ色の面積が大きかった場合、 *その範囲を真っ赤に塗ります。 *偏差が大きい場合は普通にモザイクします。 *なので、画像が細かかったり色が複雑な部分は赤くなりません。 */ import com.adobe.images.PNGEncoder; import flash.display.Bitmap; import flash.display.BitmapData; import flash.geom.Rectangle; import flash.net.FileFilter; private var fr:FileReference = new FileReference(); private var ba:ByteArray = new ByteArray(); private var mosaic:ByteArray = new ByteArray(); private var rl:Loader = new Loader(); private var bmd:BitmapData; private var bm:Bitmap = new Bitmap(); private var pbmd:BitmapData; //偏差のしきい値。1チャンネルの値は0〜255だから30くらいが妥当かと思ったのですがどうでしょうか。 private var hensaThreshold:Number = 30; private function init():void { this.image.addChild(bm); } private function onBrowseBtnClick():void { //画像ファイルを参照 this.fr.addEventListener(Event.SELECT, onFileSelect); this.fr.browse([new FileFilter("Image", "*.jpg;*.gif;*.png")]); } private function onFileSelect(evt:Event):void { this.fr.removeEventListener(Event.SELECT, onFileSelect); this.fr.addEventListener(Event.COMPLETE, onFileComplete); this.fr.load(); } private function onFileComplete(evt:Event):void { //画像をByteArrayに格納 this.fr.removeEventListener(Event.COMPLETE, onFileComplete); this.ba = this.fr.data; this.rl.contentLoaderInfo.addEventListener(Event.COMPLETE, onPreviewLoadComp); this.rl.loadBytes(this.ba); } private function onPreviewLoadComp(evt:Event):void { this.rl.contentLoaderInfo.removeEventListener(Event.COMPLETE, onPreviewLoadComp); this.bmd = new BitmapData(this.rl.contentLoaderInfo.width, this.rl.contentLoaderInfo.height, false); this.bmd.draw(rl); this.bm.bitmapData = this.bmd; this.bm.scaleX = this.bm.scaleY = 1; this.bm.scaleX = this.bm.scaleY = Math.min(this.width / this.bm.width, this.height / this.bm.height); //trace(this.bmd.width, this.bm.height); } private function onMosaicBtnClick():void { if (this.ba.length > 0) { startMosaic(); } else { //画像を参照してね } } // //画像をMosaicする // private function startMosaic():void { this.mosaic = null; this.mosaic = new ByteArray(); this.pbmd = this.bmd.clone(); this.bm.bitmapData = this.pbmd; var t:int = Math.floor(Number(this.time.text)); var blockX:int = Math.floor(this.rl.contentLoaderInfo.width / t); var blockY:int = Math.floor(this.rl.contentLoaderInfo.height / t); var newColor:uint = 0; var newAlpha:uint = 0; var newRed:uint = 0; var newGreen:uint = 0; var newBlue:uint = 0; var newColorArray:Array = new Array(); //まず端は無視してブロック処理 for (var i:int = 0; i < blockX; i++) { for (var j:int = 0; j < blockY; j++) { newColorArray = []; for (var k:int = 0; k < t; k++) { for (var l:int = 0; l < t; l++) { newColor = this.pbmd.getPixel32(l + i * t, k + j * t); newAlpha += newColor >> 24 & 0xff; newRed += newColor >> 16 & 0xff; newGreen += newColor >> 8 & 0xff; newBlue += newColor & 0xff; newColorArray.push(newColor); } } newAlpha = Math.floor(newAlpha / (t * t)); newRed = Math.floor(newRed / (t * t)); newGreen = Math.floor(newGreen / (t * t)); newBlue = Math.floor(newBlue / (t * t)); newColor = (newAlpha << 24 | newRed << 16 | newGreen << 8 | newBlue); var alphaHensa:Number=0; var redHensa:Number=0; var greenHensa:Number=0; var blueHensa:Number=0; for(var colorIndex:int = 0; colorIndex < newColorArray.length; colorIndex++) { //アルファ alphaHensa += (newColorArray[colorIndex]>>24 & 0xff - newAlpha)*(newColorArray[colorIndex]>>24 & 0xff - newAlpha); //赤 redHensa += (newColorArray[colorIndex]>>16 & 0xff - newRed)*(newColorArray[colorIndex]>>16 & 0xff - newRed); //緑 greenHensa += (newColorArray[colorIndex]>>8 & 0xff - newGreen)*(newColorArray[colorIndex]>>8 & 0xff - newGreen); //青 blueHensa += (newColorArray[colorIndex] & 0xff - newBlue)*(newColorArray[colorIndex] & 0xff - newBlue); } alphaHensa = Math.sqrt(alphaHensa/(t*t)); redHensa = Math.sqrt(redHensa/(t*t)); greenHensa = Math.sqrt(greenHensa/(t*t)); blueHensa = Math.sqrt(blueHensa/(t*t)); //trace("hensa: ",alphaHensa,redHensa,greenHensa,blueHensa); //偏差がしきい値以下の場合、そのRectangleを真っ赤にする if(alphaHensa < hensaThreshold && redHensa < hensaThreshold && greenHensa < hensaThreshold && blueHensa < hensaThreshold) { newColor = 0xffff0000; this.pbmd.fillRect(new Rectangle(i * t, j * t, t, t), newColor); } newAlpha = 0; newRed = 0; newGreen = 0; newBlue = 0; } } //残った部分を処理 var leftWidth:Number = this.rl.contentLoaderInfo.width - Math.floor(this.rl.contentLoaderInfo.width / t); var leftHeight:Number = this.rl.contentLoaderInfo.height - Math.floor(this.rl.contentLoaderInfo.height / t); for (var m:int = 0; m < blockX; m++) { for (var n:int = 0; n < t; n++) { for (var o:int = 0; o < leftHeight; o++) { newColor = this.bmd.getPixel32(n + m * t, o + blockY * t); newAlpha += newColor >> 24 & 0xff; newRed += newColor >> 16 & 0xff; newGreen += newColor >> 8 & 0xff; newBlue += newColor & 0xff; } } newAlpha = Math.floor(newAlpha / (t * leftHeight)); newRed = Math.floor(newRed / (t * leftHeight)); newGreen = Math.floor(newGreen / (t * leftHeight)); newBlue = Math.floor(newBlue / (t * leftHeight)); newColor = (newAlpha << 24 | newRed << 16 | newGreen << 8 | newBlue); this.pbmd.fillRect(new Rectangle(m * t, blockY * t, t, leftHeight), newColor); newAlpha = 0; newRed = 0; newGreen = 0; newBlue = 0; } for (var p:int = 0; p < blockY; p++) { for (var q:int = 0; q < t; q++) { for (var r:int = 0; r < leftWidth; r++) { newColor = this.bmd.getPixel32(r + blockX * t, q + p * t); newAlpha += newColor >> 24 & 0xff; newRed += newColor >> 16 & 0xff; newGreen += newColor >> 8 & 0xff; newBlue += newColor & 0xff; } } newAlpha = Math.floor(newAlpha / (t * leftWidth)); newRed = Math.floor(newRed / (t * leftWidth)); newGreen = Math.floor(newGreen / (t * leftWidth)); newBlue = Math.floor(newBlue / (t * leftWidth)); newColor = (newAlpha << 24 | newRed << 16 | newGreen << 8 | newBlue); this.pbmd.fillRect(new Rectangle(blockX * t, p * t, leftWidth, t), newColor); newAlpha = 0; newRed = 0; newGreen = 0; newBlue = 0; } for (var s:int = 0; s < leftWidth; s++) { for (var u:int = 0; u < leftHeight; u++) { newColor = this.bmd.getPixel32(s + blockX * t, u + blockY * t); newAlpha += newColor >> 24 & 0xff; newRed += newColor >> 16 & 0xff; newGreen += newColor >> 8 & 0xff; newBlue += newColor & 0xff; } } newAlpha = Math.floor(newAlpha / (leftWidth * leftHeight)); newRed = Math.floor(newRed / (leftWidth * leftHeight)); newGreen = Math.floor(newGreen / (leftWidth * leftHeight)); newBlue = Math.floor(newBlue / (leftWidth * leftHeight)); newColor = (newAlpha << 24 | newRed << 16 | newGreen << 8 | newBlue); this.pbmd.fillRect(new Rectangle(blockX * t, blockY * t, leftWidth, leftHeight), newColor); newAlpha = 0; newRed = 0; newGreen = 0; newBlue = 0; //以上モザイク処理 //モザイクBitmapDataをJPGEncoderにかける this.mosaic = PNGEncoder.encode(this.pbmd); } private function onMosaicLoadComp(evt:Event):void { this.rl.removeEventListener(Event.COMPLETE, onMosaicLoadComp); this.rl.scaleX = this.rl.scaleY = 1; this.rl.scaleX = this.rl.scaleY = Math.min(this.width / this.rl.width, this.height / this.rl.height); } private function onSaveBtnClick():void { //画像を保存 if (this.mosaic.length > 0) { this.fr.save(this.mosaic, "mosaic.png"); } else { //mosaicしてね。 } } ]]> </mx:Script> <mx:Image id = "image" /> <mx:HBox paddingTop = "10" paddingLeft = "10"> <mx:Button id = "browseBtn" label = "参照" click = "onBrowseBtnClick();" /> <mx:TextInput id = "time" text = "10" width = "50" /> <mx:Label text = "←粗さ" /> <mx:Button id = "createBtn" label = "モザイク!" click = "onMosaicBtnClick();" /> <mx:Button id = "saveBtn" label = "保存" click = "onSaveBtnClick();" /> </mx:HBox> </mx:Application> Code Fullscreen Preview Fullscreen h1ro umhr : flex clockmaker : 画像の標準偏差を求める bitmapdata flex sort new page view favorite forked pv2257 画像をフラクタル化 forked from: 単位面積あたり.. undo forked:1 favorite:7lines:199 (diff:214) tag: RGB algorithm animation bitmap bitmapdata draw fractal