DOC-02-10 使用Image Ops API

本章将为你介绍Image Ops,它是一套允许你在JavaFX应用程序中读写原始像素的API。

你将会学习如何从图片中读取像素、如何向图片中写入像素以及如何创建快照。

Image Ops API概览

Image Ops API包括下列位于javafx.scene.image包中的类/接口:

● Image:表示一张图片。这个类提供了一个PixelReader来从一张图片中直接读取像素。

● WritableImage:Image类的一个子类。这个类提供了一个PixelWriter来直接向一张图片中写入像素。一个WritableImage在初始创建时是空(透明)的,直到你向其中写入了像素。

● PixelReader:这个接口中定义了从一张图片或其它带有像素的表面获取像素数据的方法。

● PixelWriter:这个接口中定义了向一个WritableImage或其它含有可写入(writable)像素的表面中写入像素数据的方法。

● PixelFormat:定义了给定格式的像素的数据布局。

● WritablePixelFormat:PixelFormat的一个子类,表示了一种可以存储所有颜色的像素格式。它可以用作从一张任意格式图片中读取像素数据并写入的一种目标格式。

下面的章节将通过可编译运行的示例来展示该API。

从图片中读取像素

你可能已经掌握了javafx.scene.image.Image类,它在JavaFX应用程序中(与ImageView搭配使用)用于显示图片。下面的样例展示了如何展示一张从oracle.com得到的JavaFX Logo图片并将其添加到JavaFX场景图(Scene Graph)中。

例10-1 加载并显示图片

运行此程序将会产生如图10-1所示的图片。

图10-1 展示一幅图片

2_10_1 image-read-test

现在让我们修改此代码来直接从像素中读取Color信息。你可以通过调用getPixelReader()方法来执行此动作,然后使用返回的PixelReader对象的getColor(x,y)方法来获取在指定坐标上的像素的颜色。

例10-2 从像素中读取Color信息

这个版本使用了嵌套的for循环(调用了getColor方法)来从图片中的每个像素获取颜色信息。它每次读取一个像素,从左上角(0,0)开始从左到右地处理图片。Y坐标只有在一整行数据被读取后才会增加。然后每个像素的信息(颜色值、不透明度和饱和度等)被打印到了标准输出,以此检验读取操作是在正常工作。

你可能会想尝试修改每个像素的颜色并将其写到屏幕上。但是要注意Image对象是只读的,要写入新的数据,你需要一个WritableImage对象来替代之。

向图片写入像素

现在来修改此Demo来增大每个像素的亮度,然后将修改后的结果写到一个WritableImage对象中。

例10-3 写入一个WritableImage

此版本创建了一个WritableImage并被初始化成了与JavaFX Logo相同的宽度与高度。在获取一个PixelWriter(用于写入像素数据到新图像中)之后,代码中调用了brighter()方法(用于加亮当前像素的颜色),然后通过调用pixelWriter.setColor(readX,readY,Color)将数据写到了新的图像中。

图10-2展示了此处理过程的结果。

图10-2 一个更明亮的Logo,存储在一个WritableImage对象中

2_10_2 image-write-test

使用字节数组和PixelFormat来写入图像

到目前为止该Demo成功地获取并修改了像素颜色,但是与API能够做的事情对比来看,当前的代码都还是相当地简单(并且不一定是最佳)。例10-4创建了一个新的Demo,它每次写入一组像素来绘制一个矩形,并使用PixelFormat来指定如何存储像素数据。这个版本仍然在一个Canvas上展示图像数据,而没有使用ImageView。(参考第9章”使用Canvas API”来了解关于Canvas类的更多信息。)

例10-4 到Canvas上绘制矩形

图10-3写入像素到Canvas

2_10_3 imagetest

这个Demo没有从已有的图片中读取数据,它完全从零开始创建了一个新的WritableImage对象。它绘制了几行带有多种颜色的10*10的矩形,对应的颜色数据被存储在一个像素数组中,表示每个像素的RGB值。

特别有意思的是两个私有方法createImageData和drawImageData。createImageData方法设置了在每个10*10的矩形中的颜色的RGB值:

例10-5 设置像素的RGB

这个方法为矩形中的每个像素设置了R和G值(B值永远是0)。这些值被存储在名为imageData字节数组中,它保存了300个独立的字节。(在每个10*10的矩形中有100个像素,并且每个像素带有R、G和B值,总共有300字节)。

在数据准备好后,drawImageData方法将每个矩形的像素点渲染到了屏幕上:

10-6 渲染像素点

这里从Canvas中获得了PixelWriter,并且初始化了一个新的PixelFormat,指定了表示RGB值的字节数组。通过将数据传递给PixelWriter的setPixels方法每次使用像素来绘制一个完整的矩形。

创建一个快照

javafx.scene.Scene类还提供了一个snapshot方法,它返回一个WritableImage,其中包含了当前展示在你的应用程序场景中内容。当与Java中的ImageIO类配合使用时,你可以将快照存储到文件系统中。

10-7 创建并存储一个快照

需要注意start方法中下面的修改,如例10-8所示:

例10-8 修改后的start方法

如你所见,调用scene.snapshot(null)创建了一个新的快照并将其分配给了新构建的WritableImage。然后(在ImageIO和SwingFXUtils的帮助下)这个图片被写入文件系统并保存为了一个.png图片。

打赏一下
支付宝
微信
除非注明,博客文章均为原创,转载请标明文章地址
本文地址: http://www.javafxchina.net/blog/2015/08/graphics_image_ops_api/
百度已收录