## 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 android.support.v8.renderscript.ScriptIntrinsic3DLUT to apply a lookup table to process images. I’m assuming I should use ScriptIntrinsic3DLUT instead of android.support.v8.renderscript.ScriptIntrinsicLUT, 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();
scriptIntrinsic3DLUT.setLUT(allocationLut);
Bitmap bitmapIn = selectedImage;
Bitmap bitmapOut = selectedImage.copy(bitmapIn.getConfig(),true);
Allocation aIn = Allocation.createFromBitmap(renderScript, bitmapIn);
Allocation aOut = Allocation.createTyped(renderScript, aIn.getType());
aOut.copyTo(bitmapOut);
imageView.setImageBitmap(bitmapOut);
...
```

Any ideas?

### Solution

## 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.

## ScriptIntrinsic3DLUT

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(),
R.drawable.bugs);
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));
tb.setX(redDim).setY(greenDim).setZ(blueDim);
Type t = tb.create();
mAllocCube = Allocation.createTyped(mRs, t);
mAllocCube.copyFromUnchecked(lut);
mScriptlut.setLUT(mAllocCube);
mScriptlut.forEach(mAllocIn, mAllocOut);
mAllocOut.copyTo(mOutputBitmap);
```

## Demo

I have completed a presentation showing my work.

You can view it on Github

Thank you.