Rotate and pinch image effects to zoom with GLSurfaceView Android

I was developing an application for applying effects / rotation / pinch to zoom on the image. I downloaded the demo application from https://github.com/Grishu/ImageEffects .

This works well, now my problems / questions are as follows:

  • Apply several effects to images with a stroke change value (for example, first apply the brightness effect, and as a result apply a different effect, say, โ€œcontrastโ€.)

    - problem: the code effect is always applied on the original image. Therefore, changing the code to apply the effect on the final image, for example,

    if(isApplyEffectOnOriginalImage){//call first time only mEffect.apply(mTextures[0], mImageWidth, mImageHeight, mTextures[1]); }else{ mEffect.apply(mTextures[1], mImageWidth, mImageHeight, mTextures[1]); } 

    Now, if you apply the brightness effect when changing progress for the first time, it works great. But if I apply the same or different (contrast) effect, now I think that the effect of changing progress applies to mTextures [1] and the result set in mTextures [1], so that you can create temporary mTextures [2] to store mTextures [1 ] and when the user changes the value of the execution effect to mTextures [2] and sets the result to mTextures [1], for example, occurs in the if condition.

  • How to apply a pinch to enlarge images

  • Rotation problem: I rotated the image at a 90 degree angle clockwise, just setting the values โ€‹โ€‹(90, 180, 270, etc.), but the problem is that when the image is rotated from 90 to 180, the image rendering is incorrect. cm.

A) 0 image angle

0 angle image

B) 90-angle image

90 angle image

C) 180-angle image

180 angle image

+7
android image-rotation glsurfaceview pinchzoom
source share
1 answer

I modified the Grishu demo project: here Screen recording , then some explanation: asDRF.png

(Image rotated, with three effects applied - horizontal flip, cross-process, fisheye)

1) To apply an effect on the result, your proposal works fine. I really don't understand what you mean by the effect of changing progress. "Do you want to adjust the effect parameters?

2) To have gestures, you must extend GLSurfaceView and implement GestureDetector.OnGestureListener and / or ScaleGestureDetector.OnScaleGestureListener depending on your needs. See TouchGLView here: Source or snippet below:

 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 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) You can rotate the image by changing the coordinates of the vertices and taking into account the viewports. In addition, you can apply different turns. You can rotate (and enlarge) the image (the coordinates of the vertices) directly (which does not affect the original texture buffer), or you can rotate the pixels in the texture buffer (which is easy for 90 ยฐ, 180 ยฐ, etc.), and then update vertex coordinates corresponding to the new image width / height.

Here is an example of vertex coordinate manipulation:

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

I suggest you dive into OpenGL matrices and use all these transformations using them.

I changed the TextureRenderer class to implement GLSurfaceView.Renderer and changed renderMode to RENDERMODE_CONTINUOUSLY .

Finally, the source for the modified demo is here .

+5
source share

All Articles