熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

JAVA 3D動畫展示圖(Part2,使用QuickTime)

2013-11-23 19:18:34  來源: Java核心技術 

  在這一系列的第一部分中我描述了在JMF(JAVA媒體幀工作器 下同)的幫助下怎樣將一部電影片斷插入JAVA D場景中這個執行過程使用ModelViewController設計模式
  
  動畫屏幕是由JMFMovieScreen類表示的視覺元素
  
  動畫模型部分由JMFSnapper類控制
  
  java D行為類TimeBehavior是動畫中引起幀周期性恢復的控制類
  
  在這篇文章中我將使用QTJ(QuickTime for Java 下同)再次解析動畫成份QTJ提供一個覆蓋QuickTime API的依賴對象的java使之可以展示編輯和創建QuickTime動畫捕獲視頻 音頻展示D和D動畫QuickTime可用於Mac和Windows系統關於QTJ的安裝文檔和實例細節可在/quicktime/qtjava查詢
  
  由設計模式作出的推論只在動畫類JMFSnapper被QTSnapper取代時QTJ取代JMF在應用中有微小的作用
  
  圖兩幅QTJ情況下的D動畫截屏右邊圖片采取顯示屏背面視角
  
 

  從圖大致看出QTJbased 和JMF成像效果沒有明顯區別
  
  然而通過更仔細得比較可以看出有兩個變化QTJ動畫有輕微的被像素化播放的更慢像素化(像素化是對內部像素對於觀看者易見的數字圖像的顯示當一些用於普通的計算機顯示的低分辨率圖像被投射到一個大的顯示器上每一個像素都會變得單獨可見這種不常發生的現象就叫做像素化)是由於原始動畫從MPEG轉換為QuickTimes MOV格式引起的它可由更好的轉換方法矯正速度問題更基礎它與QTSnapper的潛在執行有關
  
  這篇文章的重點為?
  
  執行QTSnapper的兩種主要方法的討論一種方法是將動畫裡的每一幀都提出來顯示在屏幕上另一種方法依靠當前的時間提出幀第二種方法意味著可能將會遺漏部分幀畫面顫抖但遺漏 可以使播放更快
  
  一些簡單的FPS(framepersecond)度量器的介紹我將用它們這兩種方法的相對速度探測遺漏幀數
  
   此山非彼山
  
  與第一部分一樣編碼將利用兩個大型的API在這裡沒有時間介紹利用的細節了我將再次使用java D但API媒體將由JMF轉變為QTJ
  
  在我的OReilly book Killer Game Programming in Java (KGPJ)中有大量關於java D的信息還有圖的原碼
  
  我將不會解釋動畫屏幕和動畫更新行為因為它們與第一部分相同
  
  在QTJ技術中我將會使用QTSnapper從動畫中提取幀
  
  應用的兩種看法
  
 

  
應用流程圖

  
  此圖表與第一篇文章中的幾乎相同
  
  QuickTime動畫由QTSnapper類加載動畫屏幕由QTMovieScreen創建毫秒TimeBehavior對象調用QTMovieScreen中的nextFrame()方法然後調用QTSnapper中的getFrame()方法獲取動畫中的一個幀依次循環
  
  JMFSnapper與QTSnapper之間有一個很重要的不同JMFSnapper返回一個幀這個幀是動畫播放時的當前幀而QTSnapper返回動畫中的幀根據遞增的索引
  
  例如當getFrame()方法在JMFSnapper被反復調用時也許會重新得到幀等等它是由方法何時被調用與動畫播放速度決定的當getFrame()方法在QTSnapper被調用它將會返回幀等等
  
 

  
UML類的應用圖表僅列出公共方法

  
  此圖表除了動畫屏幕名和動畫類名(QTMovieScreen 和 QTSnapper)外與第一篇文章的相同事實上只有Snapper類的內部執行被改變
  
  JMF MovieD應用程序和QTJbased版本之間的改動需要Snapper被重寫
  
   // global variableprivate QTSnapper snapper;  // was JMFSnapper// in the constructor load the movie in fnmsnapper = new QTSnapper(fnm);
  
  這兩處改動是由於須將JMFMovieScreen重命名為QTMovieScreen
  
  這個例子中的所有代碼和文章的早期版本可以在KGPJ website查詢到
  
  一幀一幀的動畫
  
  理解QTSnapper的內在工作機理可以幫助我們對QuickTime動畫構造有一個大致的認識每一幅動畫可以理解為視頻軌跡和音頻軌跡在相同時間上的重疊是這種思想的圖示
  
 

  
