Max/MSP/Jitter 官方教程翻译17 - 图像旋转

00 翻译自 Cycling74 的 Max/MSP/Jitter 官方文档:Tutorial 15: Image Rotation

使用 jit.rota 旋转和缩放

Jitter 提供 jit.rota 对象来旋转和/或缩放图像。旋转和缩放是常见的视频效果,以不同方式组合它们还可以实现万花筒效果。jit.rota 在入口处获取视频数据矩阵(或其他类型的图像),根据对象属性的设置发送已缩放、旋转和以其他方式失真的版本。

打开教程 patch 。loadbang 触发 QuickTime 视频 dishes.mov 读入 jit.movi​​e。单击 “Display” 开关启动 metro 开始播放视频。

视频是一个对着餐盘拍摄的三秒从左到右平移镜头。jit.movi​​e 的循环属性初始化为 2,因此视频来回循环产生了来回平移的效果。

注意:Jitter 对象的许多属性使用参数 1 和 0 表示 “on” 和 “off”,因此可以合理地假设 jit.movi​​e 的 loop 属性也是这样。loop 0 关闭循环,loop 1 打开,loop 2 让视频向前播放,到达 loopend 点时向后播放,而不是跳回到视频起点。

jit.rota 的 theta 属性指定围绕中心锚点的旋转角度。

拖动 “Rotation Angle” 数字框旋转视频。正(或增加)值是逆时针旋转,负(或减小)值是顺时针旋转。旋转角度 - 也就是角度(θ) - 以弧度表示。0 或 2π 的任何倍数(如 6.283185)是正常的直立位置。π 值(3.141593)或 π 的任何奇数倍是颠倒的位置。随意尝试,直到了解 theta 值与 jit.rota 行为之间的关系。

技术细节:jit.rota 用三角法进行大量内部计算,以确定如何旋转图像。如果不是三角学迷,你可能不习惯用弧度来思考角度。平时我们更常使用度数,即一个完整的旋转是 360°。在三角学中更常使用弧度,完整旋转是 2π 弧度。这是因为半径为 1 的圆的周长恰好为 2π,可以用与单位圆相交的点来表示角度。(例如,从单位圆上的一个点开始并绕圆周移动 π/2 的距离,会得到 90° 角度 - 即 π/2 弧度的角度 - 从开始的地方以圆心为中心)

另外,在三角学中,角度的正变化是围绕单位圆逆时针旋转,而在日常生活中,把顺时针运动看做 “正” 或 “增加” 更符合惯例(如钟表时针的转动)。

因此,如果把度为单位的顺时针旋转,转换为以弧度表示,需要将度角乘以 2π,然后除以 -360。

自动旋转

除了手动旋转图像外,还可以编写自动化程序提供不断变化的旋转角度。在上一章中,我们编写了一个名为 rotate 的子 patch,它使用 line 对象将色调旋转角度从 0° 增加到 360°。现在做类似的事情,但使用 bang 视频的 metro 来增加旋转角度。为了使用上的友好,用 ° 表示旋转角度,而不是弧度(在子 patch 中转换度弧度单位),另外也显示转速为 “每秒转数”。

在标有 Degrees per bang 的数字框中输入数字 6。这让旋转角度在 metro 每次 bang 时增加 6°。由于 metro 每秒发出 20 次 bang(每 50 毫秒一次),我们可以通过公式 d * 20 / 360 计算每秒的转数(即 d / 18,d 是每次 bang 增加的角度)。现在单击标记为 On / Off 的开关开始自动旋转。

双击 rotate 查看子 patch


[rotate]子 patch 中的自动旋转

用度数 * 2π / -360,将用户指定的每次旋转角度转换为弧度量。当一个 bang 进入左入口时,如果正在旋转,bang 让旋转角度增加并添加到 accum 对象中。请注意,每次增加负的角度也 ok,这让图像逆时针旋转。当总旋转角度超过 2π(或 -2π)时,split 将值发送到使用模运算的 expr,并在发送到出口前将其恢复到范围内(重置 accum 中的值)。如过旋转关闭,我们 用 sel 0 检测到该事件,将 theta 角度重置为 0。

关闭子 patch 窗口。单击 On/Off 开关停止自动旋转。

放大或缩小

jit.rota 的另一个主要功能是缩放。缩放量由 zoom_xzoom_y 属性决定。这样可以单独放大或缩小水平和垂直尺寸;或者一次更改两个属性来同时缩放。

拖动标有 Zoom 的数字框来放大和缩小。大于 1 的值会放大图像,小于 1 的值会缩小图像。直接在 x 和 y 数字框中输入值分别更改 x 和 y 的缩放尺寸(负缩放值会翻转图像并调整其大小)。

当放大图像(如值为 2)时,图像质量仍然不错,因为我们已经用 interp 1 消息打开 jit.rota 的插值属性。如果关闭 interp,会在放大时产生像素化。当缩小时 interp 没有明显的效果,它几乎浪费了计算资源。(有关像素化和插值,请参阅 Jitter 教程16)不过插值确实可以改善旋转图像的现实,即便图像缩小。

超越边缘

将缩放的两个尺寸设置为较小的值例如 0.25。

当图像由于收缩或旋转而未填满整个显示区域时,jit.rota 必须决定如何处理位于图像区域外的矩阵的其余部分。现在 jit.rota 将图像区域外的所有单元格值设置为 0,使它们为黑色。boundmode属性决定 jit.rota 如何处理位于图像边界之外的单元格。不同的可用 boundmode 设置显示在 patch 右上角标记为 Space outside the image 的弹出菜单中。将 boundmode 的值初始化为 1,让 jit.rota 清除所有外围单元格。以下是每个 boundmode设置的含义:

