鷹翔宇空

          學(xué)習(xí)和生活

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            110 Posts :: 141 Stories :: 315 Comments :: 1 Trackbacks
          以前寫過2篇關(guān)于AWT中圖像加載顯示方法的文章,最近又多了一些對于 ImageProducer / ImagConsumer 模式的一些理解,嘗試著用文字總結(jié)了一下,接著還想再寫一篇介紹 AWT 中圖像過濾的原理和方法。你可能認為現(xiàn)在學(xué)習(xí) AWT 中的成像方法對于開發(fā)中已經(jīng)沒有太大的意義,因為已經(jīng)有了 Java 2D 和 JAI ,但是我在實際工作中感到還是無法完全離開 AWT,特別是在一些基本的應(yīng)用上。而且我覺得理解 AWT 的 Producer / Consumer (push) model 對于理解 Java 2D 的 Immediate mode model 和 JAI 的 Pipeline (pull) model 的都是有好處的。

          因為水平有限,這方面學(xué)習(xí)資料相對也不豐富,我也不知道我的理解或想法是否完全正確或者表述清楚,感興趣的朋友可以當(dāng)作學(xué)習(xí)參考,希望能夠和我聯(lián)系進行進一步的討論。



          AWT 使用 ImageProducer / ImagConsumer 模式,支持加載和顯示 GIF 圖像文件格式和 JPEG 圖像文件格式。因為圖像的加載和顯示是異步方式進行的,所以有大量加載和顯示的技術(shù)。

          在 AWT 中,提供了一個 java.awt.Image 類。java.awt.Image 類代表一個圖像對象被作為參數(shù)傳遞給其他用來顯示和處理圖像的其他 AWT 對象使用。例如,通過調(diào)用 Graphics.drawImage(java.awt.Image, int, int, ImageObserver) 方法,可以在組件中畫出圖像。

          java.awt.Image 是一個定義方法的抽象類,它定義的方法提供的對圖像信息的訪問。而創(chuàng)建和處理圖像的基本結(jié)構(gòu)則在 java.awt.image 包中。注意,這里不要和 java.awt.Image 發(fā)生混淆。

          AWT? 加載和顯示圖像使用的是 ImageProducer / ImagConsumer 模式,我們必須了解3個術(shù)語,ImageProducer(圖像生產(chǎn)者),ImageConsumer(圖像消費者)和ImageObserver(圖像觀察者)。

          ImageProducer 負責(zé)生產(chǎn)圖像的位,ImagConsumer 接受圖像的位,ImageObserver 監(jiān)視 ImageProducer 的圖像生產(chǎn)過程。ImageProducer 生產(chǎn)傳遞給 ImagConsumer 與圖像相關(guān)的位。因為圖像生產(chǎn)過程是異步進行的,并不是一次性生產(chǎn)所有圖像位,所以當(dāng) ImageProducer 加載圖像時,ImageObserver 用來監(jiān)視它的進展情況。因為 java.awt.Component 實現(xiàn)了 ImageObserver 接口,所以 AWT 中的每個組件都可以是ImageObserver,當(dāng)一個給定的 ImageProducer 進行異步操作時,這個 ImageObserver 可以選擇是否被更新。java.awt.image 包為 ImageProducer,ImagConsumer 和 ImageObserver 都定義了接口。

          ImageProducer
          和圖像相關(guān)的位并不存儲在 java.awt.Image 中,每個圖像都維護一個和一個 ImageProducer?的關(guān)聯(lián)。這個 ImageProducer?的責(zé)任是生產(chǎn)圖像的位并將它們傳送給 ImagConsumer,用于過濾該圖像。

          java.awt.image軟件包中,F(xiàn)ilteredImageSource(被過濾的圖像源)和 MemoryImageSource(內(nèi)存的圖像源)實現(xiàn)了 ImageProducer? 接口,是 ImageProducer?。


          ImagConsumer
          java.awt.image軟件包中,ImageFilter(圖像過濾器)和 PixelGrabber(像素抓取器)實現(xiàn)了 ImagConsumer 接口,是 ImagConsumer。


          ImageProducer?和 ImagConsumer 的詳細介紹請閱讀 使用 ImageProducer? / ImagConsumer 進行圖像過濾


          ImageObserver
          ImageObserver接口中,定義了一個常數(shù)集合和一個方法:

          public boolean imageUpdate(image img, int flags, int x, int y, int width, int height);

          ImageObserver的常數(shù)
          標志 含義
          ABORT 圖像加載被中斷
          ALLBITS 所有的位都已加載給圖像
          ERROR 在加載過程中發(fā)生錯誤
          FRAMEBITS 多幀圖像的一個幀被傳送,一般用于GIF
          HEIGHT 圖像的高度已經(jīng)可用
          PROPERTIES 圖像的屬性已經(jīng)可用
          SOMEBITS 圖像的縮放變體的多個位已經(jīng)可用
          WIDTH 圖像的寬度已經(jīng)可用

          參數(shù) flags 的作用是通知圖像觀察者圖像生產(chǎn)的進展情況。這些常數(shù)代表傳遞給 ImageObserver.imageUpdate() 的 flags 參數(shù)中的位。

          當(dāng) Component 作為 ImageObserver 時,一旦圖像有新的部分被加載,就會調(diào)用 Component.imageUpdate() 方法,imageUpdate() 再調(diào)用 repaint() 重新繪制圖像。repaint() 將先調(diào)用 update() 方法清除組件背景,再由 update() 方法調(diào)用 paint() 方法繪制圖像。我們可以通過重載 imageUpdate() 方法控制組件何時被更新,重載 update() 方法控制是否每次重繪都要清除背景圖像(每次重繪都清除背景圖像會造成畫面閃爍)。


          為了更好的理解,下面我們來看幾個樣例程序:

          例1,圖像位在需要之前不被生產(chǎn)
          import?java.net.URL;
          import?java.applet.Applet;
          import?java.awt.Graphics;
          import?java.awt.Image;

          public?class?ImageTestAppletSimple?extends?Applet{
          ????
          private?Image?im;
          ????
          ????
          public?void?init(){
          ????????URL?codebase?
          =?getCodeBase();
          ????????System.out.println(codebase);
          ????????
          ????????im?
          =?getImage(codebase,"flower.jpg");
          ????????
          ????????System.out.print(
          "Image?width?=?"?+?im.getWidth(this));
          ????????System.out.println(
          " hight?=?"?+?im.getHeight(this));
          ????}

          ????
          ????
          public?void?paint(Graphics?g){
          ????????g.drawImage(im,
          0,0,this);
          ????}

          }

          輸出結(jié)果:
          image width = -1 height = -1

          圖像的高度和寬度只有在圖像被完全加載后才是有效的,輸出結(jié)果說明 java.awt.image 相關(guān)的圖像位在需要之前不被生產(chǎn)。


          例2,圖像異步生產(chǎn)

          import?java.net.URL;
          import?java.applet.Applet;
          import?java.awt.Graphics;
          import?java.awt.Image;

          public?class?ImageTestAppletSimple2?extends?Applet{
          ????
          private?Image?im;
          ????
          ????
          public?void?init(){
          ????????im?
          =?getImage(getCodeBase(),"flower.jpg");
          ????}

          ????
          ????
          public?void?paint(Graphics?g){
          ????????System.out.println(
          "drawing?image...");
          ????????System.out.println(g.drawImage(im,
          0,0,this));
          ????}

          }

          輸出結(jié)果:
          drawing?image...
          false
          drawing?image...
          false
          drawing?image...
          false
          drawing?image...
          true

          輸出結(jié)果說明組件作為 ImageObserver ,監(jiān)視 ImageProducer 異步生產(chǎn)圖像,一旦有新的圖像位被生產(chǎn)時就重繪圖像,圖像完全加載后 drawImage() 方法返回 true。


          例3,重載 ImageObserver 的 imageUpdate() 方法,在圖像完全加載前不調(diào)用 repaint()

          import?java.applet.Applet;
          import?java.awt.Graphics;
          import?java.awt.Image;

          public?class?ImageTestAppletWithUpdate?extends?Applet{
          ????
          private?Image?im;
          ????
          ????
          public?void?init(){
          ????????im?
          =?getImage(getCodeBase(),"flower.jpg");
          ????????
          ????????System.out.print(
          "Image?width?=?"?+?im.getWidth(this));
          ????????System.out.println(
          "hight?=?"?+?im.getHeight(this));
          ????}

          ????
          ????
          public?void?paint(Graphics?g){
          ????????g.drawImage(im,
          0,0,this);
          ????}

          ????
          ????
          public?boolean?imageUpdate(Image?image,int?flags,int?x,int?y,int?w,int?h){
          ????????System.out.println(
          "imageUpdate():x="?+?x?+?",y="?+?y?+?",w="?+?w?+?",h="?+?h);
          ????????
          ????????
          if((flags?&?ALLBITS)?==?0)
          ????????????
          return?true;
          ????????
          else
          ????????
          {
          ????????????repaint();
          ????????????
          return?false;
          ????????}

          ????}

          }



          例4,重載? Component.update() 方法,被調(diào)用時不清除背景圖像,直接調(diào)用 paint() 方法繪制圖像,消除閃爍

          import?java.applet.Applet;
          import?java.awt.Graphics;
          import?java.awt.Image;

          public?class?ImageTestAppletWithSmoothDynamicUpdate?extends?Applet{
          ????
          private?Image?im;
          ????
          ????
          public?void?init(){
          ????????im?
          =?getImage(getCodeBase(),"hl.jpg");
          ????????
          ????????System.out.print(
          "Image?width?=?"?+?im.getWidth(this));
          ????????System.out.println(
          "hight?=?"?+?im.getHeight(this));
          ????}

          ????
          ????
          public?void?paint(Graphics?g){
          ????????g.drawImage(im,
          0,0,this);
          ????}

          ????
          ????
          public?boolean?imageUpdate(Image?image,int?flags,int?x,int?y,int?w,int?h){
          ????????System.out.println(
          "imageUpdate():x="?+?x?+?",y="?+?y?+?",w="?+?w?+?",h="?+?h);
          ????????
          ????????repaint();
          ????????
          ????????
          if((flags?&?ALLBITS)?==?0)
          ????????????
          return?true;
          ????????
          else
          ????????????
          return?false;
          ????}

          ????
          ????
          public?void?update(Graphics?g){
          ????????paint(g);
          ????}

          }
          posted on 2006-02-15 16:39 TrampEagle 閱讀(1204) 評論(0)  編輯  收藏 所屬分類: java
          主站蜘蛛池模板: 公安县| 左权县| 天峨县| 汝南县| 武宣县| 博白县| 巴里| 平南县| 吉林市| 湛江市| 贺州市| 高州市| 都江堰市| 阳朔县| 秀山| 平谷区| 平遥县| 扎赉特旗| 德令哈市| 闻喜县| 甘洛县| 崇左市| 徐州市| 白沙| 清涧县| 麻城市| 铅山县| 吉安县| 西乌珠穆沁旗| 肃宁县| 确山县| 宿迁市| 玛曲县| 湛江市| 灵武市| 永年县| 望城县| 桓仁| 晋江市| 大悟县| 揭西县|