今天有位朋友给我发了邮件,说他按照《Flex2:使用BitmapData抓图》的方法,写了简单的Bitmap抓图程序,功能很简单,用Image载入图片。然后在Image上覆盖一个Canvas用户在载入的图片上作图,代码很简单,可是就是运行不正常,代码如下:
[xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" >
<mx:Script>
<![CDATA[
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.events.MouseEvent ;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import mx.controls.Alert;
import mx.rpc.http.mxml.HTTPService;
private var g:Graphics;
private var backGroundImageData : BitmapData;
private var mouseDown : Boolean = false;
private var lineThickness : Number = 2;
private var bitMap: Bitmap;
private function setUp():void
{
drawscreen.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownListener);
drawscreen.addEventListener(MouseEvent.MOUSE_UP , mouseUpListener);
drawscreen.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener);
g = drawscreen.graphics;
}
private function mouseDownListener(event:MouseEvent):void
{
mouseDown = true;
g.moveTo(event.localX, event.localY);
}
private function mouseUpListener(event:MouseEvent):void
{
mouseDown = false;
}
private function mouseMoveListener(event:MouseEvent):void
{
if( mouseDown)
{
g.lineStyle(lineThickness, colorPicker.selectedColor, 1 );
g.lineTo( event.localX, event.localY );
}
}
public function clearScribble():void
{
g.clear();
}
private function captureBitmap():void
{
backGroundImageData = new BitmapData( scribbleBoard.width, scribbleBoard.height);
backGroundImageData.draw ( scribbleBoard, scribbleBoard.transform.matrix, scribbleBoard.transform.colorTransform );
var newBitmapData:BitmapData=new BitmapData( scribbleBoard.width, scribbleBoard.height);
var bitmap:Bitmap=new Bitmap(newBitmapData);
addChild(bitmap);
}
]]>
</mx:Script>
<mx:Canvas creationComplete="setUp()" >
<mx:Panel height="100%" width="100%">
<mx:VBox horizontalAlign="center" verticalAlign="middle" height="100%" width="100%">
<mx:Canvas id="scribbleBoard" >
<mx:Image id="image" source="yourImage.jpg"/>
<mx:Canvas id="drawscreen"
height="{image.height}"
width="{image.width}"
backgroundAlpha="0" />
</mx:Canvas>
</mx:VBox>
<mx:HBox >
<mx:Button label="Clear" click="clearScribble()" />
<mx:Button label="Save" click="captureBitmap()" />
<mx:Label text="Line Thickness"/>
<mx:HSlider id="lineWidth" minimum="1" maximum="10" mouseUp="lineThickness = lineWidth.value"/>
<mx:Label id="la" text="Change color:"/>
<mx:ColorPicker id="colorPicker"/>
</mx:HBox>
<mx:ControlBar/>
</mx:Panel>
</mx:Canvas>
</mx:Application>
以上程序和Bitmap有关的部分如下:
[java]
private function captureBitmap():void
{
backGroundImageData = new BitmapData( scribbleBoard.width, scribbleBoard.height);
backGroundImageData.draw ( scribbleBoard, scribbleBoard.transform.matrix, scribbleBoard.transform.colorTransform );
var newBitmapData:BitmapData=new BitmapData( scribbleBoard.width, scribbleBoard.height);
var bitmap:Bitmap=new Bitmap(newBitmapData);
addChild(bitmap);
}
这段代码中,有个错误:
[java] backGroundImageData.draw ( scribbleBoard, scribbleBoard.transform.matrix, scribbleBoard.transform.colorTransform );
draw()方法不能直接使用scribbleBoard.transform.matrix和scribbleBoard.transform.colorTransform 。正确的用法是,如果你不想对BitmapData做任何处理的话,直接用null就可以了。所有正确的写法如下:
[java] backGroundImageData.draw ( scribbleBoard);
为了演示方便我将上面的代码更改为如下:
[xml]
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" >
<mx:Script>
<![CDATA[
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.events.MouseEvent ;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import mx.controls.Alert;
import mx.core.UIComponent;
private var g:Graphics;
private var mouseDown : Boolean = false;
private var lineThickness : Number = 2;
private function setUp():void
{
drawscreen.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownListener);
drawscreen.addEventListener(MouseEvent.MOUSE_UP , mouseUpListener);
drawscreen.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener);
g = drawscreen.graphics;
}
private function mouseDownListener(event:MouseEvent):void
{
mouseDown = true;
g.moveTo(event.localX, event.localY);
}
private function mouseUpListener(event:MouseEvent):void
{
mouseDown = false;
}
private function mouseMoveListener(event:MouseEvent):void
{
if( mouseDown)
{
g.lineStyle(lineThickness, colorPicker.selectedColor, 1 );
g.lineTo( event.localX, event.localY );
}
}
public function clearScribble():void
{
g.clear();
}
private function captureBitmap() : void
{
var bd : BitmapData = getBitmapData( UIComponent( scribbleBoard ) );
//modify by feiy,20070523
//the old code:
//addChild(new Bitmap(bd));
//the new code:
var uiComp:UIComponent = new UIComponent();
uiComp.addChild(new Bitmap(bd));
this.addChild(uiComp);
}
private function getBitmapData( target : UIComponent ) : BitmapData
{
try{
var bd : BitmapData = new BitmapData( target.width, target.height );
bd.draw(target);
return bd;
}catch(exp:Error){
Alert.show(exp.getStackTrace()+exp.message+exp.name+exp.toString()+exp.errorID);
}
return null;
}
]]>
</mx:Script>
<mx:Panel height="300" width="600">
<mx:VBox horizontalAlign="center" verticalAlign="middle" height="100%" width="100%">
<mx:Canvas id="scribbleBoard" creationComplete="setUp()">
<mx:Image id="image" source="init.jpg"/>
<mx:Canvas id="drawscreen"
height="{image.height}"
width="{image.width}"
backgroundAlpha="0" />
</mx:Canvas>
</mx:VBox>
<mx:HBox >
<mx:Button label="Clear" click="clearScribble()" />
<mx:Button label="Save" click="captureBitmap()" />
<mx:Label text="Line Thickness"/>
<mx:HSlider id="lineWidth" minimum="1" maximum="10" mouseUp="lineThickness = lineWidth.value"/>
<mx:Label id="la" text="Change color:"/>
<mx:ColorPicker id="colorPicker"/>
</mx:HBox>
<mx:ControlBar/>
</mx:Panel>
</mx:Application>
因为组件中有Image,有一点需要注意,Flex默认的编译设置中use-network=true,而对于Image组件来说,use-network为true就意味着如果是从本地载入图片,我们是不运行访问该Image的Bitmap数据的,所有如果本地调试以上代码会报安全错误的,如果要本地调试需要将use-network设置为false编译。对应的如果要在线调试又得将use-network设置为true,关于Image的的这个限制大家可以查看Flex官方文档,里面说的很详细。
另外,说句题外话,我们在Flex的开发过程中,最好使用带Debug功能的FlashPlayer调试程序,要不在碰到不解的问题时多使用try/catch,这样的好习惯能解决您的很多问题,比如上面说到的Image Bitmap数据的访问限制问题!
O comments at "Flex:Bitmap抓图释疑"