【问题标题】:Why Pixel Bender filter behaves differently in Toolkit than in Flex/Air application?为什么 Pixel Bender 过滤器在 Toolkit 中的行为与在 Flex/Air 应用程序中的行为不同?
【发布时间】:2011-12-08 14:17:40
【问题描述】:

好的,所以我尝试了这个更简单的过滤器,其 Air 代码如下:

<languageVersion : 1.0;>

kernel NewFilter
<   namespace : "Your Namespace";
    vendor : "Your Vendor";
    version : 1;
    description : "your description";
>
{
    input image4 src;
    output pixel4 dst;

    void
    evaluatePixel()
    {
        pixel4 cPix  = sampleNearest(src,outCoord());
        pixel3 RGB = cPix .rgb;
        float r = RGB.r; 
        float g = RGB.g; 
        float b = RGB.b;
        //float minVal = min(r, g); 
        dst = pixel4(r, g, b, 1);
    }
}

事实证明,如果我取消注释这一行 float minVal = min(r, g);,我将不再获得原始图片,但这是: Result

取而代之的是: Original

如果有人能向我解释一下……我将不胜感激……

//------------------------------------------------------------------
//------------------- ORIGINAL POST --------------------------------

我正在尝试为 flex 应用程序制作像素弯曲过滤器,它将输入图像的选定色调值范围更改为定义的新色调值。 我在像素弯曲工具包中做了这样的过滤器,它给出了令人满意的结果。

这是该过滤器的代码:

<languageVersion : 1.0;>

kernel ColorChange
<   namespace : "Your Namespace";
    vendor : "Your Vendor";
    version : 1;
    description : "your description";
>
{
    input image4 src;
    output pixel4 dst;

    parameter float HUE
    <
        minValue: 0.;
        maxValue: 359.9;
        defaultValue: 0.;
    >;
    parameter float SAT
    <
        minValue: -1.;
        maxValue: 1.;
        defaultValue: 0.;
    >;
    parameter float VAL
    <
        minValue: -1.;
        maxValue: 1.;
        defaultValue: 0.;
    >;

    parameter float MIN_RANGE
    <
        minValue: 0.;
        maxValue: 360.;
        defaultValue: 0.;
    >;

    parameter float MAX_RANGE
    <
        minValue: 0.;
        maxValue: 360.;
        defaultValue: 360.;
    >;

    void
    evaluatePixel()
    {
        pixel4 cPix = sample(src,outCoord());
        pixel3 RGB = cPix.rgb;
        float3 HSV;
        //--------------------------------------------------------------
        // CONVERT RGB TO HSV
        //--------------------------------------------------------------
        pixel1 r = RGB.r; 
        pixel1 g = RGB.g; 
        pixel1 b = RGB.b;

        pixel1 minVal = min(min(r, g), b); 
        pixel1 maxVal = max(max(r, g), b);
        pixel1 delta = maxVal - minVal;
        HSV[2] = maxVal;
        if (maxVal == 0.) {
            HSV[0] = 0.;
            HSV[1] = 0.;
        } 
        else
        {
            HSV[1] = delta / maxVal;
        }

        if(r == maxVal)
            HSV[0] = (g-b)/delta;
        else if(g == maxVal)
            HSV[0] = 2. + (b-r) / delta;
        else
            HSV[0] = 4. + (r-g) / delta;

        HSV[0] *= 60.;
        if(HSV[0] <0.)
            HSV[0] += 360.;

        //--------------------------------------------------------------
        // FILTER RANGE OF HUE
        //--------------------------------------------------------------
        if((HSV[0] < MIN_RANGE) || (HSV[0] > MAX_RANGE))
        {
            dst = cPix;
        }
        else
        {
            //--------------------------------------------------------------
            // CHNAGE HSV
            //--------------------------------------------------------------
            float hH = HUE;
            float sS = SAT;
            float vV = VAL;
            HSV[0] = HUE;
            HSV[1] += SAT;
            if(HSV[1] > 1.)
                HSV[1] = 1.;
            else if(HSV[1] < 0.)
                HSV[1] = 0.;
            HSV[2] += VAL;
                if(HSV[2] > 1.)
                    HSV[2] = 1.;
                else if(HSV[2] < 0.)
                    HSV[2] = 0.;
            //----------------------------------------------------------------------
            // CONVERT HSV TO RGB
            //----------------------------------------------------------------------
            float h = HSV[0];// / 360.; 
            float s = HSV[1];// / 100. * 255.; 
            float v = HSV[2];// / 100. * 255.;

            if (s == 0.) {
                RGB.r = v;
                RGB.g = v;
                RGB.b = v;
            } else {
                h = h / 60.;
                int var_i = int(floor(h));
                float f = h - float(var_i);
                float p = v * (1.-s);
                float q = v * (1.-s*f);
                float t = v * (1.-s*(1.-f));
                if (var_i == 0) {
                    RGB.r = v; 
                    RGB.g = t; 
                    RGB.b = p;
                }
                else if (var_i == 1) {
                    RGB.r = q; 
                    RGB.g = v; 
                    RGB.b = p;
                }
                else if (var_i == 2) {
                    RGB.r = p; 
                    RGB.g = v; 
                    RGB.b = t;
                }
                else if (var_i == 3) {
                    RGB.r = p; 
                    RGB.g = q; 
                    RGB.b = v;
                }
                else if (var_i == 4) {
                    RGB.r = t; 
                    RGB.g = p; 
                    RGB.b = v;
                }
                else {
                    RGB.r = v; 
                    RGB.g = p; 
                    RGB.b = q;
                }
            }
            dst = pixel4(RGB.r, RGB.g, RGB.b, 1);
        }
    }
}

