Blog: 3D Fun with Android (2012-07-13)

Over the past week, I finally found (or rather took) the time to implement my second app for Android: AnaCam! The idea was floating around in my head already for some time (since I started experimenting with anaglyphs), and now it is done! Feel free to take a look at it, I like how you can play around with the live preview. So far, I've only tried it out in my flat (which also means that I won't provide example pictures yet since I want to have something more exciting), but hopefully will have some possibilities soon somewhere "in the wild"—I'm definitely looking forward to it!

It was however also quite "fun" to make it work. The first stumbling block for me (and also lots of others) was that the camera preview frames Android delivers, and which I use for the live preview but have to manipulate, are encoded in the YUV colour space while all the rest of Android (especially drawing) needs RGB. There is some facility available (the android.graphics.YuvImage class) to convert YUV to RGB, however only via a lot of detours of compressing the result as JPEG image, writing it to an output stream, and then loading the bitmap again.

To optimise this and also to get a usable performance of anaglyph creation for the live preview, I implemented finally some low-level image processing routines in native code. I was surprised at how easy it is to use the JNI in Android to utilise the full processing power!

And finally, Android enforces a very weird restriction on the heap size of each app. On my phone, which is already relatively old and surely on the low-end of todays Android devices, my app was only allowed to use 32 MiB of heap storage! This is ridiculously small for any modern system, and in particular given that even my device has 256 MiB memory available. Working with the camera's pictures is quite memory intensive, and so I ended up getting OutOfMemoryError's. (Note that in the mean time, Android implemented a largeHeap flag. However, this is not yet supported by my device's Android version, and thus I obviously did not make use of it.) One way out, which finally worked for me and which is described by the blog post linked at the beginning of this paragraph, is to allocate memory in native code as this does not count towards the enforced limit. Given how easy this restriction is to circumvent, it appears even more useless and silly than before, but anyways. Loading off the bitmaps to native memory (since I processed them in native code this was quite easy) and carefully null'ing every variable as soon as possible in the crucial code paths finally made it work. Still, especially this last piece about the memory limitation was really quite "fun"....


Copyright © 2011–2018 by Daniel KraftHomeContactImprint