使用GLSurfaceView Android旋转和捏缩放图像效果

时间:2014-09-10 10:33:15

标签: android image-rotation pinchzoom glsurfaceview

我正在开发一个应用程序来应用效果/旋转/捏合来放大图像的输入功能。我已经从https://github.com/Grishu/ImageEffects下载了演示应用程序。

效果很好,现在我的问题/问题如下:

  1. 对具有进度更改值的图像应用多个效果(例如,首先应用亮度效果,此结果应用另一个效果说“对比度”。)

    代码效果中的

    - 问题:始终适用于原始图像。因此,更改代码以对最终图像应用效果,例如

    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]上设置结果,就像在条件中发生一样。

  2. 如何应用捏缩放图像

  3. 旋转问题:我正在以90度角顺时针旋转图像,只需设置值(90,180,270等),但问题是当图像从90旋转到180时,图像渲染不正确。 见

  4. A)0角度图像

    0 angle image

    B)90°角度图像

    90 angle image

    C)180角度图像

    180 angle image

1 个答案:

答案 0 :(得分:5)

我修改了Grishu的演示项目: here's a Screen Recording ,然后解释一下:

(旋转图像,应用了三种效果 - 翻转水平,交叉处理,鱼眼)

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)您可以通过修改顶点坐标并将视口考虑在内来旋转图像。 此外,您可以应用不同的旋转。您可以旋转(和缩放)视图(顶点坐标)本身(不影响原始纹理缓冲区),也可以旋转纹理缓冲区中的像素(容易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