Add more docs and Filter.copy()

pull/535/head
Mattia Iavarone 6 years ago
parent e8356bb751
commit 0dbbdd0090
  1. 66
      cameraview/src/main/java/com/otaliastudios/cameraview/filters/BaseFilter.java
  2. 72
      cameraview/src/main/java/com/otaliastudios/cameraview/filters/Filter.java
  3. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/picture/SnapshotGlPictureRecorder.java
  4. 4
      cameraview/src/main/java/com/otaliastudios/cameraview/video/SnapshotVideoRecorder.java

@ -6,26 +6,34 @@ import androidx.annotation.NonNull;
import com.otaliastudios.cameraview.CameraLogger; import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.internal.GlUtils; import com.otaliastudios.cameraview.internal.GlUtils;
import com.otaliastudios.cameraview.size.Size;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
/** /**
* A Base abstract class that every effect must extend so that there is a common getShader method. * A base implementation of {@link Filter} that just leaves the fragment shader to subclasses.
* <p> * See {@link NoFilter} for a full implementation.
* This class has a default Vertex Shader implementation which in most cases not required to touch. *
* In Effects like sepia, B/W any many, only pixel color changes which can be managed by only fragment shader. * This class offers a default vertex shader implementation which in most cases is not required
* If there is some other effect which requires vertex shader also change, you can override it. * to be changed. Most effects can be rendered by simply changing the fragment shader, thus
* <p> * by overriding {@link #getFragmentShader()}.
* If your provide your own vertex and fragment shader, *
* please set the {@link #mPositionVariableName}, {@link #mTextureCoordinateVariableName}, * This class expects variable to have a certain name:
* {@link #mMVPMatrixVariableName}, {@link #mTextureMatrixVariableName} * - {@link #vertexPositionName}
* according to your shader code. * - {@link #vertexTransformMatrixName}
* <p> * - {@link #vertexModelViewProjectionMatrixName}
* Please note that these shader applies on live preview as well as pictureSnapshot and videoSnapshot, * - {@link #vertexTextureCoordinateName}
* we only support GLES11Ext.GL_TEXTURE_EXTERNAL_OES * - {@link #fragmentTextureCoordinateName}
* check EglViewport() *
* <p> * You can either change these variables, for example in your constructor, or change your
* The default implementation of this class is NoEffect. * vertex and fragment shader code to use them.
*
* NOTE - All {@link BaseFilter}s should have a no-op public constructor.
*
* NOTE - the {@link android.graphics.SurfaceTexture} restrictions apply:
* We only support the {@link android.opengl.GLES11Ext#GL_TEXTURE_EXTERNAL_OES} texture target
* and it must be specified in the fragment shader as a samplerExternalOES texture.
* You also have to explicitly require the extension: see {@link #createDefaultFragmentShader(String)}.
*/ */
public abstract class BaseFilter implements Filter { public abstract class BaseFilter implements Filter {
@ -65,6 +73,7 @@ public abstract class BaseFilter implements Filter {
+ " gl_FragColor = texture2D(sTexture, "+fragmentTextureCoordinateName+");\n" + " gl_FragColor = texture2D(sTexture, "+fragmentTextureCoordinateName+");\n"
+ "}\n"; + "}\n";
} }
// When the model/view/projection matrix is identity, this will exactly cover the viewport. // When the model/view/projection matrix is identity, this will exactly cover the viewport.
private FloatBuffer vertexPosition = GlUtils.floatBuffer(new float[]{ private FloatBuffer vertexPosition = GlUtils.floatBuffer(new float[]{
-1.0f, -1.0f, // 0 bottom left -1.0f, -1.0f, // 0 bottom left
@ -84,6 +93,7 @@ public abstract class BaseFilter implements Filter {
private int vertexTranformMatrixLocation = -1; private int vertexTranformMatrixLocation = -1;
private int vertexPositionLocation = -1; private int vertexPositionLocation = -1;
private int vertexTextureCoordinateLocation = -1; private int vertexTextureCoordinateLocation = -1;
private Size outputSize;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected String vertexPositionName = DEFAULT_VERTEX_POSITION_NAME; protected String vertexPositionName = DEFAULT_VERTEX_POSITION_NAME;
@ -126,7 +136,10 @@ public abstract class BaseFilter implements Filter {
@Override @Override
public void onDestroy(int programHandle) { public void onDestroy(int programHandle) {
// Do nothing. vertexPositionLocation = -1;
vertexTextureCoordinateLocation = -1;
vertexModelViewProjectionMatrixLocation = -1;
vertexTranformMatrixLocation = -1;
} }
@NonNull @NonNull
@ -137,7 +150,7 @@ public abstract class BaseFilter implements Filter {
@Override @Override
public void setOutputSize(int width, int height) { public void setOutputSize(int width, int height) {
outputSize = new Size(width, height);
} }
@Override @Override
@ -184,4 +197,21 @@ public abstract class BaseFilter implements Filter {
GLES20.glDisableVertexAttribArray(vertexTextureCoordinateLocation); GLES20.glDisableVertexAttribArray(vertexTextureCoordinateLocation);
} }
@Override
public BaseFilter copy() {
BaseFilter copy = onCopy();
copy.setOutputSize(outputSize.getWidth(), outputSize.getHeight());
return copy;
}
@SuppressWarnings("WeakerAccess")
protected BaseFilter onCopy() {
try {
return getClass().newInstance();
} catch (IllegalAccessException e) {
throw new RuntimeException("Filters should have a public no-op constructor.", e);
} catch (InstantiationException e) {
throw new RuntimeException("Filters should have a public no-op constructor.", e);
}
}
} }

@ -1,22 +1,82 @@
package com.otaliastudios.cameraview.filters; package com.otaliastudios.cameraview.filters;
import com.otaliastudios.cameraview.CameraView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import java.io.File;
/**
* A Filter is a real time filter that operates onto the camera preview, plus any
* snapshot media taken with {@link CameraView#takePictureSnapshot()} and
* {@link CameraView#takeVideoSnapshot(File)}.
*
* You can apply filters to the camera engine using {@link CameraView#setFilter(Filter)}.
* The default filter is called {@link NoFilter} and can be used to restore the normal preview.
* A lof of other filters are collected in the {@link Filters} class.
*
* Advanced users can create custom filters using GLES.
* It is recommended to extend {@link BaseFilter} instead of this class.
*/
public interface Filter { public interface Filter {
/**
* Returns a String containing the vertex shader.
* Together with {@link #getFragmentShader()}, this will be used to
* create the OpenGL program.
*
* @return vertex shader
*/
@NonNull
String getVertexShader();
/**
* Returns a String containing the fragment shader.
* Together with {@link #getVertexShader()}, this will be used to
* create the OpenGL program.
*
* @return fragment shader
*/
@NonNull
String getFragmentShader();
/**
* The filter program was just created. We pass in a handle to the OpenGL
* program that was created, so you can fetch pointers.
*
* @param programHandle handle
*/
void onCreate(int programHandle); void onCreate(int programHandle);
/**
* The filter program is about to be destroyed.
*
* @param programHandle handle
*/
void onDestroy(int programHandle); void onDestroy(int programHandle);
/**
* Called to render the actual texture. The given transformation matrix
* should be applied.
*
* @param transformMatrix matrix
*/
void draw(float[] transformMatrix); void draw(float[] transformMatrix);
/**
* Called anytime the output size changes.
* @param width width
* @param height height
*/
void setOutputSize(int width, int height); void setOutputSize(int width, int height);
@NonNull /**
String getVertexShader(); * Clones this filter creating a new instance of it.
* If it has any important parameters, these should be passed
@NonNull * to the new instance.
String getFragmentShader(); *
* @return a clone
*/
Filter copy();
} }

@ -104,7 +104,7 @@ public class SnapshotGlPictureRecorder extends PictureRecorder {
@Override @Override
public void onFilterChanged(@NonNull Filter filter) { public void onFilterChanged(@NonNull Filter filter) {
mViewport.setFilter(filter); mViewport.setFilter(filter.copy());
} }
}); });
} }

@ -104,9 +104,9 @@ public class SnapshotVideoRecorder extends VideoRecorder implements RendererFram
@Override @Override
public void onFilterChanged(@NonNull Filter filter) { public void onFilterChanged(@NonNull Filter filter) {
mCurrentFilter = filter; mCurrentFilter = filter.copy();
if (mEncoderEngine != null) { if (mEncoderEngine != null) {
mEncoderEngine.notify(TextureMediaEncoder.FILTER_EVENT, filter); mEncoderEngine.notify(TextureMediaEncoder.FILTER_EVENT, mCurrentFilter);
} }
} }

Loading…
Cancel
Save