Grabbing bitmap data from external swf in ActionScript 2

Also known as:

  • alternative localization method
  • grabbing bitmap data from a loaded swf in actionscript 2
  • linkageExportForAS in JSFL not working for bitmaps

For Heineken, one of TriMM’s clients, I had to work on a project called the photomodule. Originally written by Paul de Jong, it required some adaptions for another site. One of the adaptions was that the module had to be running in different languages, Portugese, English & Thai (and maybe even more I don’t know).

Since there was little time to complete the project, I didn’t want to get involved in playing with thai fonts and embedding the right glyphs. Originally the solution was to include every screen twice, once in English and once in Thai. However that wasn’t really going to work as well, since I needed it for 2 or 3 other languages, and I wanted to simplify/refactor the setup in order to get acqainted with it.

So I came up with an idea…:

I would create a large jpg with all the button skins in it, and just load that skin. Then in Flash I’d have a couple components cutting the bitmap data out of the jpg. Well it turned out that most of the buttons were already available as separate images, and creating a large skin jpg was only going to be more work.

So: external swf, lots of images in it with correct identifier. Brilliant, only there is no way to get to that data except from within that swf. Since in order to get the bitmap data, I have to pass a linkage id, and that won’t work outside the swf.

However before I tell you how to cross that bridge, I hate doing things that can be automated. For example, right clicking 30 button images, and enabling ‘export for actionscript’ and ‘export in first frame’, which is the first step required if we ever want to be able to get to this data dynamically. So you think: well I’ll be damned, I’ve got JSFL up my sleeve. AHAHAHAHA! Gotcha! Macromedia/Adobe has another bug up their sleeve! Which is that you cannot change these properties for a bitmap through JSFL.

So first step is to write a script that wraps all the bitmaps in a movieclip, and enables ‘export for actionscript’ and ‘export in first frame’ for those clips. First problem solved. Now the trick to get to the bitmap data is to create a clip within the swf that contains the images and attach a helper class to it, for example BitmapLoaderHelper.

This class contains the following:

class BitmapLoaderHelper extends MovieClip  {
	
	public function loadBitmap (linkageID:String):BitmapData {
		var tmp:MovieClip = attachMovie (linkageID, "tmp", 0);
		var bmp:BitmapData = new BitmapData (tmp._width, tmp._height, true);
		//draw the image
		bmp.draw (tmp, new Matrix(), null, "normal");
		//copy the alpha channel
		bmp.draw (tmp, new Matrix(), null, "alpha");
		tmp.removeMovieClip();
		return bmp;
	}
}

So from your main swf, the process for getting to the BitmapData becomes very simple:

  • load the appropriate skin swf for a given language code containing your bitmaps with predetermined id’s (eg ‘select_button’)
  • after loading, attach the BitmapLoaderHelper clip from that swf, to its own timeline and maintain a reference to it
  • when needed retrieve bitmapdata from the swf through the helper
  • In our case we wrapped this whole thing up in a SkinFactory and SkinnedButtonComponents, which included automatic image retrieval for rollovers etc.

    And here is the JSFL I used:

    var dom = fl.getDocumentDOM();
    var lib = dom.library;
    var items = lib.items;
    var item;
    var newSel = [];
    
    for (var i=0; i<items.length; i++) {
     item = items[i];
     if (item.itemType == "movie clip")  {
      fl.trace ("deleting "+item.name);
      lib.deleteItem (item.name);
     }
    }
    
    for (var i=0; i<items.length; i++) {
     item = items[i];
     if (item.itemType == "bitmap")  {
     
      fl.trace ("Processing "+item.name);
      item.compressionType = "lossless";
      item.allowSmoothing = true;
    
      var newName = item.name.substring (0, item.name.indexOf("."));
      fl.trace ("Creating wrapper clip with name:"+newName);
    
      lib.addNewItem( "movie clip", newName);
      lib.editItem( newName );
    
      var tl = dom.getTimeline();
      tl.layers[0].name = "Wrapped Bitmap";
      lib.addItemToDocument( {x:0, y:0}, item.name );
      
      newSel[0] = tl.layers[ 0 ].frames[ 0 ].elements[ 0 ];
      dom.selectNone();
      dom.selection = newSel;
      var mat = dom.selection[0].matrix;
      mat.tx = 0;
      mat.ty = 0;
      dom.selection[0].matrix = mat;
      dom.selectNone();
      dom.exitEditMode();
      
      lib.selectItem (newName, true);
      lib.setItemProperty( "linkageExportForAS", true);
      lib.setItemProperty( "linkageExportInFirstFrame", true);
     }
    }
    
    lib.addNewItem ("movie clip", "BitmapLoaderHelper");
    lib.selectItem ("BitmapLoaderHelper", true);
    lib.setItemProperty( "linkageExportForAS", true);
    lib.setItemProperty( "linkageExportInFirstFrame", true);
    lib.setItemProperty( "linkageClassName", "!replacethiswithyourpackage!.BitmapLoaderHelper");
    
    image_pdfimage_print
    0 replies

    Leave a Reply

    Want to join the discussion?
    Feel free to contribute!

    Leave a Reply

    Your email address will not be published. Required fields are marked *