positioning bitmapdata - actionscript-3

I have the following code:
public function Application()
{
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
var urlRequest:URLRequest = new URLRequest("image/1.jpg");
loader.load(urlRequest);
addChild(loader);
}
private function completeHandler(e:Event):void{
loader.content.width = 800;
loader.content.scaleY = loader.content.scaleX;
piece = Math.round(loader.height/10);
drawBitmaps();
}
private function drawBitmaps():void{
var bmdata:BitmapData = new BitmapData(loader.width, piece, true, 0x000000);
bmdata.draw(loader);
var bitmap:Bitmap = new Bitmap(bmdata);
addChild(bitmap);
loader.visible = false;
}
the result is a bitmap wich contains a pice of the image. The height is 80. and it starts at the top of the image. But how can i tell the bitmapdata to start drawing the image from lets say 80pixels? so it draws a middle piece of the image? Because atm it allways draws from the top of the image.

You should use BitmapData::draw clipRect parameter.
Here is an example:
package {
import flash.geom.Rectangle;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Sprite;
public class BitmapDataTest extends Sprite {
public function BitmapDataTest() {
var c:Sprite = new Sprite();
var g:Graphics;
g = c.graphics;
g.beginFill(0xFF0000);
g.drawCircle(30,30,30);
g.endFill();
addChild(c);
c.x = 10;
c.y = 10;
var bmdata:BitmapData = new BitmapData(60, 60, true, 0x000000);
bmdata.draw(c,null,null,null, new Rectangle(0,30,30,30));
var bitmap:Bitmap = new Bitmap(bmdata);
addChild(bitmap);
bitmap.x = 80;
bitmap.y = 10;
}
}
}
Please notice that the target bitmap data should have the same dimensions as source or this won't work. If you really have to cut it down you should use BitmapData::copyPixels method.

The easiest way would be to apply a mask, dynamically. Here is a good example: Actionscript 3 and dynamic masks
You can create a rectangle, the height you're looking for and position it appropriately.
Hope this helps.

Related

Stage.RESIZE : Is it possible to run this example in a browser?

Is it possible to run this simple code in a browser?
In the .swf all seems to work fine, but I'm unable to resize the .swf in a browser...
The stage is not resizing in an HTML page.
Through the .swf flile it works like a charm.
Do somebody have an idea about this issue?
package com{
import flash.display.Graphics;
import flash.display.MovieClip;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.text.TextField;
public class Main extends MovieClip{
private static const ORANGE:int = 0xff9900;
var bg:MovieClip;
var bg_mask:MovieClip;
var marginx:int = 10;
var marginy:int = 10;
var display:MovieClip;
var displayTextField:TextField;
var ellipseWidth:int = 90;
var ellipseHeight:int = 90;
public function Main(){
super();
bg = new MovieClip();
bg_mask = new MovieClip();
display = new MovieClip();
displayTextField = new TextField();
this.addChild(bg);
this.addChild(bg_mask);
this.addChild(display);
this.display.addChild(displayTextField);
displayTextField.text = "";
displayTextField.x = ellipseWidth/Math.PI;
displayTextField.y = ellipseHeight/Math.PI;
stage.align = StageAlign.TOP_LEFT; // or StageAlign.TOP
stage.scaleMode = StageScaleMode.NO_SCALE;
drawBackground();
display.mask = bg_mask;
addListeners();
}
private function drawBackground(thickness:int=1,lineColor:int=0x000000,lineAlpha:Number=0.5,fillColor:int=ORANGE,fillAlpha:Number=0.5):void{
var g:Graphics = bg.graphics;
g.clear();
g.lineStyle(thickness,lineColor,lineAlpha);
g.beginFill(fillColor,fillAlpha);
g.drawRoundRect(marginx,marginy,this.stage.stageWidth-marginx*2,this.stage.stageHeight-marginy*2,ellipseWidth,ellipseHeight);
g.endFill();
}
private function drawMask():void{
var g:Graphics = bg_mask.graphics;
g.clear();
g.lineStyle(1,0x000000,0.3);
g.beginFill(0xcccccc,0.1);
g.drawRoundRect(marginx,marginy,this.stage.stageWidth-marginx*2,this.stage.stageHeight-marginy*2,90,90);
g.endFill();
}
private function addListeners():void{
stage.addEventListener(Event.ADDED,updateLabel);
stage.addEventListener(Event.RESIZE,updateLabel);
}
private function updateLabel(e:Event):void{
updateDisplay();
drawBackground();
drawMask();
}
private function updateDisplay():void{
var tf:TextField = displayTextField;
tf.text = ("{" + this.stage.stageWidth + ";" + this.stage.stageHeight + "}");
}
}
}
In an online context, the flash document is contained within an HTML parent element (object/embed).
Your AS3 code controls how to display your flash content within that element. It does not know anything beyond it's container.
Most likely, your issue is that HTML container. If it has a fixed size, then no matter what you do in AS3 it will not scale beyond it's container.
Try giving your HTML container fluid dimensions (eg. 100% width, 100% height) as well as any grandparent html elements to make your sizing more dynamic.

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..

