开发者

Exporting frame from external swf to Javascript

I am trying to capture a still frame from an (any) external swf file, by using my own flash movie as a proxy to load it and hand information regarding the Stage onto javascript. I want to keep it as wide compatible as possible, so I went with AS2 / Flash 8 for now.

The script works fine in the Flash debugger, i.e. the

trace(flash2canvasScreenshot.getPixel(w, h).toString(16));

returns the correct pixel color, where as:

ExternalInterface.call("sendToJS",flash2canvasScreenshot.getPixel(w, h).toString(16));

in the published movie does开发者_如何学JAVAn't.

This method can obviously be quite slow for large flash (dimension wise) movies, as it iterates every single pixel. If someone has any better methods in mind, feel free to share, but as said, the problem I am facing is that I am getting differentiating results in debugging and publishing, with the pixel information not getting fetched when published.

import flash.display.BitmapData;
import flash.external.*;

var myLoader:MovieClipLoader = new MovieClipLoader();
var mclListener:Object = new Object();

mclListener.onLoadInit = function(target_mc:MovieClip)
{

        var stageW = Stage.width;
        var flash2canvasScreenshot:BitmapData = new BitmapData(stageW, Stage.height, false, 0x00000000);
        var pixels:Array = new Array();
        flash2canvasScreenshot.draw(element);

        for (w = 0; w <= stageW; w++)
        {
            trace(flash2canvasScreenshot.getPixel(w, h).toString(16)); // this gives correct color value for the pixels in the debugger
            ExternalInterface.call("sendToJS",flash2canvasScreenshot.getPixel(w, h).toString(16)); // this just returns the bitmap default color, 0 in this case.
            /*
            for (h = 0; h <= Stage.height; h++)
            {
                var pixel = flash2canvasScreenshot.getPixel(w, h).toString(16);
                pixels.push(pixel);
            }
            */
        }

        //ExternalInterface.call("sendToJS",pixels.toString());*/



};


myLoader.addListener(mclListener);

myLoader.loadClip("http://i.cdn.turner.com/cnn/cnnintl_adspaces/2.0/creatives/2010/6/9/21017300x250-03.swf", 0);
//myLoader.loadClip("https://s.ytimg.com/yt/swfbin/watch_as3-vflJjAza6.swf", 0);

//myLoader.loadClip(_level0.flash2canvasurl, _root.mc);


There are few problems with the snippet you posted:

  1. like the one Joey mentioned, but the one that stands out from my point of view is the element variable which isn't defined anywhere, so that either is a type o, or you're trying to draw an undefined object.
  2. You're drawing as soon as the load is finished, but the animation you're loading might start slightly later. Maybe take the snapshot a bit after the load is complete.
  3. Haven't touched as2 for some time and don't remember how security issue are handled, but if you're swf is loading another swf from a different domain, then the domain hosting the swf you're loading should also have a crossdomain.xml policy file allowing you to access the content of the loaded swf. If you simply load and display a swf from another domain, that's fine. However, if you're trying to draw the swf using BitmapData, you're actually attempting to access pixel data from the content of that swf, therefore you would need permissions. If you have no control over the crossdomain policy file, you might need to use a server side script to copy/proxy the file over to a domain that can grant your loaded swf access.

Here's a simplified version of your snippet that works (sans the external interface/pixel values part):

var myLoader:MovieClipLoader = new MovieClipLoader();
var mclListener:Object = new Object();
mclListener.onLoadInit = function(target_mc:MovieClip)
{
    var pixels:Array = new Array();
    setTimeout(takeSnapshot,2000,target_mc);
}

myLoader.addListener(mclListener);
myLoader.loadClip("http://www.bbc.co.uk/science/humanbody/sleep/sheep/reaction_version5.swf",1);
//myLoader.loadClip("http://i.cdn.turner.com/cnn/cnnintl_adspaces/2.0/creatives/2010/6/9/21017300x250-03.swf", 1);
//myLoader.loadClip("https://s.ytimg.com/yt/swfbin/watch_as3-vflJjAza6.swf", 0);

function takeSnapshot(target:MovieClip):Void {
    var flash2canvasScreenshot:BitmapData = new BitmapData(150, 150, false, 0x00000000);//tiny sample
    flash2canvasScreenshot.draw(target);
    _level1._alpha = 20;//fade the loaded content
    _level0.attachBitmap(flash2canvasScreenshot,0);//show the snapshop. sorry about using _root
}

Here's a quick zoomed preview of the 150x150 snap:

Exporting frame from external swf to Javascript

Here's an as3 snippet to illustrate the security sandbox handling issue:

var swf:Loader = new Loader();
swf.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderComplete);
swf.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR,loaderSecurityError);
swf.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,loaderIOError);
swf.load(new URLRequest("http://i.cdn.turner.com/cnn/cnnintl_adspaces/2.0/creatives/2010/6/9/21017300x250-03.swf"),new LoaderContext(true));

function loaderComplete(event:Event):void{
    setTimeout(takeSWFSnapshot,2000);
}
function loaderSecurityError(event:SecurityErrorEvent):void {
    trace('caught security error',event.errorID,event.text);
}
function loaderIOError(event:IOErrorEvent):void{
    trace('caught I/O error',event.errorID,event.text,'\tattempting to load\t',swf.contentLoaderInfo.url);
}
function takeSWFSnapshot():void{
    var clone:BitmapData = new BitmapData(swf.content.width,swf.content.height,false,0);
    try{
        clone.draw(swf.content);
    }catch(e:SecurityError){
        trace(e.name,e.message,e.getStackTrace());
    }
    addChild(new Bitmap(clone));
}

HTH


My approach to this would be:

-Use AS3 for the reason lukevanin commented:

Just remember that AS3 can load an AS2 SWF, but an AS2 SWF cannot load an AS3 SWF, so you actually achieve greater compatibility (with your content) if you publish AS3

-Use a proxy file to fetch the swf file to get around sandbox violation issues (although if the swf loads external resources and uses relative paths it might get a bit more complex)

-Take a snapshot of the frame ( see George Profenza's solution )

-Encode the image using base64 and send that** to a JS method, and then decode to get the image.

** I'm pretty sure there are no size limitations...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