`
djsl6071
  • 浏览: 596069 次
  • 性别: 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框架图片及代码示例

    对于图像显示,AWT提供了一个名为`java.awt.Image`的类,它可以加载和显示图像。通过`ImageIcon`类,我们可以将图像与组件关联起来,例如设置为按钮的图标或在标签中显示。以下是一个简单的代码示例,展示如何加载和...

    简单Java图像显示程序

    本项目名为“简单Java图像显示程序”,显然它的主要目的是展示如何在Java环境中加载和显示图像。以下是对这个程序可能涉及的知识点的详细解释: 1. **Java AWT 和 Swing 库**: - AWT(Abstract Window Toolkit)...

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

    总结一下,搭建Eclipse下的Swing/AWT/SWT开发环境主要包括: 1. 对于AWT,直接使用Eclipse创建Java项目即可。 2. 对于Swing,可选择安装JBuilder或WindowBuilder Pro插件进行可视化设计。 3. 对于SWT,需要安装SWT ...

    AWT与Swing使用区别

    - **AWT**:AWT中的事件模型使用了适配器和监听器,如ActionListener和WindowListener。 - **Swing**:Swing在AWT的基础上扩展了事件模型,增加了更多的事件类和监听器,如ActionEvent、MouseListener和...

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

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

    4.2在窗体中显示图像

    在Java编程环境中,结合OpenCV库进行图像处理时,我们经常需要在窗口中显示图像以进行观察和调试。本节将详细讲解如何在Java窗体中利用OpenCV库实现图像的显示。 首先,OpenCV是一个强大的计算机视觉库,它提供了...

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

    【Java AWT和JAI技术在生物数据库图像显示上的应用】 Java AWT(Abstract Window Toolkit)和JAI(Java Advanced Imaging)是Java平台中的两个重要技术,主要用于图形用户界面(GUI)的创建和图像处理。在生物信息...

    Java图像_编程.pdf

    本章主要探讨的是Java AWT中的Image类和java.awt.image包,它们为图像的显示和操作提供了支持。Image类是AWT的基础组件,而java.awt.image包则包含了一系列用于处理图像的类和接口。 首先,我们关注一下图像的文件...

    贪吃蛇(Java)、AWT/Swing

    贪吃蛇是一款经典的电子...通过阅读和理解代码,可以深入理解AWT/Swing组件的使用,事件处理机制,以及基本的游戏逻辑实现。同时,也可以在此基础上进行扩展,比如增加难度等级、实现多玩家模式,或者优化图形效果。

    AWT/Swing 可视化eclipse插件

    "AWT/Swing 可视化eclipse插件"是一个专为Eclipse定制的工具,它集成了AWT和Swing组件的可视化编辑功能。通过这个插件,开发者可以直观地看到UI组件的布局,调整组件的位置、大小、属性,而无需手动编写复杂的布局...

    java 图像处理

    Java AWT和Swing是Java的基础UI组件,它们提供了基本的图像显示和处理功能。例如,`java.awt.Image`类代表了一个图像对象,可以加载和显示图像;`java.awt.Graphics`类则提供了一组方法用于在图像上进行绘制操作,如...

    java 以椭圆形显示图像

    在Java编程中,显示图像通常涉及到使用`java.awt`和`javax.swing`这两个包中的类。当需要以椭圆形轮廓来显示图像时,我们需要利用Java的图形绘制功能。本篇文章将详细讲解如何实现这一功能。 首先,我们创建一个`...

    在Java中如何利用Applet来加载图像

    为了提高图像显示的性能和流畅性,可以使用双缓冲技术。先在内存中绘制图像,然后一次性将整个图像绘制到屏幕,避免闪烁。 8. **图像格式支持**: Java Applet通常处理GIF和JPEG格式的图像,因为它们是广泛支持的...

    java awt/swing 计算器

    Java AWT 和 Swing 是两种用于构建图形用户界面(GUI)的Java库,它们在开发桌面应用程序时非常常用,包括计算器这样的简单应用。本项目利用Java的AWT和Swing库来创建一个功能齐全的计算器,它能进行基本的四则混合...

    小型数字图像读取与显示

    例如,`LoadImage`函数可以加载图像资源,而`CreateWindow`和`UpdateWindow`函数则可以创建窗口并在其中显示图像。 3. **图像处理**:图像处理包括滤波、色彩转换、缩放、旋转等一系列操作。在Java和C++中,可以...

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

    在本实验报告中,主题是“Java实验报告之图形用户界面程序设计与AWT/Swing组件”,主要目标是让学生熟悉Java GUI设计原理、程序结构,掌握AWT和Swing组件的功能,以及学会应用这些组件来设计应用程序,特别是实现一...

    Java图片渐进显示

    Java提供了`java.awt.image`和`javax.imageio`两个包来处理图像。其中,`BufferedImage`类是核心,它支持多种图像类型,如ARGB、RGB等,并提供了读取、写入和操作图像的方法。 实现图片渐进显示的关键在于利用`...

    JAVA AWT图形用户界面设计

    AWT主要用于Java应用程序和applet中,它包含了丰富的功能,如用户界面组件、事件处理机制、图形和图像工具,以及布局管理器。 在AWT中,`java.awt`包是核心,提供了构建GUI所需的基础类和接口。主要包含三个关键...

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

    Java AWT(Abstract Window Toolkit)和Swing是Java平台上的两个图形用户界面(GUI...通过这个项目,开发者可以深入理解Java GUI编程的基本原理和实践,同时也能锻炼到事件处理、数学运算以及异常处理等多方面的技能。

Global site tag (gtag.js) - Google Analytics