AIR BitmapData.draw slow - actionscript-3

I am working with large bitmapdata that I need to resize, doing some test I realized that the same code runs tooooo slow in AIR.
This is the code:
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.display.Bitmap;
import flash.geom.Point;
var MAX_BITMAP_SIZE:Point = new Point( 596, 842 );
var bitmapdata:BitmapData = new MyBitmap();
var sc:Number = Math.min( MAX_BITMAP_SIZE.x / bitmapdata.width, MAX_BITMAP_SIZE.y / bitmapdata.height );
var outBitmap:BitmapData = new BitmapData( bitmapdata.width >> 1, bitmapdata.height >> 1, false, 0x0 );
var bitmap:Bitmap = new Bitmap();
addChild( bitmap );
var scaleMatrix:Matrix = new Matrix();
scaleMatrix.scale(sc,sc);
var time:Number = new Date().getTime();
outBitmap.draw( bitmapdata, scaleMatrix, null,null,null,true );
trace( new Date().getTime()-time );
bitmap.bitmapData = outBitmap;
The same code tests:
Publish as flash 11.4 -> 1ms
Publish as AIR 3.4 ->62ms
Anyone?

Related

Get a ByteArray from BitmapData in AS3

I would like to get a ByteArray from a BitmapData in AS3. I tried the following:
var ba:ByteArray = myBitmapData.getPixels(0,0);
It didn't work and I got this error ArgumentError: Error #1063: Argument count mismatch on flash.display::BitmapData/getPixels(). Expected 1, got 2.:
As Adobe said about BitmapData.getPixels : "Generates a byte array from a rectangular region of pixel data...", so your parameter should be a Rectangle object.
Take this example from Adobe.com :
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
var bmd:BitmapData = new BitmapData(80, 40, true);
var seed:int = int(Math.random() * int.MAX_VALUE);
bmd.noise(seed);
var bounds:Rectangle = new Rectangle(0, 0, bmd.width, bmd.height);
var pixels:ByteArray = bmd.getPixels(bounds);
As was mentioned in the other answer, getpixels expects a .rect meaning rectangular area of some displayObject (like Sprite, MovieClip, Shape or other already exisiting BitmapData.
getPixels(). Expected 1, got 2. is becuase it should have been:
var ba:ByteArray = myBitmapData.getPixels( myBitmapData.rect);
Study this code and see if it helps you :
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.net.URLRequest;
import flash.display.BitmapData;
var ba:ByteArray = new ByteArray;
var picBMP:Bitmap; var picBMD:BitmapData;
var pic_canvas:Sprite = new Sprite(); //container for image
var loader:Loader = new Loader(); //image loader
loader.load(new URLRequest("pic1.jpg")); //load some JPG/PNG/GIF/SWF
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, img_load_Complete);
function img_load_Complete(evt:Event):void
{
picBMP = loader.content as Bitmap;
pic_canvas.addChild(picBMP);
stage.addChild(pic_canvas); //container now added to stage (screen)
BMP_toBytes(); //do function to convert to bytes
}
function BMP_toBytes():void
{
var PC = pic_canvas; //shortcut reference to pic_canvas (less typing)
picBMD = new BitmapData(PC.width, PC.height, true, 0xFFFFFF);
picBMD.draw(PC); //make bitmapdata snapshot of container
ba = picBMD.getPixels(picBMD.rect);
trace("BA length : " + ba.length); //check how many bytes in there
ba.position = 0; //reset position to avoid "End of File error"
bytes_toPixels(); //do function for bytes as pixels to some new container
}
function bytes_toPixels():void
{
var new_BMP:Bitmap = new Bitmap; var new_BMD:BitmapData;
var new_canvas:Sprite = new Sprite(); //another new container for pixels
ba.position = 0; //reset position to avoid "End of File error"
//we can reuse picBMD W/H sizes since we have copy of same pixels
new_BMD = new BitmapData(picBMD.width, picBMD.height, true, 0xFFFFFFFF);
new_BMD.setPixels(new_BMD.rect, ba); //paste from BA bytes
new_BMP.bitmapData = new_BMD; //update Bitmap to hold new data
new_canvas.x = 150; new_canvas.y = 0; new_canvas.addChild(new_BMP);
stage.addChild(new_canvas); //add to screen
}
Hope it helps..

action script 3.0 import fla with xml

