在Flashplayer中顯示PDF檔案, SWFTools怎麼用
目前在百度文件和另外一個什麼線上文件中見過這個做法,在美國的box網站也見過。
在網址:http://www.swftools.org/download.html(或http://wiki.swftools.org/wiki/Main_Page)下載SWFTools的最新版的exe安裝檔案,然後安裝到Windows。
現在,本地已經有pdf2swf.exe了,在cmd視窗中使用它:
C:\Program Files\SWFTools>pdf2swf D:\KONICA\displayPDF\Q_CRCC_0123.pdf -o D:\KONICA\displayPDF\Q_CRCC_0123.swf
建立的SWF檔案,看起來與原版的PDF沒有什麼不同:
28th June 2012增補:
現在再來看看如何將一個swf的第一幀輸出為一個影象:
SWFTools這套工具並非對所有的SWF都有效,因為SWF裡面可能包含actionscript,而actionscript可能會通過網路訪問其他域名下的資源,並且同時,所有執行SWF的環境都會應用安全沙箱的規則來限制actionscript對於外界的訪問,所以在SWF裡的程式碼要訪問網路才能正常呈現的情況下,SWFTools並不能如我們期望的那樣解決問題。而如果畫面的內容是主要通過actionscript繪製的,那麼不能期待它正常工作
13rd Dec 2012增補:
不過,我剛剛用swfrender將swftool從pdf轉製出來的swf的畫面輸出為png,是成功的。
C:\Program Files\SWFTools>swfrender Q_CRCC_0213.swf -o C:\sample.png
18th Dec 2012增補:
現在又出現一個新問題,當我真正嘗試將轉製出來的SWF載入至我的Flash裡播放時,我發現一個問題,就是被載入進來的SWF的型別是AVM1Flash影片。我們先假設文件類的內容如下:
package { import flash.display.MovieClip; import flash.display.Loader; import flash.events.Event; import flash.net.URLRequest; import flash.display.AVM1Movie; public class main extends MovieClip { private var _ldr:Loader; public function main() { this.addEventListener(Event.ADDED_TO_STAGE, this.addedToStageHandler); } private function addedToStageHandler($e:Event):void { this._ldr = new Loader(); this._ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, this.loadedHandler); var $req:URLRequest = new URLRequest("iso.swf"); this._ldr.load($req); } private function loadedHandler($e:Event):void { trace($e.target.content); var $dd:AVM1Movie = $e.target.content as AVM1Movie; this.addChild($dd:); } } }
我們將會看到, trace($e.target.content) 輸出的內容為: [object AVM1Movie]。而且我們同時也得到一個異常:
ArgumentError: Error #2180: 在 AVM1 內容已載入至 AVM2 (AS3) 內容的情況下,將 AVM1 內容 (AS1 或 AS2) 移動至 displayList 的不同部分是不合法的。
假如這個時候,我們想要解決的問題僅僅是顯示這個SWF的問題的話,那麼可以在載入完成事件觸發以前,就把Loader物件新增到 displayList 中。這樣,上述寫法就變成:
package {
import flash.display.MovieClip;
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;
import flash.display.AVM1Movie;
public class main extends MovieClip
{
private var _ldr:Loader;
public function main()
{
this.addEventListener(Event.ADDED_TO_STAGE, this.addedToStageHandler);
}
private function addedToStageHandler($e:Event):void
{
this._ldr = new Loader();
this._ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, this.loadedHandler);
var $req:URLRequest = new URLRequest("iso.swf");
this._ldr.load($req);
this.addChild(_ldr);
}
private function loadedHandler($e:Event):void
{
trace($e.target.content);
var $dd:AVM1Movie = $e.target.content as AVM1Movie;
}
}
}
然而這個辦法的壞處是很顯然的,你無法進一步操作這個載入進來的AVM1物件。於是進一步的搜尋令我尋找到一個稱為ForcibleLoader的工具類,它可以將AVM1轉換為MovieClip。示例程式碼可以點此下載。
ForcibleLoader的使用方法為:
package {
import flash.display.MovieClip;
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;
import flash.display.AVM1Movie;
public class main extends MovieClip
{
private var _ldr:Loader;
private var _fLoader:ForcibleLoader;
private var _mc:MovieClip ;
public function main()
{
this.addEventListener(Event.ADDED_TO_STAGE, this.addedToStageHandler);
}
private function addedToStageHandler($e:Event):void
{
this._ldr = new Loader();
this._fLoader = new ForcibleLoader(_ldr)
this._fLoader.load(new URLRequest('iso.swf'));
this.addChild(_ldr);
this.addEventListener(Event.ENTER_FRAME, this.onloadFunction);
}
private function onloadFunction(e:Event):void
{
if (this._ldr.content != null)
{
this.removeEventListener(Event.ENTER_FRAME, onloadFunction);
this._mc = this._ldr.content as MovieClip;
//this._mc.addFrameScript(12, loop);
trace(this._mc.totalFrames);
this._mc.gotoAndStop(1);
}
}
}
}
18th Dec 2012增補:
之所以會堅持以為通過在AS載入AVM1的swf時,尋找解決方法,是因為受到一篇文章的誤導:
這個印度阿三在裡面確定無疑地說SWFTools不能生成AVM2影片剪輯。不過這篇文章寫於2009年。後來我在SWFTools的官網上面找到連結:
於是我嘗試了使用新的命令來建立SWF(注意:其中insertstop的結果將使SWF的每一幀都有stop()指令,否則,SWF將會自動在逐個幀之間迴圈播放,而幀頻被設定為0.25,即每幀停留4秒):
C:\Program Files\SWFTools>pdf2swf -T9 -s insertstop ISO27001.pdf -o xxx.swf
現在使用最初的文件類的寫法載入這個新生成的SWF:
package {
import flash.display.MovieClip;
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;
public class main extends MovieClip
{
private var _ldr:Loader;
public function main()
{
this.addEventListener(Event.ADDED_TO_STAGE, this.addedToStageHandler);
}
private function addedToStageHandler($e:Event):void
{
_ldr = new Loader();
_ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, this.loadedHandler);
var $req:URLRequest = new URLRequest("t9.swf");
_ldr.load($req);
}
private function loadedHandler($e:Event):void
{
trace($e.target.content);
var $mc:MovieClip = $e.target.content as MovieClip;
addChild($mc);
trace($mc.totalFrames);
$mc.gotoAndStop(5);
}
}
}
其中 trace($e.target.content) 得到的第一行輸出為:
[object MainTimeline_9549329e]
另外,在通過windows上面的GUI版本的SWFTools可以建立帶有閱覽器的SWF,但是我並未能夠成功用命令列建立帶有viewer的SWF檔案。
19th Dec 2012增補:
根據上面連結中的內容,做了如下嘗試:
C:\Program Files\SWFTools>swfcombine -o ff.swf rfx8.swf viewport=sss.swf
viewport後面的swf即是之前從pdf轉制的swf。當然,需要注意,兩個被合併的swf需要版本相同。不然會得到警告:
Warning: File contains both flash 8 and flash 9 actionscript
可是現在的問題仍然是,如何在轉制的時候就一起合併。
在之前的實驗中已經發現,viewer的swf需要與pdf2swf.exe在同一路徑下。所以在這個前提下,下面的命令是會成功執行並且得到期望結果的:
C:\Program Files\SWFTools>pdf2swf -B rfx8.swf ISO27001.pdf -o 19th.swf
但從執行過程的輸出來看,其實pdf2swf自動呼叫了swfcombine:
C:\Program Files\SWFTools>pdf2swf -B rfx8.swf ISO27001.pdf -o 19th.swf
NOTICE processing PDF page 1 (841x595:0:0)
NOTICE File contains jpeg pictures
NOTICE processing PDF page 2 (841x595:0:0)
NOTICE processing PDF page 3 (841x595:0:0)
NOTICE processing PDF page 4 (841x595:0:0)
NOTICE processing PDF page 5 (841x595:0:0)
NOTICE processing PDF page 6 (841x595:0:0)
NOTICE processing PDF page 7 (841x595:0:0)
NOTICE processing PDF page 8 (841x595:0:0)
NOTICE processing PDF page 9 (841x595:0:0)
NOTICE processing PDF page 10 (841x595:0:0)
NOTICE processing PDF page 11 (841x595:0:0)
NOTICE processing PDF page 12 (841x595:0:0)
NOTICE processing PDF page 13 (841x595:0:0)
NOTICE processing PDF page 14 (841x595:0:0)
NOTICE processing PDF page 15 (841x595:0:0)
NOTICE processing PDF page 16 (841x595:0:0)
NOTICE processing PDF page 17 (841x595:0:0)
NOTICE processing PDF page 18 (841x595:0:0)
NOTICE processing PDF page 19 (841x595:0:0)
NOTICE processing PDF page 20 (841x595:0:0)
NOTICE processing PDF page 21 (841x595:0:0)
NOTICE processing PDF page 22 (841x595:0:0)
NOTICE Writing SWF file 19th.swf
swfcombine -X 841 -Y 595 "rfx8.swf" viewport="19th.swf" -o "19th.swf"
現在的問題是如何自制一個flash 9版本的viewer。過程如下,首先stage的尺寸是600x800;建立三個MovieClip元件,其子內容皆為在Flash Pro CS5.5中繪製的Graphic,將三者拖放到stage中:
三個元件的名稱為:prev,next,viewport。
第一幀程式碼層上as程式碼如下:
import flash.events.MouseEvent;
prev.addEventListener(MouseEvent.MOUSE_DOWN, onPrev);
next.addEventListener(MouseEvent.MOUSE_DOWN, onNext);
function onPrev($e:MouseEvent):void
{
viewport.prevFrame();
}
function onNext($e:MouseEvent):void
{
viewport.nextFrame();
}
viewport.gotoAndStop(1);
測試執行,生成一個名為viewer.swf的flash檔案。將它複製到SWFTools的路徑下,重新執行命令。
C:\Program Files\SWFTools>pdf2swf -T9 -s insertstop -B viewer.swf ISO27001.pdf -o 19th-2.swf
NOTICE processing PDF page 1 (841x595:0:0)
NOTICE File contains jpeg pictures
NOTICE processing PDF page 2 (841x595:0:0)
NOTICE processing PDF page 3 (841x595:0:0)
NOTICE processing PDF page 4 (841x595:0:0)
NOTICE processing PDF page 5 (841x595:0:0)
NOTICE processing PDF page 6 (841x595:0:0)
NOTICE processing PDF page 7 (841x595:0:0)
NOTICE processing PDF page 8 (841x595:0:0)
NOTICE processing PDF page 9 (841x595:0:0)
NOTICE processing PDF page 10 (841x595:0:0)
NOTICE processing PDF page 11 (841x595:0:0)
NOTICE processing PDF page 12 (841x595:0:0)
NOTICE processing PDF page 13 (841x595:0:0)
NOTICE processing PDF page 14 (841x595:0:0)
NOTICE processing PDF page 15 (841x595:0:0)
NOTICE processing PDF page 16 (841x595:0:0)
NOTICE processing PDF page 17 (841x595:0:0)
NOTICE processing PDF page 18 (841x595:0:0)
NOTICE processing PDF page 19 (841x595:0:0)
NOTICE processing PDF page 20 (841x595:0:0)
NOTICE processing PDF page 21 (841x595:0:0)
NOTICE processing PDF page 22 (841x595:0:0)
NOTICE Writing SWF file 19th-2.swf
swfcombine -X 841 -Y 595 "viewer.swf" viewport="19th-2.swf" -o "19th-2.swf"
實際上有一些地方需要注意,我將兩個黃色翻頁按鈕擺放的Y位置是511,因為通過pdf2swf生成的SWF的高是按照pdf中的高度來設定的,就是提示中的595,而之後當呼叫swfcombine時這個數字作為引數被傳入,結果,與viewer合成後的swf的高就變成了595了。現在的問題是,如何在pdf2swf中就指定這個高度,來調整輸出的swf的高度,這樣就可以令按鈕不必遮住pdf的內容。
現在,這個新生成的swf是flash 9的版本,同時又具有了viewer,我們再來看看把它載入進一個Flash之後,得到的是個什麼東東:
trace($mc.numChildren); // 3
var $obj1:* = $mc.getChildAt(0); // MovieClip, viewport
var $obj2:* = $mc.getChildAt(1); // MovieClip, prev
var $obj3:* = $mc.getChildAt(2); // MovieClip, next
這個結構與當初建立viewer時的結構是一樣的,參見上面的截圖。
相關文件:
Refs: