Sunday, March 24, 2013

Fast way for per pixel bitmap manipulation in HaXe NME

I'm not sure whether this is the fastest way, but the nme.Memory API is something you must know for per pixel bitmap manipulation in NME. I learned the method from the stackoverflow thread here:
http://stackoverflow.com/questions/10157787/haxe-nme-fastest-method-for-per-pixel-bitmap-manipulation
nme.Memory support both flash and cpp targets. For flash, it use the Alchemy fast memory opcodes which can greatly boost the speed.

I ported Ralph Hauwert's Alchemy lookup-table effects to NME as a simple example for showing you how to use nme.Memory API for per pixel bitmap manipulation.

The basic idea is to do everything using a ByteArray. Create a ByteArray to hold your screen buffer, select it and use the getI32/setI32 function of the nme.Memory API. One problem is when you need to use extra data, such as some texture buffer in the process, you may need another ByteArray to hold your data. Because "selecting different memory blocks in cycles may lead to a performance loss", as stated in the API's docs, the simple trick is to create a single ByteArray as the virtual RAM, and write everything into it, while store the different position variables of the data block for later use.

In my example, I use the first part of the virtual RAM ByteArray for screen buffer and the next part for holding the texture. So you can just use the "select" function only once and then get/set values from different data blocks by the position variables you stored as the offsets of the virtual RAM's addresses.

Source Code of the example:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/HXFastBitmapData
Binary:  
(Win-32)https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/HXFastBitmapData/bin/w32-bin.zip
(Flash)https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/HXFastBitmapData/bin/HXFastBitmapData.swf 

For pure AS3 projects, the Azoth tool also provides similar memory API for utilizing the Alchemy opcodes. If you don't want any Alchemy opcodes, you may try Vectors in AS3.

Update 2013/04/11: ASC2 now supports using fast memory opcodes in AS3.
Update 2013/05/08: Only AIR SDK 3.6 support those fast opcodes, the latest SDK 3.7 won't compile. You can download the SDK 3.6 here:
http://helpx.adobe.com/air/kb/archived-air-sdk-version.html
http://helpx.adobe.com/flash-player/release-note/fp_116_air_36_release_notes.html

Update 2013/05/07: This method also works on Android platform:
Try this pre-build apk:
https://flaswf.googlecode.com/svn/trunk/flaswfblog/Tutorials/HXFastBitmapData/bin/HXFastBitmapData-debug.apk

Note: When compiling for Android, run "nme setup android" first, you will install Android SDK, Android NDK, Apache ANT and Java SDK.Then open Android SDK manager and install Android 2.2 (API 8), otherwise you may encounter the "Unable to resolve target 'android-8'" problem:
http://www.nme.io/community/forums/installing-nme/unable-to-resolve-target-android-8/

Links:
http://haxe.org/api/flash/memory
http://www.nme.io/api/types/nme/Memory.html
http://stackoverflow.com/questions/10157787/haxe-nme-fastest-method-for-per-pixel-bitmap-manipulation
FlasCC version of the example: http://bruce-lab.blogspot.com/2012/12/migrating-from-alchemy-to-flascc.html
http://philippe.elsass.me/2010/05/as3-fast-memory-access-without-alchemy/
Compile AS3 Fast Memory Opcodes by ASC2:
http://obtw.wordpress.com/2013/04/03/making-bytearray-faster/

TIPS: There is no good tools for auto-formatting HaXe source code as far as I know. (FlashDevelop only supports AS3 formatting.) So I use Emacs. First rename the XXX.hx file to XXX.java, open it in Emacs, C-x h (M-x mark-whole-buffer) C-M-\ (M-x indent-region), rename it back to XXX.hx, that's it.

Sponsors