将帧从外部swf导出到Javascript

时间:2011-08-11 12:59:44

标签: javascript flash actionscript-3 actionscript

我试图从(任何)外部swf文件中捕获一个静止帧,通过使用我自己的flash影片作为代理加载它并将有关Stage的信息传递到javascript。我希望尽可能保持广泛的兼容性,所以我现在使用AS2 / Flash 8。

该脚本在Flash调试器中工作正常,即

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

返回正确的像素颜色,其中:

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

在已发布的电影中没有。

对于大型闪存(尺寸方面)电影来说,这种方法显然会非常慢,因为它会迭代每一个像素。如果有人有任何更好的方法,请随意分享,但正如所说,我面临的问题是我在调试和发布方面获得了差异化的结果,在发布时没有获取像素信息。

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

2 个答案:

答案 0 :(得分:10)

您发布的代码段几乎没有问题:

  1. 就像乔伊所提到的那样,但是那个从我的身上脱颖而出的人 观点是未定义的element变量 在任何地方,所以要么是一个类型o,或者你正试图绘制一个 undefined对象。
  2. 您在加载完成后即刻绘制,但您加载的动画可能会稍后开始。也许在加载完成后稍稍拍摄快照。
  3. 有一段时间没有触及as2并且不记得如何处理安全问题,但是如果你是swf从另一个域加载另一个swf,那么托管你正在加载的swf的域也应该有一个crossdomain.xml策略文件,允许您访问加载的swf的内容。如果您只是从另一个域加载并显示一个swf,那很好。但是,如果您尝试使用BitmapData绘制swf,那么您实际上是在尝试从该swf的内容访问像素数据,因此您需要权限。如果您无法控制跨域策略文件,则可能需要使用服务器端脚本将文件复制/代理到可以授予您加载的swf访问权限的域。
  4. 以下是您的代码段的简化版本(无外部接口/像素值部分):

    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
    }
    

    这是150x150快照的快速缩放预览: preview

    这是一个as3代码段,用于说明安全沙箱处理问题:

    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

答案 1 :(得分:2)

我的方法是:

- 使用AS3因为lukevanin评论:

  

请记住,AS3可以加载AS2 SWF,但AS2 SWF无法加载   一个AS3 SWF,所以你实际上实现了更大的兼容性(与你的   content)如果你发布AS3

- 使用代理文件来获取swf文件以解决沙箱违规问题(尽管如果swf加载外部资源并使用相对路径,它可能会变得更复杂一些)

- 拍摄相框的快照(参见George Profenza的解决方案)

- 使用base64对图像进行编码,然后将**发送到JS method,然后进行解码以获取图像。

**我很确定没有尺寸限制......