Friday, 26 June 2015

JPG image loaded into a test application. First converted to 32-bit float / channel, then linearized, dynamic range expanded and a quick saturation mod applied. Then dynamic range compressed back, set to gamma 2.22 and converted back to 8-bits for displaying the image using Processing's PImage. Simple.

Image editor in Processing

For the past few years I've fiddled with lots of different languages, mainly with Unity3D's javascript / C# and some really basic edits of C++ code. I never really got my hands dirty with Java but I did try out Processing a long time ago when it came out and every now and then I've tweaked a bit on some cool demos that I've come across. 

It was 2013 that I really started to look into Processing as a semi-serious development IDE as most of the stuff I would need (as an artist) is already there and the possibility to get your stuff running on Linux and Android was a major plus. I did a mockup of a drawing app for my Android tablet and the performance was top notch and the development was just so unbelievably easy that I started to really think about all the other apps I've always wanted to have. And one was my own photo editor.

And not just any photo editor, but a one where I would always know what really happens to the image data under the hood. No unnecessary conversions and keeping the data in high precision.

Also I wanted to harness the processing power of my GPU and that is very easy in Processing, just a few lines of code. But my problem for that was that 8-bits per channel is not going to cut it. I want 32-bit float processing all the way (because I'm insane). 

At the moment of writing this, Processing developers are looking into adding higher precision images to Processing, but I just thought I'd test out myself what kind of performance I can squeeze out of the code. 

If you feed normal 8-bits / channel (24-bit) images to Processing, it's just zipzap. couple of lines of code and you're on your way. But loading something that's 32-bit float / channel is a totally different matter. I had to create my own internal image format to store the data which opened another can of worms: memory. If I open an image that's 6000 x 4000 pixels, it's not a biggie if it's 8-bits / channel. But holy whopping hamburgers Batman when it's 32-bit float - my computer actually started to cough out blood.

And I want to load as many as 5-10 images and layer them together. and image sizes that are even bigger, say 7000 x 10 000 that my texture generator spits out. Holy kääk. 

And if I wanted to edit those in the GPU, well, the card has to have that much memory available to fit the images in there and blend them together or do color swapping tweaks and comparisons or whatever. 

OpenCL to the Rescue (well, almost)

All OpenCL libraries failed with similar error - they can't find the native libraries or they can't connect to the card.

So I thought that I'd use OpenCL for this as there are quite a few libraries available for Java and they all seems to perform really really well. This would give the option of not processing all the data at once but in chunks and in parallel. 

But now after two months of testing and fiddling with this, I still haven't gotten any of them to work. The only one that did work was JOCL from the Jogamp package and that only did it's own self test which printed out loads of OpenGL details about my card and said 'everything's ok, let's do it'. So it should work though. 

But even the Eclipse project setup that I followed from their pages failed. JOCL had no idea the native libraries were inside the .jar packages and cried when it couldn't find them in the project's root folder. Setting up Eclipse with JOGL

The problem with each of the libraries was that some of the API was changed so much that the examples just failed. But the most common problem was that the libraries couldn't find their native libraries which are essential.

And trying to fire up OpenCL from Processing? That's even trickier. There were some test implementations of Aparapi and JOCL for Processing that I could find but none of them worked.

To someone who does Java as their second language this would be like a 3 minute fix to see what was happening and why they don't work. I don't want to hit the Jogamp forums and complain "It doesn't work" because I can't give a clear description of what really is happening (most likely my build environment setup is wrong as this was primarily made for Android development).

It could be a gazillion things like
- The Java version I use is wrong (1.8.0_45, most stuff want 1.6)
- The Java JDK is installed wrong
- The libraries don't like the Nvidia driver or the .so that gives OpenCL the data about installed GPU's
- The AMD APP SDK that I have installed will not work with my card
- The OpenCL bindings that are installed in the OS are wrong or conflicting
- Linux Mint was not meant for this
- I'm just too stupid to use a computer

So I'm leaving OpenCL alone for the time being. I'll try to setup a new build environment that is made just for this and see if that works. 

Processing the images in 32-bit float using hardware = would be friggin awesome though. 

I thought I had a point when writing this. Just thinking out loud here and trying to come up with a solution. > . <

Back to coding. >>