天天看点

《交互式程序设计 第2版》一3.7 将外部数据载入Processing

本节书摘来华章计算机《交互式程序设计 第2版》一书中的第3章 ,第3.7节,joshua noble 著 毛顺兵 张婷婷 陈宇 沈鑫 任灿江 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。

目前已经介绍了一些processing绘图基础和基本的用户交互捕获方式,你还要学习如何在processing中载入数据、图像和视频。前面已经提及processing项目的默认设置,知道了可以在和.pde同名的文件夹下建立data文件夹来存放所需的数据。processing应用程序希望把所有需要的数据都放入data文件夹中。如果你想载入一个名叫sample.jpg的文件,你应该把该文件放到与正在处理的.pde文件同名的文件夹下的data文件夹中。

首先,你要学会如何载入图像。载入和显示图像的最基本的手段是一个类和两个方法:pimage类、loadimage()方法和image()方法。

pimage类

processing依靠一个名为pimage的类来对图像进行显示和缩放。当你创建了一个pimage对象后,你就可以将图像装入到这个对象中,然后可将图像显示出来。想声明一个pimage对象,可以在程序的任何地方声明,但最好在程序代码的顶端,如下所示:

pimage img;

在声明了pimage对象之后,可以用loadimage()方法将图像装入到该对象中。

loadimage()方法

该方法将图像文件名作为参数,将此图像装入到pimage对象中。图像文件名既可以是文件系统中的(具体到processing软件,是你的项目目录的data目录中的文件名),也可以是用url表示的文件名。这意味着你可以装入一个来自internet的图像文件,象下面这样:

你也可以装入你的项目目录的data文件夹中的图像,像下面这样:

loadimage()方法可以装入jpeg、png、gif和tga格式的图像。其他格式的图像,如tif、bmp或raw,是无法用processing显示的,除非对processing的一些方法进行认真修改。

你已经学习了如何声明图像对象和如何装入图像,剩下的就是如何用image()方法来显示图像。

image()方法

image()方法有3个参数:

第一个参数是要被显示的pimage图像对象。如果只是声明了该对象,还未用loadimage()方法创建它,那么用image()方法去显示它会引发一个错误。有一些技巧可以解决这个问题,我们留到第10章来讲。在目前可以这样讲,一个pimage对象只有在装入图像之后,才能用image()方法来显示。另两个参数是图像放到窗口上以后左上角的x和y坐标,它们表明了图像在窗口上的摆放位置。参考示例3-13。

示例3-13:image.pde

只要setup()方法被调用,那么窗口大小就确定了,图像文件sample.jpg就被装入pimage对象并被显示在窗口的(0,0)处(即窗口的左上角)。也可以用image()方法对pimage图像对象中的图形进行缩放。就象processing中的很多方法一样,image()也是一组重载方法,你可以在调用时将想要的图像宽度和高度作为参数传递给它:

如果没有指明宽度和高度,图像会以实际尺寸显示在窗口上。如果图像太大,就只能显示一部分。你也可以指定显示时的宽度和高度,以便对图像进行缩放。如果指定的宽高比和图像实际的宽高比不一致,那么图像会出现拉伸或挤压现象。

processing程序包含了一个名为movie的类来显示视频。该类依赖苹果公司的quicktime视频处理库,因此如果你的计算机还没有安装这个库,你需要下载并安装它。要说明的是,目前在linux上用processing处理视频是相当困难和复杂的。gsvideo库很新,设置过程稍显复杂;但它看起来相当可行,它允许linux用户在processing中处理不同格式的视频。为了本书的简洁性考虑,我们将它留给读者去自行研究。

用movie类可以装入quicktime视频;可以装入扩展名为.mov的视频文件;可以播放、循环、暂停;可以改变播放速度;可以调整视频色彩。用movie类创建视频对象和用pimage类创建图像对象有些相似,但也有一个很大的不同:你需要先导入包含movie类相关信息以及视频处理的所有库。这些库放置在另一个地方,可以用导入语句import来访问,如下所示:

接下来声明一个movie变量:

在setup()方法中,你需要创建一个movie类的实例。如何创建呢?你可以调用movie类的构造函数。该类的构造函数也是一组重载方法,有4种签名:

参数parent是将要使用和显示视频的processing应用程序。在简单的应用程序中,参数parent往往是这个应用程序本身,所以你可以用关键字this来引用它:

