1. --*************************************************************************
  2. -- @Version: 0.3
  3. -- @Author Valentin Schmidt
  4. -- @Created 2014-06-11
  5. -- @Modified 2014-06-13
  6. --
  7. -- @Description
  8. -- This script allows to load image files and apply filters on them, including shader filters.
  9. -- Operation mode is asynchronous, result is passed to previously specified callback (as lingo image object).
  10. --
  11. -- @Dependencies
  12. -- Script needs to be attached to (empty) flash 10+ sprite
  13. --
  14. -- @History
  15. --
  16. -- v0.1
  17. -- First version
  18. --
  19. -- v0.2
  20. -- filter handling fixed, filters now applied explicitely on bitmapData object
  21. -- new public method "addFilter" added
  22. --
  23. -- v0.3
  24. -- addFilter now returns a filterID (integer) that can be used to get a reference to the flash filterObject using
  25. -- the new function getFilter(filterID), and to remove the filter using the new function removeFilter(filterID).
  26. -- Such a filterID is also passed to the shaderCallback (or false in case of failure).
  27. --
  28. --**************************************************************************
  29.  
  30. property pFlashSprite
  31. property pFileRef
  32. property pLoader
  33. property pFileFilterList
  34. property pBitmapFilters
  35.  
  36. -- callbacks
  37. property pImageCbHandler
  38. property pImageCbTarget
  39.  
  40. property pShaderCbHandler
  41. property pShaderCbTarget
  42.  
  43.  
  44. --**************************************
  45. -- PUBLIC API
  46. --**************************************
  47.  
  48. ----------------------------------------
  49. -- Specify a callback that is called when the shader file was loaded
  50. -- @param symbol tCbHandler (=shaderCallback)
  51. -- @param object tCbTarget (optional)
  52. ----------------------------------------
  53. on setShaderCallback (me, tCbHandler, tCbTarget)
  54.   if voidP(tCbTarget) then tCbTarget = _movie
  55.   pShaderCbHandler = tCbHandler
  56.   pShaderCbTarget = tCbTarget
  57. end
  58.  
  59. ----------------------------------------
  60. -- Callback passed to setShaderCallback
  61. -- @callback shaderCallback
  62. -- @param integer filterID Value>=0 or 0 in case of failure
  63. ----------------------------------------
  64.  
  65. ----------------------------------------
  66. -- Load a binary shader file (*.pbj)
  67. -- @param string tShaderFile Full path to shader file
  68. ----------------------------------------
  69. on loadShaderFile (me, tShaderFile)
  70.   loader = pFlashSprite.newObject("flash.net.URLLoader")
  71.   loader.dataFormat = "binary"
  72.   loader.addEventListener("complete", pFlashSprite.newProxyCallback(#pbjFileLoaded, me))
  73.   loader.addEventListener("ioError", pFlashSprite.newProxyCallback(#pbjFileError, me))
  74.   req = pFlashSprite.newObject("flash.net.URLRequest", tShaderFile)
  75.   loader.load(req)
  76. end
  77.  
  78. ----------------------------------------
  79. -- Specify a callback that is called when the image file was loaded
  80. -- @param symbol tCbHandler (=imageCallback)
  81. -- @param object tCbTarget (optional)
  82. ----------------------------------------
  83. on setImageCallback (me, tCbHandler, tCbTarget)
  84.   if voidP(tCbTarget) then tCbTarget = _movie
  85.   pImageCbHandler = tCbHandler
  86.   pImageCbTarget = tCbTarget
  87. end
  88.  
  89. ----------------------------------------
  90. -- Callback passed to setImageCallback
  91. -- @callback imageCallback
  92. -- @param image|void loadedImage (VOID in case of failure)
  93. ----------------------------------------
  94.  
  95. ----------------------------------------
  96. -- Let user browse for input image
  97. -- @return boolean success
  98. ----------------------------------------
  99. on browseForImageFile (me)
  100.   if voidP(pImageCbHandler) then
  101.     put "Error: no callback specified yet!"
  102.     return false
  103.   end if
  104.   pFileRef.browse(pFileFilterList)
  105.   return true
  106. end
  107.  
  108. ----------------------------------------
  109. -- Load the specified image file (*.jpg,*.png,*.gif)
  110. -- @param string tImageFile Full path to image file
  111. -- @return boolean success
  112. ----------------------------------------
  113. on loadImageFile (me, tImageFile)
  114.   if voidP(pImageCbHandler) then
  115.     put "Error: no callback specified yet!"
  116.     return false
  117.   end if
  118.   loader = pFlashSprite.newObject("flash.net.URLLoader")
  119.   loader.dataFormat = "binary"
  120.   loader.addEventListener("complete", pFlashSprite.newProxyCallback(#imageFileLoaded, me))
  121.   loader.addEventListener("ioError", pFlashSprite.newProxyCallback(#imageFileError, me))
  122.   req = pFlashSprite.newObject("flash.net.URLRequest", tImageFile)
  123.   loader.load(req)
  124.   return true
  125. end
  126.  
  127. ----------------------------------------
  128. -- Add a flash bitmap filter that is automatically applied to loaded images
  129. -- @param string tFilterName Supported FilterNames are:
  130. --     BevelFilter, BlurFilter, ColorMatrixFilter, ConvolutionFilter, DisplacementMapFilter,
  131. --     DropShadowFilter, GlowFilter, GradientBevelFilter, GradientGlowFilter, ShaderFilter
  132. -- @param propList tProps Properties are filter specific, see AS3 docs
  133. -- @return integer filterID
  134. ----------------------------------------
  135. on addFilter (me, tFilterName, tProps)
  136.   tFilter = pFlashSprite.newObject("flash.filters."&tFilterName)
  137.   if not voidP(tProps) then
  138.     cnt = tProps.count
  139.     repeat with i = 1 to cnt
  140.       p = string(tProps.getPropAt(i))
  141.       v = tProps[i]
  142.       tFilter[p] = v
  143.     end repeat
  144.   end if
  145.   pBitmapFilters.add(tFilter)
  146.   return pBitmapFilters.count
  147. end
  148.  
  149. ----------------------------------------
  150. -- Removes a filter (specified by previously returned filterID) from the list
  151. -- @param integer filterID
  152. -- @return boolean success
  153. ----------------------------------------
  154. on removeFilter (me, tFilterID)
  155.   if tFilterID<1 OR tFilterID>pBitmapFilters.count then return false
  156.   pBitmapFilters[tFilterID] = VOID
  157.   return true
  158. end
  159.  
  160. ----------------------------------------
  161. -- Returns a flash bitmapFilter object (specified by previously returned filterID)
  162. -- @param integer filterID
  163. -- @return object filter
  164. ----------------------------------------
  165. on getFilter (me, tFilterID)
  166.   if tFilterID>0 AND tFilterID<=pBitmapFilters.count then
  167.     return pBitmapFilters[tFilterID]
  168.   end if
  169. end
  170.  
  171.  
  172. --**************************************
  173. -- PRIVATE
  174. --**************************************
  175.  
  176. ----------------------------------------
  177. --
  178. ----------------------------------------
  179. on beginsprite (me)
  180.   pFlashSprite = sprite(me.spriteNum)
  181.  
  182.   pFileRef = pFlashSprite.newObject("flash.net.FileReference")
  183.   pFileRef.addEventListener("select", pFlashSprite.newProxyCallback(#imageFileSelected, me))
  184.   pFileRef.addEventListener("complete", pFlashSprite.newProxyCallback(#imageFileLoaded, me))
  185.  
  186.   tFileFilter = pFlashSprite.newObject("flash.net.FileFilter", "Images", "*.jpg;*.gif;*.png")
  187.   pFileFilterList = pFlashSprite.newObject("Array", tFileFilter)
  188.  
  189.   pLoader = pFlashSprite.newObject("flash.display.Loader")
  190.   pLoader.contentLoaderInfo.addEventListener("complete", pFlashSprite.newProxyCallback(#bytesLoaded, me))
  191.  
  192.   pBitmapFilters = []
  193. end
  194.  
  195. ----------------------------------------
  196. --
  197. ----------------------------------------
  198. on pbjFileLoaded (me, evt)
  199.   --put "pbjFileLoaded", evt.toString()
  200.   tShader = pFlashSprite.newObject("flash.display.Shader")
  201.   tShaderFilter = pFlashSprite.newObject("flash.filters.ShaderFilter")
  202.   tShader.byteCode = evt.target.data
  203.   tShaderFilter.shader = tShader
  204.   pBitmapFilters.add(tShaderFilter)
  205.   if not voidP(pShaderCbHandler) then
  206.     call(pShaderCbHandler, pShaderCbTarget, pBitmapFilters.count)
  207.   end if
  208. end
  209.  
  210. ----------------------------------------
  211. --
  212. ----------------------------------------
  213. on pbjFileError (me, evt)
  214.   --put "pbjFileError", evt.toString()
  215.   if not voidP(pShaderCbHandler) then
  216.     call(pShaderCbHandler, pShaderCbTarget, false)
  217.   end if
  218. end
  219.  
  220. ----------------------------------------
  221. --
  222. ----------------------------------------
  223. on imageFileSelected (me, evt)
  224.   --put "imageFileSelected", evt.toString()
  225.   pFileRef.load()
  226. end
  227.  
  228. ----------------------------------------
  229. --
  230. ----------------------------------------
  231. on imageFileLoaded (me, evt)
  232.   --put "imageFileLoaded", evt.toString()
  233.   tFlashByteArray = evt.target.data
  234.   pLoader.loadBytes(tFlashByteArray)
  235. end
  236.  
  237. ----------------------------------------
  238. --
  239. ----------------------------------------
  240. on imageFileError (me, evt)
  241.   --put "imageFileError", evt.toString()
  242.   call(pImageCbHandler, pImageCbTarget, void)
  243. end
  244.  
  245. ----------------------------------------
  246. --
  247. ----------------------------------------
  248. on bytesLoaded (me, evt)
  249.   --put "bytesLoaded", evt.toString()
  250.  
  251.   tBmpData = pLoader.content.bitmapData
  252.   -- limitation still in effect in current director versions?
  253.   w_max = 4095
  254.   h_max = 4095
  255.   w = tBmpData.width
  256.   h = tBmpData.height
  257.   r = pFlashSprite.newObject("flash.geom.Rectangle", 0, 0, w, h)
  258.   p = pFlashSprite.newObject("flash.geom.Point", 0, 0)
  259.  
  260.   -- apply all filters in list
  261.   repeat with tFilter in pBitmapFilters
  262.     if not voidP(tFilter) then
  263.       tBmpData.applyFilter(tBmpData, r, p, tFilter)
  264.     end if
  265.   end repeat
  266.  
  267.   if w>w_max OR h>h_max then -- image too big for director => scale
  268.     mw = w_max / w
  269.     mh = h_max / h
  270.     if mw < mh then
  271.       ratio = mw
  272.       w_new = w_max
  273.       h_new = h * ratio
  274.     else
  275.       ratio = mh
  276.       h_new = h_max
  277.       w_new = w * ratio
  278.     end if
  279.     m = pFlashSprite.newObject("flash.geom.Matrix")
  280.     m.scale(ratio, ratio)
  281.     tBmpDataCopy = pFlashSprite.newObject("flash.display.BitmapData", w_new, h_new, false)
  282.     tBmpDataCopy.draw(tBmpData, m, void, void, void, true)
  283.     tBmpData.dispose()
  284.     img = pFlashSprite.convert(#image, tBmpDataCopy)
  285.     call(pImageCbHandler, pImageCbTarget, img)
  286.     tBmpDataCopy.dispose()
  287.   else
  288.     img = pFlashSprite.convert(#image, tBmpData)
  289.     call(pImageCbHandler, pImageCbTarget, img)
  290.     tBmpData.dispose()
  291.   end if
  292. end
  293.  
[raw code]