How to beginBitmapFill without repeats?(AS3)

my code:
myCircle = new Shape();
function doStuffWithBitmapData(bmd:BitmapData):void
{
myCircle = new Shape();
var matrix:Matrix = new Matrix();
matrix.translate(0, 0);
myCircle.graphics.beginBitmapFill(bmd, matrix, false);
myCircle.graphics.drawCircle(0, 0, 17);
myCircle.graphics.endFill();
myCircle.x = 40;
myCircle.y = 63;
addChild(myCircle);
// your code
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(e:Event)
{
myCircle.rotation += 3;
}
I need to fill the circle with image , but the image is repeating many times, but if I set the repeat to false, the picture will be bigger, can I make no repeat and at the same time don't change the sizes of the filled image?
i'm not too sure of the the bitmapfill method, but creating your own bitmap and bitmapData, and then using your image's bitmapdata, you can manipulate the image pixel/data anyway you like.
-Using the setPixel/setPixel32 method of the bitmapData class will be helpful in your task (google is your friend)
Adobe's help: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/BitmapData.html
Please look closely at the draw() method of BitmapData Class Documents. It is very important.
and refer a following code.
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Bitmap;
var myCircle:Shape;
var bmd:BitmapData = new BitmapData(600,400,false,0xffffff);
var bmp:Bitmap = new Bitmap(bmd);
this.addChild(bmp);
var circleBitmapData:BitmapData = new BitmapData(20,20,false,0xffffff * Math.random());
myCircle = new Shape();
var matrix:Matrix = new Matrix();
myCircle.graphics.beginBitmapFill(circleBitmapData);
myCircle.graphics.drawCircle(0, 0, 20);
myCircle.graphics.endFill();
myCircle.x = 40;
myCircle.y = 63;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame(e:Event)
{
bmd.draw(myCircle, myCircle.transform.matrix, myCircle.transform.colorTransform);
myCircle.x = Math.random() * stage.width;
myCircle.y = Math.random() * stage.height;
}

AS3 - Scale BitmapData

I'd like to scale a BitmapData to different sizes such as 200, 400, 600 and 800.
What is a good way to do that?
You can't directly scale a BitmapData but you can make a scaled clone of it.
Here is a quick example for scaling a BitmapData :
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.Matrix;
import mx.core.BitmapAsset;
public class Test extends Sprite {
[Embed(source="test.jpg")]
private var Image:Class;
public function Test() {
var originalBitmapData:BitmapData = BitmapAsset(new Image()).bitmapData;
function scaleBitmapData(bitmapData:BitmapData, scale:Number):BitmapData {
scale = Math.abs(scale);
var width:int = (bitmapData.width * scale) || 1;
var height:int = (bitmapData.height * scale) || 1;
var transparent:Boolean = bitmapData.transparent;
var result:BitmapData = new BitmapData(width, height, transparent);
var matrix:Matrix = new Matrix();
matrix.scale(scale, scale);
result.draw(bitmapData, matrix);
return result;
}
var bitmapA:Bitmap = new Bitmap(originalBitmapData);
addChild(bitmapA);
var bitmapB:Bitmap = new Bitmap(scaleBitmapData(originalBitmapData, 0.5));
addChild(bitmapB);
}
}
}
Setting the width and height of a bitmap object scales that image, so create a bitmap with your bitmapData then scale it using width/height, or use scaleX/Y if you want to use scaling values.
var bmp:Bitmap = new Bitmap(bmpData);
bmp.width = 400; // or 600,800 etc.
bmp.height = 400;
If you don't want to use a bitmap object and directy scale the BitmapData see this
What is the best way to resize a BitmapData object?

How to change the pixels in an image

