使用 GLSurfaceView Android 进行旋转和捏合缩放的图像效果
Posted
技术标签:
【中文标题】使用 GLSurfaceView Android 进行旋转和捏合缩放的图像效果【英文标题】:Image effects with rotation and pinch to zoom using GLSurfaceView Android 【发布时间】:2014-11-03 23:15:24 【问题描述】:我正在开发一个应用程序来应用效果/旋转/捏合来放大图像的功能。我已经从https://github.com/Grishu/ImageEffects下载了演示应用程序。
效果很好,现在我的问题/问题如下:
对具有进度变化值的图像应用多种效果(例如,首先应用亮度效果,然后应用另一个效果,例如“对比度”。)
- 问题: 在代码效果中始终适用于原始图像。因此,更改代码以对最终图像应用效果,例如,
if(isApplyEffectOnOriginalImage)//call first time only
mEffect.apply(mTextures[0], mImageWidth, mImageHeight, mTextures[1]);
else
mEffect.apply(mTextures[1], mImageWidth, mImageHeight, mTextures[1]);
现在,如果第一次对进度更改应用亮度效果,它可以正常工作。但是,如果我应用相同或其他(对比)效果,现在我认为进度更改效果适用于 mTextures[1] 和 mTextures[1] 中的结果集,因此可以创建临时 mTextures[2] 来存储 mTextures[ 1] 最初,当用户更改进度值时,对 mTextures[2] 应用效果并在 mTextures[1] 上设置结果,就像在 if 条件下发生的那样。
如何应用捏合缩放图像
旋转问题:我只是通过设置值(90,180,270 等)将图像顺时针旋转 90 度,但问题是当图像从 90 旋转到 180 时,图像渲染不正确。 见
A) 0 角度图像
B) 90 角图像
C) 180 度角图像
【问题讨论】:
【参考方案1】:我已经修改了 Grishu 的演示项目:here's a Screen Recording,然后是一些解释:
(图像旋转,应用了三种效果 - 水平翻转、交叉处理、鱼眼)
1) 要将效果应用于结果,您的建议效果很好。我真的不明白你的意思是什么,进度变化效果''。是否要调整效果的参数?
2) 要拥有手势,您应该扩展GLSurfaceView
并根据您的需要实现GestureDetector.OnGestureListener
和/或ScaleGestureDetector.OnScaleGestureListener
。请在此处查看 TouchGLView:Source,或下面的 sn-p:
private class TouchGLView extends GLSurfaceView
implements GestureDetector.OnGestureListener,
ScaleGestureDetector.OnScaleGestureListener
private TextureRenderer mRenderer;
private GestureDetector mTapDetector;
private ScaleGestureDetector mScaleDetector;
private float mLastSpan = 0;
TouchGLView(Context c)
super(c);
// Use android's built-in gesture detectors to detect
// which touch event the user is doing.
mTapDetector = new GestureDetector(c, this);
mTapDetector.setIsLongpressEnabled(false);
mScaleDetector = new ScaleGestureDetector(c, this);
// Create an OpenGL ES 2.0 context.
setEGLContextClientVersion(2);
mRenderer = new TextureRenderer(c);
setRenderer(mRenderer);
@Override
public boolean onTouchEvent(final MotionEvent e)
// Forward touch events to the gesture detectors.
mScaleDetector.onTouchEvent(e);
mTapDetector.onTouchEvent(e);
return true;
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
final float dx, final float dy)
// Forward the drag event to the renderer.
queueEvent(new Runnable()
public void run()
mRenderer.drag(dx, dy);
);
return true;
@Override
public boolean onScale(ScaleGestureDetector detector)
// Forward the scale event to the renderer.
final float amount = detector.getCurrentSpan() - mLastSpan;
queueEvent(new Runnable()
public void run()
mRenderer.zoom(amount);
);
mLastSpan = detector.getCurrentSpan();
return true;
...
3) 您可以通过修改顶点坐标并考虑视口来旋转图像。 此外,您可以应用 不同 旋转。您可以旋转(和缩放)视图(顶点坐标)本身(不会影响原始纹理缓冲区),也可以旋转纹理缓冲区中的像素(90°、180° 很容易)等),然后更新您的顶点坐标以匹配新的图像宽度/高度。
这是一个使用顶点坐标进行操作的示例:
private void computeOutputVertices()
if (mPosVertices != null)
float imgAspectRatio = mTexWidth / (float)mTexHeight;
float viewAspectRatio = mViewWidth / (float)mViewHeight;
float x0, y0, x1, y1;
// Set initial vertex coords based in texture aspect
if (imgAspectRatio > 1.0f)
x0 = -1.0f ;
y0 = -1.0f / imgAspectRatio;
x1 = 1.0f ;
y1 = 1.0f / imgAspectRatio;
else
x0 = -1.0f *imgAspectRatio;
y0 = -1.0f;
x1 = 1.0f *imgAspectRatio;
y1 = 1.0f;
float[] coords = new float[] x0, y0, x1, y0, x0, y1, x1, y1 ;
// Scale coordinates with mZoom
for (int i = 0; i < 8; i++)
coords[i] *= mZoom;
// Rotate coordinates with mRot
float cosa = (float)Math.cos(mRot);
float sina = (float)Math.sin(mRot);
float x,y;
for (int i = 0; i < 8; i+=2)
x = coords[i]; y = coords[i+1];
coords[i] = cosa*x-sina*y;
coords[i+1] = sina*x+cosa*y;
// Finally scale again to match screen aspect
if (viewAspectRatio > 1.0f)
for (int i = 0; i < 8; i+=2)
coords[i] = coords[i]/viewAspectRatio;
else
for (int i = 1; i < 8; i+=2)
coords[i] = coords[i]*viewAspectRatio;
mPosVertices.put(coords).position(0);
我建议您深入研究 OpenGL 矩阵并使用它们进行所有这些转换。
我已修改TextureRenderer
类以实现GLSurfaceView.Renderer
,并将renderMode 更改为RENDERMODE_CONTINUOUSLY
。
最后是source for the modified demo is here。
【讨论】:
首先感谢您的回复 1)是否可以对seekbar的进度更改应用效果?因为当我将效果从“mTextures [0]”应用到“mTextures [1]”和rander textureId“mTextures [1]”时,它第一次工作文件。第一次应用效果后,如果应用第二个效果,在搜索栏的进度更改上说“对比度”,然后效果从“mTextures [1]”应用到“mTextures [1]”并渲染textureId“mTextures [1]”。你会注意到图像会变黑。 我想如果我重用“mTextures[1]”作为新鲜纹理。将解决我的问题,但不知道如何重新使用它。 2)捏缩放:效果很好,但滚动图像的问题。任何想法? 3)旋转:效果很好。是否可以在 (90,180,270,...) 顺时针使用内置旋转效果来应用旋转。 Guys 旋转和缩放效果很好,但拖动不起作用...如何解决。以上是关于使用 GLSurfaceView Android 进行旋转和捏合缩放的图像效果的主要内容,如果未能解决你的问题,请参考以下文章
android-glsurfaceview Activity框架程序
转玩转Android Camera开发:国内首发---使用GLSurfaceView预览Camera 基础拍照demo
在 android 中使用 opengl 在 glsurfaceview 中显示 3D 模型的问题
玩转Android Camera开发:国内首发---使用GLSurfaceView预览Camera 基础拍照demo
使用 OpenGL 2.0 API 在 GLSurfaceView 上将 Android 相机预览旋转 90 度
我的OpenGL学习进阶之旅关于OpenGL ES 绘制中使用到的 Android中GLSurfaceView的两种渲染模式