0 Ignor:保持所有外围单元格不变。

1 Clear:将所有外围单元格值设置为0。

2 Wrap:根据需要重复图像以填充矩阵。

3 Clip:对于所有外围单元格,继续使用图像边界单元格的值。

4 Fold:重复图像,向相反方向翻转。

  • 对于缩小图像时的特殊效果,尝试将 boundmode 属性设置为 2(Wrap)以获得 “Warhol” 复制图像效果,或设置为 4(Fold)得到万花筒效果。
  • 现在试着重新打开自动旋转,组合旋转和缩放,并修改参数(每次 bang 的度数、缩放、Space outside the image)。
  • 尝试完以后,关闭自动旋转并将缩放属性( zoom_xzoom_y)调整回 1。

调整锚点和偏移

目前为止,我们一直使用图像的中心作为旋转锚点。其实可以选择任意一点。用 anchor_xanchor_y 属性设置旋转中心。现在是 160 和 120(图像尺寸的一半),可以在标记为 Anchor 的数字框中更改。

尝试不同的锚点,然后在 Rotation Angle 数字框上拖动查看效果。可以尝试 0,0 或 40,30 或 160,-120 或 320,240。将 boundmode属性设置为 1 可以更清楚地看到不同旋转的效果。请注意,anchor_xanchor_y 值是相对于矩阵的左上角指定的,但它们可以超出矩阵维度的边界。

此外可以用 offset_xoffset_y 属性在缩放和旋转后,将图像移动到输出矩阵中的其他位置。

要最有效地查看此内容,请先单击 patch 右下角的 pvar 对象上方的消息框。这会将旋转角度/边界模式/缩放/锚点恢复到本章开头的设置。(已经为相关的 UI 指定了名称,以便通过 pvar 与它们通信)现在将缩放数字框设置为 0~1 的某个值来缩小图像。

使用 Location offset 数字框,更改 offset_xoffset_y 值来移动图像。同时设置 boundmode 4,在 “kaleidoscope” 模式下查看效果。

完成后,将位置偏移值重置为 0。

鼠标控制旋转

我们为你设计了另一种旋转图像的方法。

单击 jit.pwindow 显示对象,按住鼠标,围绕对象中心以小圆周运动拖动。

jit.pwindow 跟踪鼠标移动,当鼠标按下时,它会以鼠标消息的形式将坐标信息(和其他鼠标信息)发送到右输出口。鼠标消息的前两个参数是相对于 jit.pwindow 左上角的 x 和 y 坐标。使用这些坐标来计算鼠标相对于 jit.pwindow 中心的角度并发送到 jit.rota 作为theta 属性的参数。


jit.pwindow 中的鼠标位置作为控制信息

技术细节

想知道这是如何计算的吗?

如果将 jit.pwindow 的中心点视为原点 0,0,把当前鼠标位置看做是位于该点圆周上的点,那么可以基于这两点得到一个直角三角形。获取鼠标坐标 y / x 的反正切值,得到鼠标相对于 jit.pwindow 中心的角度。

接收到传入的 x 和 y 坐标要做的第一件事是做转换,使它们以 jit.pwindow 为中心。

1
expr-1.0*atan(($i1-160.)/(-1.*$i2+119.5))+($i2>=120)*-3.141593

用 x 坐标减去 160 (x 值现在在 -160~160)并将 y 坐标乘以 -1(这样上移时值正向增大)然后加上 119.5。(如果正好添加120,那么每次从 jit.pwindow 得到 120 的 y 坐标时都会尝试在 expr 中除以0,这是一个未定义的数学运算)转换了 x 和 y 坐标,用 atan(y / x) 来获得弧度,然后乘以 -1 使鼠标顺时针旋转,从而使图像顺时针旋转。

此方法仅在 180° 范围内有效,因为反正切函数无法区分鼠标位置与圆上相对点之间的差异(这两个点 y / x 的值相同)。因此每当鼠标的 y 坐标进入 jit.pwindow 的下半部分时,我们在 θ 角度上添加 -π 的偏移量来区分那些来自另外一边的位置。(表达式中的最后一部分)

请注意,此表达式仅适用于 jit.pwindow 中的点 160,120。如果想创建一个适用于任何大小 jit.pwindow 中心点的表达式,要使用 getsize 消息获取 jit.pwindow 的维度,并用 size 值作为表达式中的变量。正如书上所说,“我们把这个练习留给读者”。

小结

jit.rota 对象用 theta 属性指定旋转角度,以弧度表示旋转图像。它还提供了使用 zoom_xzoom_y 属性放大和缩小图像的简便方法。用 anchor_xanchor_y 属性更改旋转的中心点,用 offset_xoffset_y 属性在输出矩阵中移动生成的图像。可以用 boundmode 属性更改 jit.rota 处理位于结果图像之外的矩阵单元格的方式。结合这些功能,除了缩放和旋转之外,你还可以获得重复图像和万花筒效果。

缩放和旋转涉及 jit.rota 相当密集的内部计算,这些操作对计算机的处理器提出了很高的要求。本教程中未提及的其他属性,可以调整旋转公式中的几乎每个系数,提供更多扭曲和旋转图像的可能性。请查看 jit.rota 文档说明。

要同时管理对如此多属性,可以设计自动流程以生成属性值,和/或交互式控件来更改值。



友情提示:独自折腾 Max 易患上癔症……不妨入群互助

👇👇👇

kidult00 wechat
扫码关注 00 的公众号
如果文章帮您节省时间或者解答疑问,不妨打个赏 :)