2011年3月28日 星期一

Pixel Bender RGB 調整Demo

//Pixel Bender 檔名 RGB.pbj

<languageVersion : 1.0;>
kernel RGBFilter
<   namespace : "jt.com.tw";
    vendor : "jt";
    version : 1;
    description : "";
>
{
    input image4 src;
    output pixel4 dst;
    //parameter的<>是可無的,有的話是限制輸入數值
    parameter float amount
    <
     minValue: 0.0;
     maxValue: 1.0;
     defaultValue: 0.5;
    >;
    parameter float red
    <
    minValue: -1.0;
    maxValue: 1.0;
    defaultValue: 0.0;
    >;
    parameter float green
    <
    minValue: -1.0;
    maxValue: 1.0;
    defaultValue: 0.0;
    >;
    parameter float blue
    <
    minValue: -1.0;
    maxValue: 1.0;
    defaultValue: 0.0;
    >;
    
    void
    evaluatePixel()
    {       
        //取樣32bit       
        //old method
        dst = sampleNearest(src,outCoord());       
        dst.r +=  (red*amount);
        dst.b +=  (green*amount);
        dst.g +=  (blue*amount);        
    }
}
//Flex 程式碼如下


<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
  xmlns:s="library://ns.adobe.com/flex/spark" 
  xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
  applicationComplete="application1_applicationCompleteHandler(event)"  
  >
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
import mx.events.FlexEvent;
import mx.events.Request;

import spark.components.supportClasses.SliderBase;
import spark.filters.ShaderFilter;
import spark.primitives.BitmapImage;

//生命週期第一步,用來建立所有的顯示元件
override protected function createChildren():void
{
 super.createChildren();
}
//生命週期,當屬性變更時
override protected function commitProperties() : void
{
 super.commitProperties();
 if(_redUpdate)
 {
  updateShader('red',rSlider);
  _redUpdate = false;
  needUpdateDisplay();
 }
 if(_greenUpdate)
 {
  updateShader('green',gSlider);
  _greenUpdate = false;
  needUpdateDisplay();
 }
 if(_blueUpdate)
 {
  updateShader('blue',bSlider);
  _blueUpdate = false;
  needUpdateDisplay();
 }
}

private function updateShader(parameter:String , slider:SliderBase):void
{
 _shader.data[parameter].value[0] =  slider.value;
}

private function needUpdateDisplay():void
{
 _needUpdateDisplay = true;
 invalidateDisplayList();
}

//生命週期之一,畫面重繪
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
{
 super.updateDisplayList(unscaledWidth , unscaledHeight);
 if(_needUpdateDisplay)
 {
  image.filters = [_shaderFilter];
  _needUpdateDisplay = false;
 }
}

//用來載入圖檔
private var _imageLoader:Loader;
private var _imageLoaderComplete:Boolean;

//用來載入PBJ檔
private var _loader:URLLoader;
private var _loaderComplete:Boolean;
//pixle Bender 成員
private var _shader:Shader;
private var _shaderFilter:ShaderFilter;;
/* Embed的做法
* [Embed(source="pixelBender/RGB.pbj", mimeType="application/octet-stream")]
* private var shaderObj:Class;
*/

private var _redUpdate:Boolean;
private var _greenUpdate:Boolean;
private var _blueUpdate:Boolean;

private var _needUpdateDisplay:Boolean;

//Application所有的Childeren生命週期完成後發送
protected function application1_applicationCompleteHandler(event:FlexEvent):void
{
 createLoader(URLLoaderDataFormat.BINARY);
 startLoader('../pixelBender/RGB.pbj');

 createImageLoader();
 startImageLoader('../img/image001.jpg');
}

private function createLoader(dataFormat:String):void
{
 _loader = new URLLoader();
 _loader.dataFormat = dataFormat;
}
private function startLoader(url:String):void
{
 //偵聽
 _loader.addEventListener(IOErrorEvent.IO_ERROR , loaderIO_Error);
 _loader.addEventListener(Event.COMPLETE , loaderComplete);
 //開始load
 _loader.load(new URLRequest(url));
}
protected function loaderIO_Error(e:IOErrorEvent):void
{
 trace("error");
 //throw new IOError;
}
protected function loaderComplete(e:Event):void
{
 trace("complete");
 var l:URLLoader = URLLoader(e.currentTarget);
 createShaderMembers(ByteArray(l.data));
 setParameter(_shader);
 _loaderComplete = true;
 activityOnStart();
}
private function createShaderMembers(data:ByteArray):void
{
 _shader = new Shader(data);
 _shaderFilter = new spark.filters.ShaderFilter(_shader);
}

