Search code examples
actionscript-3actionscriptalpha-transparency

as3 - setting textures alpha-value


For an Actionscript 3 "drawing application", I want to be able to chose a Texture and set it's transparency. Therefore I try to set the alpha-transparency of a texture. But it's not working.

What I do:

  1. At first I use graphics.linestyle() to set the lines thickness and ALPHA-value.
  2. After that I (a) load a png, (b) read it's bitmapData and (c) then use it with lineBitmapStyle.

Result:

When drawing lines (with moveTo, lineTo, etc) the lines use the texture, but IGNORE THE "Alpha" which was set with lineStyle.

What am I doing wrong?

myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, setTexture);        

setTexture(e:Event):void 
{
  e.currentTarget.removeEventListener(e.type, arguments.callee);

  //Try 1: Trying to set the Alpha-Trasparency with "lineStyle"-Command:
  myDrawContainer.graphics.lineBitmapStyle(5, 0xFF0000, 0,6);

  //Try 2: Trying to set the Alpha-Transparency by changing the Alpha-Value of the loaded content:
  myLoader.content.alpha = 0.6;

  //Getting the BitmapData of the Image:
  BitmapDataOfMyTexture = Bitmap(LoaderInfo(e.target).content).bitmapData

  //"Using" the TBitmapData as "Color/Texture" for my Drawing:
  myDrawContainer.graphics.lineBitmapStyle( BitmapDataOfMyTexture );

  //Test-Drawing:
  myDrawContainer.graphics.moveTo( 0, 0 );
  myDrawContainer.graphics.moveTo( 500, 500 ); //-> RESULT: Textured Line WITHOUT Transparency! 

}

RESULT: I get a line which uses the texture but WITHOUT Transparency.

(Update) THE SOLUTION: (Thanks to DodgerThud)
For setting/changing the Alpha-Channel of a loaded image, you don't use "lineStyle" but...

  1. Create a NEW colorTransform-object

  2. Then set it's "alphaMultiplier"-attribute to the specific alphaChannel

  3. And then apply this newly created colorTransform-Object to the loaded BitmapData, by using the "colorTransform"-Method of the loaded BitmapData.

BUT :

This does NOT work with images that don't have an alpha-Channel or don't have their alpha-channel activated. Those images only get DARKER when lowering the alpha-Channel. In those cases you have to do this:

  1. At FIRST I create NEW BitmapData-Object with "new", set its width and height to the width and height of the loaded Image and set it 3rd Argument to TRUE (= transparency: ON). So you got a "Container" which has transparency ACTIVATED.
  2. Then you use "copyPixels" on this "Container"-Object to fill it with the pixels of the LOADED BitmapData-Object.
  3. And right after this the above approach with the "colorTransform"-Object brings the expected result.

So HERE'S THE WORKING CODE:

myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, setTexture);

setTexture(e:Event):void 
{
  e.currentTarget.removeEventListener(e.type, arguments.callee);

  //Getting the BitmapData of the Image:
  BitmapDataOfMyTexture = Bitmap(LoaderInfo(e.target).content).bitmapData

  //Create an ADDITIONAL BitmapData-Object with 3rd  
  //argument set to TRUE and with same width and height
  //as the LOADED image:
  var BMDContainerWithAlphaActivated:BitmapData;
  BMDContainerWithAlphaActivated = new BitmapData(BitmapDataOfMyTexture.width, BitmapDataOfMyTexture.height, true, 0xFFFFFF);

  //Copy the pixels of the loaded image into the newly created 
  //"BitmapData-Container with activated AlphaChannel":
  BMDContainerWithAlphaActivated.copyPixels(BitmapDataOfMyTexture, new Rectangle(0, 0, BitmapDataOfMyTexture.width, BitmapDataOfMyTexture.height), new Point(0,0))

  //Modify the Alpha-Value (of the NEW BitmapData-Object):
  var colorChanges:ColorTransform = new ColorTransform();
      colorChanges.alphaMultiplier = 0.3;
  BMDContainerWithAlphaActivated.colorTransform(new Rectangle(0, 0, BitmapDataOfMyTexture.width, BitmapDataOfMyTexture.height), colorChanges);  


  //"Using" the (NEW) BitmapData as "Color/Texture" for my Drawing:
  myDrawContainer.graphics.lineBitmapStyle( BMDContainerWithAlphaActivated );

  //Test-Drawing:
  myDrawContainer.graphics.moveTo( 0, 0 );
  myDrawContainer.graphics.moveTo( 500, 500 ); //-> RESULT: Textured Line WITH Transparency 0.3!        
}

Solution

  • Ah I see, this is a bit more complex than I initially thought.

    Alright, looking at the documentation for lineBitmapStyle shows me that the function expects the following parameters: lineBitmapStyle(bitmap:BitmapData, matrix:Matrix = null, repeat:Boolean = true, smooth:Boolean = false)

    Now, matrix, repeat and smooth will not help us here (matrix is used here for transformation, i.e. positioning, rotation etc.), but bitmap:BitmapData might. What we need to do is manipulate the BitmapData of the loaded PNG file before passing it to lineBitmapStyle. Sadly we cannot set the alpha value directly on the BMD, so we can try to colorTransform it.

    This is untested code, but I think it is the right approach:

    ..
    //store the bitmapdata in a seperate local variable
    var bmd:BitmapData = LoaderInfo(e.target).content;
    //create a ColorTransform Object to change the values of the BMD
    var cTransform:ColorTransform = new ColorTransform();
    //now here I am unsure, manipulating the alpha value of the BMD
    cTransform.alphaMultiplier = 0.6;
    //defining the rectangle dimensions of the bmd, we want it to be over the entire texture
    var rect:Rectangle = new Rectangle(0,0,bmd.width,bmd.height);
    //apply the colorTransformation on the BMD
    bmd.colorTransform(rect,cTransform);
    ...
    //the now manipulated BMD gets set as lineBitmapStyle
    myDrawContainer.graphics.lineBitmapStyle(bmd);
    

    And now that I think about it, maybe we can workaround setting the alpha value on the BMD, by creating a Bitmap first, set the alpha value there and use the bitmapdata of the Bitmap instead. Like this:

    var bmd:BitmapData = LoaderInfo(e.target).content;
    var bm:Bitmap = new Bitmap(bmd);
    bm.alpha = 0.6;
    myDrawContainer.graphics.lineBitmapStyle(bm.bitmapData);
    

    Alright, the first snippet from above seems to be the way to do it, but the transparent value of the BitmapData needs to be true. Given that you do not directly create the BitmapData yourself and the value is false, we have quite a tricky situation here.

    Another approach would be to create an additional bitmapdata that allows for transparancy and draw() the bitmapdata of the loaded image on it:

    var bmdSource:BitmapData = LoaderInfo(e.target).content;
    var bmd:BitmapData = new BitmapData(bmdSource.width, bmdSource.height,true,0xffffffff);
    var cTransform:ColorTransform = new ColorTransform();
    cTransform.alphaMultiplier = 0.6;
    var rect:Rectangle = new Rectangle(0,0,bmd.width,bmd.height);
    bmd.colorTransform(rect,cTransform);
    //now we have a completely white bitmapdata bmd, with an alpha value of 0.6
    //we draw the contents of the bmdSource onto bmd, the alpha value effect should carry over
    bmd.draw(bmdSource);