/* 画像処理の練習 -->トーンカーブ(濃度変換) */ package { import flash.display.Sprite; import flash.events.MouseEvent; [SWF(framerate = "30", width = "500",height="500",backgroundColor="0xffffff")] public class Practice32 extends Sprite{ private var image:ImagePanel; public function Practice32() { var xy:XYGraph = new XYGraph(180,180); xy.x = 310; xy.y = 200; addChild(xy); var lines:Lines = new Lines(180, 180); lines.x = 310; lines.y = 200; addChild(lines); stage.addEventListener(MouseEvent.MOUSE_DOWN, lines.onDown); stage.addEventListener(MouseEvent.MOUSE_UP, lines.onUp); stage.addEventListener(MouseEvent.MOUSE_MOVE, lines.onMove); image = new ImagePanel(lines); addChild(image); image.x = 5; image.y = 20; stage.addEventListener(MouseEvent.MOUSE_UP, image.onMouseUp); var hist:Histgram = new Histgram(180, 180); image.hist = hist; hist.x = 310; hist.y = 10; addChild(hist); var _url:String = "http://assets.wonderfl.net/images/related_images/f/f0/f08c/f08c673a6768eaef2ce5226ebba5d0c0fcc80126"; image.load(_url); } } } import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; import flash.display.MovieClip; import flash.net.URLRequest; import flash.system.LoaderContext; class ImagePanel extends MovieClip { private var backup:Vector.<uint>; public var bmpdata:BitmapData; private var loader:Loader; private var bmp:Bitmap; private var lines:Lines; public var hist:Histgram = null; public function ImagePanel(_lines:Lines):void { lines = _lines; loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleted); } public function load(_url:String):void { loader.load(new URLRequest(_url), new LoaderContext(true)); } private function loadCompleted(e:Event):void { backup = new Vector.<uint>(); bmpdata = new BitmapData(loader.width, loader.height); bmpdata.draw(loader); for (var i:int = 0; i < bmpdata.width; i++) { for (var j:int = 0; j < bmpdata.height; j++) { backup.push(bmpdata.getPixel(i,j)); } } bmp = new Bitmap(bmpdata); addChild(bmp); if (hist != null) { hist.bmpdata = bmpdata; hist.draw(); } } public function onMouseUp(e:MouseEvent):void { if(!lines.isChanged)return; var id:int = 0; for (var i:int = 0; i < bmpdata.width; i++) { for (var j:int = 0; j < bmpdata.height; j++) { var color:uint = backup[id++]; var r:int = (color & 0xff0000) >> 16; r = Math.min(Math.max(0,r * lines.getValue(r / 255.0)),255); color = (r << 16) + (r << 8) + r; bmpdata.setPixel(i, j, color); } } if (hist != null) hist.draw(); lines.isChanged=false; } } class Lines extends MovieClip { private var xp:Vector.<Number>; private var yp:Vector.<Number>; private var selected:int = -1; public var isChanged:Boolean=false; public function Lines(w:Number,h:Number):void { xp = new Vector.<Number>(); yp = new Vector.<Number>(); xp.push(0); yp.push(h); xp.push(w); yp.push(0); draw(); } private function vector(x0:Number, y0:Number, x1:Number, y1:Number):Point { var len:Number = Math.sqrt(Math.pow(x1 - x0, 2) + Math.pow(y1 - y0, 2)); return new Point((x1 - x0) / len, (y1 - y0) / len); } public function getValue(xv:Number):Number { xv = Math.min(1.0, Math.max(0.0, xv)); var xx:Number = xp[xp.length - 1]; var px:int = xx * xv; if (px == 0) return 0.0; var id:int = getId(px); var py:Number = (yp[id] - yp[id - 1]) / (xp[id] - xp[id - 1]); py = py * (px - xp[id - 1]) + yp[id - 1]; return (yp[0]-py)/yp[0]; } private function draw():void { graphics.lineStyle(3, 0x222222); graphics.moveTo(xp[0], yp[0]); for (var i:int = 1; i < xp.length; i++) { graphics.lineTo(xp[i], yp[i]); } graphics.lineStyle(1, 0xff0000); for (i = 1; i < xp.length-1; i++) { graphics.drawCircle(xp[i], yp[i], 5); } } public function onUp(e:MouseEvent):void { selected = -1; } public function onMove(e:MouseEvent):void { if (selected < 1) return; var px:Number = e.stageX - x; var py:Number = e.stageY - y; xp[selected] = Math.min(xp[selected + 1]-1, Math.max(xp[selected - 1]+1, px)); yp[selected] = Math.max(yp[yp.length - 1] - 1, Math.min(yp[0] + 1, py)); graphics.clear(); draw(); isChanged=true; } public function onDown(e:MouseEvent):void { var px:Number = e.stageX - x; var py:Number = e.stageY - y; for (var i:int = 0; i < xp.length; i++) { var len:Number = Math.sqrt(Math.pow(xp[i] - px, 2) + Math.pow(yp[i] - py, 2)); if (len < 10) { selected = i; return; } } selected = getId(px); if (selected < 1) return; var yy:Number = (yp[selected] - yp[selected - 1]) / (xp[selected] - xp[selected - 1]); yy = yy * (px - xp[selected - 1]) + yp[selected - 1]; if (Math.abs(yy - py) < 10) { insetNode(selected, px, py); }else { selected = -1; } } private function getId(px:Number):int { for (var i:int = 1; i < xp.length; i++) { if (xp[i - 1] < px && xp[i] >= px) { return i; } } return -1; } private function insetNode(id:int, xx:int, yy:int):void { xp.splice(id, 0, xx); yp.splice(id, 0, yy); draw(); } } class XYGraph extends MovieClip { public function XYGraph(w:Number,h:Number):void { draw(w,h); } private function draw(w:Number,h:Number):void { graphics.lineStyle(2, 0x000000); graphics.drawRect(0, 0, w, h); for (var i:int = 1; i < 5; i++) { var x0:Number = i * 0.2 * h; dashedLine(x0, 0, x0, h, 1, 5, 0xaaaaaa); dashedLine(0, x0, w, x0, 1, 5, 0xaaaaaa); } } private function dashedLine(x0:int, y0:int, x1:int, y1:int, w:Number, s:int, color:uint):void { graphics.lineStyle(w, color); var lx:Number = x1 - x0; var ly:Number = y1 - y0; var dist:Number = Math.sqrt(lx * lx + ly * ly); var dx:Number = lx / dist; var dy:Number = ly / dist; var len:Number = 0; var px:Number = x0; var py:Number = y0; var i:int = 0; while (true) { graphics.moveTo(px, py); px += dx * s; py += dy * s; len = len + s; if (len > dist) break; if (i++ % 2 == 0) { graphics.lineTo(px, py); } } } } class Histgram extends MovieClip { public var bmpdata:BitmapData=null; private var hist:Vector.<int>; private var _width:int; private var _height:int; public function Histgram(w:int,h:int):void { _width = w; _height = h; hist = new Vector.<int>(); } private function clear():void { for (var i:int = 0; i < 256; i++) hist[i] = 0; graphics.clear(); } public function draw():void { clear(); graphics.lineStyle(2, 0x000000); graphics.drawRect(0, 0, _width, _height); for (var i:int = 0; i < bmpdata.width; i++) { for (var j:int = 0; j < bmpdata.height; j++) { var r:int = (bmpdata.getPixel(i, j) & 0xff0000) >> 16; hist[r]++; } } var max:Number = 0; for (i = 0; i < 256; i++) if(hist[i]>max)max=hist[i]; max = max * 1.5; graphics.lineStyle(1, 0x888888); for (i = 0; i < 256; i++) { var col:Number = (i / 256.0) * (_width - 2); var val:Number = (hist[i] / max) * (_height - 2); graphics.moveTo(col, _height - 1); graphics.lineTo(col,_height-1-val); } } } トーンカーブと濃度補正