i want import fla movie from xml. i can't make it. Thank for help.
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.text.engine.TabAlignment;
import flash.net.URLRequest;
import flash.media.Sound;
//i create timer for sound.
var tmr:Timer=new Timer(1000,1);
tmr.addEventListener(TimerEvent.TIMER, sesiBaslat);
function sesiBaslat(evt:TimerEvent){
var yol:URLRequest=new URLRequest("../../../sound/aaa/1/1/1.mp3");
var ses:Sound=new Sound();
ses.load(yol);
ses.play();
}
tmr.start();
//i was use this code in old times
/*var vid:Video = new Video(1600, 910);
flvPlaceHolder.addChild(vid);
addChild(flvPlaceHolder);
flvPlaceHolder.x = stage.stageWidth/2-vid.width/2;
flvPlaceHolder.y = stage.stageHeight/2-vid.height/2;
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
vid.attachNetStream(ns);
var listener:Object = new Object();
listener.onMetaData = function(evt:Object):void {};
ns.client = listener;
ns.play("fla/683-bak.flv");
*/
//now i want to write this format now,because i want to make it dynamic
var veriler:XML;
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, XMLokundu);
loader.load(new URLRequest("../../../xml/aaa/1/1/1.xml"));
function XMLokundu(e:Event):void{
veriler= new XML(e.target.data);
var loader1:Loader = new Loader();
loader1.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
loader1.load(new URLRequest(veriler.animasyonlar.animasyon[1].yolu));
//This blog was made a import sound,image etc. but doesnt work from fla
function imageLoaded(e:Event):void {
var flvPlaceHolder:MovieClip = new MovieClip();
var vid:Video = new Video();
e.target.content.smoothing = true;
addChild(loader1);
loader1.x = veriler.animasyonlar.animasyon[1].xkor;
loader1.y = veriler.animasyonlar.animasyon[1].ykor;
loader1.width = veriler.animasyonlar.animasyon[1].width;
loader1.height = veriler.animasyonlar.animasyon[1].height;
}
}
/*
//XML FİLE
//This is my xml file
<animasyonlar>
<animasyon>
<first>sound/16/1153.mp3</first>
<ikincises>sound/16/1154.mp3</ikincises>
<ucuncuses>sound/16/1151.mp3</ucuncuses>
<dorduncuses>sound/16/1152.mp3</dorduncuses>
<yolu>../../../../bbb/7/fla/683-look.flv</yolu> 1.fla way
<xkor>800</xkor> 2.x value
<ykor>100</ykor> 3.y value
<width>50%</width>
<height>50%</height>
</animasyon>
</animsyonlar>
Your XML is not formatted properly because your closing tag is missing the 2nd "a".
<animasyonlar>
...
</animsyonlar>

How to make a volume slider that uses channels

I am trying to make a volume slider that uses channels.
I am not sure how to do this.
Here is my code:
import flash.media.SoundChannel;
import flash.net.URLRequest;
import flash.media.Sound;
// Enter Frame Event
var sliderValue:uint = mySlider.sliderKnob.x;
addEventListener(Event.ENTER_FRAME, frame);
function frame(event):void {
sliderValue = mySlider.sliderKnob.x ;
status_txt.text = "Volume: "+sliderValue;
var snd:Sound = new Sound();
var channel:SoundChannel = new SoundChannel();
var volumeLevel = channel.soundTransform;
var req:URLRequest = new URLRequest("Background.mp3")
snd.load(req);
channel = snd.play();
var newLevel:Number = mySlider.sliderKnob.x / 100;
volumeLevel.volume = newLevel;
channel.soundTransform = volumeLevel;
}
You are instantiating and loading the sound on every single frame. And you need to make a new SoundTransform instance! I take it that the slider itself is working!
var snd:Sound = new Sound();
var channel:SoundChannel = new SoundChannel();
var volumeLevel:SoundTransform = new SoundTransform();
snd.load(new URLRequest("Background.mp3"));
channel = snd.play();
addEventListener(Event.ENTER_FRAME, frame);
function frame(event):void {
sliderValue = mySlider.sliderKnob.x ;
status_txt.text = "Volume: "+sliderValue;
var newLevel:Number = sliderValue / 100;
volumeLevel.volume = newLevel;
channel.soundTransform = volumeLevel;
}

Flash AS3 copyPixels from BitmapData into jpeg screenshot

I have code to create a live screenshot of the stage in my swf.
After that it saves as a jpeg. All good.
Only, I don't need the whole stage, I only need a cutout:
x,y: 357,341
widt,height: 319,483
My code looks like this..
Where and how do I insert the copypixels function?
(I'm a Flash novice, so go easy on me :-)
function mouseReleaseSave(event:MouseEvent):void {
import com.adobe.images.JPGEncoder;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequestHeader;
import flash.net.URLRequest;
var jpgSource:BitmapData = new BitmapData(this.stage.stageWidth, this.stage.stageHeight);
jpgSource.draw(this.stage);
var jpgEncoder:JPGEncoder = new JPGEncoder(70);
var jpgStream:ByteArray = jpgEncoder.encode(jpgSource);
//set the request's header,method and data
var header:URLRequestHeader = new URLRequestHeader("Content-type","application/octet-stream");
var loader:URLLoader = new URLLoader();
//sends jpg bytes to saveJPG.php script
var myRequest:URLRequest = new URLRequest("saveJPG.php");
myRequest.requestHeaders.push(header);
myRequest.method = URLRequestMethod.POST;
myRequest.data = jpgStream;
loader.load(myRequest);
//fire complete event;
loader.addEventListener(Event.COMPLETE,saved);
function saved(e:Event){
//trace the image file name
trace(loader.data);
}
}
This should help:
var subArea:Rectangle = new Rectangle(0,0, 319,483 );
var newBmp:Bitmap = new BitmapData( 319,483 );
var cutoutBmp:Bitmap = new Bitmap( newBmp, PixelSnapping.ALWAYS, true );
cutoutBmp.bitmapData.draw( jpgSource, new Matrix(1, 0, 0, 1, -357, -341) , null, null, subArea, true );

find top right corner of rotated textfield

I am using the following to rotate a textfield from its top right corner, I would like to know the best way to find the point of the top right corner.
var txt:TextField = new TextField();
txt.autoSize = TextFieldAutoSize.LEFT;
txt.htmlText = "Some text here>";
mtx = txt.transform.matrix.clone();
MatrixTransformer.rotateAroundInternalPoint(mtx, txt.width, 0, -45);
txt.transform.matrix = mtx;
EDITED:
I just written this test code below in the flash IDE (omg that hurts...), obviously there is an embedded font called Arial in the library. I can't get the circle to correctly position on the top right of the textfield.
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.geom.Matrix;
import flash.display.Shape;
import fl.motion.MatrixTransformer;
import flash.geom.Point;
import flash.text.TextFormat;
import flash.text.Font;
Font.registerFont(Arial);
var angle:Number = -45
var txt:TextField = new TextField();
txt.autoSize = TextFieldAutoSize.LEFT;
txt.embedFonts = true;
txt.defaultTextFormat = new TextFormat("Arial", 20, 0x0000ff);
txt.text = "Here is some text";
txt.border = true;
txt.x = 100;
txt.y = 100;
addChild(txt);
var circle:Shape = new Shape();
circle.graphics.beginFill(0x00ff00);
circle.graphics.drawCircle(-5, -5, 10);
circle.graphics.endFill();
addChild(circle);
var mtx:Matrix = txt.transform.matrix.clone();
MatrixTransformer.rotateAroundInternalPoint(mtx, txt.width, 0, angle);
txt.transform.matrix = mtx;
// The top right after being turned -45°
var localPoint:Point = new Point( txt.width, txt.height );
var globalPosition:Point = txt.localToGlobal( localPoint );
circle.x = globalPosition.x;
circle.y = globalPosition.y;
If you mean what was the top right before turning it:
// The field's original top right corner:
var localPoint:Point = new Point( txt.width, 0 );
var globalPosition:Point = txt.localToGlobal( localPoint );
If you mean, after having turned the field:
// The top right after being turned -45°
var localPoint:Point = new Point( txt.width, txt.height );
var globalPosition:Point = txt.localToGlobal( localPoint );
EDIT:
Ok, after seeing your test I experimented with a bunch of things and I think I found something that will work:
var angle:Number = -45
var txt:TextField = new TextField();
txt.autoSize = TextFieldAutoSize.LEFT;
txt.defaultTextFormat = new TextFormat("Arial", 20, 0x0000ff);
txt.text = "Here is some text";
txt.border = true;
txt.x = 100;
txt.y = 250;
stage.addChild(txt);
var local3d:Vector3D = new Vector3D( txt.width, txt.height );
var circle:Shape = new Shape();
circle.graphics.beginFill(0x00ff00);
circle.graphics.drawCircle(-5, -5, 10);
circle.graphics.endFill();
stage.addChild(circle);
var mtx:Matrix = txt.transform.matrix.clone();
mtx.rotate( -45 / 180 * Math.PI );
txt.transform.matrix = mtx;
var globalPosition:Point = txt.local3DToGlobal( local3d );
circle.x = globalPosition.x;
circle.y = globalPosition.y;
If I run this, I get a TextField, turned -45 degrees with a green ball stuck to what-used-to-be-the-bottom-right corner. I don't know your MatrixTransformer class, but it should be able to work with any matrix.
Try and copy&paste this code and fiddle around with it until you get the result you want.