所以原理很简单,将每个像素转换为 HSV 颜色空间,检查色调是否在所选范围内,如果确实将其色调更改为定义的色调并转换回 RGB。

问题是,在 Air 应用程序中使用时,我没有得到相同的结果,从仅使用过滤器的默认参数开始。

这是Air应用的代码:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                       xmlns:s="library://ns.adobe.com/flex/spark"
                       width="1400" height="800" backgroundAlpha="0.0" xmlns:mx="library://ns.adobe.com/flex/mx" 
                       creationComplete="windowedapplication1_creationCompleteHandler(event)">
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>

    <fx:Script>
        <![CDATA[
            import mx.events.ColorPickerEvent;
            import mx.events.FlexEvent;

            import spark.filters.ShaderFilter;
            import spark.utils.BitmapUtil;

            [Embed(source="myFilter.pbj", mimeType="application/octet-stream")]
            private var MyBender:Class;

            private var shader:Shader = new Shader();
            private var shaderJob:ShaderJob;
            private var shaderResult:BitmapData;


            private function filter():void
            {                       
                // Configure desired input parameters of shader.
                shader.data.src.input = originalImage.bitmapData;

//              shader.data.HUE.value = [H_slider.value];
//              shader.data.SAT.value = [S_slider.value];
//              shader.data.VAL.value = [V_slider.value];
//              shader.data.MAX_RANGE.value = [H_max_slider.value];
//              shader.data.MIN_RANGE.value = [H_min_slider.value];

                shaderJob = new ShaderJob(shader, shaderResult);
                shaderJob.start(true);
                bendedImage.source = new Bitmap(shaderResult);
            }

            private function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
            {
                // Create new shader instance and initialize with embedded byte code.
                shader = new Shader(new MyBender());
                shaderResult = new BitmapData(originalImage.width, originalImage.height);
                filter();
            }

        ]]>
    </fx:Script>
    <s:HGroup width="100%">
        <s:Group id="originalGroup" width="100%">
            <s:Image id="originalImage" source="mandelbrot.png"/>
        </s:Group>
        <s:Group id="bendedGroup" width="100%">
            <s:SWFLoader id="bendedImage" source="mandelbrot.png" />
            <s:HSlider id="H_slider" minimum="0" maximum="359.9" stepSize="0.1" value="0" change="filter()" width="500" toolTip="HUE"/>
            <s:HSlider id="S_slider" minimum="-1" maximum="1" stepSize="0.1" value="0" y="20" change="filter()" width="500" toolTip="SAT"/>
            <s:HSlider id="V_slider" minimum="-1" maximum="1" stepSize="0.1" value="0" y="40" change="filter()" width="500" toolTip="VAL"/>
            <s:HSlider id="H_max_slider" minimum="0" maximum="360" stepSize="0.1" value="360" y="60" change="filter()" width="500" toolTip="HUE MAX"/>
            <s:HSlider id="H_min_slider" minimum="0" maximum="360" stepSize="0.1" value="0" y="80" change="filter()" width="500" toolTip="HUE MIN"/>
        </s:Group>
    </s:HGroup> 
</s:WindowedApplication>

因此,使用默认参数在 Air 应用程序中应用 PixelBender 过滤器会产生以下结果:

http://i.stack.imgur.com/UyoZR.png

但在 Pixel Bender Toolkit 中,我使用相同的参数看到了这一点:

http://i.imgur.com/LNnCi.png

在应用程序中更改 HUE_MAX 滑块(绑定到过滤器的 MAX_RANGE 参数),它不会平滑地过滤掉 HUE 值,而是在 HUE_MAX=59.9 的阈值,其中较低的值看起来像没有应用过滤器,并且在 HUE_MAX= 299.9 在 60 和 299.9 之间看起来像这样:

http://i.stack.imgur.com/5kePu.png(抱歉,新用户)

任何想法我做错了什么?

【问题讨论】:

  • 很久没用PB了,这种情况下不应该用ShaderFilter吗?我在您的代码中看到了导入,但从未使用过。

标签: apache-flex filter air pixel-bender hsv


【解决方案1】:

min 函数对其参数做了一些我无法解释的事情。 但是使用的时候问题就解决了

pixel1 minVal = r;
if(g < minVal)
minVal = g;
if(b < minVal)
minVal = b;

而不是

pixel1 minVal = min(min(r, g), b);

【讨论】:

    【解决方案2】:

    您的 PB 代码中有很多浮点比较。像这样的行:

    if (maxVal == 0.) 
    

    极易出现舍入误差。我建议改用这样的东西:

    if (abs(maxVal) < epsilon) 
    

    【讨论】:

    • 不幸的是,这没有帮助。但奇怪的巧合是这些阈值和这行代码:HSV[0] *= 60.; if(HSV[0] &lt;0.) HSV[0] += 360.; if((HSV[0] &lt; MIN_RANGE) || (HSV[0] &gt; MAX_RANGE))... 因为阈值分别为 60 (1*60) 和 300 (-60 + 360)
    【解决方案3】:

    您的 AS 代码中设置参数值的行已被注释掉。您可以尝试重新评论它们并将值设置为默认值。您放入 PB 文件的默认值不会由运行时自动设置,它们只是作为 UI 的提示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-15
      • 1970-01-01
      • 2010-11-07
      • 1970-01-01
      • 1970-01-01
      • 2021-03-08
      • 1970-01-01
      相关资源
      最近更新 更多