合成图像
您不必从文件中读取所有的图像 — 您可以创建自己的图像。要创建自己的图像,最灵活的方法是用一个BufferedImage对象,它是Image类的一个子类,它把图像数据存储在一个可以被访问的缓冲区中。它还支持各种存储像素数据的方法:使用或不使用 alpha 通道、不同种类的颜色模型以及颜色组件的各种精确度。ColorModel类提供一种灵活的方法定义各种颜色模型,以和 BufferedImage对象一起使用。为了理解颜色模型工作的基本知识,我们将只使用一个缺省的颜色模型,其颜色组件由 RGB值和一个缓冲类型(存储 8 位的RGB 颜色值加上一个alpha 通道)组成。这一缓冲类型由 BufferedImage类中的常量 TYPE_INT_ARGB 指定,它意味着每个像素要用一个int值。每个像素的值是以 8 位字节形式存储一个alpha 组件加上 RGB 颜色组件。我们可以用给定的宽度和高度创建一个这种类型的BufferedImage对象,代码语句如下:
int width = 200;
int height = 300;
BufferedImage image = new BufferedImage(width,
height,BufferedImage.TYPE_INT_ARGB);
这段代码创建了一个BufferedImage对象,它代表一个200像素宽、300像素高的图像。为了应用这个图像,我们需要有图形上下文,而 BufferedImage对象的createGraphics()方法就返回一个与该图像相关的Graphics2D对象:
int width = 200;
Graphics2D g2D = image.createGraphics();
使用 g2D对象的操作会修改 BufferedImage对象 image 的像素。利用这个对象,您现在完全有能力应用 BufferedImage对象。您可以绘制形状、图像、GeneralPath对象或任何别的东西,还可以为图形上下文设置alpha 组合对象。您同时还拥有 Graphics2D对象提供的全部仿射变形能力。
如果要从 BufferedImage对象获取单个像素,可以通过调用它的getRGB()方法,并提供该像素的x,y 坐标作为int类型的参数。这个像素会按 TYPE_INT_ARGB 格式以 int类型返回,它由四个8 位的值(代表 alpha值和 RGB 颜色组件)组成一个32 位字。同时 getRGB() 还有一个重载的版本,它从一部分图像数据中返回一个像素数组。您也可以通过调用 setRGB()方法来设置单个像素。前两个参数是该像素的坐标值,第三个参数是待设定的值,类型为int。这个方法也有一个版本可以设置像素数组的值。
至此我们已经完成了像素操作的学习。下面我们要建立一个applet,它在Wrox 徽标背景上使 BufferedImage对象具有动画效果。我们的示例还将演示怎样能让图像局部透明。applet 的基本内容如下所示:
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;
public class ImageDrawDemo extends JApplet
{
// The init() method to initialize everything...
// The start() method to start the animation...
// The stop() method to stop the animation...
// The ImagePanel class defining the panel displaying the animation...
// Data members for the applet...
}
创建一个图像
一个子图形是一个小的图形图像,可以将其绘制在静态图像以创建动画。要创建动画效果,您只要随着时间推移,在不同的位置和方向上绘制子图形。当然,利用坐标系的变形可以使之简化许多。游戏经常使用子图形 — 由于您只需要在一个静态背景上绘制子图形,所以可以使动画所占用的处理器的时间大大减少。我们对使用 BufferedImage对象的兴趣意味着我们将不再花费精力去研究减少处理器时间的最佳技术,而是把注意力放在理解怎样才能在一个程序内部创建和使用图像上。
我们的BufferedImage对象看上去如图 1 中的图像:
图 1. BufferedImage 子图形
这个图像是一个以 spriteSize 为边长的正方形。图像其它部分的尺寸值都与这个边长相关。实际上这里只有两个几何实体,一条线和一个圆,都在不同位置和方向重复出现。如果我们创建一个Line2D.Double对象代表线,创建一个Ellipse2D.Double对象代表圆,那么我们就可以通过移动用户坐标系和画这两个对象中的一个或其它的对象而画出整个图像。