I am drawing a rounded rect into BitmapData: (bg)
var bg:Shape= new Shape();
bg.graphics.beginFill(0xdddddd);
bg.graphics.drawRoundRect(0, 0, 200, 400, 20);
bg.graphics.endFill();
var imageData:BitmapData = new BitmapData(bg.width, bg.height);
image.draw(bg);
But when I create a Bitmap from imageData the bitmap corners are not transparent as expected, instead its white color .. any idea?
try:
// see the argb color value 0x00000000 -> the first two '0' after '0x' are for transparency
var imageData:BitmapData = new BitmapData( bg.width, bg.height, true, 0x00000000 );
Related
I have a sprite that is drawn in random and complicated way. Pixels would be either transparent or not. And now I need to check if pixel new Point(10, -5) is transparent or not.
How can I do that ?
This is not for collision detection.
I also draw in the negative area of the sprite graphics. It is not centered.
Solution:
The main problem was the drawing in negative area. I figured it out myself:
var bitmapData: BitmapData = new BitmapData(sprite.width, sprite.height, true, 0x0);
var rect: Rectangle = sprite.getBounds(sprite);
var mat: Matrix = new Matrix();
mat.translate(-rect.left, -rect.top);
bitmapData.draw(sprite, mat);
bitmapData.getPixel32(xCoordToTest - rect.left, yCoordToTest - rect.top);
// etc
Create new BitmapData object and draw your sprite onto it. Then check desired BitmapData pixel.
var bitmapData:BitmapData = new BitmapData(mySprite.width,mySprite.height,true,0x00000000);
bitmapData.draw(mySprite);
bitmapData.getPixel32(10,5);
Just like SzRaPnEL says, draw your sprite into a BitmapData object with the 3rd parameter set to true (enabling transparency).
Then...
var pixelValue:uint = bitmapData.getPixel32(xCoordToTest, yCoordToTest);
var alphaValue:uint = pixelValue >> 24 & 0xFF;
According to the BitmapData online docs, that should work...
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/BitmapData.html#getPixel32()
I have a shape drawn using Shape.graphics.drawRoundRect() with a lineStyle applied. I'm trying to capture that shape as a Bitmap using BitmapData.draw() but I am running into an issue with the stroke. See below:
As you can see, the stroke gets clipped when using draw() (and drawWithQuality()). The line is drawn centered on the object, so a thickness of 4 (as I used in the example) has 2 pixels outside the shape's area and 2 pixels inside it. draw() captures everything from (0,0) to (BitmapData.width,BitmapData.height), it seems, so everything to the left and top of (0,0) is lost. I tried to compensate using the clipRect option, but that just evened out the clipped border, ironically.
Any idea how to capture that remaining data?
As a more general solution, you can get the bounds of the object in its own coordinate space, and use that to set the size of the BitmapData and offset the draw():
import flash.geom.Matrix;
import flash.geom.Rectangle;
const thickness:int = 4;
const radius:int = 10;
const size:int = 100;
var shape:Shape = new Shape();
shape.graphics.lineStyle( thickness, 0xaaaaaa );
shape.graphics.beginFill( 0xdddddd );
shape.graphics.drawRoundRect( 0, 0, size, size, radius, radius );
shape.graphics.endFill();
addChild( shape );
var bounds:Rectangle = shape.getBounds(shape);
var m:Matrix = new Matrix();
m.translate(-bounds.left, -bounds.top);
var bmp1:Bitmap = new Bitmap();
bmp1.bitmapData = new BitmapData( bounds.width, bounds.height, true, 0 );
bmp1.x = 310;
bmp1.y = 100;
addChild( bmp1 );
bmp1.bitmapData.draw( shape, m );
And of course, the second I post the question, I figure out the way to do it. You have to offset your shape to match the line outside of the bounds and compensate for the additional size the line adds to the shape when using draw
const thickness:int = 4;
const radius:int = 10;
const size:int = 100;
var shape:Shape = new Shape();
shape.graphics.lineStyle( thickness, 0xaaaaaa );
shape.graphics.beginFill( 0xdddddd );
shape.graphics.drawRoundRect( thickness / 2, thickness / 2, size, size, radius, radius );
shape.graphics.endFill();
addChild( shape );
var bmp1:Bitmap = new Bitmap();
bmp1.bitmapData = new BitmapData( size + thickness, size + thickness, true, 0 );
bmp1.x = 310;
bmp1.y = 100;
addChild( bmp1 );
bmp1.bitmapData.draw( shape );
See the outcome here (you can ignore the clip rect one):
I'm resizing a bitmapData the usual way, using a Matrix. The bitmapData has an alpha channel (it comes from a PNG), and the alpha channel is ignored...
var m:Matrix = new Matrix();
m.scale(.5, .5);
var bmp:BitmapData = new BitmapData(bitmapData.width * .5, bitmapData.height * .5,true);
bmp.draw(bitmapData,m);
var resizedBitmap = new Bitmap(bmp);
I've added the third parameter true to the BitmapData() constructor to support alpha channel, but I'm still loosing all the transparency after the draw() call.
What's wrong?
The solution to this problem comes from adding the fourth parameter (fillColor) to the BitmapData constructor.
var bmp:BitmapData = new BitmapData(bitmapData.width * .5, bitmapData.height * .5,true,0x00000000);
From the documentation:
To create a fully transparent bitmap, set the value of the transparent parameter to true and the value of the fillColor parameter to 0x00000000 (or to 0).
I know how to draw a square:
graphics.moveTo(0, 0);
graphics.beginFill(0x00ff00, 1);
graphics.lineTo(point, 0);
graphics.lineTo(point, point);
graphics.lineTo(0, point);
graphics.lineTo(0, 0);
graphics.endFill();
now how would i draw another square inside the first one with an alpha of 0.5?
The following snippet will draw a green square then substract a square to its center (live demo).
// Size of the main square
var point:uint = 100;
// Create two sprites
var s1:Sprite = new Sprite();
var s2:Sprite = new Sprite();
// Shortcuts to graphics objects
var g1:Graphics = s1.graphics;
var g2:Graphics = s2.graphics;
// Draw the main square
g1.beginFill(0x00ff00, 1.0);
g1.drawRect(0, 0, point, point);
g1.endFill();
// Draw the eraser square
g2.beginFill(0x000000, 0.5);
g2.drawRect(0, 0, point/2, point/2);
g2.endFill();
// Configure blend modes to erase the center of the first square
s1.blendMode = BlendMode.LAYER;
s2.blendMode = BlendMode.ERASE;
// Add the eraser square to the first one and adjust its position
s1.addChild(s2);
s2.x = s2.y = point/4;
// Add the first square to the stage
addChild(s1);
Without having to use any blend modes, you can exclude portions of a drawn shape by drawing over (erasing) the desired portion before ending the fill.
Here's an example:
import flash.display.Shape;
var squares:Shape = new Shape();
squares.graphics.beginFill(0xFF0000, 1.0);
squares.graphics.drawRect(0, 0, 200, 200);
squares.graphics.drawRect(50, 50, 100, 100); //exclude
squares.graphics.endFill();
squares.graphics.beginFill(0x0000FF, 0.5);
squares.graphics.drawRect(75, 75, 100, 100);
squares.graphics.endFill();
addChild(squares);
var squ1:Sprite = new Sprite();
with(squ1.graphics){
beginFill(0xFF0000);
drawRect(0,0,100,100);
endFill();
}
addChild(squ1);
var inSq:Sprite = new Sprite();
with(inSq.graphics){
beginFill(0x00FF00,.5);
drawRect(0,0,25,25);
endFill();
}
squ1.addChild(inSq);
inSq.x = squ1.width/2 - inSq.width/2;
inSq.y = squ1.height/2 - inSq.height/2;
Let say I have a BitmapData with different pixels representing an object, and some black pixels around it that I want to remove.
I would like to obtain a new BitmapData, with width and height of the object represented by non-black pixels.
For example, let say I have a BitmapData 400x400px, but the object represented by non-black pixels occupies the rect: x=100, y=100, width=200, height=200. I want to get new BitmapData representing that rect, all black pixels should be removed. Of course, i have no coordinates for that rectangle, i need somehow to make difference between a full black bitmapdata and the original one, and construct a new bitmapdata (different width and height).
Any idea on how to do this please ?
You can use getColorBoundsRect to find the dimensions of the differently-colored-pixels inside your BitmapData:
//some fake data
var yourBigBmd:BitmapData = new BitmapData( 300, 300, false, 0 );
yourBigBmd.fillRect( new Rectangle( 10, 10, 30, 60 ), 0xFF0000 );
//a little notch
yourBigBmd.fillRect( new Rectangle( 10, 10, 10, 10), 0x00000 );
var blackColor:uint = 0x000000;
var littleBmdBounds:Rectangle = yourBigBmd.getColorBoundsRect( 0xFFFFFF, blackColor, false );
trace( "littleBmdBounds: " + littleBmdBounds );
This will trace littleBmdBounds: (x=10, y=10, w=30, h=60)
Next, we need to copy what's in those bounds into a new BitmapData:
var littleBmd:BitmapData = new BitmapData( littleBmdBounds.width, littleBmdBounds.height, true, 0 );
var mx:Matrix = new Matrix();
mx.translate( -littleBmdBounds.x, -littleBmdBounds.y );
littleBmd.draw( yourBigBmd, mx );
Finally, use threshold to remove any remaining black and make it transparent:
var blackAlphaColor:uint = 0xFF000000;
var transparentColor:uint = 0x00000000;
littleBmd.threshold( littleBmd, littleBmd.rect, littleBmd.rect.topLeft, "==", blackAlphaColor, transparentColor )