关于Pixel Bender

Pixel Bender介绍

 

下面是摘自Adobe官方文档 Adobe Pixel Bender Developer’s Guide对Pixel Bender的介绍:

 

The Adobe Pixel Bender technology delivers a common image and video processing infrastructure which provides automatic runtime optimization on heterogeneous hardware. You can use the Pixel Bender kernel language to implement image processing algorithms (filters or effects) in a hardware-independent manner.

 

翻译(翻得烂,建议大家还是看原文吧):

Pixel Bender是Adobe开发的一套针对图像、视频处理的底层框架,可以依赖于多种不同硬件来进行优化加速。使用Pixel Bender,需要用专门的语言Pixel Bender kernel来编写图像处理逻辑(比如自定义滤镜或者特效)。

 

Pixel Bender development offers many advantages:

  1. Low learning curve Pixel Bender offers a small number of tools that are sufficient to write complex image-processing algorithms. Learning Pixel Bender is easier than learning C/C++ and each application’s plug-in SDK. You do not need to know any graphics shading language or multi-threading APIs.

  2. Parallel processing Pixel Bender allows the same filter to run efficiently on different GPU and CPU architectures, including multi-core and multiprocessor systems. It delivers excellent image processing performance in Adobe products.

  3. Supports all bit-depths The same kernel runs in 8-bit/16-bit/32-bit within the application.

  4. Support by multiple Adobe applications Pixel Bender is integrated with multiple Adobe applications. It allows you to develop filters that are portable among various Adobe products. There is an active Pixel Bender Exchange where developers share their filters.

 

翻译: 

Pixel Bender的优点:

  1. 容易学习。Pixel Bender提供了一些功能齐全的工具,可用于编写复杂的图像处理逻辑。学习简单,使用类似C++的语法,结构简单,而且不要求开发人员对图像shading language基础或多线程的API有所了解。
  2. 在8-bit/16-bit/32-bit的机器上都可运行。
  3. 多款Adobe产品支持(Photoshop、After Effect、Flash)。(“在一定规范下” -- 译者注)开发人员可编写一款各产品通用的滤镜。在Pixel Bender Exchange上,有很多开发人员还分享出来他们编写的滤镜。

 

Pixel Bender技术可应用于 Photoshop、After Effect、Flash等Adobe产品,但对于Flash的应用,会有比较大的限制:

  1. 只能应用使用ActionScript 3.0编写的swf,且使用Flash Player 10.0之后的版本。
  2. 除了if/else,无法使用任何形式的循环和其他程序流控制。
  3. 不支持数组。
  4. 不允许自定义函数或库。
  5. 不允许使用region functions。
  6. 不允许使用dependent values
  7. non-constant indices into vector values
  8. 无法调用GPU资源(至少到目前2010年10月份为止是这样)

 

=_=|||
确实是很多限制,一开始想使用Pixel Bender对Flash展示层做大规模优化的幻想破灭了。

 

 

Pixel Bender的应用场合

 

对于Pixel Bender的应用,主要有下面几种:

  • 自定义滤镜
  • 填充:即某块区域的绘制完全由Pixel Bender来生成,比如可用于制作游戏中特效。
  • Blend Mode
  • 32位的浮点运算(这一点是比较神奇,但不在谈论之列,后续可以再另外分享)

 

但是,有时候使用Pixel Bender写的滤镜效率并没有想象中那么高。下面有个例子:

首先,大家可以先看一下StackOverFlow上的这个贴:using PixelBender to double the size of a bitmap.

提问者提出了一个问题:

同样是将一张图片的尺寸放大一倍,使用Pixel Bender,和使用AS3自带的库类BitmapData.draw()方法,在执行时间上分别是前者是后者的4倍。

后面就有人回答:

在这个场景中,Pixel Bender代码对比的对象,其实是player底层代码(因为想BitmapData这种类肯定是player底层实现的),而不是ActionScript 3。所以对于一些player原生支持的功能,如果用Pixel Bender重新实现一遍,并不会快于player(否则,Adobe的工程师们早就利用Pixel Bender的技术去提高Flash Player的执行效率了)。

 

因此,Pixel Bender的效率应该是高于(远远高于)使用ActionScript直接控制像素;但在同一程序逻辑下,不会高于player本身的效率。

那么,Pixel Bender的应用场合应该是:当需要写一些自定义、灵活的滤镜效果,这时候就应该使用它。它是对那些效率高但不灵活的滤镜效果(player自带的)和效率低但很灵活的滤镜效果(AS3写)的一个折衷。

 

 

Pixel Bender与Flash结合的运行方式 

 

在Flash Player 10里集成了有一个Pixel Bender runtime,解释运行由Pixel Bender toolkit生成了pbj文件。Pixel Bender runtime之于pbj,就相当于Flash Player之于swf。

Pixel Bender runtime是使用多线程的,不会和player使用同一线程。在多核的机器上,可以使用多个cpu资源,所以在效率上是有很大提高的,而且不会导致Flash UI的阻塞。所以,我猜上一节中的案例应该是在单核环境中的。如果在多核环境中,Pixel Bender多个线程的执行速度应该会高于player一个线程的速度。

目前版本的Pixel Bender runtime(2010年10月份)是无法支持GPU加速的。那既然Pixel Bender Toolkit有GPU模式,那为什么不把这个功能集成到Flash Player中呢?这篇文章(Adobe Pixel Bender in Flash Player 10 Beta)有做介绍。作者是Flash Player的工程师,诉尽苦衷,主要考虑的还是那两个方面:1.平台兼容性;2.Flash Player的大小。

 

 

 

 

 参考资料

 

单色化滤镜的代码(MonochromeFilter.pbk)

<languageVersion: 1.0;>

kernel MonochromeFilter
<
    namespace: "com.tencent.qqshow";
    vendor: "Tencent";
    version: 1;
    description: "Monochrome Filter";
>
{
    parameter pixel4 color
    <
        defaultValue: float4(0.5, 0.5, 0.5, 1);
    >;
    
    output pixel4 dst;
    
    input image4 src;    

    void evaluatePixel()
    {
        pixel4 c = sampleNearest(src, outCoord());
        pixel4 target = c;
        
        //caculate the 256 grey level
        float gl = c.r * 0.3086 + c.g * 0.6094 + c.b * 0.082;
                
        if(gl < 0.5)
        {
            target.r = color.r * gl * 2.0;
            target.g = color.g * gl * 2.0;
            target.b = color.b * gl * 2.0;
        }
        else
        {
            target.r = color.r + (1.0 - color.r) * (gl - 0.5) * 2.0;
            target.g = color.g + (1.0 - color.g) * (gl - 0.5) * 2.0;
            target.b = color.b + (1.0 - color.b) * (gl - 0.5) * 2.0;
        }
        
        dst = target;
    }
}