- Max/MSP/Jitter 教程 01 - 什么是矩阵?
- Max/MSP/Jitter 教程 02 - Jitter 对象的属性
- Max/MSP/Jitter 教程 03 - 播放 QuickTime 视频
- Max/MSP/Jitter 教程 04 - 创建矩阵
00 翻译自 Cycling74 的 Max/MSP/Jitter 官方文档:Tutorial 3: Math Operations on a Matrix
本教程介绍如何对存储在 Jitter 矩阵中的数据做简单的数学运算,使用 jit.op
对象来缩放矩阵单元格或单个平面。
教程分为三个简单的例子,你可以使用 jit.op
对象执行这些操作。jit.op
对矩阵的所有对象而不是单个数字执行数学运算。
向矩阵中的所有单元格添加常量
第一个示例显示了连接到 jit.op
的 jit.matrix
对象,其输出可由 jit.pwindow
查看。每次改变连接到 jit.op
右输入口的数字框,都会从 jit.matrix
输出一个新的矩阵。从参数中可以看出,jit.matrix
生成一个 4x3 的单平面 char(0-255) 矩阵。jit.pwindow
把这个矩阵可视化为一个灰度图像。拖动数字框将改变显示的灰度级别(黑色 0 ~ 白色 255)。
请注意,jit.matrix
输出了一个所有单元格都为 0 的矩阵。如果将 jit.matrix
和 jit.pwindow
对象绕过 jit.op
连接在一起,无论向 jit.matrix
发送多少次 bang 消息,都只能看到黑色图像。jit.op
向 jit.matrix
和 jit.op
之间的矩阵的所有单元都加上了一个值(由数字框给定)。
@ 操作符
jit.op
根据参数指定的运算(用 @op 表示)向矩阵加了一个值(不是乘或除)。@op 之后的参数是一个符号(或符号列表),它定义了 jit.op
在输入矩阵上执行的数学运算。
在这个例子中,op 属性设置为 + ,它对从左入口输入的任何矩阵都执行加法操作。右侧入口中的整数值会加到矩阵中的所有单元格。这个值被称为标量(scalar),因为它向整个矩阵添加了相同的值(在教程 11 中我们会展示 jit.op
如何使用两个矩阵进行数学运算)。
要点:更改
jit.op
右侧入口中的标量值不会输出新矩阵。如果断开数字框和按钮之间的接线,jit.pwindow
将停止显示任何新内容。原因在于,大多数 Jitter 对象与大多数 Max 对象一样,仅在数据进入其最左侧入口时才会输出数据。在上面的例子中,每次更改数字框时
jit.op
都会存储新的标量值。此时按钮发送一个 bang 给jit.matrix
,让它将新的矩阵(所有值设置为 0)发送到jit.op
的左入口,触发输出矩阵。如果在按钮上方的接线上放置一个断点,然后 shift-cmd-T 逐步执行消息,就能看到它是如何运作的。(有关如何使用断点功能跟踪 Max 消息,请参阅教程:消息顺序和调试)
使用 jit.op
的 val 属性,标量值也可以作为常量。例如,如果想要为矩阵的所有单元格添加 134,可以使用 val 属性并省去数字框:
类似地,如果想要更改由任何给定的 jit.op
对象执行的数学运算,可以用消息 op
后跟数学符号,发送到对象的左入口。
多平面数据的数学运算
第二个示例显示了使用 jit.op
将值传入矩阵的更复杂的例子。
为矩阵的每个平面使用单独的标量
这个 patch 跟第一个类似,区别在于现在使用的是 4 平面矩阵。这由 jit.matrix
的第一个参数给出。jit.pwindow
现在有颜色了,它正在解析矩阵 α/红/绿/蓝 4 个单独存储颜色通道的平面。这个例子中的 jit.op
包含 op 属性的四个符号的列表:每个符号设置输入矩阵的一个平面的数学运算。在这个 patch 中,保留第一个(alpha)平面不做改动,而为其他 3 个平面做加法运算。
pak
对象向 jit.op
右输入口传送四个打包的整数。pak
和 pack
的唯一区别是,当更改任何数字时,pak
都会输出一个新列表(pack
需要一个新数字或左侧入口的一个 bang 来触发输出新列表)。由 pak
生成的四个数字决定了传入 jit.op
矩阵的每个平面的标量值。
在上面的示例中,平面 0 没有添加任何内容(op 属性的第一个参数是 pass)。平面 1,2 和 3 将分别添加 161,26 和 254。jit.pwindow
将输出矩阵的单元格解析为洋红色(即使只看到一种颜色,矩阵中实际上有 12 个单元格,都设置为相同的值)。
要点:如果
jit.op
对象的 op 属性只有一个值(只使用一个数字作为标量),jit.op
将在输入矩阵的所有平面都使用该运算符号和标量值。
修改图像中的颜色
第三个例子说明如何在矩阵中使用 jit.op
,这个矩阵已经存储了相关数据:
将单个平面与标量相乘
单击消息框 importmovie colorbars.png
,jit.matrix
的 importmovie
消息将图像或 QuickTime 视频文件中的单帧图像加载到对象存储的矩阵中。它会将原图像缩放到矩阵的尺寸(320 x 240)。
单击按钮,jit.pwindow
中显示图像校准颜色条。这时 jit.op
的算术运算符设置为:alpha 平面不做修改(pass), 其他平面设置为 *(乘)。这个矩阵有 4 个平面,因此使用 4 个浮点数列表设置每个标量。平面 1~3 中的值都是 1.,结果是显示原始的图像:
所有标量均为 1
如果将标量设置为 1.0,0 和 0.,会看到以下图像:
包含颜色条的矩阵的所有平面(平面 1 除外)都乘以 0。这将消除矩阵的α,绿色和蓝色平面,仅留下红色(平面 1)。
将中间值(例如 0.,0.,1. 和 0.5)设置为 jit.op
的标量,会得到颜色栏看起来不同的图像:
在这种情况下,忽略 alpha 通道并将红色通道归零。蓝色平面的值是它们的一半。绿色通道(平面 2)保持不变。
要点:
jit.op
中的一些数学标量使用浮点数,有些则使用整数。这取决于相关运算符(由 op 属性定义)以及输入矩阵的类型。本教程所有示例都使用了 char 矩阵,因此在添加时可以使用整数(任何浮点数都将被截断,因为矩阵数据保留 0-255 范围内的整数)。如果使用 float32 矩阵作为输入,就需要添加浮点数。同样,用 char 乘以浮点标量的矩阵也可以(240 * 0.5 = 120,整数)。但是,由于
jit.op
输出的矩阵仍然是 char 矩阵(参见下面的注释),因此仍然只能获得 0-255 范围内的值。
如果你尝试使用标量值,容易看到某些颜色条消失或与相邻条形图合并。这是因为颜色条都设置为范围相似的标准颜色值。如果一次只显示一个通道(设置一个平面为 1,其余为 0),顶部七个条形中的四个将显示颜色。
本教程中只演示了 + 和 * 运算符,实际上 jit.op
对象可以执行许多其他的数学运算。运算符的完整列表请查看参考文档,或双击 jit.op
帮助文件中的 p op_list 子 patch。
调整大小
创建 jit.pwindow
对象时,它默认显示为 80 像素宽,60 像素高。它可以像 Max 中的许多 UI 对象一样改变大小。如果要精确地指定大小,可以使用 inspector 或向其发送尺寸消息,后跟宽度和高度(以像素为单位):
更改 jit.pwindow
的大小
如果给某个固定尺寸(像素)的 jit.pwindow
发送不同的尺寸的矩阵,jit.pwindow
会按自身的大小来缩放传入的矩阵。如果将非常小的矩阵发送到非常大的 jit.pwindow
,会做像素化处理(图像中颜色完全相同的矩形区域)。如果发送大矩阵到一个小的 jit.pwindow
,可能会丢失不同程度的细节。
要点:在上面的示例中,含有颜色块的
jit.matrix
的大小(由其维度决定)为 320 x 240 个单元格,planecount 为 4,类型是 char。jit.op
对象(以及大多数 Jitter 对象)识别出信息并自动适配计算、输出相同规格的矩阵。如果要更改
jit.matrix
的大小,jit.op
将立即识别变化并重新适应。jit.pwindow
也适配传入的矩阵,但方式略有不同。如果输入矩阵小于其自身的尺寸,则使用重复数据填充所有像素。(这会产生前一段中描述的像素化效果)如果输入矩阵大于其自身的维度,则必须忽略某些数据,只显示它可以显示的内容。因此,即使教程 patch 中的jit.pwindow
跟输入矩阵的大小不同,它们也会尽可能适配jit.op
矩阵。最后一个例子中的
jit.pwindow
尽可能显示了jit.op
输出的整个矩阵,但它必须忽略所有其他行和列,以使其接收的 320x240 矩阵适合自己的 160x120 显示区域。
小结
jit.op
对矩阵上的所有数据进行数学运算。可以分别对矩阵单元格中的整体或每个平面执行计算。jit.op
的 op 属性决定要执行什么数学运算,可以输入 @op [operator]
属性参数,或者由左入口中的 op [operator]
消息提供。
对于多平面矩阵(例如彩色图片和视频),可以给出运算符列表(例如,op pass *)来指定每个平面的操作,并且可以为每个平面提供不同的标量值。在教程 11 中我们会看到如何使用矩阵来代替简单的标量。
你可以使用 size [width] [height]
消息设置 jit.pwindow
的大小。jit.pwindow
将尽可能适应接收到的矩阵的大小。如果输入矩阵小于其维度,它将复制数据;如果输入矩阵大于其自身维度,它将忽略某些数据。大多数 Jitter 对象都尽量适应它们接收的矩阵的维度、类型和平面数量。对 jit.op
而言,它没有自己的维度,所以它自动适配传入的矩阵大小。
友情提示:独自折腾 Max 易患上癔症……不妨入群互助
👇👇👇