Max/MSP/Jitter 官方教程翻译08 - 调整颜色

00 翻译自 Cycling74 的 Max/MSP/Jitter 官方文档:Tutorial 6: Adjust Color Levels

jit.scalebias

本教程进一步讨论了上一章的颜色话题,并介绍专门用于修改矩阵 ARGB 颜色平面的对象:jit.scalebias

“scale” 是缩放因子,乘以给定的数值。”bias” 是加上一定的量来偏移某个值。组合乘法和加法,可以实现输入值到输出值的线性映射。

因为 jit.scalebias 修改图像中的 ARGB 颜色信息,所以它只处理 char 数据类型的 4 平面矩阵。(有关 ARGB 颜色和 char 数据的内容,请参阅 教程 7

用 char 类型数据计算

前一章讲到,char (8位)数据可以表示 0~255 之间的整数值,或 0~1 之间的小数值。比如在教程 4 中,我们用 jit.print 输出 0~255 的整数值。但是很多时候要修改矩阵的 char 值(更改其中一个属性)时,Jitter 对象只接收浮点数属性值。这可能有点费解,让我们来看看本教程的 patch。

打开教程 patch。双击打开中间的 explain_scalebias查看子 patch:


char 数据的浮点类型演示

在上面的例子中有一个非常小的矩阵。它有 4 个 char 平面,但只有一个单元。这样我们只需要注意矩阵中单个数值的变化。已将平面 2(绿色平面)的值设置为 100。在右侧,把整数值转换为 0~1 之间的小数值:用 100/255,得到 0~1 之间的值 0.392。

jit.scalebias 对象乘上指定的缩放因子,然后再加上偏移因子。jit.scalebias 计算时会把所有值看做浮点数,然后再转换为 char 数据重新存储到矩阵中。

这里用 scale 2.0bias 0.2消息来设置缩放和偏移因子。缩放因子(乘数)是 2.0,偏移因子(之后添加的偏移)是 0.2。为了了解 jit.scalebias 内部机制,将绿色值看做 0.392 x 2.0 + 0.2,等于 0.984。jit.iter 对象逐一输出每个单元中每个平面的值(矩阵只有一个单元),(以 char 类型存储在矩阵中)为 251(或是 0~1 范围的 0.984)。

(作为练习,请计算 jit.scalebias 在上面例子中在红色和蓝色平面中产生的值。在原矩阵中这些平面的值为 0,因此结果矩阵中的值将为 0 x 2.0 + 0.2 = 0.2,在 0~255 的范围内等于 51。因此底部的 jit.pwindow 对象显示的 RGB 值是 51 251 51)

更多例子

如果前一部分的讲解你已经理解得很清楚,可以跳过这部分。如果还是不太清楚 char 数据(特别是 jit.scalebias)的数学运算是如何工作的,这里还有一些例子。

从左到右逐个点击 preset 对象中的每个预设值。下面我们解释每个预设。

  1. 原始矩阵的绿色平面中的值为 255.(相当于 0~1 范围的 1.0) jit.scalebias 将其乘以 0.5 得到 127.5; 但是将值存储为 char 时,jit.scalebias 会截断小数部分,将值存储为 127。

    这产生了相当不精确的结果。(0~255 范围的 127 等于 0~1 范围内的 0.498,而不是我们期望的 0.5)但用 8 位 char 数据只能这样了。如果需要更高的精度,char 数据就不适合,需要用 long,float32 或 float64 数据的矩阵,以及 jit.op @op *jit.op @op + 对象。

  2. 原始值为 100,将它加倍(缩放因子 2.0)会得到预期结果 200。这样不会有精度损失。

  3. 原始值为 100(0.392)。缩放 1.0 倍保持不变,然后加上 -0.2 (也就是减去 0.2)得到结果 49(即 0.192)。
  4. 0.392 x 2.0 + 0.2 = 0.984。在 0~255 的范围内为 251。
  5. 此示例和下一个示例说明当乘法和加法运算的结果超过 8 位字符的容量时会发生什么。jit.scalebias 会直接裁剪结果为 char 的最大或最小值。这里,0.392 x 4.0 = 1.568(即 100x4 = 400),因此取上限为 255。
  6. 在另一个方向,0.392 - 0.5 = -0.108,因此结果为 0。

注意,这些误差和裁剪只发生在将结果重新存储为 char 时。在此之前,这些值在内部用浮点数计算,可以保证精度。即使乘法使内部值超出0~1 范围,也不会做裁剪,而且加法运算可以让其回到范围。这里 0.392 x 3.0(= 1.176)- 0.5 = 0.676。存储为 char 时会产生小的误差。0.676 在 0~255 范围内等于 172.38,但是小数部分会被截断并存储为 172(即 0.675)。如果没有变化,比例因子应为 1,偏移量应为 0。

你可以尝试更多的值,直到完全了解 jit.scalebias 以及 8 位 char 数据产生的结果。完成后关闭 [explain_scalebias] 窗口。

调整图像的颜色亮度

现在将 jit.scalebias 应用于彩色图像。在教程 patch 的左上角可以看到熟悉的配置:jit.movi​​e 对象,加载视频的 read 消息,和从 jit.movi​​e 触发 jit_matrix 消息的 metro对象。在这个 patch 中,jit.scalebias 用乘法和加法来修改矩阵。


加载图片或视频

点击 read chilis.jpg 读取 JPEG 静态图像(而非视频)到 jit.movi​​e。QuickTime 可以处理各种媒体格式,包括 PICT 或 JPEG 格式的静止图像。jit.movi​​e 将静止图像视为 1 帧长的视频。

jit.movi​​e 的输出将传到 jit.scalebias 处理,然后显示在 jit.pwindow 中(现在先忽略 jit.matrix 对象。我们在本章后面讨论)。可以修改 jit.scalebias 的 scale 和 bias 属性来更改值。

点击开关启动 metro。拖动 scale $1 消息框上方的数字框,将 scale 属性值增加到 1.25。


增加图像亮度; scale 值越大亮度越大

这将使图像的 4 个平面的所有非零值放大到 1.25 倍(增加 25%)。请注意,乘法会让较大的被乘数增加更多值。例如,如果原始矩阵中某单元格的红色值为 200,它将增加到 250(净增加 50),而同一单元格的蓝色值可能从 30 增加到 37(净增加 7)。

  • 尝试将 scale 增加到非常大,如 20。原始矩阵中 13 或更大的值将被增大到最大值 255(甚至非常小的值也会增加到可见水平),产生人为的过度曝光。
  • 尝试将 scale 降低到 0~1 之间。这会使图像变暗。scale ≤ 0 会将所有值设置为 0。
  • 将 scale 属性恢复为 1。现在尝试调整 bias 属性,为矩阵中所有值添加常量。正值使图像变亮,负值使图像变暗。


以常量提升(或降低)亮度

还可以尝试几种更极端的 scale 和 bias 设置。设置 scale 为 40,bias 为 -20。这会将几乎所有值推到 255 或 0,除白色或黑色之外仅留下少数颜色。尝试设置 scale 为 -1,bias 为 1。高低值会互换,反转颜色。继续降低 scale(比如 -4 或 -8)会产生类似的反转,但只有原始值较低的值才会被正 bias 提升回 0~1 范围。

单独调整平面

你可以用 scale,abias,rscale,rbias 等属性在 jit.scalebias 中单独调整每个平面中的亮度。

将 scale 设置回 1,将 bias 设置回 0。然后提供新的值来独立调整每个颜色平面。


调整每个颜色平面的亮度

这里有一个可以同时调整三个颜色平面缩放比例的控制器,让过程更具交互性。单击或拖动 swatch 对象时,它发送一个表示鼠标所在位置 RGB 颜色值的列表。这些值之前以 0~255 范围表示,现在已经被改为 0.0~1.0 的值(如果需要,inspector 中有一个复选框可选择用旧样式输出)。用 unpack 拆分列表为三个单独的浮点数来改变 jit.scalebias 的 rscale,gscale 和 bscale 属性 。


swatch 的值作为 jit.scalebias 的属性

  • 拖动 swatch 同时缩放 RGB 三个平面。这会产生 0~1 范围内的缩放值来降低所有亮度,让图像稍微变暗。
  • 可以在不同图像上尝试这些操作。读取其他彩色图像如 colorswatch.pict 或 wheel.mov, 并尝试调整颜色亮度。

重新分配矩阵的平面

上一个教程中,我们使用 jit.unpackjit.pack 来重新组合矩阵的平面。使用 jit.matrix 对象的planemap 属性也可以做到。在这个例子中,用 jit.matrix 传递 jit.movi​​e的输出来演示如何设置 planemap 属性。

jit.matrix 重新分配矩阵的平面

jit.matrixplanemap 属性可以映射(分配)输入矩阵的任何平面到输出矩阵的任何平面上。planemap 后面跟的数字表示矩阵中有多少平面(在本例中为 4)。列表中的每个位置代表输出平面(第一个代表输出平面 0,第二个代表平面 1,等等),数字表示分配给它的输入平面。默认情况下,平面值为 0 1 2 3(等),输入矩阵中的每个平面都分配给输出矩阵中的同一平面。可以随意更改这些映射。例如,如果发送消息 planemap 0 3 2 1jit.matrix ,会把输入平面 3 分配给输出平面 1(3 位于输出平面 1 的列表位置),把输入平面 1 输出到平面 3。这样就调换了图像的红色和蓝色平面。

  • 点击 read wheel.mov 消息框并启动 metro 显示视频。(设置jit.scalebias scale 属性为 1,bias 属性为 0,就可以在 jit.pwindow 中看到未改变的图像)在 patch 的右下角,单击planemap 0 3 2 1 消息框交换矩阵的红色和蓝色平面。单击消息框 planemap 0 1 2 3 恢复正常的平面映射。如果设置所有 RGB 输出平面设置为相同的输入平面,将在三个 RGB 平面中得到相等的值,从而产生灰度图像。

  • 单击消息框 planemap 0 1 1 1 查看效果。三个 RGB 平面在列表中的值都是 1,因此原始的红色平面用来输出矩阵的所有 RGB 平面。用一个 coll 对象存储所有平面映射的组合,发送到 jit.matrix 来更改 planemap 属性。

  • 双击 patcher rotatecolorplanes 查看子 patch。里面有一个 1 到 6 的计数器,逐一执行主 patch 中 coll 对象中的不同映射。(当它关闭时会发出数字 1 重置为默认平面映射)

  • 点击主 patch rotatecolorplanes 对象上方的开关,以每秒切换一次设置的速率,逐一执行不同的平面映射。将右输入口上方的数字框更改为较小的值(例如 80),查看快速重新分配平面的闪烁效果。

在下一章节中,你将了解如何使用 jit.hue 以更微妙的方式调整图像色调,以及使用 jit.brcosa 调整颜色的其他方法。

读取和导入图像

在本教程 patch 中,将三种不同类型的图像加载到 jit.movi​​e 中:PICT 和 JPEG 静止图像,以及 QuickTime 视频。在视频对象中读入静止图像看起来有点奇怪,但 QuickTime 确实可以播放多种类型的媒体文件,jit.movi​​e 知道如何读取它们。(jit.movi​​e 还可以读入 AIFF 音频文件,用 start 和 stop 消息播放,用 time 属性跳转到不同的位置等等。当然这时看不到矩阵的任何视觉内容)

如教程 5 所示,用 importmovie 消息加载静止图像到 jit.matrix 中很方便。用这种方式导入 QuickTime 视频,只有一帧存储在 jit.matrix 中。

在这个 patch 中,我们用 jit.movi​​e 加载所有图像。原因一是我们要加载整个视频(不只是视频的一帧)。原因二是想演示 jit.matrix 的 planemap 属性。矩阵有实际输入(左入口传入 jit_matrix 消息)时,planemap 属性才起作用。如果用 importmovie 直接导入图像到 jit.matrixplanemap 不起作用。

小结

jit.scalebias 用乘法和加法来修改 4 平面 char 矩阵中指定的平面(或所有平面)的值。scale 是矩阵中的每个值要乘上的缩放因子;bias 是乘法之后被加到每个单元的值。scale 和 bias 属性影响矩阵的所有平面。如果想一次只影响一个平面,请使用特定的属性例如 ascale,abias,rscale,rbias 等。

必须用浮点数定义这些属性值。当执行乘法和加法运算时,jit.scalebias 将 char 值视为 0~1 范围内的小数值,使用 floats 执行数学运算,然后将结果转换回 char(0~255 之间的整数)并存储。超出 0~1 范围的结果,在转换回 char 之前截取为 0 或 1。

可以用 jit.matrixplanemap 属性重新分配矩阵的平面。planemap 的参数按顺序列出输出平面,列表中的值是要分配给每个输出平面的输入平面。例如,要将输入矩阵的平面 1 分配给输出矩阵的所有四个平面,属性应设置为 planemap 1 1 1 1

jit.scalebias 提供了强大的工具来调整 4 平面 char(ARGB 颜色)矩阵中的颜色值。下一章节将介绍更多此类工具。


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

👇👇👇

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