使用 Java 2D API 制作艺术动画
2008-12-18 14:36
351 查看
Paul Reiners 展示了如何通过 Java 2D API 和细胞自动机(cellular
automata)以独特的艺术方式制作图像动画。在这个过程中,他演示了用 Java 代码实现图像操作器并介绍了循环空间(cyclic space
),循环空间是一种 2D 细胞自动机。您可以根据本文的思路创建自己的图像操作器,并使用 Java 技术创建艺术应用程序。
本文说明如何通过实现
细胞自动机(CA),即循环空间,来构造图像处理应用程序。CA 会 “操作” 图像(例如,一个 PEG
文件),使图像不断地按有趣的方式转换。我希望本文能开阔您的视野,使您能编写一个全新的图像处理应用程序类。
2D 细胞自动机
2D 细胞自动机由分布在 2D 网格(通常称为布局)中的细胞 组成。每个细胞都有一个状态,可以是 0 到
n 之间的任意整数。清单 1 显示了如何用 Java 代码声明一个细胞自动机布局:
清单
1. 定义
所有细胞每个时刻都同时更新状态。一个细胞的新状态取决于该细胞的当前状态和它相邻细胞的当前状态,状态的转换根据特定的规则进行。清单 2
更新了下一时刻的布局:
清单 2.
类(部分清单)
不同类型的 CA 更新单个细胞所用的规则不相同。规则的定义由子类完成。
循环空间
在循环空间中,每个细胞都有一个状态,它是 n 种状态中的一种。每个细胞的初始状态通常是随机定义的,也就是说,是 0 和 n -
1(包括 0 和 n - 1)之间的一个随机数字。细胞的邻居定义为 von Neumann 邻居:包括它的上下左右 4
个邻近细胞。
清单 3 通过给出每个细胞邻居和细胞本身的不同坐标来定义该细胞的 von Neumann 邻居:
清单 3. 定义
循环空间由以下规则定义:
如果一个细胞的状态是 k,它有一个邻居的状态是 k + 1,那么该状态在下一时刻将会有一个新的状态 k
+ 1。否则,该细胞的状态将保持不变。
这个规则是循环的,因此,如果一个细胞处于状态 n - 1,而且有一个状态为 0 的邻居,那么该细胞在下一时刻的状态将为
0。
这个简单规则会导致意想不到的复杂行为。清单 4 实现了在循环空间中更新细胞的规则:
清单 4. 定义
我曾说过,循环空间布局的初始状态是随机的。细胞会被 “更大的” 细胞 “吃掉”,最后会再次循环回到状态
[i]0。在这个过程中,区域自行组织并展开,成为波浪形。最后,会出现一个稳定的波浪图案。这些波浪呈对角线在布局中移动,看上去有点像纸风车。
创建图像操作器
接口允许您创建自己的图像操作器(也称为过滤器)。本文只讨论
将它命名为 Seurat(参见 下载 获取完整的示例代码)。
Seurat 应用程序
您可能知道图像像素与 CA 中的细胞存在映射关系。它们都以 2D 网格形式存在,每个都有状态,对于像素就是它的红绿蓝(RGB)值。我将在
清单 5 显示如何迭代
清单 5.
本文转自IBM Developerworks中国
请点击此处查看全文
automata)以独特的艺术方式制作图像动画。在这个过程中,他演示了用 Java 代码实现图像操作器并介绍了循环空间(cyclic space
),循环空间是一种 2D 细胞自动机。您可以根据本文的思路创建自己的图像操作器,并使用 Java 技术创建艺术应用程序。
本文说明如何通过实现
BufferedImageOp接口来编写自定义 Java 2D 图像处理类。它使用一个 2D
细胞自动机(CA),即循环空间,来构造图像处理应用程序。CA 会 “操作” 图像(例如,一个 PEG
文件),使图像不断地按有趣的方式转换。我希望本文能开阔您的视野,使您能编写一个全新的图像处理应用程序类。
2D 细胞自动机
2D 细胞自动机由分布在 2D 网格(通常称为布局)中的细胞 组成。每个细胞都有一个状态,可以是 0 到
n 之间的任意整数。清单 1 显示了如何用 Java 代码声明一个细胞自动机布局:
清单
1. 定义
TwoDCellularAutomaton.universe
protected int[][] universe; |
更新了下一时刻的布局:
清单 2.
TwoDCellularAutomaton
类(部分清单)
public void update() { int[][] newUniverse = new int[rowCount][colCount]; for (int row = 0; row < rowCount; row++) { for (int col = 0; col < colCount; col++) { newUniverse[row][col] = updateCell(row, col); } } for (int row = 0; row < rowCount; row++) { for (int col = 0; col < colCount; col++) { universe[row][col] = newUniverse[row][col]; } } } protected abstract int updateCell(int row, int col); |
循环空间
|
1(包括 0 和 n - 1)之间的一个随机数字。细胞的邻居定义为 von Neumann 邻居:包括它的上下左右 4
个邻近细胞。
清单 3 通过给出每个细胞邻居和细胞本身的不同坐标来定义该细胞的 von Neumann 邻居:
清单 3. 定义
TwoDCellularAutomaton.VON_NEUMANN_NEIGHBORHOOD
protected static final int[][] VON_NEUMANN_NEIGHBORHOOD = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } }; |
如果一个细胞的状态是 k,它有一个邻居的状态是 k + 1,那么该状态在下一时刻将会有一个新的状态 k
+ 1。否则,该细胞的状态将保持不变。
这个规则是循环的,因此,如果一个细胞处于状态 n - 1,而且有一个状态为 0 的邻居,那么该细胞在下一时刻的状态将为
0。
|
清单 4. 定义
CyclicSpace.updateCell(int, int)
protected int updateCell(int row, int col) { int[] neighborStates = getNeighborStates(row, col, neighborhood); int currentState = universe[row][col]; for (int i = 0; i < neighborStates.length; i++) { int neighborState = neighborStates; if (neighborState == (currentState + 1) % n) { return neighborState; } } return currentState; } |
[i]0。在这个过程中,区域自行组织并展开,成为波浪形。最后,会出现一个稳定的波浪图案。这些波浪呈对角线在布局中移动,看上去有点像纸风车。
|
java.awt.image.BufferedImageOp
接口允许您创建自己的图像操作器(也称为过滤器)。本文只讨论
BufferedImageOp的一个方法:
BufferedImage filter(BufferedImage src, BufferedImage dest) |
src和
dest是 2D 像素网格。实现此方法时,您可以按任意方式从
src构建
dest。普遍做法是在
src中迭代像素,并按照一定规则在
dest中创建相应的像素。这就是在图像处理应用程序中需要做的事情,我根据著名的法国画家 Georges-Pierre Seurat
将它命名为 Seurat(参见 下载 获取完整的示例代码)。
Seurat 应用程序
您可能知道图像像素与 CA 中的细胞存在映射关系。它们都以 2D 网格形式存在,每个都有状态,对于像素就是它的红绿蓝(RGB)值。我将在
filter(BufferedImage src, BufferedImage dest)实现中探讨这种映射关系。对于
src中的每个像素,我会根据一定规则将该像素的 RGB 值与 CA 中相应细胞的状态组合起来,创建
dest中相应像素的新 RGB 值。这个规则将定义一个过滤器。
清单 5 显示如何迭代
src中的所有像素并在
dest中构建像素。抽象方法
getNewRGB(Color)由单独的过滤器定义。它为输入颜色计算并返回经过过滤的 RGB 值。
清单 5.
CellularAutomataFilter类(部分清单)
本文转自IBM Developerworks中国
请点击此处查看全文
相关文章推荐
- 使用 Java 2D API 制作艺术动画
- Java制作说明书并使用说明文档,Math,API
- 使用uGUI制作游戏内2D动画
- 使用Java2D改善API的绘制效果
- 使用 2DToolkit 插件 制作2D精灵动画
- 使用Java2D改善API的绘制效果
- 【Unity 3D】使用 2DToolkit 插件 制作2D精灵动画
- tookit2D使用6——动画制作(animation)
- 【Unity 3D 游戏引擎】使用 2DToolkit 插件 制作2D精灵动画
- 使用Dockerfile制作基于Centos7支持ssh的java环境镜像
- HBase java API 使用实例(二)——查询、分页
- Ceph RGW服务 使用s3 java sdk 分片文件上传API 报‘SignatureDoesNotMatch’ 异常的定位及规避方案
- java使用redis部分API示例
- java动画编程:使用双缓冲,消除闪烁
- 在EasyJWeb中使用Java Excel API 处理电子表格
- 使用HTML语言和CSS开发商业站点_利用CSS3制作网页动画
- 使用Java语言进行2D游戏编程基础 Fundamental 2D Game Programming with Java 全书笔记(未完结)
- 六:ZooKeeper的java客户端api的使用
- HBase总结(十一)hbase Java API 介绍及使用示例
- JAVA面试 不使用API情况下,把数字字符串转换成int类型