private function setParameter(shader:Shader):void
{
 var parameter:ShaderParameter;
 for each(var obj:Object in shader.data)
 {
  if(obj is ShaderParameter )
  {
   parameter = obj as ShaderParameter;
   //init Slider value
   if(parameter.name == "red"){
    setSliderInitValue(rSlider , parameter);
    continue;
   }
   if(parameter.name == "green"){
    setSliderInitValue(gSlider , parameter);
    continue;
   }
   if(parameter.name == "blue"){
    setSliderInitValue(bSlider , parameter);
   }
  }
 }
}

//set Slider Value
private function setSliderInitValue(slider:SliderBase , parameter:ShaderParameter):void
{
 slider.maximum = parameter.maxValue[0];
 slider.minimum = parameter.minValue[0];
 slider.value = parameter.value[0];
 slider.stepSize = (slider.maximum - slider.minimum ) / 100;  
}
//----------------------------
// Image loader
//----------------------------
private function createImageLoader():void
{
 _imageLoader = new Loader();
}
private function startImageLoader(url:String):void
{
 _imageLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR ,imageLoaderIO_Error);
 _imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE , image_complete);
 _imageLoader.load( new URLRequest(url));
}
private function imageLoaderIO_Error(e:IOErrorEvent):void
{
 trace('image loader IOError');
}
private function image_complete(e:Event):void
{
 trace('image Complete');
 _imageLoaderComplete = true;
 activityOnStart()
 var loader:Loader = Loader(e.target.loader);
 var bp:Bitmap = Bitmap(loader.content);
 var bitmapData:BitmapData = bp.bitmapData;
 image.source = bitmapData;
}


//兩個資料都載入才開始動作
private function activityOnStart():void
{
 if(_imageLoaderComplete && _loaderComplete)
 {
  setSliderListener();
 }

}

//Red Slider value by change
protected function changeRed(e:Event):void
{
 _redUpdate = true;
 invalidateProperties();
}
//Green Slider value by change
protected function changeGreen(e:Event):void
{
 //將數值變更動作加入佇列,下個影格時一次執行
 _greenUpdate = true;
 invalidateProperties();
}
//Blue Slider value by change
protected function changeBule(e:Event):void
{
 _blueUpdate = true;
 invalidateProperties();
}

//set Slider EvenListener
private function setSliderListener():void
{
 addSliderListener(rSlider , Event.CHANGE ,changeRed );
 addSliderListener(gSlider , Event.CHANGE ,changeGreen );
 addSliderListener(bSlider , Event.CHANGE ,changeBule );
}
//Listener Tools
private function addSliderListener(slider:SliderBase ,type:String ,listener:Function):void
{
 addEventListenerProxy(slider ,type ,listener);
}
private function addEventListenerProxy(target:IEventDispatcher , type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
{
 target.addEventListener(type, listener, useCapture , priority , useWeakReference);
}


]]>
</fx:Script>

<s:Group>
 <s:BitmapImage id="image"/>
 <s:VGroup id="controlGroub" x="600" y="300">
  <s:HGroup >
   <s:Label text="R" backgroundColor="#FF0000" width="20"/>
   <s:HSlider id="rSlider" liveDragging="true" minimum="-1" maximum="1"/>
  </s:HGroup >
  <s:HGroup>
    <s:Label text="G" backgroundColor="#00FF00" width="20"/>
    <s:HSlider id="gSlider" liveDragging="true"  minimum="-1" maximum="1"/>
  </s:HGroup>
  <s:HGroup>
   <s:Label text="B" backgroundColor="#0000FF" width="20"/>
   <s:HSlider id="bSlider" liveDragging="true" minimum="-1" maximum="1"/>
  </s:HGroup>
 </s:VGroup>
</s:Group>
</s:Application>

//檔案結構


//原始圖片
//執行結果


參考資料:
Adobe PixelBender技術中心文章:
Adobe PixelBender Toolkit2內含說明文件

3 則留言: