我正在开发一个应用效果/旋转/捏缩以缩放图像功能的应用程序。我已经从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条件一样。
见
A)0角影像
B)90度影像
C)180度影像
最佳答案
我已经修改了Grishu的演示项目: here's a Screen Recording ,然后进行一些解释:
(图像旋转,并应用了三种效果-水平翻转,交叉处理, fish 眼)
1)为了对结果施加效果,您的建议可以正常工作。我真的不明白你所说的``进步改变效果''是什么意思。您要调整效果的参数吗?
2)要进行手势操作,您应该扩展GLSurfaceView
并根据需要实现GestureDetector.OnGestureListener
和/或ScaleGestureDetector.OnScaleGestureListener
。请在此处查看TouchGLView:Source或以下代码段:
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)您可以通过修改顶点坐标并考虑视口(viewport)来旋转图像。
另外,您可以应用不同的旋转。您可以旋转(和缩放) View (顶点坐标)本身(不影响原始纹理缓冲区),也可以旋转纹理缓冲区中的像素(易于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。