AEJoy —— AE 插件开发中的 PF_EffectWorld / PF_LayerDef 结构体

500 阅读4分钟

「这是我参与11月更文挑战的第 28 天,活动详情查看:2021最后一次更文挑战」。

参加该活动的第 50 篇文章

正文

PF_EffectWorld 结构体

After Effects 使用 PF_EffectWorlds 表示图像,也称为 PF_LayerDefs

world_flags

目前,唯一的标志是:

  • PF_WorldFlag_DEEP —— 如果世界是 16-bpc 的话就设置它

  • PF_WorldFlag_WRITEABLE —— 表示允许更改世界的图像数据。

通常效果不能改变输入的图像数据; 只输出。

data

指向图像数据的指针,存储为 PF_PixelPtr 。不要直接访问; 使用PF_PixelPtr 访问器宏。

After Effects 中的图像数据总是按顺序排列,从低字节到高字节,每个包含 Alpha, Red, Green, Blue

rowbytes

图像像素块中每一行的长度,以字节为单位。像素块包含 height 行和 width 像素,后面是一些填充字节。宽度像素(乘以 4 ,因为每个像素都是 4 个字节长)加上可选的额外填充加起来就是行字节数。使用此值遍历图像数据。

使用特定于平台的行尾填充来遍历整个缓冲区是不明智的。相反,应该使用高度和行字节来查找每一行的开头。

注意:该值不会根据字段呈现是否活动而变化。

注意:具有相同维度的输入和输出世界可以使用不同的行字节值。

width

像素缓冲区的宽度。

height

像素缓冲区的高度。

extent_hint

包含层中所有不透明(非零)像素的最小矩形。这定义了需要输出的区域。

如果您的插件随范围(如扩散抖动)而变化,请忽略这一点,并每次渲染完整的帧。

pix_aspet_ratio

像素宽高比表示为 PF_Rational

注意: Effects 可以对签出层使用此值,但必须为所应用的图层使用 PF_InData.pixel_aspect_ratio

platform_ref

在 CS5 中不再使用。

特定于平台的参考信息。在 Windows 上,它包含一个不透明的值。在 macOS 上,PF_GET_PLATFORM_REFS 提供了来自 PF_EffectWorldCGrafPtrGDeviceHandle

注意: 您不能在 PF_Cmd_GLOBAL_SETUP 期间获取platform_ref,因为还没有任何输出上下文。

dephault

仅用于层参数。

PF_LayerDefault_MYSELFPF_LayerDefault_NONE

16.0 的新特性

PF_Cmd_SMART_RENDER_GPU 期间,PF_LayerDef 将被与常规 CPU 渲染相同地填充,但 PF_LayerDef.data 将为 null ; 所有其他字段都是有效的。

PF_EffectWorlds 中的行字节

不要假设你可以使用(width * sizeof(current_pixel_type)) + 4,或其他方法到达 PF_EffectWorld 的下一个扫描线; 使用 PF_EffectWorld 的行字节(rowbytes)代替。

永远不要在 PF_EffectWorld 的指定区域之外写入; 这可能会损坏不属于您的缓存图像缓冲区。

要测试效果是否符合 PF_EffectWorld -> rowbytes,请在效果之后应用 Grow Bounds 效果。

输出缓冲区的行数将大于输入(尽管它仍然具有相同的逻辑大小)。

字节对齐

PF_EffectWorld 中的像素不能保证是 16 字节对齐的。一个效果可以得到一个更大的 PF_EffectWorld 的子区域。苹果像素处理优化样例代码的用户,你已经收到警告。

除了 8 位每通道颜色,After Effects 支持 16 位和 32 位浮动每通道颜色。

效果将永远不会接收具有不同位深的输入和输出世界,也不会接收比它们声称能够处理的更高位深的世界。

用于不透明(数据类型)像素的访问器宏

使用下面的宏访问(不透明的) PF_PixelPtrs 中的数据。

强调一下,简单地将一种类型的指针转换为另一种类型是不安全的! 要让它工作,需要一个类型转换,没有什么可以阻止你错误地类型转换。我们可能会在以后更改它的实现(届时您将感谢我们强制执行这个抽象级别)。

PF_PixelPtr Accessor Macros

PF_GET_PIXEL_DATA16

获取指向指定世界中的 16-bpc 像素的指针。

如果世界不是 16-bpc ,返回的像素指针将是 NULL 。

第二个参数是可选的; 如果它不是 NULL ,返回的像素将是传入像素中的值的解释,就像它在指定的 PF_EffectWorld 中一样。

PF_GET_PIXEL_DATA16 (
  PF_EffectWorld wP,
  PF_PixelPtr    pP0,
  PF_Pixel16     *outPP);

PF_GET_PIXEL_DATA8

在指定的世界中获取一个指向 8-bpc 像素的指针。

如果世界不是 8-bpc,返回的像素指针将是 NULL 。

第二个参数是可选的; 如果它不是 NULL ,返回的像素将是传入像素中的值的解释,就像它在指定的 PF_EffectWorld 中一样。

PF_GET_PIXEL_DATA8 (
  PF_EffectWorld wP,
  PF_PixelPtr    pP0,
  PF_Pixel8      *outPP);

可以将 PF_GET_PIXEL_DATA16PF_GET_PIXEL_DATA8 看作是安全的(咳咳)强制转换例程。

PF_EffectWorld 输出中获取 PF_Pixel16* 所需的代码实际上非常简单:

{
  PF_Pixel16 *deep_pixelP = NULL;
  PF_Err     err = PF_Err_NONE;
  err = PF_GET_PIXEL_DATA16(output, NULL, &deep_pixelP);
}

如果世界没有深度像素,则返回 deep_pixelPNULL

第二个参数不经常使用,应该作为 NULL 传递; 传递一个 PF_PixelPtr 对象,该对象不包含在 PF_EffectWorld 中,以强制其达到PF_EffectWorld 的深度)。