最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

flash - Exporting frame from external swf to Javascript - Stack Overflow

programmeradmin2浏览0评论

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 patible 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 doesn'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(".0/creatives/2010/6/9/21017300x250-03.swf", 0);
//myLoader.loadClip(".swf", 0);

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

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 patible 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 doesn'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./cnn/cnnintl_adspaces/2.0/creatives/2010/6/9/21017300x250-03.swf", 0);
//myLoader.loadClip("https://s.ytimg./yt/swfbin/watch_as3-vflJjAza6.swf", 0);

//myLoader.loadClip(_level0.flash2canvasurl, _root.mc);
Share Improve this question asked Aug 11, 2011 at 12:59 NiklasNiklas 30k5 gold badges53 silver badges74 bronze badges 4
  • Have you tried something like ExternalInterface.call("sendToJS", '42'); to make sure your JS is displaying the data correctly? – kolufild Commented Aug 11, 2011 at 15:27
  • @kolufild Yes, tried something similar to it and it is receiving data fine. – Niklas Commented Aug 11, 2011 at 15:42
  • If this is all the code, then h is undefined. – Joe Commented Aug 14, 2011 at 21:02
  • 3 Just remember that AS3 can load an AS2 SWF, but an AS2 SWF cannot load an AS3 SWF, so you actually achieve greater patibility (with your content) if you publish AS3. – Luke Van In Commented Aug 16, 2011 at 12:25
Add a ment  | 

2 Answers 2

Reset to default 9 +50

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 plete.
  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./cnn/cnnintl_adspaces/2.0/creatives/2010/6/9/21017300x250-03.swf", 1);
//myLoader.loadClip("https://s.ytimg./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:

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./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 mented:

Just remember that AS3 can load an AS2 SWF, but an AS2 SWF cannot load an AS3 SWF, so you actually achieve greater patibility (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 plex)

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

  1. 暂无评论