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.internal.GlUtils;
import com.otaliastudios.cameraview.size.Size;
import java.nio.FloatBuffer;
/**
* A Base abstract class that every effect must extend so that there is a common getShader method.
* <p>
* 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.
* If there is some other effect which requires vertex shader also change, you can override it.
* <p>
* If your provide your own vertex and fragment shader,
* please set the {@link #mPositionVariableName}, {@link #mTextureCoordinateVariableName},
* {@link #mMVPMatrixVariableName}, {@link #mTextureMatrixVariableName}
* according to your shader code.
* <p>
* Please note that these shader applies on live preview as well as pictureSnapshot and videoSnapshot,
* we only support GLES11Ext.GL_TEXTURE_EXTERNAL_OES
* check EglViewport()
* <p>
* The default implementation of this class is NoEffect.
* A base implementation of {@link Filter} that just leaves the fragment shader to subclasses.
* See {@link NoFilter} for a full implementation.
*
* This class offers a default vertex shader implementation which in most cases is not required
* to be changed. Most effects can be rendered by simply changing the fragment shader, thus
* by overriding {@link #getFragmentShader()}.
*
* This class expects variable to have a certain name:
* - {@link #vertexPositionName}
* - {@link #vertexTransformMatrixName}
* - {@link #vertexModelViewProjectionMatrixName}
* - {@link #vertexTextureCoordinateName}
* - {@link #fragmentTextureCoordinateName}
*
* You can either change these variables, for example in your constructor, or change your
* 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 {
@ -65,6 +73,7 @@ public abstract class BaseFilter implements Filter {
+ " gl_FragColor = texture2D(sTexture, "+fragmentTextureCoordinateName+");\n"
+ "}\n";
}
// When the model/view/projection matrix is identity, this will exactly cover the viewport.
private FloatBuffer vertexPosition = GlUtils.floatBuffer(new float[]{
-1.0f, -1.0f, // 0 bottom left
@ -84,6 +93,7 @@ public abstract class BaseFilter implements Filter {
private int vertexTranformMatrixLocation = -1;
private int vertexPositionLocation = -1;
private int vertexTextureCoordinateLocation = -1;
private Size outputSize;
@SuppressWarnings("WeakerAccess")
protected String vertexPositionName = DEFAULT_VERTEX_POSITION_NAME;
@ -126,7 +136,10 @@ public abstract class BaseFilter implements Filter {
@Override
public void onDestroy(int programHandle) {
// Do nothing.
vertexPositionLocation = -1;
vertexTextureCoordinateLocation = -1;
vertexModelViewProjectionMatrixLocation = -1;
vertexTranformMatrixLocation = -1;
}
@NonNull
@ -137,7 +150,7 @@ public abstract class BaseFilter implements Filter {
@Override
public void setOutputSize(int width, int height) {
outputSize = new Size(width, height);
}
@Override
@ -184,4 +197,21 @@ public abstract class BaseFilter implements Filter {
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;
import com.otaliastudios.cameraview.CameraView;
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 {
/**
* 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);
/**
* The filter program is about to be destroyed.
*
* @param programHandle handle
*/
void onDestroy(int programHandle);
/**
* Called to render the actual texture. The given transformation matrix
* should be applied.
*
* @param transformMatrix matrix
*/
void draw(float[] transformMatrix);
/**
* Called anytime the output size changes.
* @param width width
* @param height height
*/
void setOutputSize(int width, int height);
@NonNull
String getVertexShader();
@NonNull
String getFragmentShader();
/**
* Clones this filter creating a new instance of it.
* If it has any important parameters, these should be passed
* to the new instance.
*
* @return a clone
*/
Filter copy();
}

@ -104,7 +104,7 @@ public class SnapshotGlPictureRecorder extends PictureRecorder {
@Override
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
public void onFilterChanged(@NonNull Filter filter) {
mCurrentFilter = filter;
mCurrentFilter = filter.copy();
if (mEncoderEngine != null) {
mEncoderEngine.notify(TextureMediaEncoder.FILTER_EVENT, filter);
mEncoderEngine.notify(TextureMediaEncoder.FILTER_EVENT, mCurrentFilter);
}
}

Loading…
Cancel
Save