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.