Image and video filters like snapchat in android
Asked Answered
G

2

11

I am developing an application where I want the filters to be applied the way snapchat does, From what I can understand is that they are using PagerAdapter but I do not know how they are applying filters over the image or videos and it's not another image with filter applied to it. Any idea or code snippet which can do the same is highly appreciated for images and videos both and saving them too. Thanks :Dthis is what I am trying to achieve[![][1][1]

Galicia answered 13/8, 2015 at 6:42 Comment(4)
No clue whatsoever, I had given up on this but I will pick it up again. Will post a solution if I get anyGalicia
Any progress? How about the face masks? Any clue on how they record the video with the overlay? The technologies/frameworks they use?Edict
Snapchat acquired Looksery and they did what you are currently talking about. I might be able to do the filter thing, I believe I have a solution for it. But the face masks requires lot in-depth knowledge .Galicia
Hey @Edict I have answered the question. You can have a look if you still need it. :) Cheers and happy coding.Galicia
G
5

What I am doing here is overlaying two bitmaps over one another. How much either of the bitmaps should be visible is determined using the touch of the user. I have an enum for which direction the user is scrolling basically LEFT OR RIGHT and NONE. Depending on which direction the user scrolls different bitmap is applied on the current bitmap.

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    if (mCurrentScrollDirection.ordinal() == ScrollDirection.NONE.ordinal()) {
        if (distanceX > 0) {
            mCurrentScrollDirection = ScrollDirection.LEFT;
        } else {
            mCurrentScrollDirection = ScrollDirection.RIGHT;
        }
    }
    mTouchX = (int) e2.getX();
    overlayBitmaps(mTouchX);
    return false;
}

private void overlayBitmaps(int coordinateX) {

    switch (mCurrentScrollDirection) {
        case NONE: {
            //do nothing here
            break;
        }
        case LEFT: {
            overlayNextBitmap(coordinateX);
            break;
        }
        case RIGHT: {
            overlayPreviousBitmap(coordinateX);
            break;
        }
    }
}

private void overlayPreviousBitmap(int coordinateX) {
    mImageCanvas.save();

    Bitmap OSBitmap = Bitmap.createBitmap(mCurrentBitmap, coordinateX, 0, mCurrentBitmap.getWidth() - coordinateX, mCurrentBitmap.getHeight());
    mImageCanvas.drawBitmap(OSBitmap, coordinateX, 0, null);

    Bitmap FSBitmap = Bitmap.createBitmap(mPreviousBitmap, 0, 0, coordinateX, mCurrentBitmap.getHeight());
    mImageCanvas.drawBitmap(FSBitmap, 0, 0, null);

    mImageCanvas.restore();

    mCapturedImageView.setImageDrawable(new BitmapDrawable(getResources(), mResultBitmap));
}

private void overlayNextBitmap(int coordinateX) {
    mImageCanvas.save();

    Bitmap OSBitmap = Bitmap.createBitmap(mCurrentBitmap, 0, 0, coordinateX, mCurrentBitmap.getHeight());
    mImageCanvas.drawBitmap(OSBitmap, 0, 0, null);

    Bitmap FSBitmap = Bitmap.createBitmap(mNextBitmap, coordinateX, 0, mCurrentBitmap.getWidth() - coordinateX, mCurrentBitmap.getHeight());
    mImageCanvas.drawBitmap(FSBitmap, coordinateX, 0, null);

    mImageCanvas.restore();

    mCapturedImageView.setImageDrawable(new BitmapDrawable(getResources(), mResultBitmap));
}

This works quite well, I just haven't tested on low memory devices considering I could not find many :)

For complete code reference check this link out. It's my own library where you can capture images apply filters and get a callback to the calling activity. It's still work in progress.

Galicia answered 19/7, 2016 at 10:30 Comment(11)
I'm new in android, I really liked your code, and i have a simple question, what i have to do if i want to add more than three filters that exist in your project, for example if i want to add 5 filters. what should i modify in your code, i think that you know the answer can you help me please. thank you.Percheron
Add the type of filters that you want to add in 'Filters' of the file 'BitmapFilters'. Provide their Bitmap implementation and you should be good to go.Galicia
thank you @PunK l RuLz for your answer, this is what i did exactly in BitmapFilters but i'm completely confused in camera1fragment class especially in loadImageTask also in overlayPreviousBitmap and overlayNextBitmap also in shuffleBitmap, can you please provide for me all of modification that i have to do in camera1fragment class your answer are going to help me a lot, thank you very much.Percheron
I am not sure what are you confused with but drop an email and I'll gladly help you out.Galicia
I didn't found the solution yet @PunK l RuLz , what i want to achieve is really simple i just want to add filters, instead of 3 filters that exist in this project i want 6 filters. can you please modify the project and share it with me in GitHub. i'm really stuck with this problem please help ! and this is my gmail : [email protected]Percheron
Sure. Give me some time. I'll help you out.Galicia
@PunK_l_RuLz When i use your code for adding filters to images chosen from gallery, then i am getting errors 'int android.graphics.Bitmap.getWidth()' on a null object reference How to solve this?Iminourea
The code is not written in a way to handle images from Gallery. And the NPE is because the 'Bitmap' is either not created or destroyed.Galicia
Hi @PunK_l_RuLz . I figured out how to handle the NPE. Now I want to add more filters. I added type of filters in BitmapFilters and provided the Bitmap implementation too. But its not working. How to resolve this?Iminourea
I apologize for the late reply, what trouble are you facing? Create an improvement in the repo if you are still facing the same problem.Galicia
It would be helpful if you provide the steps on how to add more filters. I created a new filter. How to add it in the activity?Iminourea
R
0

An alternative solution:

Render the image onto a SurfaceTexture. Use that SurfaceTexture as an OpenGL "GL_OES_EGL_image_external" texture input into an OpenGL fragment shader. Draw a full-screen quad using this fragment shader onto a secondary SurfaceTexture. Render the secondary SurfaceTexture into a TextureView.

Getting this first part working is the difficult part. Once you've got that working, you will be able to apply different shaders to images, but not switch between them as shown in the picture. To add smooth swapping between images, render two different fragment shaders onto the secondary SurfaceTexture, using GL_SCISSOR to slice the screen in half depending on an offset value.

The main advantage of this method is that it will use significantly less memory. The bitmap can be loaded once, and after being rendered onto the SurfaceTexture once, may be discarded.

A secondary advantage of this method is that more complicated filters can be applied, and that with a little bit of extra work, you will be able to render videos as well.

If you're interested in seeing an implementation of this technique (which includes video filtering as well), check out the Kfilter library for photo and video filtering/processing.

Rouen answered 25/1, 2018 at 10:38 Comment(1)
Let me know how you go, I'm interested on feedback for this library.Rouen

© 2022 - 2024 — McMap. All rights reserved.