11

我正在开发一个应用程序,我希望以 snapchat 的方式应用过滤器,据我所知,他们正在使用 PagerAdapter 但我不知道他们如何在图像或视频上应用过滤器,它不是另一个图像过滤器应用到它。任何可以做到这一点的想法或代码片段都非常感谢图像和视频并保存它们。感谢:D这就是我想要实现的目标[![][1][1]

4

2 回答 2

5

我在这里所做的是将两个位图叠加在一起。使用用户的触摸来确定任一位图应该可见的程度。我有一个枚举,用户滚动的方向基本上是向左或向右和无。根据用户滚动的方向,在当前位图上应用不同的位图。

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

这很好用,我只是没有在低内存设备上测试过,因为我找不到很多:)

有关完整的代码参考,请查看链接。这是我自己的库,您可以在其中捕获图像应用过滤器并获取对调用活动的回调。它仍在进行中。

于 2016-07-19T10:30:54.407 回答
0

另一种解决方案:

将图像渲染到 SurfaceTexture。将该 SurfaceTexture 用作 OpenGL“GL_OES_EGL_image_external”纹理输入到 OpenGL 片段着色器中。使用此片段着色器在辅助 SurfaceTexture 上绘制一个全屏四边形。将辅助 SurfaceTexture 渲染到 TextureView。

让第一部分工作是困难的部分。完成该工作后,您将能够对图像应用不同的着色器,但不能如图所示在它们之间切换。要在图像之间添加平滑交换,请将两个不同的片段着色器渲染到辅助 SurfaceTexture 上,使用 GL_SCISSOR 根据偏移值将屏幕切成两半。

这种方法的主要优点是它会使用更少的内存。位图可以加载一次,在渲染到 SurfaceTexture 上一次后,可能会被丢弃。

这种方法的第二个优点是可以应用更复杂的过滤器,并且通过一些额外的工作,您也可以渲染视频。

如果您有兴趣查看此技术的实现(也包括视频过滤),请查看Kfilter库以进行照片和视频过滤/处理。

于 2018-01-25T10:38:58.237 回答