i actually try to do the following: I have loaded an external image in a bitmapdata object and create a bitmap from it which i attach it to a sprite/MovieClip in order to have mouse events on it. Now under the previous logic i loaded two images (let's say circles) of the same size one that has a particular color and is covered by its black foreground circle. When i press left mouse button and hold it down i want while the mouse is moved to erase the foreground circle's pixels and so the background image starting to appear. I tried this to achieve but had no luck. In my best attempt i achieve to draw a line in the foreground image but i cannot reveal the background!
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.BlendMode;
public class Test2 extends MovieClip
{
// properties - state
// to attach the image and have mouse events
private var frontImage:Sprite;
private var backImage:Sprite;
// to load the image
private var myLoader:Loader;
// to get the bitmap data of the image
private var frontBitmapData:BitmapData;
private var frontBitmap:Bitmap;
// test
private var frontMask:Bitmap;
// constructor
function Test2():void
{
// load the background image
backImage = new Sprite();
attachImageToSprite1(new URLRequest("btest.jpg"));
backImage.mouseEnabled = false;
this.addChild( backImage );
// load the front image
frontImage = new Sprite();
attachImageToSprite2(new URLRequest("test.jpg"));
frontImage.mouseEnabled = true; // enable mouse
frontImage.buttonMode = true; // set button mode
this.addChild(frontImage); // load to stage
this.frontImage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
this.frontImage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
// methods
private function attachImageToSprite1(Name:URLRequest):void
{
this.myLoader = new Loader();
this.myLoader.load(Name);
this.myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete1);
}
private function attachImageToSprite2(Name:URLRequest):void
{
this.myLoader = new Loader();
this.myLoader.load(Name);
this.myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete2);
}
private function getImageBitmapDataFromSprite(srcImage:Sprite):BitmapData
{
var tmpBitmapData:BitmapData = new BitmapData(frontImage.width, frontImage.height, true, 0xFFCCCCCC);
tmpBitmapData.lock();
tmpBitmapData.draw(frontImage);
tmpBitmapData.unlock();
return tmpBitmapData;
}
private function isPixelAlpha(bitmapdata:BitmapData):Boolean
{
var pixelValue:uint = bitmapdata.getPixel32(mouseX, mouseY);
var alphaValue:uint = pixelValue >> 24 & 0xFF;
//var red:uint = pixelValue >> 16 & 0xFF;
//var green:uint = pixelValue >> 8 & 0xFF;
//var blue:uint = pixelValue & 0xFF;
return (alphaValue == 0x00) ? true : false;
}
private function deletePixelUnderMouse(bitmapdata:BitmapData, bitmap:Bitmap):void
{
bitmapdata.lock();
if ( !isPixelAlpha(bitmapdata) ) {
bitmapdata.setPixel32(mouseX, mouseY, 0xFF << 24); // how to make the current pixel's alpha
} // equal to zero.
bitmap = new Bitmap(bitmapdata);
bitmap.x = frontImage.x;
bitmap.y = frontImage.y;
this.frontImage.addChild(bitmap);
bitmapdata.unlock();
}
// events
public function onLoadComplete1(e:Event):void
{
frontImage.addChild(this.myLoader.content);
}
public function onLoadComplete2(e:Event):void
{
backImage.addChild(this.myLoader.content);
}
public function onMouseDown(e:MouseEvent):void
{
// delete a pixel from the sprite under the mouse
frontBitmapData = getImageBitmapDataFromSprite(frontImage);
deletePixelUnderMouse(frontBitmapData, frontBitmap);
frontImage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseDown);
trace("start");
}
public function onMouseUp(e:MouseEvent):void
{
frontImage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseDown);
trace("stop")
}
}
}
Not sure if I got it right, but if you want a 'reveal' effect, as in you draw a mask to display a hidden image for example, this could be achieved slightly easier:
var bitmapToReveal:BitmapData = new BitmapToReveal(0,0);
var brush:BitmapData = new Brush(0,0);
var canvasData:BitmapData = new BitmapData(bitmapToReveal.width,bitmapToReveal.height,true,0x00FFFFFF);
var cursor:Point = new Point();//used as destination point when painting
var zero:Point = new Point();//reused for painting
var reveal:Bitmap = new Bitmap(bitmapToReveal);
var canvas:Bitmap = new Bitmap(canvasData);
reveal.cacheAsBitmap = canvas.cacheAsBitmap = true;
addChild(reveal);
addChild(canvas);
reveal.mask = canvas;
stage.addEventListener(MouseEvent.MOUSE_DOWN, brushDown);
stage.addEventListener(MouseEvent.MOUSE_UP, brushUp);
function brushDown(event:MouseEvent):void {
this.addEventListener(Event.ENTER_FRAME, paint);
}
function brushUp(event:MouseEvent):void {
this.removeEventListener(Event.ENTER_FRAME, paint);
}
function paint(event:Event):void {
cursor.x = mouseX-brush.width*.5;
cursor.y = mouseY-brush.height*.5;
canvasData.copyPixels(brush,brush.rect,cursor,brush,zero,true);
}
I'm using two Bitmaps form the library(bitmapToReveal and brush).
The main thing to look at is the copyPixels() method. I copy
the brush bitmap into the canvas(an empty transparent bitmap data),
using the offset cursor position(so the brush centered), and using the
alpha channel to do that. Note that I've set cacheAsBitmap to true
for both mask and maskee. You need to do that to get a transparent mask,
which is key to the effect.
Here is the result:
You can 'paint' the mask here. CS4 Source is here.
HTH,
George