文章詳情頁(yè)
基于Java 開(kāi)發(fā)QuickTime 程序
瀏覽:7日期:2024-06-16 13:09:31
內(nèi)容: 摘要:QuickTime 視頻文件播放程序如今已經(jīng)發(fā)展和成長(zhǎng)15年了,在添加新特性的同時(shí)也保持了極好的向后兼容性:1990年在系統(tǒng)6或7上制造的QuickTime movie2005年仍然能在Mac 操作系統(tǒng)X 10.3.7上播放。這是因?yàn)镼uickTime 的共享代碼片段的組件系統(tǒng)可被發(fā)現(xiàn)和被動(dòng)態(tài)的調(diào)用。QuickTime 所需要用來(lái)播放movie的大部分是一個(gè)組件:理解文件格式的代碼;使在文件中使用的音頻,視頻,或其他編解碼器減壓的代碼;處理流媒體協(xié)議的代碼;等等。舊的組件簡(jiǎn)單的維護(hù),新的組件向QuickTime 添加了更多的功能。當(dāng)QuickTime 的一個(gè)新版本增加了對(duì)新的格式或編解碼器的支持,或當(dāng)用戶自己安裝了新的特性,一個(gè)運(yùn)行良好的應(yīng)用程序?qū)?huì)自動(dòng)增加這些新的特性。并且,幸運(yùn)地,組件為Java 程序員做好了準(zhǔn)備,他們可以使用適合于Java 應(yīng)用編程接口的QuickTime 。在這篇來(lái)自《適用于JAVA的QuickTime :開(kāi)發(fā)者的寶典》,Chris Adamson 指出怎么寫這樣一個(gè)性質(zhì)良好的應(yīng)用程序。第四章:用組件工作介紹了組件的類型和子類型的識(shí)別模式并指出如何導(dǎo)出一個(gè)QuickTime movie到固定格式,或運(yùn)行時(shí)能找到的任何格式。它說(shuō)明了如何導(dǎo)入導(dǎo)出圖形,并提供了顯示所有已安裝組件的一個(gè)實(shí)用程序。版權(quán)聲明:任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必保留以下作者信息和鏈接作者:Chris Adamson;Amydeng(作者的blog:http://blog.matrix.org.cn/page/Amydeng)譯文:http://www.matrix.org.cn/resource/article/44/44269_Java+QuickTime.html關(guān)鍵字:Java;QuickTime用組件工作 當(dāng)QuickTime1990年問(wèn)世的時(shí)候,它能夠播放一張郵票大小的movie——僅僅在價(jià)值7000美圓的硬盤上。它使用音頻和視頻的編解碼器,盡管這些編解碼器今天仍然被支持,但已被用戶淘汰很久了。然而,從 Apple 視頻到Cinepak 視頻再到MPEG-4,是一個(gè)平滑的變換。這是由于一個(gè)特別的標(biāo)準(zhǔn)化設(shè)計(jì)——QuickTime 里大部分繁重的任務(wù)都是由組件或共享的動(dòng)態(tài)代碼執(zhí)行。組件提供了如下的支持:導(dǎo)入導(dǎo)出圖片和movie格式,執(zhí)行圖片和聲音的壓縮和解壓縮,訪問(wèn)系統(tǒng)資源及更多其它功能。QuickTime安裝程序提供了很多組件,這些組件具備許多有效的特性,而用戶也可以自己從Apple或者第三方添加其他組件進(jìn)來(lái),這些組件能夠提供更多的功能,如支持更多的多媒體格式。 API里組件并不處于中心位置——畢竟,在開(kāi)始的幾章里已經(jīng)設(shè)法完全避免提到它們。當(dāng)我們需要打開(kāi)文件并將它們轉(zhuǎn)換為movie,解壓縮和解釋數(shù)據(jù),保存它們到硬盤等等時(shí),這個(gè)時(shí)候我們QuickTime做正確的事情。當(dāng)需要的時(shí)候,QuickTime為了必需的功能瀏覽它的組件目錄并得到它所需要的東西。 但是有些時(shí)候開(kāi)發(fā)者為了指出什么是可用的,或者為了指定特定地行為,或者需要更直接地使用組件。這個(gè)時(shí)候, 找出運(yùn)行時(shí)可用的工具是一個(gè)強(qiáng)有力的方法。指定組件類型 QuickTime里,組件由類型和子類型來(lái)識(shí)別,類型指定了功能范圍,子類型是該功能的一個(gè)特定實(shí)現(xiàn)。例如,有一個(gè)“movie 導(dǎo)出器類型,代表可以導(dǎo)出一部movie到非QuickTime格式的組件。它用子類型確定適合AVI(Video for windows 的多媒體文件格式),MPEG-4的導(dǎo)出器, 這些標(biāo)識(shí)符是32比特的整型值,但它們不列舉你可能期望來(lái)自JAVA的常數(shù)。通常地,32比特被分成是4個(gè)8比特的ASCII 字符來(lái)讀取,組成一個(gè)簡(jiǎn)短的,易讀的名字。這些在本地API包里定義為OSTypes類型,但是當(dāng)與有意義的值組裝到一起時(shí),它們被稱為“四字符代碼,來(lái)自本地FOUR_CHAR_CODE函數(shù),該函數(shù)為一個(gè)字符串返回一個(gè)OSType類型。這經(jīng)常簡(jiǎn)稱為 FCC或4CC。 這種模式采納了C程序員的觀點(diǎn)。例如,為一部movie定義4CC需要一個(gè)好的,簡(jiǎn)單的短語(yǔ),就像在本地頁(yè)眉文件Movies.h 中所見(jiàn)的一樣: MovieResourceType = 'moov' 然而,由于Java的更先進(jìn)的文本處理方法,在Java中用4CCs 處理要困難的多。因?yàn)椋琔nicode的應(yīng)用意味著每個(gè) Java字符是2個(gè)比特,這說(shuō)明我們需要額外的幫助來(lái)將Java字符轉(zhuǎn)化為4CC。我們?nèi)绾巫瞿兀? 幸運(yùn)地,QTUtils類提供了2個(gè)方法:toOSType()和fromOSType()。例4-1展示了這些方法,將一個(gè)Java 字符串轉(zhuǎn)化為一個(gè)4CC 表示,并從它的4CC 表示轉(zhuǎn)化回來(lái)。Example 4-1. Converting to and from FOUR_CHAR_CODEs package com.oreilly.qtjnotebook.ch04;import quicktime.util.QTUtils;public class FourCharCodeTest extends Object { public static void main (String[] args) { if (args.length < 1) { System.out.println ('Usage: FourCharCodeTest '); return; } System.out.println (args[0])int fcc = QTUtils.toOSType (args[0]); System.out.println (fcc); System.out.println (Integer.toHexString (fcc)); String fccString = QTUtils.fromOSType(fcc); System.out.println (fccString); }}main()函數(shù)從命令行取得一個(gè)String ,把它轉(zhuǎn)換成一個(gè)4CC,打印出4CC的十進(jìn)制和十六進(jìn)制值,然后把它轉(zhuǎn)換回一個(gè)String 。用moov 作實(shí)驗(yàn)時(shí),導(dǎo)出如下: 剛剛發(fā)生了什么?這些有用的方法提供了一些好的,老式的bit-munging來(lái)做它們的轉(zhuǎn)換。toOSType()以一個(gè)String 為依據(jù),取每個(gè)字符的低8位并把它們放在所返回整型值的適當(dāng)位置。換句話說(shuō),第一個(gè)字符的低8為代替了整數(shù)的開(kāi)始8位,然后下一個(gè)字符作為下一個(gè)8位,等等。圖4-1說(shuō)明了在 'moov'位轉(zhuǎn)移中在哪里位結(jié)束。(圖4-1)fromOSType()做相反的轉(zhuǎn)換,轉(zhuǎn)換整型的比特位為一個(gè)四字符的Java 字符串。導(dǎo)出movie 最明顯的有用的組件之一是MovieExporter,你可以用它來(lái)將一個(gè)QuickTime movie轉(zhuǎn)換為一個(gè)非QuickTime 格式的movie,如AVI 或MPEG-4。我們?nèi)绾巫瞿兀款恞uicktime.std.qtcomponents.MovieExporter圍繞movie導(dǎo)出組件提供了方便的Java 封裝。這需要你傳遞給它一個(gè)子類型參數(shù),告訴他你想使用哪種導(dǎo)出類——也就是,你想要導(dǎo)出為哪種格式。例4-2展示了從固定的子類型列表中創(chuàng)造和利用MovieExporter。Example 4-2. Simple MovieExporter creation and use package com.oreilly.qtjnotebook.ch04;import quicktime.*;import quicktime.std.*;import quicktime.std.movies.*;import quicktime.io.*;import quicktime.std.qtcomponents.*;import quicktime.utils.QTUtils;import java.awt.*;import javax.swing.*;import com.oreilly.qtjnotebook.ch01.QTSessionCheck;public class SimpleMovieExport extends Object { public static final void main (String[] args) { new SimpleMovieExport(); } public SimpleMovieExport() { // build choices ExportChoice[] choices = new ExportChoice[3]; choices[0] = new ExportChoice ('QuickTime Movie', StdQTConstants.kQTFileTypeMovie); choices[1] = new ExportChoice ('AVI file', StdQTConstants.kQTFileTypeAVI); choices[2] = new ExportChoice ('MPEG-4 file', QTUtils.toOSType('mpg4')); try { // query user for a movie to open QTSessionCheck.check(); QTFile file = QTFile.standardGetFilePreview (QTFile.kStandardQTFileTypes); OpenMovieFile omFile = OpenMovieFile.asRead (file); Movie movie = Movie.fromFile (omFile); // offer a choice of movie exporters JComboBox exportCombo = new JComboBox (choices); JOptionPane.showMessageDialog (null, exportCombo, 'Choose exporter', JOptionPane.PLAIN_MESSAGE); ExportChoice choice = (ExportChoice) exportCombo.getSelectedItem(); // create an exporter MovieExporter exporter = new MovieExporter (choice.subtype); QTFile saveFile =new QTFile (new java.io.File('Untitled')); // do the export movie.setProgressProc(); movie.convertToFile (null, saveFile, StdQTConstants.kQTFileTypeMovie, StdQTConstants.kMoviePlayer, IOConstants.smSystemScript, StdQTConstants.showUserSettingsDialog | StdQTConstants.movieToFileOnlyExport | StdQTConstants.movieFileSpecValid, exporter); // need to explicitly quit (since awt is running) System.exit(0);} catch (QTException qte) { qte.printStackTrace();}} public class ExportChoice {String name; int subtype; public ExportChoice (String n, int st) { name = n; subtype = st; } public String toString() { return name; } }}運(yùn)行時(shí),程序提示用戶打開(kāi)一個(gè)movie文件。一旦movie裝載了,程序提供一個(gè)導(dǎo)出格式選擇對(duì)話框。如圖4-2所示。 Figure 4-2. Choice dialog with canned MovieExporter types 然后,顯示一個(gè)保存對(duì)話框提示導(dǎo)出信息(例如,“轉(zhuǎn)換為MPEG-4格式)和一個(gè)選擇按扭。該按扭關(guān)聯(lián)一個(gè)明確導(dǎo)出格式的對(duì)話框。例如,AVI 導(dǎo)出對(duì)話框相當(dāng)簡(jiǎn)單,僅僅提供幾個(gè)設(shè)置供選擇。相反,MPEG-4導(dǎo)出對(duì)話框,圖4-3所示,格外的繁瑣,充斥著多種選擇的描述,幫助用戶理解他們的選擇和并會(huì)保證他們的導(dǎo)出文件適應(yīng)MPEG-4的標(biāo)準(zhǔn)。 在用戶做了選擇并按下OK鍵后,比較長(zhǎng)的導(dǎo)出過(guò)程便開(kāi)始了。因?yàn)閙ovie導(dǎo)出是潛在的計(jì)算密集的,每個(gè)視頻畫面和每個(gè)音頻示例都必須被重新編碼——這個(gè)過(guò)程之間會(huì)出現(xiàn)一個(gè)進(jìn)度框,這樣用戶可以看到導(dǎo)出過(guò)程完成了多少,還要花多長(zhǎng)時(shí)間。剛剛發(fā)生了什么?這個(gè)程序使用了一個(gè)內(nèi)部類ExportType 封裝一個(gè)子類型,整型和一個(gè)字符串。很大程度上是為了簡(jiǎn)化在格式選擇對(duì)話框中使用的JcomboBox 。這些子類型來(lái)自StdQTConstants 中定義的常量。一旦做出了選擇,程序?qū)⒆宇愋蛥?shù)傳遞給它的構(gòu)造器來(lái)選擇適當(dāng)?shù)腗ovieExporter。下一步,調(diào)用setProgressProc()方法請(qǐng)求一個(gè)前進(jìn)對(duì)話框。最后,通過(guò)調(diào)用convertToFile()方法,程序開(kāi)始執(zhí)行導(dǎo)出。這個(gè)方法需要幾個(gè)參數(shù): Track ,指明僅僅導(dǎo)出這個(gè)軌跡,null代表需要導(dǎo)出所有軌跡。 QTFile ,導(dǎo)出到的文件。 文件類型,如StdQTConstants.kQTFileTypeMovie。 一個(gè)構(gòu)造器,如StdQTConstants.kMoviePlayer。 一個(gè)腳本標(biāo)簽,典型的是IOConstants.smSystemScript。 行為標(biāo)志。這個(gè)例子使用了所有3個(gè)有效值:showUserSettingsDialog 讓導(dǎo)出過(guò)程調(diào)用包含文件名和選擇按扭的保存對(duì)話框;movieToFileOnlyExport 限制導(dǎo)出組件的導(dǎo)出選擇格式子類型;movieFileSpecValid 聲明QTFile 是有效的并且應(yīng)該作為默認(rèn)在對(duì)話中作為默認(rèn)值使用。 MovieExporter 用來(lái)進(jìn)行導(dǎo)出。關(guān)于…… 用MovieExporter 本身來(lái)導(dǎo)出?那是一個(gè)可供選擇的辦法。導(dǎo)出器的toFile()方法導(dǎo)出movie到一個(gè)文件,而toHandle()方法導(dǎo)出文件到內(nèi)存。同時(shí)也可以僅導(dǎo)出部分movie,比如指定開(kāi)始時(shí)間和持續(xù)時(shí)間參數(shù)。注意要這樣做的話需要不同的程序流程,因?yàn)槭紫饶阈枰玫接行У腝TFile (可能是用AWT文件對(duì)話框),然后你需要調(diào)用導(dǎo)出器的doUserDialog()方法去設(shè)定導(dǎo)出。Movie 類的convertToFile()方法能更方便一些,因?yàn)椋襁@兒所看到的,它允許使用默認(rèn)的前進(jìn)對(duì)話框。當(dāng)使用MovieExporter 方法時(shí),程序無(wú)權(quán)訪問(wèn)默認(rèn)對(duì)話框。在那種情況下,唯一可選的辦法是提供一個(gè)自定義的前進(jìn)對(duì)話框和用setProgressProc()方法處理進(jìn)程回調(diào)。也有不好的地方:我試著在windows下導(dǎo)出MPEG-4,但得不到任何音頻選項(xiàng)。當(dāng)我點(diǎn)擊導(dǎo)出對(duì)話框里的音軌菜單,我得到如圖4-4所示的無(wú)用的面板。 這不是技術(shù)上的問(wèn)題而是一種合理的情況。Apple 得到了適合它的基于Mac的QuickTime 用戶的MPEG-4的音頻編碼許可,但不適合Windows 用戶。這個(gè)編解碼器存在,但顯然你必須就許可條件聯(lián)系Dolby ,讓它們適合Windows操作系統(tǒng)。導(dǎo)出movie到任何已安裝的格式 導(dǎo)出到已知格式的列表會(huì)受到一些限制——如果終端用戶已經(jīng)安裝了新的或者來(lái)自第三方或者是QuickTime自身更新的movie 導(dǎo)出器,使用固定導(dǎo)出器列表的程序?qū)⒉荒茏R(shí)別他們。幸運(yùn)的是,QuickTime提供了一個(gè)詢問(wèn)方法可以查詢到關(guān)于某個(gè)類型目前已經(jīng)安裝的組件。你可以用這個(gè)策略找到所有可用的導(dǎo)出器列表。我如何做那個(gè)呢? AdvancedMovieExport 排除了SimpleMovieExport 所用的選擇數(shù)組里的3個(gè)固定入口改,而通過(guò)動(dòng)態(tài)發(fā)現(xiàn)來(lái)構(gòu)造數(shù)組。這段代碼將代替SimpleMovieExport 構(gòu)造器里的“build choices代碼塊但需要添加到try-catch內(nèi)部,因?yàn)樗赡軖伋鯭TException異常。運(yùn)行時(shí),支持的導(dǎo)出器列表讓人出乎意料的大,如圖4-5所示。在這種情況下,一個(gè)“普通的movie,這將會(huì)導(dǎo)出一個(gè)video track和一個(gè)audio track,這意味著任何只導(dǎo)出audio或audio/video格式都行。 你也應(yīng)該注意,一些導(dǎo)出器不能導(dǎo)出movie。這些是比較笨的標(biāo)準(zhǔn): 這些失敗是因?yàn)樵磎ovie中沒(méi)有包含可以導(dǎo)出為這些格式的tracks。源movie有各種不同的tracks時(shí),一些能成功導(dǎo)出,另一些將會(huì)失敗。剛剛發(fā)生了什么?由子類型尋找組件的過(guò)程是非常奇特的。它重復(fù)調(diào)用“find方法,傳入上一個(gè)匹配的組件。這樣做需要一個(gè)ComponentDescription來(lái)作為模板進(jìn)行下一次匹配,同時(shí)需要一個(gè)ComponentIdentifier, 代表特定的組件(并不是該特定的組件的實(shí)例)。為了找到movie導(dǎo)出器,用常量movieExporterType來(lái)初始化ComponentDescription 模板。靜態(tài)ComponentIdentifier.find()方法會(huì)尋找匹配的組件,但要求你重復(fù)地傳入ComponentDescription 模板以及該方法先前找到的ComponentIdentifier。第一次重復(fù)時(shí),將是空值。調(diào)用find()方法返回一個(gè)ComponentIdentifier,傳遞給MovieExporter 構(gòu)造器創(chuàng)造一個(gè)新的導(dǎo)出。find()返回空時(shí),表明不再有合適的匹配。匹配的ComponentIdentifier 通過(guò)getInfo()方法提供了關(guān)于它自身的信息。這將會(huì)返回另一個(gè)ComponentDescription 對(duì)象,不同于之前作為模板使用的ComponentDescription對(duì)象。你可以利用這個(gè)去得到類型和子類型的信息(FOUR_CHAR_CODE ints),名字,消息字符串,制造商代碼等等。找到一個(gè)MovieExporter 并不能夠保證它能真正的工作。你可以調(diào)用validate()方法,像這個(gè)例子這樣,來(lái)檢查示例的導(dǎo)出器能夠?qū)С鼋o定的movie。在這個(gè)例子中,如果validate()方法拋出異常,它就是非標(biāo)準(zhǔn)的并且導(dǎo)出器沒(méi)有被添加到JcomboBox。關(guān)于……能否通過(guò)程序來(lái)設(shè)置導(dǎo)出參數(shù),而不是每次都使用導(dǎo)出對(duì)話框?這是可能的,盡管需要開(kāi)發(fā)中至少需要使用一次導(dǎo)出對(duì)話框。一個(gè)配置好了的MovieExporter 經(jīng)由getExportSettingsFromAtomContainer()方法能夠以AtomContainer對(duì)象的形式返回它的配置狀態(tài)。 這個(gè)AtomContainer對(duì)象可以經(jīng)由setExportSettingsFromAtomContainer()方法傳遞給一個(gè)導(dǎo)出器。在單獨(dú)的應(yīng)用程序里,這是非常直接的。為了保證各個(gè)sessions之間的持久,你必須在AtomContainer 上調(diào)用getBytes()得到本地結(jié)構(gòu)然后把它保存到硬盤,數(shù)據(jù)庫(kù)等。這樣,將來(lái)我們能夠重新生成這個(gè)配置,將所有字節(jié)讀入一個(gè)字節(jié)數(shù)組,從該數(shù)組中創(chuàng)造一個(gè)QTHandle ,然后將它傳遞給AtomContainer.fromQTHandle()來(lái)創(chuàng)建AtomContainer。QuickTime 6.3版引入了一個(gè)新API來(lái)設(shè)置導(dǎo)出器,但是這樣寫,它沒(méi)有通過(guò)QTJ方法的調(diào)用顯示出來(lái)。而且,如果我指定類型和子類型,我將總是得到一個(gè)匹配嗎?不,在一些情況下,你將得到多重匹配組件,并且你可能需要使用其它的標(biāo)準(zhǔn)來(lái)選擇用哪一個(gè)。在一個(gè)相當(dāng)經(jīng)典的case中我的一位技術(shù)導(dǎo)師指出了:某些時(shí)候用同樣的子類型你得到了不止一個(gè)導(dǎo)出器,這個(gè)時(shí)候你需要用“manufacturer代碼去區(qū)分它們。 這特別適用于AIFF導(dǎo)出器——你所找到的第一個(gè)導(dǎo)出器類型僅導(dǎo)出MIDI類型。為了導(dǎo)出任意的QT視頻文件到AIFF,你需要明確地迭代并繼續(xù)選擇第二個(gè)!導(dǎo)入導(dǎo)出圖形QuickTime提供了許多組件來(lái)導(dǎo)入導(dǎo)出不同的圖象格式。正如你所期望的,這些組件被封裝在類GraphicsImporter和GraphicsExporter里。GraphicImportExport例示應(yīng)用程序使用了這兩個(gè)類來(lái)說(shuō)明動(dòng)態(tài)的查找輸入導(dǎo)出器。Example 4-3. Graphics import and exportpackage com.oreilly.qtjnotebook.ch04;import quicktime.*;import quicktime.io.*;import quicktime.std.*;import quicktime.std.comp.*;import quicktime.std.image.*;import quicktime.app.view.*;import java.awt.*;import java.awt.event.*;import javax.swing.*;import java.util.Vector;import java.io.*;import com.oreilly.qtjnotebook.ch01.QTSessionCheck;public class GraphicImportExport extends Object { Button exportButton; Frame frame; GraphicsImporter importer; static final int[] imagetypes = { StdQTConstants.kQTFileTypeQuickTimeImage}; /* other interesting values: StdQTConstants.kQTFileTypeGIF, StdQTConstants.kQTFileTypeJPEG, StdQTConstants4.kQTFileTypePNG, StdQTConstants4.kQTFileTypeTIFF StdQTConstants.kQTFileTypeMacPaint, StdQTConstants.kQTFileTypePhotoShop, StdQTConstants.kQTFileTypePICS, StdQTConstants.kQTFileTypePicture, */ public static void main (String[] args) { new GraphicImportExport(); } public GraphicImportExport() { try { QTSessionCheck.check(); QTFile inFile = QTFile.standardGetFilePreview (imagetypes); importer = new GraphicsImporter (inFile); // put image onscreen QTComponent qtc = QTFactory.makeQTComponent (importer); java.awt.Component c = qtc.asComponent(); frame = new Frame ('Imported image'); frame.setLayout (new BorderLayout()); frame.add (c, BorderLayout.CENTER); exportButton = new Button ('Export'); exportButton.addActionListener (new ActionListener() { public void actionPerformed (ActionEvent ae) { try { doExport(); } catch (QTException qte) { qte.printStackTrace(); } } }); frame.add (exportButton, BorderLayout.SOUTH); frame.pack(); frame.setVisible(true); } catch (QTException qte) { qte.printStackTrace(); } } public void doExport() throws QTException { // build list of GraphicExporters Vector choices = new Vector(); ComponentDescription cd = new ComponentDescription ( StdQTConstants.graphicsExporterComponentType); ComponentIdentifier ci = null; while ( (ci = ComponentIdentifier.find(ci, cd)) != null) { choices.add (new ExportChoice (ci.getInfo().getName()ci.getInfo().getSubTyp } // offer a choice of movie exporters JComboBox exportCombo = new JComboBox (choices); JOptionPane.showMessageDialog (frame,exportCombo,'Choose exporter',JOptionPane.PLAIN_MESSAGE); ExportChoice choice = (ExportChoice) exportCombo.getSelectedItem(); System.out.println ('chose ' + choice.name); // build a GE, wire up to the GraphicsImporter GraphicsExporter exporter = new GraphicsExporter (choice.subtype); exporter.setInputGraphicsImporter (importer); // ask for destination, settings FileDialog fd = new FileDialog (frame, 'Save As', FileDialog.SAVE); fd.setVisible(true); String filename = fd.getFile(); if (filename.indexOf('.') == -1) filename = filename + '.' + exporter.getDefaultFileNameExtension(); File file = new File (fd.getDirectory(), filename); exporter.setOutputFile (new QTFile(file)); exporter.requestSettings();// export exporter.doExport(); // need to explicitly quit (since awt is running) System.exit(0); } public class ExportChoice { String name; int subtype; public ExportChoice (String n, int st) { name = n; subtype = st; } public String toString() { return name; } }}運(yùn)行時(shí),程序顯示一個(gè)對(duì)話框,選擇要導(dǎo)入的圖形。在Windows環(huán)境下,該對(duì)話框里的“文件類型是QuickTime圖象。一旦圖象被選定,它和一個(gè)“導(dǎo)出按扭一起顯示在窗口中。當(dāng)用戶點(diǎn)擊該按扭,她會(huì)詢問(wèn)你類型,如圖4-6所示。 之后,程序顯示一個(gè)配置對(duì)話框指定選定的導(dǎo)出類型——最小值,這個(gè)對(duì)話框也提供一個(gè)顏色深度的選擇(256色,256灰度,百萬(wàn)像素等等)。下一步,將會(huì)出現(xiàn)一個(gè)保存對(duì)話框, 要求你指定導(dǎo)出文件的位置。一旦通過(guò),程序轉(zhuǎn)換該圖象到指定的格式,并保存在提供的位置。剛剛發(fā)生了什么?注意QTFile.standardGetFilePreview(),它顯示一個(gè)文件打開(kāi)對(duì)話框并帶出一串4整型的數(shù)字,代表各種文件格式常數(shù)的FOUR_CHAR_CODEs,作為可選文件類型的過(guò)濾器。你可以利用QTFileTypeQuickTimeImage作為方便的通配符來(lái)匹配QuickTime能打開(kāi)的任何種類的圖象,盡管它看起來(lái)僅工作在Windows操作系統(tǒng)上(實(shí)際上, 在Mac上,任何文件都可被選中)。給定一個(gè)文件,你可以創(chuàng)建一個(gè)GraphicsImporter對(duì)象將它裝載到QuickTime。為了導(dǎo)入圖片到屏幕上,需要將importer傳給 QTFactory.makeQTComponent()方法,該方法返回一個(gè)QTComponent,你可以造型(cast)為一個(gè)AWT組件, 或者為了類型安全安全,通過(guò)asComponent()方法來(lái)轉(zhuǎn)換為了將圖片導(dǎo)出到另外一種格式,你可以通過(guò)創(chuàng)造一個(gè)ComponentDescription模板來(lái)匹配graphicsExporterComponentType的組件, 來(lái)查找導(dǎo)出器的子類型。在例子中,匹配組件的名字將出現(xiàn)在一個(gè)JComboBox里。當(dāng)一個(gè)子類型被選中了,傳遞該子類型到GraphicsExporter的構(gòu)造函數(shù)來(lái)創(chuàng)建GraphicsExporter對(duì)象。GraphicsExporter需要綁定到某類型的圖片源。有了GraphicsImporter,你可以用setInputGraphicsImporter()方法來(lái)實(shí)現(xiàn)這點(diǎn)。導(dǎo)出器還需要一個(gè)目的文件。如果寫出到一個(gè)文件,你可以用setOutputFile()來(lái)設(shè)置它——僅為了安全起見(jiàn),檢查用戶提供的文件擴(kuò)展名和導(dǎo)出器用getDefaultFileNameExtension()方法返回的值是明智的。用戶可能想在導(dǎo)出顏色,圖片質(zhì)量,和其它設(shè)置上進(jìn)行某些改變,這個(gè)時(shí)候,requestSettings()方法可提供一個(gè)對(duì)話框。所有這些做完后,你可以用doExport()方法來(lái)導(dǎo)出了。關(guān)于…有其它的源適合該導(dǎo)出嗎?GraphicsExporter的Javadoc提供了一系列的setInputXXX()方法。在下一章,我們將探討這些問(wèn)題,包括Picts, QDGraphics,和PixMaps。那么關(guān)于導(dǎo)出參數(shù)的設(shè)置呢?QTJ有一些方法可以代替用戶對(duì)話框。像setDepth()和setCompressionMethod()。一個(gè)有趣的方法,setTargetDataSize(),讓導(dǎo)出器可以有“quality選擇(像JPEG)找一個(gè)值將導(dǎo)致產(chǎn)生一個(gè)給定字節(jié)大小的文件。發(fā)現(xiàn)所有已安裝的組件我希望到這里,你至少對(duì)適用于QuickTime的其它組件有了些許的興趣。很容易發(fā)現(xiàn)所有的組件,用一個(gè)相同的方法我們可以發(fā)現(xiàn)各種MovieExporters和GraphicExporters:提供一個(gè)ComponentDescription模板,并利用ComponentIdentifier.find()方法。而使用一個(gè)空白模板,將會(huì)顯示所有的組件。我怎樣做呢?例子4-4發(fā)現(xiàn)了所有已安裝的組件并記錄了他們的類型,子類型和描述。Example 4-4. Discovering al instaled componentspackage com.oreilly.qtjnotebook.ch04;import quicktime.*;import quicktime.std.*;import quicktime.std.comp.*;import quicktime.util.QTUtils;import com.oreilly.qtjnotebook.ch01.QTSessionCheck;public class ComponentTour { public static void main (String[] args) { try { QTSessionCheck.check(); /* use this wildcard to show all components in QT */ ComponentDescription wildcard = new ComponentDescription(); ComponentIdentifier ci = null; while ( (ci = ComponentIdentifier.find(ci, wildcard)) != null) { ComponentDescription cd = ci.getInfo(); System.out.println (cd.getName() + ' (' + QTUtils.fromOSType (cd.getType()) + '/' + QTUtils.fromOSType (cd.getSubType()) + } catch (QTException qte) { qte.printStackTrace(); } }}導(dǎo)出結(jié)果有幾百行長(zhǎng),像下面這樣:run-ch04-componenttour:[java] Apple MP3 Decoder (adec/.mp3) An AudioCodec that decodes MPEG-1,MPEG-2, MPEG-2.5 Layer III into linear PCM data[java] MPEG-4 AAC Decoder (adec/aac ) An AudioCodec that decodes MPEG-4AAC into linear PCM data [java] Apple Lossless Decoder (adec/alac) An AudioCodec that decodesApple Lossless into linear PCM data [java] Apple IMA4 Decoder (adec/ima4) An AudioCodec that decodes IMA4into linear PCM data[java] MPEG-4 AAC Encoder (aenc/aac ) An AudioCodec that encodes linearPCM data into MPEG-4 AAC [java] Apple Lossless Encoder (aenc/alac) An AudioCodec that encodeslinear PCM data into Apple Lossless[java] Apple IMA4 Encoder (aenc/ima4) An AudioCodec that encodes linearPCM data into IMA4 [java] Applet (aplt/scpt) The component that runs script applications [java] Apple: AUConverter (aufc/conv) AudioConverter unit [java] Apple: AUVarispeed (aufc/vari) Apple's varispeed playback[...]剛剛發(fā)生了什么?關(guān)鍵點(diǎn)是通過(guò)沒(méi)有參數(shù)的構(gòu)造器得到ComponentDescriptor的那行。這為ComponentIdentifier. find()方法創(chuàng)建了一個(gè)完全的空白模板。當(dāng)然,如果你僅僅想遍歷特定類型的組件,你可以傳遞一個(gè)像StdQTConstants,movieImportType的類型值,限制MovieImporters的查找,這樣,指明QuickTime可以導(dǎo)入的格式類型。證明和解釋每種類型的組件超出了本書的范圍——實(shí)際上,在舊的Macintosh series中它們占了大量的篇幅。當(dāng)然,重要的一些在表4-1中列出來(lái)了。注意不是所有的組件都在Java封裝類里。 待續(xù)..資源:Matrix Java社區(qū): http://www.matrix.org.cn Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd
標(biāo)簽:
Java
上一條:體驗(yàn) JAVA 5 的新增語(yǔ)言特性下一條:Java中Collection Frame中常用集合簡(jiǎn)析(ArrayList,Vector,HashSet,TreeSe
相關(guān)文章:
1. 解決運(yùn)行django程序出錯(cuò)問(wèn)題 'str'object has no attribute'_meta'2. Vue基于iview table展示圖片實(shí)現(xiàn)點(diǎn)擊放大3. 基于Docker部署GitLab環(huán)境搭建的方法步驟4. 手把手教你用python發(fā)送短消息(基于阿里云平臺(tái))5. PHP程序員的學(xué)習(xí)技術(shù)成長(zhǎng)規(guī)劃6. python 批量下載bilibili視頻的gui程序7. JavaScript 面向?qū)ο蟪绦蛟O(shè)計(jì)詳解【類的創(chuàng)建、實(shí)例對(duì)象、構(gòu)造函數(shù)、原型等】8. python基于tkinter制作無(wú)損音樂(lè)下載工具(附源碼)9. 基于javaweb+jsp實(shí)現(xiàn)個(gè)人日記管理系統(tǒng)10. MySQL基于java實(shí)現(xiàn)備份表操作
排行榜
