package com.marshalchen.common.uimodule.imageprocessing.filter.processing; import com.marshalchen.common.uimodule.imageprocessing.filter.BasicFilter; import android.opengl.GLES20; /** * Applies an abitrary transform to the image. Allows for the image to be center or achored top left while this transform is being applied. * @author Chris Batt */ public class TransformFilter extends BasicFilter { private static final String UNIFORM_TRANSFORM_MATRIX = "u_TransformMatrix"; private static final String UNIFORM_ORTHO_MATRIX = "u_OrthoMatrix"; private int transformMatrixHandle; private int orthoMatrixHandle; private float[] transformMatrix; private float[] orthoMatrix; private boolean ignoreAspect; private boolean anchorTopLeft; public TransformFilter(float[] transformMatrix, boolean ignoreAspect, boolean anchorTopLeft) { this.transformMatrix = transformMatrix; this.ignoreAspect = ignoreAspect; this.anchorTopLeft = anchorTopLeft; } @Override protected String getVertexShader() { return "attribute vec4 "+ATTRIBUTE_POSITION+";\n" + "attribute vec2 "+ATTRIBUTE_TEXCOORD+";\n" +"uniform mat4 "+UNIFORM_ORTHO_MATRIX+";\n" +"uniform mat4 "+UNIFORM_TRANSFORM_MATRIX+";\n" + "varying vec2 "+VARYING_TEXCOORD+";\n" + "void main() {\n" + " "+VARYING_TEXCOORD+" = "+ATTRIBUTE_TEXCOORD+";\n" + " gl_Position = "+UNIFORM_TRANSFORM_MATRIX+" * vec4("+ATTRIBUTE_POSITION+".xyz, 1.0) * "+UNIFORM_ORTHO_MATRIX+";\n" + "}\n"; } @Override protected void handleSizeChange() { super.handleSizeChange(); if(ignoreAspect) { if(anchorTopLeft) { setRenderVertices(new float[]{ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, }); } loadOrthoMatrix(-1, 1, -1, 1, -1, 1); } else { float normalizedHeight = (float)getHeight() / (float)getWidth(); if(anchorTopLeft) { setRenderVertices(new float[] { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, normalizedHeight, 1.0f, normalizedHeight, }); } else { setRenderVertices(new float[] { -1.0f, -normalizedHeight, 1.0f, -normalizedHeight, -1.0f, normalizedHeight, 1.0f, normalizedHeight, }); } loadOrthoMatrix(-1, 1, (-1 * (float)getHeight()/(float)getWidth()), (1 * (float)getHeight()/(float)getWidth()), -1, 1); } } @Override protected void initShaderHandles() { super.initShaderHandles(); transformMatrixHandle = GLES20.glGetUniformLocation(programHandle, UNIFORM_TRANSFORM_MATRIX); orthoMatrixHandle = GLES20.glGetUniformLocation(programHandle, UNIFORM_ORTHO_MATRIX); } private void loadOrthoMatrix(float left, float right, float bottom, float top, float near, float far) { float r_l = right - left; float t_b = top - bottom; float f_n = far - near; float tx = - (right + left) / (right - left); float ty = - (top + bottom) / (top - bottom); float tz = - (far + near) / (far - near); float scale = 2.0f; if (anchorTopLeft) { scale = 4.0f; tx=-1.0f; ty=-1.0f; } orthoMatrix = new float[] { scale / r_l, 0f, 0f, tx, 0f, scale / t_b, 0f, ty, 0f, 0f, scale / f_n, tz, 0f, 0f, 0f, 1f }; } @Override protected void passShaderValues() { super.passShaderValues(); GLES20.glUniformMatrix4fv(transformMatrixHandle, 1, false, transformMatrix, 0); GLES20.glUniformMatrix4fv(orthoMatrixHandle, 1, false, orthoMatrix, 0); } }