Java教程是为JDK 8编写的。本页面中描述的示例和实践不利用后续版本引入的改进,可能使用不再可用的技术。
请参阅Java语言更改了解Java SE 9及其后续版本中更新的语言特性的摘要。
请参阅JDK发行说明了解所有JDK版本的新功能、增强功能和已删除或弃用选项的信息。
正如你已经学到的那样,Graphics.drawImage方法会在指定位置绘制一张图片:
boolean Graphics.drawImage(Image img,
int x, int y,
ImageObserver observer);
x,y位置指定了图片左上角的位置。观察者observer参数用于通知应用程序异步加载的图片的更新。观察者observer参数通常不直接使用,并且对于BufferedImage类不需要,因此通常为null。
上述方法只处理整个图片被绘制的情况,将图片像素映射到用户空间坐标1:1。有时候应用程序需要绘制图片的一部分(子图像),或者按比例缩放图片以覆盖绘制表面的特定区域,或者在绘制之前对图片进行变换或过滤。
drawImage()方法的重载执行这些操作。例如,下面的drawImage()方法重载可以绘制指定图像的尽可能多的可用区域,并按比例缩放以适应目标绘制表面的指定区域:
boolean Graphics.drawImage(Image img,
int dstx1, int dsty1, int dstx2, int dsty2,
int srcx1, int srcy1, int srcx2, int srcy2,
ImageObserver observer);
src参数表示要复制和绘制的图像区域。dst参数表示要用源区域覆盖的目标区域。dstx1, dsty1坐标定义了绘制图片的位置。目标区域的宽度和高度由以下表达式计算:(dstx2-dstx1), (dsty2-dsty1)。如果源区域和目标区域的尺寸不同,Java 2D API将根据需要进行缩放。
下面的代码示例将一张图片分成四个象限,并随机将源图片的每个象限绘制到目标的不同象限。
这个applet的完整代码在JumbledImageApplet.java中。
这个例子使用以下代码绘制了混乱的duke_skateboard.jpg图像。它迭代源图像的四个子图像,依次将每个子图像绘制到随机选择的目标象限中。
/* 将图像'bi'分成四个矩形区域,并将每个区域绘制到图像的不同部分,从而使图像混乱起来。
* 'cells'是一个已经填充了将一个子区域绘制到另一个子区域的值的数组。
*/
int cellWidth = bi.getWidth(null)/2;
int cellHeight = bi.getHeight(null)/2;
for (int x=0; x<2; x++) {
int sx = x*cellWidth;
for (int y=0; y<2; y++) {
int sy = y*cellHeight;
int cell = cells[x*2+y];
int dx = (cell / 2) * cellWidth;
int dy = (cell % 2) * cellHeight;
g.drawImage(bi,
dx, dy,
x+cellWidth, dy+cellHeight,
sx, sy,
sx+cellWidth, sy+cellHeight,
null);
}
}
除了复制和缩放图像外,Java 2D API还可以对图像进行过滤。 过滤是通过对源图像的像素应用算法来绘制或生成新图像。可以使用以下方法来应用图像过滤器:
void Graphics2D.drawImage(BufferedImage img,
BufferedImageOp op,
int x, int y)
BufferedImageOp参数实现了过滤器。下面的小程序表示在文本上方绘制了一个图像。拖动滑块可以通过图像显示更多或更少的文本,并使图像更或更少透明。
以下代码显示了如何通过使用具有alpha通道的BufferedImage对象并使用RescaleOp对象来重新调整该alpha通道来完成过滤操作。alpha通道确定每个像素的半透明度,并指定了此图像覆盖的程度。
/* 创建一个带有ARGB的BufferedImage */
BufferedImage img = ImageIO.read(imageSrc);
int w = img.getWidth(null);
int h = img.getHeight(null);
BufferedImage bi = new
BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.getGraphics();
g.drawImage(img, 0, 0, null);
/*
* 创建一个使图像50%不透明的重新调整滤镜操作。
*/
float[] scales = { 1f, 1f, 1f, 0.5f };
float[] offsets = new float[4];
RescaleOp rop = new RescaleOp(scales, offsets, null);
/* 绘制图像,应用滤镜 */
g2d.drawImage(bi, rop, 0, 0);
完整的示例在 SeeThroughImageApplet.java 中,包括使用滑块调整透明度从初始的50%开始的代码。该示例还需要 duke_skateboard.jpg 图像。
RescaleOp 对象只是可以创建的许多滤镜之一。Java 2D API 中内置了几个滤镜,包括以下几种:
ConvolveOp。每个输出像素是从源图像周围像素计算得出的。它可以用于模糊或锐化图像。AffineTransformOp。此滤镜通过在像素位置上应用变换将源中的像素映射到目标中的不同位置。LookupOp。此滤镜使用应用提供的查找表来重新映射像素颜色。RescaleOp。此滤镜通过某个因子乘以颜色。可用于使图像变亮或变暗,增加或减少其不透明度等。下面的示例使用了上述每个滤镜以及缩放:
此 applet 的完整代码在 ImageDrawingApplet.java 中,该 applet 需要 bld.jpg 图像。
使用下拉菜单选择图像缩放或滤镜操作。