Java – How do I use ScriptIntrinsic3DLUT with .cube files?

How do I use ScriptIntrinsic3DLUT with .cube files?… here is a solution to the problem.

How do I use ScriptIntrinsic3DLUT with .cube files?

First of all, I am not familiar with image processing in Android. I have a .cube file “generated by Resolve”, i.e. LUT_3D_SIZE 33. I’m trying to use to apply a lookup table to process images. I’m assuming I should use ScriptIntrinsic3DLUT instead of, right?

I’m having trouble looking for sample code to do this, so here’s what I’m putting together so far. The problem I’m having is how do I create a distribution from my .cube file?

final RenderScript renderScript = RenderScript.create(getApplicationContext());
final ScriptIntrinsic3DLUT scriptIntrinsic3DLUT = ScriptIntrinsic3DLUT.create(renderScript, Element.U8_4(renderScript));

 How to create an Allocation from .cube file?
final Allocation allocationLut = Allocation.createXXX();


Bitmap bitmapIn = selectedImage;
Bitmap bitmapOut = selectedImage.copy(bitmapIn.getConfig(),true);

Allocation aIn = Allocation.createFromBitmap(renderScript, bitmapIn);
Allocation aOut = Allocation.createTyped(renderScript, aIn.getType());


Any ideas?


Parse the .cube file

First of all, what you should do is parse the .cube file.
OpenColorIO shows how to do this in C++. It has some ways to parse LUT files like .cube, .lut, etc.
For example, FileFormatIridasCube.cpp Shows how
Process a .cube file.

You can easily pass
LUT_3D_SIZE。 I contacted an image processing algorithm engineer.
Here’s what he said:

  • In general, a cube of 17^3 is considered the highest quality output of preview, normal of 33^3, and highest quality output of 65^3.

Note that in the .cube file we can get 3*LUT_3D_SIZE^3 float.
The key point is how to handle float groups. We can’t use Allocation to set this array to a cube in ScriptIntrinsic3DLUT.
Before we can do this, we need to deal with float groups.

Process data from .cube files

For all we know, if it is 8-bit depth, each RGB component is an 8-bit int.
R is in the upper 8 bits, G is in the middle, and B is in the lower 8 bits. Such a 24-bit int could contain these
Contains three components at the same time.

In a .cube file, each data row contains 3 floats.
Please note: The blue component is in the first !!!

I came to this conclusion from trial and error. (Or who can give a more accurate explanation.) )

Each float represents the coefficient of the component by 255, so we need to calculate the real one
The value of these three components:

int getRGBColorValue(float b, float g, float r) {
    int bcol = (int) (255 * clamp(b, 0.f, 1.f));
    int gcol = (int) (255 * clamp(g, 0.f, 1.f));
    int rcol = (int) (255 * clamp(r, 0.f, 1.f));
    return bcol | (gcol << 8) | (rcol << 16);

So we can get an integer from each row of data, which contains 3 floats.
Finally, we get an array of integers with a length of LUT_3D_SIZE^3. This array is expected to be
Apply to a cube.


RsLutDemo shows how to apply ScriptIntrinsic3DLUT.

RenderScript mRs;
Bitmap mBitmap;
Bitmap mLutBitmap;
ScriptIntrinsic3DLUT mScriptlut;
Bitmap mOutputBitmap;
Allocation mAllocIn;
Allocation mAllocOut;
Allocation mAllocCube;
int redDim, greenDim, blueDim;
int[] lut;
if (mScriptlut == null) {
    mScriptlut = ScriptIntrinsic3DLUT.create(mRs, Element.U8_4(mRs));
if (mBitmap == null) {
    mBitmap = BitmapFactory.decodeResource(getResources(),

mOutputBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), mBitmap.getConfig());

mAllocIn = Allocation.createFromBitmap(mRs, mBitmap);
    mAllocOut = Allocation.createFromBitmap(mRs, mOutputBitmap);
 get the expected lut[] from .cube file.
Type.Builder tb = new Type.Builder(mRs, Element.U8_4(mRs));
Type t = tb.create();
mAllocCube = Allocation.createTyped(mRs, t);

mScriptlut.forEach(mAllocIn, mAllocOut);



I have completed a presentation showing my work.
You can view it on Github
Thank you.

Related Problems and Solutions