QuickTime動畫的內部構造機理

  
  每個軌跡控制著其自身數據例如它包含的媒體類型和媒體本身媒體容器(media container)有它自己的數據結構包括它的持續時間和播放率(每秒播放抽樣數)媒體是由一組抽樣(或幀)組成第一個抽樣時間為(與媒體時間有關)抽樣是被變址的第一個抽樣在位置(非
  
  圖大致描述了QuickTime的軌跡和媒體結構
  
 

  
QuickTime軌跡和媒體的內在構造機理

  
  想要得到更多信息請查詢QuickTime指南的movie section
  
  打開動畫視頻媒體
  
  QTSnapper構造器打開動畫
  
  // globalsprivate boolean isSessionOpen = false;private OpenMovieFile movieFile;private Movie movie;// in the constructor// start a QuickTime sessionQTSessionopen();isSessionOpen = true;// open the moviemovieFile =  OpenMovieFileasRead( new QTFile(fnm) );movie = MoviefromFile(movieFile);
  
  在QuickTime使用之前調用QTSessionopen()方法將其初始化在終止時相應的調用QTSessionclose()方法
  
  軌跡定位和媒體訪問
  
  // more globalsprivate Track videoTrack;private Media vidMedia;// in the constructor // extract the video track from the movievideoTrack =   moviegetIndTrackType(       StdQTConstantsvideoMediaType      StdQTConstantsmovieTrackMediaType);if (videoTrack == null) { Systemoutprintln(Sorry not a video); Systemexit();}// get the media used by the video trackvidMedia = videoTrackgetMedia();
  
  一旦媒體打開從中提取各種信息
  
  // more globalsprivate MediaSample mediaSample;private int numSamples; // number of samplesprivate int sampIdx;   // current sample indexprivate int width;    // frame widthprivate int height;   // frame height// in the constructornumSamples = vidMediagetSampleCount();sampIdx = ;  // get first sample in the trackmediaSample = vidMediagetSample(  vidMediasampleNumToMediaTime(sampIdx)time);// store width and height of image in the sampleImageDescription imgDesc =    ImageDescription) mediaSampledescription;width = imgDescgetWidth();height = imgDescgetHeight();
  
  sampIdx作為計數器將在抽樣中被重復調用(抽樣於位置開始)
  
  動畫圖像的寬度和高度由第一個抽樣獲得接下來所有的抽樣都是同樣的尺寸
  
  測算 FPS
  
  由QTSnapper返回的 幀數/秒 將在稍後被用作類的不同使用方法的比較參數構造器中必要的參數已被初始化
  
  // frame rate globalsprivate long startTime;private long numFramesMade;// initialize them in the constructorstartTime = SystemcurrentTimeMillis(); numFramesMade = ;
  
  結束
  
  將應用程序結束時QTSnapper類中的stopMovie()方法將被調用它報告FPS關閉QuickTime
  
  // globalsprivate DecimalFormat frameDf =   new DecimalFormat(#); // dpsynchronized public void stopMovie(){ if (isSessionOpen) {  // report frame rate  long duration =     SystemcurrentTimeMillis() startTime;  double frameRate =    ((double) numFramesMade*)/duration;  Systemoutprintln(FPS: +          frameDfformat(frameRate));  QTSessionclose(); // close down QuickTime  isSessionOpen = false; }}
  
  由於stopMovie()和getFrame()是同步的所以從動畫中提取幀和QuickTime關閉在時間上是不可能同時進行
  
  緩存幀
  
  getFrame()返回一次抽樣樣品稱作BufferedImage對象被選擇的幀利用索引指數存貯在sampIdx
  
  // globalsprivate BufferedImage img formatImg;synchronized public BufferedImage getFrame(){ if (!isSessionOpen)  return null; if (sampIdx > numSamples)    // start back with the first sample  sampIdx = ; try {  /* Get the sample starting at the    specified index time */  TimeInfo ti =    vidMediasampleNumToMediaTime(sampIdx);  mediaSample=vidMediagetSample(titime);  sampIdx++;  writeToBufferedImage(mediaSample img);  // resize img writing it to formatImg  Graphics g = formatImggetGraphics();  gdrawImage(img      FORMAT_SIZE FORMAT_SIZE null);   // Overlay current t
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26629.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.