`
djsl6071
  • 浏览: 578768 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

AWT使用ImageProducer/ImagConsumer模式加载和显示图像的原理[zz]

阅读更多

[Image] AWT使用ImageProducer/ImagConsumer模式加载和显示图像的原理

以前写过2篇关于AWT中图像加载显示方法的文章,最近又多了一些对于 ImageProducer / ImagConsumer 模式的一些理解,尝试着用文字总结了一下,接着还想再写一篇介绍 AWT 中图像过滤的原理和方法。你可能认为现在学习 AWT 中的成像方法对于开发中已经没有太大的意义,因为已经有了 Java 2D 和 JAI ,但是我在实际工作中感到还是无法完全离开 AWT,特别是在一些基本的应用上。而且我觉得理解 AWT 的 Producer / Consumer (push) model 对于理解 Java 2D 的 Immediate mode model 和 JAI 的 Pipeline (pull) model 的都是有好处的。

因为水平有限,这方面学习资料相对也不丰富,我也不知道我的理解或想法是否完全正确或者表述清楚,感兴趣的朋友可以当作学习参考,希望能够和我联系进行进一步的讨论。



AWT 使用 ImageProducer / ImagConsumer 模式,支持加载和显示 GIF 图像文件格式和 JPEG 图像文件格式。因为图像的加载和显示是异步方式进行的,所以有大量加载和显示的技术。

在 AWT 中,提供了一个 java.awt.Image 类。java.awt.Image 类代表一个图像对象被作为参数传递给其他用来显示和处理图像的其他 AWT 对象使用。例如,通过调用 Graphics.drawImage(java.awt.Image, int, int, ImageObserver) 方法,可以在组件中画出图像。

java.awt.Image 是一个定义方法的抽象类,它定义的方法提供的对图像信息的访问。而创建和处理图像的基本结构则在 java.awt.image 包中。注意,这里不要和 java.awt.Image 发生混淆。

AWT  加载和显示图像使用的是 ImageProducer / ImagConsumer 模式,我们必须了解3个术语,ImageProducer(图像生产者),ImageConsumer(图像消费者)和ImageObserver(图像观察者)。

ImageProducer 负责生产图像的位,ImagConsumer 接受图像的位,ImageObserver 监视 ImageProducer 的图像生产过程。ImageProducer 生产传递给 ImagConsumer 与图像相关的位。因为图像生产过程是异步进行的,并不是一次性生产所有图像位,所以当 ImageProducer 加载图像时,ImageObserver 用来监视它的进展情况。因为 java.awt.Component 实现了 ImageObserver 接口,所以 AWT 中的每个组件都可以是ImageObserver,当一个给定的 ImageProducer 进行异步操作时,这个 ImageObserver 可以选择是否被更新。java.awt.image 包为 ImageProducer,ImagConsumer 和 ImageObserver 都定义了接口。

ImageProducer
和图像相关的位并不存储在 java.awt.Image 中,每个图像都维护一个和一个 ImageProducer 的关联。这个 ImageProducer 的责任是生产图像的位并将它们传送给 ImagConsumer,用于过滤该图像。

java.awt.image软件包中,FilteredImageSource(被过滤的图像源)和 MemoryImageSource(内存的图像源)实现了 ImageProducer  接口,是 ImageProducer 。


ImagConsumer
java.awt.image软件包中,ImageFilter(图像过滤器)和 PixelGrabber(像素抓取器)实现了 ImagConsumer 接口,是 ImagConsumer。


ImageProducer 和 ImagConsumer 的详细介绍请阅读 使用 ImageProducer  / ImagConsumer 进行图像过滤


ImageObserver
ImageObserver接口中,定义了一个常数集合和一个方法:

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

ImageObserver的常数
标志 含义
ABORT 图像加载被中断
ALLBITS 所有的位都已加载给图像
ERROR 在加载过程中发生错误
FRAMEBITS 多帧图像的一个帧被传送,一般用于GIF
HEIGHT 图像的高度已经可用
PROPERTIES 图像的属性已经可用
SOMEBITS 图像的缩放变体的多个位已经可用
WIDTH 图像的宽度已经可用

参数 flags 的作用是通知图像观察者图像生产的进展情况。这些常数代表传递给 ImageObserver.imageUpdate() 的 flags 参数中的位。

当 Component 作为 ImageObserver 时,一旦图像有新的部分被加载,就会调用 Component.imageUpdate() 方法,imageUpdate() 再调用 repaint() 重新绘制图像。repaint() 将先调用 update() 方法清除组件背景,再由 update() 方法调用 paint() 方法绘制图像。我们可以通过重载 imageUpdate() 方法控制组件何时被更新,重载 update() 方法控制是否每次重绘都要清除背景图像(每次重绘都清除背景图像会造成画面闪烁)。


为了更好的理解,下面我们来看几个样例程序:

例1,图像位在需要之前不被生产

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

}

输出结果:
image width = -1 height = -1

图像的高度和宽度只有在图像被完全加载后才是有效的,输出结果说明 java.awt.image 相关的图像位在需要之前不被生产。


例2,图像异步生产

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

}

输出结果:
drawing image...
false
drawing image...
false
drawing image...
false
drawing image...
true

输出结果说明组件作为 ImageObserver ,监视 ImageProducer 异步生产图像,一旦有新的图像位被生产时就重绘图像,图像完全加载后 drawImage() 方法返回 true。


例3,重载 ImageObserver 的 imageUpdate() 方法,在图像完全加载前不调用 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() 方法,被调用时不清除背景图像,直接调用 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 @ 2005-10-11 10:35 leon 阅读(1051) | 评论 (3)编辑 收藏

[Download] Java 2D API 程序员指南

Programmer's Guide to the JavaTM 2D API 中文版

http://www.blogjava.net/Files/leon/Java2DAPI程序员指南.rar

posted @ 2005-09-13 17:09 leon 阅读(1175) | 评论 (5)编辑 收藏

[Image] 使用Jimi输出PICT格式图像的一处BUG及解决办法

使用sun提供的图像管理工具包 Jimi1_0 版本,保存PICT文件格式时输出的图像宽、高和内存中的图像源一致,可是显示出来却是纯白的。这是 Jimi1_0 版本对写Pict格式的一处 BUG,下载了新的补订类PICTWriter.java 重新编译成PICTWriter.class加入 JimiProClasses.zip 中覆盖原有的 PICTWriter.class,遂写 PICT 格式成功。


参考:http://amug.org/~glguerin/other/index.html#PICTWriter
提醒:编译 PICTWriter.java 时需要兼容JDK以前的版本。

posted @ 2005-07-21 12:28 leon 阅读(724) | 评论 (1)编辑 收藏

AWT中图像的异步加载和等待图像的完全加载

图像的异步加载

图像的加载和显示是异步进行的,图像的生产者(ImageProducer)传递给图像的消费者(ImageConsumer)一个与图像相关的位,因为图像的生产过程是一个异步行为,所以 AWT 也提供一个图像观察(ImageObserver),用来监视图像生产者的图像生产过程。

因为 java.awt.Component 实现 ImageObserver 接口,所以 AWT 中每个构件都是ImageObserver ,当一个给定的 ImageProducer 采取异步操作时,这个 ImageObserver 可以选择是否被更新。

现在看一个例子:

<!---->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(), "lena.jpg");
  }

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

当这个 Applet 第一次被调用时,将打印出下面的结果:
drawing image...
false
drawing image...
false
drawing image...
false
drawing image...
true

执行结果说明 drawImage() 在第一次被调用时,没有图像被加载,drawImage() 只是向和图像相关的 ImageProducer 注册 ImageObserver,图像被完全加载前 drawImage() 方法返回 false 直到图像被完全加载返回 true。

当 drawImage() 返回之后,只要有图像的新的部分被加载,ImageObserver 中的 imageUpdate() 方法就会被调用。当 ImageObserver 是 AWT 构件时,Component.imageUpdate() 调用 repaint() 方法清除构件背景并调用 paint() 方法重绘刚刚得到的图像位。重复循环,ImageProducer 加载图像的下一块,调用 ImageObserver 的 imageUpdate()。当图像被完全加载时,ImageProducer 停止调用 ImageObserver 的 imageUpdate(),循环中断。

load -> imageUpdate() -> repaint() -> update() -> paint()


等待图像的完全加载

上面的例子介绍了图像的异步加载,现在介绍2个方法使图像完全加载前不显示。

·重载 ImageObserver 中的 imageUpdate() 方法,使其在图像完全加载前不调用 repaint()。


 

使用 java.awt.MediaTracker 类跟踪图像的加载,不必重载 imageUpdate() 方法。


 

我们可以把使用 java.awt.MediaTracker 类将图像完全加载的方法包装成一个实用方法

 

<!---->/**   *//**
   * 使用 java.awt.MediaTracker 将图像完全加载。
   * 
@param  component Component
   * 
@param  img Image
   
*/
  
public   static   void  waitForImage(Component component, Image img) {
    MediaTracker tracker 
=   new  MediaTracker(component);
    
try  {
      tracker.addImage(img, 
0 );
      tracker.waitForID(
分享到:
评论

相关推荐

    使用文本方式(控制台输入输出)和使用图形方式(可以使用AWT或者SWING)来实现猜数游戏。

    使用文本方式(控制台输入输出)和使用图形方式(可以使用AWT或者SWING)来实现猜数游戏。 进入程序后,显示文本内容,提示用户输入1-100之间的数字,然后程序对其进行判断,用户根据系统提供的提示信息继续猜,...

    在eclipse下搭建swing/awt/swt开发环境的方法和插件

    搭建方法文档和插件---在eclipse下搭建swing/awt/swt开发环境的方法和插件

    AWT与Swing使用区别

    对照了解AWT与Swing的区别,能更好地理解GUI

    java 显示awt

    java awt 可视化ui编程 Java awt ui界面设计教程

    贪吃蛇(Java)、AWT/Swing

    Awt/Swing简易版贪吃蛇源码,可正常运行,非常基础的一个Java小游戏。

    AWT与AWT事件处理

    什么是AWT 用AWT构建GUI 事件处理 AWT组件类库

    java实验报告之图形用户界面程序设计与 AWT/Swing组件

    1.熟悉Java图形用户界面的设计原理和程序结构; 2.能设计符合问题要求的图形用户界面程序; 3.熟悉Java AWT、swing组件的功能; 4.掌握常用组件的事件接口; 5.会应用AWT、swing组件进行应用程序设计。 二、实验内容...

    JAVA AWT图形用户界面设计

    绝对好资料!!!下载就不后悔!!! 抽象窗口工具包AWT (Abstract Window Toolkit) 是 API为Java 程序提供的建立图形用户界面GUI (Graphics User Interface)工具集,AWT可...图形和图像工具,包括形状、颜色和字体类

    Java AWT和JAI技术在生物数据库图像显示上的应用.pdf

    利用java AWT和JAI技术绘制生物图像的方法可以使在实验室中得到的生物实验数据自动转化为需要的图谱,并且图像的精确度高。绘制成的图像既可以保存在本地硬盘中,也可以在浏览器中以网页的形式展示出来供研究人员分析...

    java awt/swing 计算器

    用java 的awt和swing 编辑的计算器,编辑的思路比较好,代码精简。实现计算器四则混合运算。

    awt包java Android

    awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android awt包java Android ...

    appengine-awt:自动从code.google.compappengine-awt导出

    appengine-awt是在Google AppEngine环境中使用的java.awt和javax.imageio包的纯Java实现。 该代码主要基于Apache Harmony和Apache Sanselan项目。 当前,该库提供了足够的功能,可以使用蜡染将svg文件转码为图像。...

    java awt/swing做的简单的弹球游戏

    java awt/swing做的很简单的弹球游戏,只实现了球在空间里传,算是java awt/swing的一个基础应用吧

    使用Java AWT和Swing实现的简单计算器

    使用Java AWT和Swing实现的计算器,其中的输入输出框为TextField,其余按钮均为JButton,可以实现加、减、乘、除、取反、求倒运算。

    swing基础学习和awt的区别

    swing基础学习和awt的区别,swing基础学习和awt的区别swing基础学习和awt的区别swing基础学习和awt的区别

    AWT/Swing 可视化eclipse插件

    Swing可视化插件 jigloo_SWT_Swing可视化设计工具

    Java 2 图形设计

    在AWT中,除了支持多框架图像(如动画GIF)外,还支持加载和显示GIF图像文件格式和JPEG图像文件格式。由于图像的加载和显示是采用异步方式进行的,所以有大量的用于图像加载和显示的技术。在本章中,将全面对这些方法...

    基于可视化界面(awt/swing)的横板过关类小游戏

    因为时间紧促,目前行为模式没有什么区别,但设计了简单的反应,例如在发现玩家之后会主动冲向玩家(设计了关于敌人是否发现玩家的hasFoundPlayer()方法放在npc类之中,并对其进行相关使用来实现),而不是机械性的...

    AWT基础知识

    实际开发中使用AWT的情况非常少,但是我们仍然有必要学习AWT。主要原因如下: 1. Swing是在AWT基础上构建的,事件模型和一些支持类(形状、颜色、字体)都一样。掌握AWT有利于后面学习SWING. Eclipse不是swing开发的,...

    java计算器,swing和awt

    java计算器,swing和awt,可以实现+-*/和根号

Global site tag (gtag.js) - Google Analytics