--*************************************************************************
-- @Version: 0.3
-- @Author Valentin Schmidt
-- @Created 2014-06-11
-- @Modified 2014-06-13
--
-- @Description
-- This script allows to load image files and apply filters on them, including shader filters.
-- Operation mode is asynchronous, result is passed to previously specified callback (as lingo image object).
--
-- @Dependencies
-- Script needs to be attached to (empty) flash 10+ sprite
--
-- @History
--
-- v0.1
-- First version
--
-- v0.2
-- filter handling fixed, filters now applied explicitely on bitmapData object
-- new public method "addFilter" added
--
-- v0.3
-- addFilter now returns a filterID (integer) that can be used to get a reference to the flash filterObject using
-- the new function getFilter(filterID), and to remove the filter using the new function removeFilter(filterID).
-- Such a filterID is also passed to the shaderCallback (or false in case of failure).
--
--**************************************************************************
property pFlashSprite
property pFileRef
property pLoader
property pFileFilterList
property pBitmapFilters
-- callbacks
property pImageCbHandler
property pImageCbTarget
property pShaderCbHandler
property pShaderCbTarget
--**************************************
-- PUBLIC API
--**************************************
----------------------------------------
-- Specify a callback that is called when the shader file was loaded
-- @param symbol tCbHandler (=shaderCallback)
-- @param object tCbTarget (optional)
----------------------------------------
on setShaderCallback (me, tCbHandler, tCbTarget)
if voidP(tCbTarget) then tCbTarget = _movie
pShaderCbHandler = tCbHandler
pShaderCbTarget = tCbTarget
end
----------------------------------------
-- Callback passed to setShaderCallback
-- @callback shaderCallback
-- @param integer filterID Value>=0 or 0 in case of failure
----------------------------------------
----------------------------------------
-- Load a binary shader file (*.pbj)
-- @param string tShaderFile Full path to shader file
----------------------------------------
on loadShaderFile (me, tShaderFile)
loader = pFlashSprite.newObject("flash.net.URLLoader")
loader.dataFormat = "binary"
loader.addEventListener("complete", pFlashSprite.newProxyCallback(#pbjFileLoaded, me))
loader.addEventListener("ioError", pFlashSprite.newProxyCallback(#pbjFileError, me))
req = pFlashSprite.newObject("flash.net.URLRequest", tShaderFile)
loader.load(req)
end
----------------------------------------
-- Specify a callback that is called when the image file was loaded
-- @param symbol tCbHandler (=imageCallback)
-- @param object tCbTarget (optional)
----------------------------------------
on setImageCallback (me, tCbHandler, tCbTarget)
if voidP(tCbTarget) then tCbTarget = _movie
pImageCbHandler = tCbHandler
pImageCbTarget = tCbTarget
end
----------------------------------------
-- Callback passed to setImageCallback
-- @callback imageCallback
-- @param image|void loadedImage (VOID in case of failure)
----------------------------------------
----------------------------------------
-- Let user browse for input image
-- @return boolean success
----------------------------------------
on browseForImageFile (me)
if voidP(pImageCbHandler) then
put "Error: no callback specified yet!"
return false
end if
pFileRef.browse(pFileFilterList)
return true
end
----------------------------------------
-- Load the specified image file (*.jpg,*.png,*.gif)
-- @param string tImageFile Full path to image file
-- @return boolean success
----------------------------------------
on loadImageFile (me, tImageFile)
if voidP(pImageCbHandler) then
put "Error: no callback specified yet!"
return false
end if
loader = pFlashSprite.newObject("flash.net.URLLoader")
loader.dataFormat = "binary"
loader.addEventListener("complete", pFlashSprite.newProxyCallback(#imageFileLoaded, me))
loader.addEventListener("ioError", pFlashSprite.newProxyCallback(#imageFileError, me))
req = pFlashSprite.newObject("flash.net.URLRequest", tImageFile)
loader.load(req)
return true
end
----------------------------------------
-- Add a flash bitmap filter that is automatically applied to loaded images
-- @param string tFilterName Supported FilterNames are:
-- BevelFilter, BlurFilter, ColorMatrixFilter, ConvolutionFilter, DisplacementMapFilter,
-- DropShadowFilter, GlowFilter, GradientBevelFilter, GradientGlowFilter, ShaderFilter
-- @param propList tProps Properties are filter specific, see AS3 docs
-- @return integer filterID
----------------------------------------
on addFilter (me, tFilterName, tProps)
tFilter = pFlashSprite.newObject("flash.filters."&tFilterName)
if not voidP(tProps) then
cnt = tProps.count
repeat with i = 1 to cnt
p = string(tProps.getPropAt(i))
v = tProps[i]
tFilter[p] = v
end repeat
end if
pBitmapFilters.add(tFilter)
return pBitmapFilters.count
end
----------------------------------------
-- Removes a filter (specified by previously returned filterID) from the list
-- @param integer filterID
-- @return boolean success
----------------------------------------
on removeFilter (me, tFilterID)
if tFilterID<1 OR tFilterID>pBitmapFilters.count then return false
pBitmapFilters[tFilterID] = VOID
return true
end
----------------------------------------
-- Returns a flash bitmapFilter object (specified by previously returned filterID)
-- @param integer filterID
-- @return object filter
----------------------------------------
on getFilter (me, tFilterID)
if tFilterID>0 AND tFilterID<=pBitmapFilters.count then
return pBitmapFilters[tFilterID]
end if
end
--**************************************
-- PRIVATE
--**************************************
----------------------------------------
--
----------------------------------------
on beginsprite (me)
pFlashSprite = sprite(me.spriteNum)
pFileRef = pFlashSprite.newObject("flash.net.FileReference")
pFileRef.addEventListener("select", pFlashSprite.newProxyCallback(#imageFileSelected, me))
pFileRef.addEventListener("complete", pFlashSprite.newProxyCallback(#imageFileLoaded, me))
tFileFilter = pFlashSprite.newObject("flash.net.FileFilter", "Images", "*.jpg;*.gif;*.png")
pFileFilterList = pFlashSprite.newObject("Array", tFileFilter)
pLoader = pFlashSprite.newObject("flash.display.Loader")
pLoader.contentLoaderInfo.addEventListener("complete", pFlashSprite.newProxyCallback(#bytesLoaded, me))
pBitmapFilters = []
end
----------------------------------------
--
----------------------------------------
on pbjFileLoaded (me, evt)
--put "pbjFileLoaded", evt.toString()
tShader = pFlashSprite.newObject("flash.display.Shader")
tShaderFilter = pFlashSprite.newObject("flash.filters.ShaderFilter")
tShader.byteCode = evt.target.data
tShaderFilter.shader = tShader
pBitmapFilters.add(tShaderFilter)
if not voidP(pShaderCbHandler) then
call(pShaderCbHandler, pShaderCbTarget, pBitmapFilters.count)
end if
end
----------------------------------------
--
----------------------------------------
on pbjFileError (me, evt)
--put "pbjFileError", evt.toString()
if not voidP(pShaderCbHandler) then
call(pShaderCbHandler, pShaderCbTarget, false)
end if
end
----------------------------------------
--
----------------------------------------
on imageFileSelected (me, evt)
--put "imageFileSelected", evt.toString()
pFileRef.load()
end
----------------------------------------
--
----------------------------------------
on imageFileLoaded (me, evt)
--put "imageFileLoaded", evt.toString()
tFlashByteArray = evt.target.data
pLoader.loadBytes(tFlashByteArray)
end
----------------------------------------
--
----------------------------------------
on imageFileError (me, evt)
--put "imageFileError", evt.toString()
call(pImageCbHandler, pImageCbTarget, void)
end
----------------------------------------
--
----------------------------------------
on bytesLoaded (me, evt)
--put "bytesLoaded", evt.toString()
tBmpData = pLoader.content.bitmapData
-- limitation still in effect in current director versions?
w_max = 4095
h_max = 4095
w = tBmpData.width
h = tBmpData.height
r = pFlashSprite.newObject("flash.geom.Rectangle", 0, 0, w, h)
p = pFlashSprite.newObject("flash.geom.Point", 0, 0)
-- apply all filters in list
repeat with tFilter in pBitmapFilters
if not voidP(tFilter) then
tBmpData.applyFilter(tBmpData, r, p, tFilter)
end if
end repeat
if w>w_max OR h>h_max then -- image too big for director => scale
mw = w_max / w
mh = h_max / h
if mw < mh then
ratio = mw
w_new = w_max
h_new = h * ratio
else
ratio = mh
h_new = h_max
w_new = w * ratio
end if
m = pFlashSprite.newObject("flash.geom.Matrix")
m.scale(ratio, ratio)
tBmpDataCopy = pFlashSprite.newObject("flash.display.BitmapData", w_new, h_new, false)
tBmpDataCopy.draw(tBmpData, m, void, void, void, true)
tBmpData.dispose()
img = pFlashSprite.convert(#image, tBmpDataCopy)
call(pImageCbHandler, pImageCbTarget, img)
tBmpDataCopy.dispose()
else
img = pFlashSprite.convert(#image, tBmpData)
call(pImageCbHandler, pImageCbTarget, img)
tBmpData.dispose()
end if
end