android 中的图像和视频过滤器,例如 snapchat
Image and video filters like snapchat in android
我正在开发一个应用程序,我希望像 snapchat 那样应用滤镜,据我所知,他们正在使用 PagerAdapter,但我不知道他们如何对图像或视频应用滤镜,以及它不是另一个应用了滤镜的图像。对于图像和视频以及保存它们,任何可以做同样事情的想法或代码片段都会受到高度赞赏。谢谢 :D
我在这里所做的是将两个位图相互叠加。使用用户的触摸来确定应显示多少位图。我有一个枚举,用户滚动的方向基本上是向左或向右和 NONE。根据用户滚动的方向不同的位图应用于当前位图。
@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 link。这是我自己的库,您可以在其中捕获图像应用过滤器并获得对调用 activity 的回调。仍在进行中。
另一种解决方案:
将图像渲染到 SurfaceTexture 上。使用该 SurfaceTexture 作为 OpenGL "GL_OES_EGL_image_external" 纹理输入到 OpenGL 片段着色器中。使用此片段着色器在辅助 SurfaceTexture 上绘制全屏四边形。将辅助 SurfaceTexture 渲染到 TextureView。
让第一部分工作是困难的部分。完成该操作后,您将能够对图像应用不同的着色器,但不能如图所示在它们之间切换。要在图像之间添加平滑交换,请将两个不同的片段着色器渲染到辅助 SurfaceTexture 上,使用 GL_SCISSOR 根据偏移值将屏幕切成两半。
此方法的主要优点是它将使用更少的内存。位图只能加载一次,渲染到 SurfaceTexture 一次后,可能会被丢弃。
此方法的第二个优点是可以应用更复杂的滤镜,并且通过一些额外的工作,您也可以渲染视频。
如果您有兴趣查看此技术的实现(也包括视频过滤),请查看 Kfilter 照片和视频库 filtering/processing。
我正在开发一个应用程序,我希望像 snapchat 那样应用滤镜,据我所知,他们正在使用 PagerAdapter,但我不知道他们如何对图像或视频应用滤镜,以及它不是另一个应用了滤镜的图像。对于图像和视频以及保存它们,任何可以做同样事情的想法或代码片段都会受到高度赞赏。谢谢 :D
我在这里所做的是将两个位图相互叠加。使用用户的触摸来确定应显示多少位图。我有一个枚举,用户滚动的方向基本上是向左或向右和 NONE。根据用户滚动的方向不同的位图应用于当前位图。
@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 link。这是我自己的库,您可以在其中捕获图像应用过滤器并获得对调用 activity 的回调。仍在进行中。
另一种解决方案:
将图像渲染到 SurfaceTexture 上。使用该 SurfaceTexture 作为 OpenGL "GL_OES_EGL_image_external" 纹理输入到 OpenGL 片段着色器中。使用此片段着色器在辅助 SurfaceTexture 上绘制全屏四边形。将辅助 SurfaceTexture 渲染到 TextureView。
让第一部分工作是困难的部分。完成该操作后,您将能够对图像应用不同的着色器,但不能如图所示在它们之间切换。要在图像之间添加平滑交换,请将两个不同的片段着色器渲染到辅助 SurfaceTexture 上,使用 GL_SCISSOR 根据偏移值将屏幕切成两半。
此方法的主要优点是它将使用更少的内存。位图只能加载一次,渲染到 SurfaceTexture 一次后,可能会被丢弃。
此方法的第二个优点是可以应用更复杂的滤镜,并且通过一些额外的工作,您也可以渲染视频。
如果您有兴趣查看此技术的实现(也包括视频过滤),请查看 Kfilter 照片和视频库 filtering/processing。