android 如何将颜色 LUT 应用到位图图像以实现滤镜效果?
How to Apply Color LUT to bitmap images for filter effects in android?
这里我有一个关于 android 中 LUT 的问题。
我的问题是,我有 4X4 LUT,使用这些 LUT 对 android 中的位图图像应用滤镜效果。下面是我的示例 LUT 文件 link。
Lut link sample
android可以吗?如果可以请帮我看看如何申请。
提前致谢。
这就是您使用 RenderScript 的 ScriptIntrinsic3DLUT 处理图像的方式
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsic3DLUT;
import android.renderscript.Type;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
ImageView imageView1;
RenderScript mRs;
Bitmap mBitmap;
Bitmap mLutBitmap;
ScriptIntrinsic3DLUT mScriptlut;
Bitmap mOutputBitmap;
Allocation mAllocIn;
Allocation mAllocOut;
Allocation mAllocCube;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView1 = (ImageView) findViewById(R.id.imageView);
mRs = RenderScript.create(this);
Background background = new Background();
background.execute();
}
class Background extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
if (mRs == null) {
mRs = RenderScript.create(MainActivity.this);
}
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);
}
if (mLutBitmap == null) {
mLutBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.dawizfe);
int w = mLutBitmap.getWidth();
int h = mLutBitmap.getHeight();
int redDim = w / 4;
int greenDim = h / 4;
int blueDim = 16;
android.renderscript.Type.Builder tb = new Type.Builder(mRs, Element.U8_4(mRs));
tb.setX(redDim);
tb.setY(greenDim);
tb.setZ(blueDim);
Type t = tb.create();
mAllocCube = Allocation.createTyped(mRs, t);
int[] pixels = new int[w * h];
int[] lut = new int[w * h];
mLutBitmap.getPixels(pixels, 0, w, 0, 0, w, h);
int i = 0;
for (int r = 0; r < redDim; r++) {
for (int g = 0; g < greenDim; g++) {
for (int b = 0; b < blueDim; b++) {
int gdown = g / 4;
int gright = g % 4;
lut[i] = pixels[b + r * w + gdown * w * redDim + gright * blueDim];
i++;
}
}
}
// This is an identity 3D LUT
// i = 0;
// for (int r = 0; r < redDim; r++) {
// for (int g = 0; g < greenDim; g++) {
// for (int b = 0; b < blueDim; b++) {
// int bcol = (b * 255) / blueDim;
// int gcol = (g * 255) / greenDim;
// int rcol = (r * 255) / redDim;
// lut[i] = bcol | (gcol << 8) | (rcol << 16);
// i++;
// }
// }
// }
mAllocCube.copyFromUnchecked(lut);
}
if (mScriptlut == null) {
mScriptlut = ScriptIntrinsic3DLUT.create(mRs, Element.U8_4(mRs));
}
mScriptlut.setLUT(mAllocCube);
mScriptlut.forEach(mAllocIn, mAllocOut);
mAllocOut.copyTo(mOutputBitmap);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
imageView1.setImageBitmap(mOutputBitmap);
}
}
}
我正在开发一个 LUT 应用程序库,它可以简化 Android 中 LUT 图像的使用。它使用下面的算法,但我想在未来增强它以优化内存使用。现在它也猜测 LUT 的颜色轴:
https://github.com/dntks/easyLUT/wiki
您的 LUT 图像的红-绿-蓝颜色维度与我习惯的顺序不同,所以我不得不更改获取 lutIndex 时的顺序(在 getLutIndex()
) .
请检查我编辑过的答案:
final static int X_DEPTH = 16;
final static int Y_DEPTH = 16; //One little square has 16x16 pixels in it
final static int ROW_DEPTH = 4;
final static int COLUMN_DEPTH = 4; // the image consists of 4x4 little squares
final static int COLOR_DISTORTION = 16; // 256*256*256 => 256 no distortion, 64*64*64 => 256 dividied by 4 = 64, 16x16x16 => 256 dividied by 16 = 16
private Bitmap applyLutToBitmap(Bitmap src, Bitmap lutBitmap) {
int lutWidth = lutBitmap.getWidth();
int lutColors[] = new int[lutWidth * lutBitmap.getHeight()];
lutBitmap.getPixels(lutColors, 0, lutWidth, 0, 0, lutWidth, lutBitmap.getHeight());
int mWidth = src.getWidth();
int mHeight = src.getHeight();
int[] pix = new int[mWidth * mHeight];
src.getPixels(pix, 0, mWidth, 0, 0, mWidth, mHeight);
int R, G, B;
for (int y = 0; y < mHeight; y++)
for (int x = 0; x < mWidth; x++) {
int index = y * mWidth + x;
int r = ((pix[index] >> 16) & 0xff) / COLOR_DISTORTION;
int g = ((pix[index] >> 8) & 0xff) / COLOR_DISTORTION;
int b = (pix[index] & 0xff) / COLOR_DISTORTION;
int lutIndex = getLutIndex(lutWidth, r, g, b);
R = ((lutColors[lutIndex] >> 16) & 0xff);
G = ((lutColors[lutIndex] >> 8) & 0xff);
B = ((lutColors[lutIndex]) & 0xff);
pix[index] = 0xff000000 | (R << 16) | (G << 8) | B;
}
Bitmap filteredBitmap = Bitmap.createBitmap(mWidth, mHeight, src.getConfig());
filteredBitmap.setPixels(pix, 0, mWidth, 0, 0, mWidth, mHeight);
return filteredBitmap;
}
//the magic happens here
private int getLutIndex(int lutWidth, int redDepth, int greenDepth, int blueDepth) {
int lutX = (greenDepth % ROW_DEPTH) * X_DEPTH + blueDepth;
int lutY = (greenDepth / COLUMN_DEPTH) * Y_DEPTH + redDepth;
return lutY * lutWidth + lutX;
}
你可以通过这个,希望它能帮助你获得正确的过程。
照片是这里的主要位图。
mLut3D是存储在drawable中的LUT图片数组
RenderScript mRs;
Bitmap mLutBitmap, mBitmap;
ScriptIntrinsic3DLUT mScriptlut;
Bitmap mOutputBitmap;
Allocation mAllocIn;
Allocation mAllocOut;
Allocation mAllocCube;
int mFilter = 0;
mRs = RenderScript.create(yourActivity.this);
public Bitmap filterapply() {
int redDim, greenDim, blueDim;
int w, h;
int[] lut;
if (mScriptlut == null) {
mScriptlut = ScriptIntrinsic3DLUT.create(mRs, Element.U8_4(mRs));
}
if (mBitmap == null) {
mBitmap = photo;
}
mOutputBitmap = Bitmap.createBitmap(mBitmap.getWidth(),
mBitmap.getHeight(), mBitmap.getConfig());
mAllocIn = Allocation.createFromBitmap(mRs, mBitmap);
mAllocOut = Allocation.createFromBitmap(mRs, mOutputBitmap);
// }
mLutBitmap = BitmapFactory.decodeResource(getResources(),
mLut3D[mFilter]);
w = mLutBitmap.getWidth();
h = mLutBitmap.getHeight();
redDim = w / h;
greenDim = redDim;
blueDim = redDim;
int[] pixels = new int[w * h];
lut = new int[w * h];
mLutBitmap.getPixels(pixels, 0, w, 0, 0, w, h);
int i = 0;
for (int r = 0; r < redDim; r++) {
for (int g = 0; g < greenDim; g++) {
int p = r + g * w;
for (int b = 0; b < blueDim; b++) {
lut[i++] = pixels[p + b * h];
}
}
}
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);
return mOutputBitmap;
}
你调大mFilter的值,不同的LUT图片得到不同的滤镜效果,你有,看看。
您可以在 github 上查看此 link 以获得更多帮助,我从这里得到了答案:-
https://github.com/RenderScript/RsLutDemo
希望对您有所帮助
这里我有一个关于 android 中 LUT 的问题。
我的问题是,我有 4X4 LUT,使用这些 LUT 对 android 中的位图图像应用滤镜效果。下面是我的示例 LUT 文件 link。 Lut link sample
android可以吗?如果可以请帮我看看如何申请。
提前致谢。
这就是您使用 RenderScript 的 ScriptIntrinsic3DLUT 处理图像的方式
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsic3DLUT;
import android.renderscript.Type;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
ImageView imageView1;
RenderScript mRs;
Bitmap mBitmap;
Bitmap mLutBitmap;
ScriptIntrinsic3DLUT mScriptlut;
Bitmap mOutputBitmap;
Allocation mAllocIn;
Allocation mAllocOut;
Allocation mAllocCube;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView1 = (ImageView) findViewById(R.id.imageView);
mRs = RenderScript.create(this);
Background background = new Background();
background.execute();
}
class Background extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
if (mRs == null) {
mRs = RenderScript.create(MainActivity.this);
}
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);
}
if (mLutBitmap == null) {
mLutBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.dawizfe);
int w = mLutBitmap.getWidth();
int h = mLutBitmap.getHeight();
int redDim = w / 4;
int greenDim = h / 4;
int blueDim = 16;
android.renderscript.Type.Builder tb = new Type.Builder(mRs, Element.U8_4(mRs));
tb.setX(redDim);
tb.setY(greenDim);
tb.setZ(blueDim);
Type t = tb.create();
mAllocCube = Allocation.createTyped(mRs, t);
int[] pixels = new int[w * h];
int[] lut = new int[w * h];
mLutBitmap.getPixels(pixels, 0, w, 0, 0, w, h);
int i = 0;
for (int r = 0; r < redDim; r++) {
for (int g = 0; g < greenDim; g++) {
for (int b = 0; b < blueDim; b++) {
int gdown = g / 4;
int gright = g % 4;
lut[i] = pixels[b + r * w + gdown * w * redDim + gright * blueDim];
i++;
}
}
}
// This is an identity 3D LUT
// i = 0;
// for (int r = 0; r < redDim; r++) {
// for (int g = 0; g < greenDim; g++) {
// for (int b = 0; b < blueDim; b++) {
// int bcol = (b * 255) / blueDim;
// int gcol = (g * 255) / greenDim;
// int rcol = (r * 255) / redDim;
// lut[i] = bcol | (gcol << 8) | (rcol << 16);
// i++;
// }
// }
// }
mAllocCube.copyFromUnchecked(lut);
}
if (mScriptlut == null) {
mScriptlut = ScriptIntrinsic3DLUT.create(mRs, Element.U8_4(mRs));
}
mScriptlut.setLUT(mAllocCube);
mScriptlut.forEach(mAllocIn, mAllocOut);
mAllocOut.copyTo(mOutputBitmap);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
imageView1.setImageBitmap(mOutputBitmap);
}
}
}
我正在开发一个 LUT 应用程序库,它可以简化 Android 中 LUT 图像的使用。它使用下面的算法,但我想在未来增强它以优化内存使用。现在它也猜测 LUT 的颜色轴: https://github.com/dntks/easyLUT/wiki
您的 LUT 图像的红-绿-蓝颜色维度与我习惯的顺序不同,所以我不得不更改获取 lutIndex 时的顺序(在 getLutIndex()
) .
请检查我编辑过的答案:
final static int X_DEPTH = 16;
final static int Y_DEPTH = 16; //One little square has 16x16 pixels in it
final static int ROW_DEPTH = 4;
final static int COLUMN_DEPTH = 4; // the image consists of 4x4 little squares
final static int COLOR_DISTORTION = 16; // 256*256*256 => 256 no distortion, 64*64*64 => 256 dividied by 4 = 64, 16x16x16 => 256 dividied by 16 = 16
private Bitmap applyLutToBitmap(Bitmap src, Bitmap lutBitmap) {
int lutWidth = lutBitmap.getWidth();
int lutColors[] = new int[lutWidth * lutBitmap.getHeight()];
lutBitmap.getPixels(lutColors, 0, lutWidth, 0, 0, lutWidth, lutBitmap.getHeight());
int mWidth = src.getWidth();
int mHeight = src.getHeight();
int[] pix = new int[mWidth * mHeight];
src.getPixels(pix, 0, mWidth, 0, 0, mWidth, mHeight);
int R, G, B;
for (int y = 0; y < mHeight; y++)
for (int x = 0; x < mWidth; x++) {
int index = y * mWidth + x;
int r = ((pix[index] >> 16) & 0xff) / COLOR_DISTORTION;
int g = ((pix[index] >> 8) & 0xff) / COLOR_DISTORTION;
int b = (pix[index] & 0xff) / COLOR_DISTORTION;
int lutIndex = getLutIndex(lutWidth, r, g, b);
R = ((lutColors[lutIndex] >> 16) & 0xff);
G = ((lutColors[lutIndex] >> 8) & 0xff);
B = ((lutColors[lutIndex]) & 0xff);
pix[index] = 0xff000000 | (R << 16) | (G << 8) | B;
}
Bitmap filteredBitmap = Bitmap.createBitmap(mWidth, mHeight, src.getConfig());
filteredBitmap.setPixels(pix, 0, mWidth, 0, 0, mWidth, mHeight);
return filteredBitmap;
}
//the magic happens here
private int getLutIndex(int lutWidth, int redDepth, int greenDepth, int blueDepth) {
int lutX = (greenDepth % ROW_DEPTH) * X_DEPTH + blueDepth;
int lutY = (greenDepth / COLUMN_DEPTH) * Y_DEPTH + redDepth;
return lutY * lutWidth + lutX;
}
你可以通过这个,希望它能帮助你获得正确的过程。
照片是这里的主要位图。
mLut3D是存储在drawable中的LUT图片数组
RenderScript mRs;
Bitmap mLutBitmap, mBitmap;
ScriptIntrinsic3DLUT mScriptlut;
Bitmap mOutputBitmap;
Allocation mAllocIn;
Allocation mAllocOut;
Allocation mAllocCube;
int mFilter = 0;
mRs = RenderScript.create(yourActivity.this);
public Bitmap filterapply() {
int redDim, greenDim, blueDim;
int w, h;
int[] lut;
if (mScriptlut == null) {
mScriptlut = ScriptIntrinsic3DLUT.create(mRs, Element.U8_4(mRs));
}
if (mBitmap == null) {
mBitmap = photo;
}
mOutputBitmap = Bitmap.createBitmap(mBitmap.getWidth(),
mBitmap.getHeight(), mBitmap.getConfig());
mAllocIn = Allocation.createFromBitmap(mRs, mBitmap);
mAllocOut = Allocation.createFromBitmap(mRs, mOutputBitmap);
// }
mLutBitmap = BitmapFactory.decodeResource(getResources(),
mLut3D[mFilter]);
w = mLutBitmap.getWidth();
h = mLutBitmap.getHeight();
redDim = w / h;
greenDim = redDim;
blueDim = redDim;
int[] pixels = new int[w * h];
lut = new int[w * h];
mLutBitmap.getPixels(pixels, 0, w, 0, 0, w, h);
int i = 0;
for (int r = 0; r < redDim; r++) {
for (int g = 0; g < greenDim; g++) {
int p = r + g * w;
for (int b = 0; b < blueDim; b++) {
lut[i++] = pixels[p + b * h];
}
}
}
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);
return mOutputBitmap;
}
你调大mFilter的值,不同的LUT图片得到不同的滤镜效果,你有,看看。
您可以在 github 上查看此 link 以获得更多帮助,我从这里得到了答案:- https://github.com/RenderScript/RsLutDemo
希望对您有所帮助