这不是非理解不可的。每一个processing应用程序都是名为papplet的java类的实例。papplet类调用setup()方法和draw()方法,处理鼠标和键盘事件。有时,一个应用程序实例被载入另一个应用程序中,内部的那个称为papplet子对象,外部的称为papplet父对象。如果在子对象中引用父对象,那么父对象就是居于外部的那个应用程序。这点比较高深难懂,你多半也不想面对它。如果你遇到parent参数使用this关键字或papplet对象作实参,你会知道这些实参都引用主程序类。

用filename和url参数表示视频文件都是可行的,这就象用loadimage()方法装载本地图像和网络上的图像一样。当要载入本机上的一个.mov文件时,用该文件的文件名。当要载入网络上的一个视频时,就用url方式。最后有可选的参数fps表示帧速率。如果视频自身的帧速率和应用程序的帧速率不同,你可以用这个参数设置读取视频时的帧速率。下面的代码在processing应用程序的setup()方法中,使用对该程序的引用和本地视频文件作为参数,从而构造了一个movie对象:

看看代码中的play()方法。它告诉processing应用程序要立刻读取视频文件。这很重要,因为如果不调用这个方法,那么processing应用程序就不会从视频中读取视频帧,也就不会显示视频。想要让processing应用程序显示视频,你必须调用play()方法或loop()方法。

要读视频,你需要定义一个movieevent()方法。为什么呢?当quicktime播放视频时,视频片段或帧(和视频帧没有太大区别)源源不断地流向processing应用程序,而processing应用程序会将它们显示在窗口上。quicktime播放器准备好一个视频帧后,通过调用movieevent()方法来告诉processing环境,一个视频帧准备显示了。这和mousepressed()的原理是一样的,mousepressed()告诉processing环境发生了鼠标按键事件。想要获得该帧的信息,你需要调用movie类的read()方法。该方法读取一帧的信息并放到movie对象中,准备显示出来:

要在窗口中显示当前视频帧,你可以用image()方法。这与前面所讲的用image()方法来显示pimage对象中的图像一样。

这段代码将当前视频帧显示在(0,0)处(即窗口左上角)。图3-7是示例3-14的应用程序运行时的画面。

示例3-14:movie.pde

《交互式程序设计 第2版》一3.7 将外部数据载入Processing

图3-7:用movie类显示视频

最后还要了解如何读写文件。要读一个文件有两种方式,其中一种就是根据文件类型使用对应的载入方法。要载入图像,可以用loadimage()方法;要载入简单文本文件,可以用loadstrings()方法;要载入二进制文件(除文本文件之外的其他文件),可以用loadbytes()方法。由于载入和分析二进制文件要复杂得多,我们将这些内容留到第12章来讲,本节只讲简单文本文件的读写。

loadstrings()方法

仅当要载入纯文本文件时,loadstrings()很有用。这就意味着,要用它来载入像word文档这样的文件不会如你期望的那样顺利,因为word文档中除了少量文本以外还包含了大量二进制数据。一般来讲,以.txt为扩展名的文件和没有扩展名的纯文本文件都是纯文本文件。也就是说,用notepad和textedit创建的文件一定可以用loadstrings()方法正确载入。要用loadstrings()方法载入文件,括号中的参数既可以是本地电脑中的文件名,也可以是用url方式表示的网络文件:

仅仅将文本文件载入还不够,还需要将文件内的数据存放在某个地方。比如,将数据存放在一个字符串对象数组中:

这条语句建立了一个字符串数组来存放文本文件的所有行,数组中的每个元素可以引用文件中的一行。要显示这些字符串,需要用一个for循环。每一次循环,都会用text()方法将一个字符串显示在窗口画布上。参见示例3-15。

示例3-15:loadstringsdemo.pde

再次提醒一下,所用到的文本文件必须位于processing应用程序目录下的data文件夹中,或者来自internet。

savestrings()方法

前面介绍了用loadstrings()方法从文本文件中读取所有字符串,现在再学习如何将若干字符串输出到文本文件就很容易了。这两种操作是相反的。首先,需要建立字符串数组:

建立字符串数组之后,调用savestrings()方法就可以将数组中的所有字符串写到文本文件中。当然,调用时需要将文件名和数组名作为参数传递进去:

savestrings("data/greeting.txt", lines);

这条语句建立了一个名为greeting.txt的文本文件,并将数组中所有字符串都写到该文件中,每个字符串在文件中占据一行。

继续阅读