/* PixelClip 「Load IMG」ボタンで画像をステージに読み込んで、 マウスで矩形を作って、jpg/pngで書き出すことができる。 =========================================== 重いPhotoShop(FireWorks)を起動しても やりたいことは ・画像の座標を知りたい。 ・色番号を知りたい。 ・矩形の幅を知りたい。 ・切り抜いて書き出し(透明の1pxの枠つけたり)。 だけだったりすることがある。 これくらいなら、ASでつくれるかも?? まずは頭の整理のために基礎部分を作ってみた。 [今後の参考]GIMP矩形ツール http://iccii.seesaa.net/article/28058268.html */ package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Shape; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; [SWF(backgroundColor="0x777777")] public class Main extends Sprite { private var _highlite:Highlite; private var _imageCanvas:Sprite; private var _toolsBar:ToolsBar; private var _targetBitmap:Bitmap; public function Main() { stage.scaleMode = "noScale"; stage.align = "TL"; stage.addEventListener(Event.RESIZE,onResize); _imageCanvas = new Sprite(); this.addChild(_imageCanvas); _highlite = new Highlite(); this.addChild(_highlite); _toolsBar = new ToolsBar(); _toolsBar.x = Math.floor((stage.stageWidth-_toolsBar.width)/2); _toolsBar.y = stage.stageHeight-82; _toolsBar.atLoadComp = atLoadComp; _toolsBar.atTextChange = atTextChange; this.addChild(_toolsBar); stage.addEventListener(MouseEvent.MOUSE_DOWN,onDown); stage.addEventListener(MouseEvent.MOUSE_MOVE,onMove); } private function atTextChange(a:Point,b:Point):void{ _highlite.atTextChange(a,b); atSelect(); } private function onResize(event:Event):void{ _toolsBar.x = Math.floor((stage.stageWidth-_toolsBar.width)/2); _toolsBar.y = stage.stageHeight-82; _imageCanvas.x = Math.floor((stage.stageWidth-_targetBitmap.width)/2); _imageCanvas.y = Math.floor((stage.stageHeight-_targetBitmap.height-_toolsBar.height)/2); _highlite.rectangle.x = _highlite.x = _imageCanvas.x; _highlite.rectangle.y = _highlite.y = _imageCanvas.y; } private function atSelect():void{ if(_highlite.selectedRectangle == null){return}; if(_highlite.selectedRectangle.width*_highlite.selectedRectangle.height<=0){return}; var bitmapData:BitmapData = new BitmapData(_highlite.selectedRectangle.width,_highlite.selectedRectangle.height); bitmapData.draw(_targetBitmap,new Matrix(1,0,0,1,-_highlite.selectedRectangle.x,-_highlite.selectedRectangle.y)); var bitmap:Bitmap = new Bitmap(bitmapData); _toolsBar.atSelect(_highlite.selectedRectangle,bitmap); } private function atLoadComp(bitmap:Bitmap):void{ while (_imageCanvas.numChildren > 0) { _imageCanvas.removeChildAt(0); } _imageCanvas.addChild(bitmap); _imageCanvas.x = Math.floor((stage.stageWidth-bitmap.width)/2); _imageCanvas.y = Math.floor((stage.stageHeight-bitmap.height-_toolsBar.height)/2); var monoglam:Shape = getBGMonoglam(bitmap.width,bitmap.height); _imageCanvas.addChildAt(monoglam,0); _highlite.rectangle = new Rectangle(_imageCanvas.x,_imageCanvas.y,bitmap.width,bitmap.height); _highlite.clear(); _targetBitmap = bitmap; } private function onDown(event:MouseEvent):void{ _highlite.onDown(); } private function onMove(event:MouseEvent):void{ if(!event.buttonDown){return}; _highlite.onMove(); atSelect(); } private function getBGMonoglam(width:int, height:int):Shape { var patern:BitmapData = new BitmapData(2, 2, false,0xFFFFFF); patern.setPixel(0, 1, 0xCCCCCC); patern.setPixel(1, 0, 0xCCCCCC); var shape:Shape = new Shape(); shape.graphics.beginBitmapFill(patern, new Matrix(8, 0, 0, 8)); shape.graphics.drawRect(0, 0, width, height); shape.graphics.endFill(); return shape; } } } import com.bit101.components.CheckBox; import com.bit101.components.HSlider; import com.bit101.components.Label; import com.bit101.components.Panel; import com.bit101.components.PushButton; import flash.display.Bitmap; import flash.display.Sprite; import flash.events.MouseEvent; import flash.geom.Point; import flash.text.TextField; import flash.text.TextFormat; class ToolsBar extends Sprite{ private var _hSlider:HSlider; private var _is32BitColor:CheckBox; private var _isClearEdge:CheckBox; private var _isEven:CheckBox; private var _jpgLavel:Label; private var _loadImgTF:TextField; private var _selectedTF:TextField; private var _selectedTFx:NumericTextField; private var _selectedTFy:NumericTextField; private var _selectedTFwidth:NumericTextField; private var _selectedTFheight:NumericTextField; private var _selectedTFarray:Array; private var _loadImgColorChip:Shape; private var _selectedColorChip:Shape; private var _selectedBitmap:Bitmap; public var atTextChange:Function = function(a:Point,b:Point):void{}; public var atLoadComp:Function = function(bitmap:Bitmap):void{}; public function ToolsBar(){ var panelLoad:Panel = new Panel(this,0,0); panelLoad.width = 116; panelLoad.height = 82; new PushButton(panelLoad,8,8,"Load IMG",atLoadClick); var panelJPG:Panel = new Panel(this,116*2,0); panelJPG.width = 116; panelJPG.height = 82; _jpgLavel = new Label(panelJPG,8,4,"Quality:90"); _hSlider = new HSlider(panelJPG,8,8+16,atJPGSlider); _hSlider.value = 90; new PushButton(panelJPG,8,8+16*3,"SAVE JPG",atJPGClick); var panelPNG:Panel = new Panel(this,116*3,0); panelPNG.width = 116; panelPNG.height = 82; _is32BitColor = new CheckBox(panelPNG,8,8,"32 Bit Color"); _is32BitColor.selected = true; _isClearEdge = new CheckBox(panelPNG,8,8+16,"Clear Edge"); _isEven = new CheckBox(panelPNG,8,8+16*2,"Even"); new PushButton(panelPNG,8,8+16*3,"SAVE PNG",atPNGClick); _loadImgTF = new TextField(); _loadImgTF.defaultTextFormat = new TextFormat("_sans", 9, "0x555555",null,null,null,null,null,null,null,null,null,2); _loadImgTF.text = "width:0\nheight:0\ncolor average"; _loadImgTF.x = 8; _loadImgTF.y = 28; _loadImgTF.width = 100; _loadImgTF.height = 50; panelLoad.addChild(_loadImgTF); _loadImgColorChip = new Shape(); _loadImgColorChip.x = 90; _loadImgColorChip.y = 55; panelLoad.addChild(_loadImgColorChip); var panelData:Panel = new Panel(this,116,0); panelData.width = 116; panelData.height = 82; _selectedTF = new TextField(); _selectedTF.defaultTextFormat = new TextFormat("_sans", 9, "0x555555"); _selectedTF.text = "color average"; _selectedTF.x = 8; _selectedTF.y = 5+12*4; _selectedTF.width = 100; _selectedTF.height = 82-8; panelData.addChild(_selectedTF); _selectedColorChip = new Shape(); _selectedColorChip.x = 90; _selectedColorChip.y = 55; panelData.addChild(_selectedColorChip); var templeteNTF:Object = {step:1,isKeyboardControl:true,minimum:0,maximum:4080,numeric:0,onChange:onTextChange}; var templeteTF:Object = {autoSize:"left",type:"input"}; var tx:Array = ["x:","y:","width:","height:"]; _selectedTFarray = []; var n:int = tx.length; for (var i:int = 0; i < n; i++) { var tf:TextField = new TextField(); tf.defaultTextFormat = new TextFormat("_sans", 9, "0x555555"); tf.text = tx[i]; tf.x = 8; tf.y = 5+12*i; tf.autoSize = "left"; tf.selectable = false; panelData.addChild(tf); _selectedTFarray[i] = new NumericTextField({defaultTextFormat:new TextFormat("_sans", 9, "0x555555")},templeteNTF,templeteTF); _selectedTFarray[i].x = int(tf.x+tf.width); _selectedTFarray[i].y = 5+12*i; _selectedTFarray[i].addEventListener(Event.CHANGE,onTextChange); panelData.addChild(_selectedTFarray[i]); } } private function onTextChange(event:Event = null):void{ var a:Point = new Point(_selectedTFarray[0].numeric,_selectedTFarray[1].numeric); var b:Point = new Point(_selectedTFarray[2].numeric+_selectedTFarray[0].numeric,_selectedTFarray[3].numeric+_selectedTFarray[1].numeric); atTextChange(a,b); } private function atLoadClick(event:MouseEvent):void{ var loadFile:LoadFile = new LoadFile(); loadFile.atComplete = atLoadComplete; loadFile.start(); } private function atLoadComplete(event:Event):void{ atLoadComp(event.target.content); var bitmapData:BitmapData = new BitmapData(event.target.content.width,event.target.content.height); bitmapData.draw(event.target.content); var rgb:uint = getColorAverage(bitmapData); _loadImgTF.text = "width:"+event.target.content.width+"\nheight:"+event.target.content.height+"\nave."+"0x"+rgb.toString(16).toUpperCase(); _loadImgColorChip.graphics.clear(); _loadImgColorChip.graphics.beginFill(rgb%0x1000000,(rgb >> 24 & 0xFF)/0xFF); _loadImgColorChip.graphics.drawRect(0,0,9,9); _loadImgColorChip.graphics.endFill(); } public function atSelect(selectedRectangle:Rectangle,bitmap:Bitmap):void{ var bitmapData:BitmapData = new BitmapData(selectedRectangle.width,selectedRectangle.height); bitmapData.draw(bitmap); var rgb:uint = getColorAverage(bitmapData); _selectedTF.text = "ave."+"0x"+rgb.toString(16).toUpperCase(); _selectedTFarray[0].numeric = selectedRectangle.x; _selectedTFarray[1].numeric = selectedRectangle.y; _selectedTFarray[2].numeric = selectedRectangle.width; _selectedTFarray[3].numeric = selectedRectangle.height; _selectedColorChip.graphics.clear(); _selectedColorChip.graphics.beginFill(rgb%0x1000000,(rgb >> 24 & 0xFF)/0xFF); _selectedColorChip.graphics.drawRect(0,0,9,9); _selectedColorChip.graphics.endFill(); _selectedBitmap = bitmap; } private function getColorAverage(bitmapData:BitmapData):uint{ var w:int = bitmapData.width; var h:int = bitmapData.height; var n:int = w*h; var a:uint; var r:uint; var g:uint; var b:uint; for (var i:int = 0; i < n; i++) { var argb:uint = bitmapData.getPixel32(i%w,Math.floor(i/w)); a += argb >> 24 & 0xFF; r += argb >> 16 & 0xFF; g += argb >> 8 & 0xFF; b += argb & 0xFF; } a = Math.floor(a/n); r = Math.floor(r/n); g = Math.floor(g/n); b = Math.floor(b/n); return ((a*0x1000000+r*0x10000+g*0x100+b)); } private function atPNGClick(event:MouseEvent):void{ if(_selectedBitmap.width*_selectedBitmap.height){ SaveImage.PNGfromDisplayObject(_selectedBitmap,_is32BitColor.selected,_isClearEdge.selected,_isEven.selected); } } private function atJPGClick(event:MouseEvent):void{ if(_selectedBitmap.width*_selectedBitmap.height){ SaveImage.JPGfromDisplayObject(_selectedBitmap,Number(_jpgLavel.text.substr(8))); } } private function atJPGSlider(event:Event):void{ _jpgLavel.text = String("Quality:"+Math.round(event.target.value)); } } import flash.display.Shape; import flash.geom.Point; import flash.geom.Rectangle; class Highlite extends Shape{ private var _down:Point; public var selectedRectangle:Rectangle; private var _rectangle:Rectangle; public function Highlite(x:Number=0,y:Number=0,width:Number=0,height:Number=0){ rectangle = new Rectangle(x,y,width,height); _down = new Point(); }; private function target(a:Point,b:Point):void{ var x:Number = Math.max(0,Math.min(a.x,b.x)); var y:Number = Math.max(0,Math.min(a.y,b.y)); var w:Number = Math.min(rectangle.width,Math.max(a.x,b.x))-x; var h:Number = Math.min(rectangle.height,Math.max(a.y,b.y))-y; if(w<0 || h<0){return}; this.graphics.clear(); this.graphics.beginFill(0xCC3333,0.5); this.graphics.drawRect(0,0,rectangle.width,rectangle.height); this.graphics.drawRect(x,y,w,h); this.graphics.endFill(); selectedRectangle = new Rectangle(x,y,w,h); } public function atTextChange(a:Point,b:Point):void{ target(a,b); } public function set rectangle(rect:Rectangle):void{ this.x = rect.x; this.y = rect.y; _rectangle = rect; } public function get rectangle():Rectangle{ return _rectangle; } public function clear():void{ this.graphics.clear(); } public function onDown():void{ _down = new Point(this.mouseX,this.mouseY); } public function onMove():void{ var up:Point = new Point(this.mouseX,this.mouseY); target(_down,up); } } import flash.events.Event; import flash.events.KeyboardEvent; import flash.text.TextField; class NumericTextField extends TextField{ private var _base:int = 10; private var _isDecimalPoint:Boolean = true; private var _isKeyboardControl:Boolean; private var _isUpperCase:Boolean = true; private var _length:int = -1; private var _maximum:Number = Infinity; private var _minimum:Number = -Infinity; private var _numeric:Number; private var _isPrefix:Boolean; private var _step:Number =1; public function NumericTextField(... args){ for (var i:int = 0; i < args.length; i++) { var params:Object = args[i]; for (var str:String in params) { this[str] = params[str]; } } this.addEventListener(Event.ADDED_TO_STAGE,atAddedToStage); } private function atAddedToStage(event:Event):void{ this.removeEventListener(Event.ADDED_TO_STAGE,atAddedToStage); this.addEventListener(Event.REMOVED_FROM_STAGE,atRemoverFromStage); //isKeyboardControl = _isKeyboardControl; } private function atRemoverFromStage(event:Event):void{ this.removeEventListener(Event.REMOVED_FROM_STAGE,atRemoverFromStage); this.removeEventListener(KeyboardEvent.KEY_DOWN,atKeyboardEvent); } private function atKeyboardEvent(event:KeyboardEvent):void{ if(event.keyCode == 38){ numeric += _step; }else if(event.keyCode == 40){ numeric -= _step; } } public var onChange:Function = function():void{}; /** * 基数(value進数)の設定。デフォルトは10進数。10/16/2の設定ができる。 */ public function get base():int{return _base;}; public function set base(value:int):void{ if(value != 16 && value != 10 && value != 2){return}; _base = value; if(value == 16){ if(_isPrefix){ this.restrict = "A-F a-f 0-9 x"; }else{ this.restrict = "A-F a-f 0-9"; } }else if(value == 10){ if(_isDecimalPoint){ this.restrict = "0-9 \."; }else{ this.restrict = "0-9"; } }else if(value == 2){ this.restrict = "0-1"; } setText(); } /** * 小数点入力の可否。デフォルトは可 */ public function get isDecimalPoint():Boolean{return _isDecimalPoint;}; public function set isDecimalPoint(value:Boolean):void{ if(_isDecimalPoint == value){return}; _isDecimalPoint = value; if(_base == 10){ if(value){ this.restrict = "0-9 \."; }else{ this.restrict = "0-9"; } } } /** * キーボードでのコントロールをするか否か。デフォルトは否 */ public function get isKeyboardControl():Boolean{return _isKeyboardControl;}; public function set isKeyboardControl(value:Boolean):void{ if(_isKeyboardControl == value){return}; _isKeyboardControl = value; if(value){ this.removeEventListener(KeyboardEvent.KEY_DOWN,atKeyboardEvent); this.addEventListener(KeyboardEvent.KEY_DOWN,atKeyboardEvent); }else{ this.removeEventListener(KeyboardEvent.KEY_DOWN,atKeyboardEvent); } } /** * プレフィックス(0x)を付けるか否か。デフォルトはつけない */ public function get isPrefix():Boolean{return _isPrefix;}; public function set isPrefix(value:Boolean):void{ if(_isPrefix == value){return}; _isPrefix = value; if(_base == 16){ if(value){ this.restrict = "A-F a-f 0-9 x"; }else{ this.restrict = "A-F a-f 0-9"; } } setText(); } /** * 大文字か小文字か。デフォルトは大文字 */ public function get isUpperCase():Boolean{return _isUpperCase;}; public function set isUpperCase(value:Boolean):void{ if(_isUpperCase == value){return}; _isUpperCase = value; setText(); } /** * int型でテキストの桁数指定。-1でなりゆき。デフォルトは-1; */ public function set length(value:int):void{ if(_length == value){return}; _length = value; setText(); } /** * Number型でテキストを設定。デフォルトは0 */ public function get numeric():Number{ var string:String = super.text; if(string.substr(0,2) != "0x" && base == 16){ return Number("0x"+super.text); }else{ return Number(super.text); } }; public function set numeric(value:Number):void{ if(_numeric == value){return}; if(!isNaN(value)){ _numeric = Math.max(Math.min(value,_maximum),_minimum); }else{ //_numeric = minimum; }; setText(); } /** * 一回のキー押し下げでどれくらい値が変わるか。デフォルトは1 */ public function get step():Number{return _step;}; public function set step(value:Number):void{ if(_step == value){return}; _step = value; } /** * 最大値。デフォルトはInfinity */ public function get maximum():Number{return _maximum;}; public function set maximum(value:Number):void{ if(_maximum == value){return}; _maximum = value; numeric = Math.min(value,_numeric); } /** * 最小値。デフォルトは-Infinity */ public function get minimum():Number{return _minimum;}; public function set minimum(value:Number):void{ if(_minimum == value){return}; _minimum = value; numeric = Math.max(value,_numeric); } override public function set text(value:String):void{ if(super.text == value){return}; if(base == 16){ if(_isPrefix){ numeric = Number(value); }else{ numeric = Number("0x"+value); } }else if(base == 10){ numeric = Number(value); }else if(base == 2){ numeric = Number(value); } } private function setText():void{ var string:String = _numeric.toString(_base); if(string == "NaN"){ string = ""; } if(_isUpperCase){ string = string.toUpperCase(); } if(_length > 0){ string = ("0000000000000000000000000000000000000000000000000000000000000000"+string).substr(-_length); } if(_isPrefix && _base == 16 && _length > 0){ string = "0x"+string; } super.text = string; if(this.stage && this.root.stage.focus == this){ onChange(); } } } import flash.display.Loader; import flash.events.Event; import flash.net.FileReference; import flash.system.LoaderContext; class LoadFile{ private var _fileReference:FileReference; public var atComplete:Function = function(event:Event):void{}; /** * 開始 * */ public function start():void { if(_fileReference){ return; } _fileReference = new FileReference(); _fileReference.browse(); _fileReference.addEventListener(Event.SELECT,atSelect); } /** * ファイルの選択が完了すると動く * @param event * */ private function atSelect(event:Event):void{ _fileReference.removeEventListener(Event.SELECT,atSelect); _fileReference.addEventListener(Event.COMPLETE,atFileComplete); _fileReference.load(); } /** * 選択したファイルを読み込み完了すると動く * @param event * */ private function atFileComplete(event:Event):void{ _fileReference.removeEventListener(Event.COMPLETE,atFileComplete); var loader:Loader = new Loader(); loader.loadBytes(event.target.data,new LoaderContext()); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,atBytesComplete); } /** * 読み込んだファイルのバイトアレイを変換完了で動く * @param event * */ private function atBytesComplete(event:Event):void{ event.target.removeEventListener(Event.COMPLETE,atBytesComplete); atComplete(event); } } import com.adobe.images.JPGEncoder; import com.adobe.images.PNGEncoder; import flash.display.BitmapData; import flash.display.DisplayObject; import flash.geom.Matrix; import flash.net.FileReference; import flash.utils.ByteArray; class SaveImage{ public function SaveImage(){}; /** * PNG画像を書き出すためのメソッド * @param displayObject * @param is32BitColor//アルファチャンネル付きか否か * @param isClearEdge//1pxの余白を付けるか否か * @param isEven//画像の大きさ(縦横)を偶数にするか否か * */ public static function PNGfromDisplayObject(displayObject:DisplayObject,is32BitColor:Boolean = true,isClearEdge:Boolean=false,isEven:Boolean=false):void{ var width:int = displayObject.width+(isClearEdge?2:0); var height:int = displayObject.height+(isClearEdge?2:0); var txty:int = isClearEdge?1:0; if(isEven){ width += width%2; height += height%2; } var bitmapData:BitmapData = new BitmapData(width,height,is32BitColor,0xFFFFFF); bitmapData.draw(displayObject,new Matrix(1,0,0,1,txty,txty)); var byteArray:ByteArray = PNGEncoder.encode(bitmapData); var fileReference:FileReference = new FileReference(); fileReference.save(byteArray,"image.png"); } /** * JPG画像を書き出すためのメソッド * @param displayObject * @param quality//画質0-100 * */ public static function JPGfromDisplayObject(displayObject:DisplayObject,quality:Number=50):void{ var width:int = displayObject.width; var height:int = displayObject.height; var bitmapData:BitmapData = new BitmapData(width,height); bitmapData.draw(displayObject); var jPGEncoder:JPGEncoder = new JPGEncoder(quality); var byteArray:ByteArray = jPGEncoder.encode(bitmapData); var fileReference:FileReference = new FileReference(); fileReference.save(byteArray,"image.jpg"); } } PixelClip