How to Apply Color LUT to bitmap images for filter effects in android?

和自甴很熟 提交于 2019-12-19 08:52:23

问题


here i have a question on LUTs in android.

my question is, i have 4X4 LUTs, Using these LUTs apply filter effect for bitmap image in android. Below is my sample LUT file link. Lut link sample

Is it Possible in android? if possible please help me how to apply.

Thanks in advance.


回答1:


I'm working on a LUT applier library which eases the use of LUT images in Android. It uses the algorythm below, but I'd like to enhance it in the future for optimising memory usage. Now it also guesses the color axes of the LUT: https://github.com/dntks/easyLUT/wiki

Your LUT image has the red-green-blue color dimension in an other order than what I've been used to, so I had to change the order of when getting the lutIndex (at getLutIndex()). Please check my edited answer:

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;
}



回答2:


This is how you would process an image with RenderScript's 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);
        }
    }
}



回答3:


u can go through this, hope it will help you to get the right process.

photo is the main bitmap here.

mLut3D is the array of LUT images stored in drawable

    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;
    }

you increase the mFilter value to get different filter effect with different LUT images, you have, check it out.

you can go through the this link on github for more help, i got the answer from here:- https://github.com/RenderScript/RsLutDemo

hope it will help



来源:https://stackoverflow.com/questions/32905539/how-to-apply-color-lut-to-bitmap-images-for-filter-effects-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!