//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內含說明文件
有趣
回覆刪除測試123挖是小花!
回覆刪除網誌管理員已經移除這則留言。
回覆刪除