pull/559/head
Mattia Iavarone 6 years ago
parent 47c93f5aa3
commit 2af34efb5b
  1. 36
      cameraview/src/main/java/com/otaliastudios/cameraview/filter/MultiFilter.java
  2. 21
      docs/_posts/2019-08-06-filters.md

@ -15,6 +15,26 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/**
* A {@link MultiFilter} is a special {@link Filter} that can group one or more filters together.
* When this happens, filters are applied in sequence:
* - the first filter reads from input frames
* - the second filters reads the output of the first
* And so on, until the last filter which will read from the previous and write to the real output.
*
* New filters can be added at any time through {@link #addFilter(Filter)}, but currently they
* can not be removed because we can not easily ensure that they would be correctly released.
*
* The {@link MultiFilter} does also implement {@link OneParameterFilter} and {@link TwoParameterFilter},
* dispatching all the parameter calls to child filters, assuming they support it.
*
* There are some important technical caveats when using {@link MultiFilter}:
* - each child filter requires the allocation of a GL framebuffer. Using a large number of filters
* will likely cause memory issues (e.g. https://stackoverflow.com/q/6354208/4288782).
* - some of the children need to write into {@link GLES20#GL_TEXTURE_2D} instead of
* {@link GLES11Ext#GL_TEXTURE_EXTERNAL_OES}! To achieve this, we replace samplerExternalOES
* with sampler2D in your fragment shader code. This might cause issues for some shaders.
*/
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class MultiFilter implements Filter, OneParameterFilter, TwoParameterFilter { public class MultiFilter implements Filter, OneParameterFilter, TwoParameterFilter {
@ -35,11 +55,19 @@ public class MultiFilter implements Filter, OneParameterFilter, TwoParameterFilt
private float parameter1 = 0F; private float parameter1 = 0F;
private float parameter2 = 0F; private float parameter2 = 0F;
/**
* Creates a new group with the given filters.
* @param filters children
*/
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public MultiFilter(@NonNull Filter... filters) { public MultiFilter(@NonNull Filter... filters) {
this(Arrays.asList(filters)); this(Arrays.asList(filters));
} }
/**
* Creates a new group with the given filters.
* @param filters children
*/
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public MultiFilter(@NonNull Collection<Filter> filters) { public MultiFilter(@NonNull Collection<Filter> filters) {
for (Filter filter : filters) { for (Filter filter : filters) {
@ -47,6 +75,12 @@ public class MultiFilter implements Filter, OneParameterFilter, TwoParameterFilt
} }
} }
/**
* Adds a new filter. It will be used in the next frame.
* If the filter is a {@link MultiFilter}, we'll use its children instead.
*
* @param filter a new filter
*/
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public void addFilter(@NonNull Filter filter) { public void addFilter(@NonNull Filter filter) {
if (filter instanceof MultiFilter) { if (filter instanceof MultiFilter) {
@ -153,12 +187,14 @@ public class MultiFilter implements Filter, OneParameterFilter, TwoParameterFilt
@NonNull @NonNull
@Override @Override
public String getVertexShader() { public String getVertexShader() {
// Whatever, we won't be using this.
return new NoFilter().getVertexShader(); return new NoFilter().getVertexShader();
} }
@NonNull @NonNull
@Override @Override
public String getFragmentShader() { public String getFragmentShader() {
// Whatever, we won't be using this.
return new NoFilter().getFragmentShader(); return new NoFilter().getFragmentShader();
} }

@ -91,6 +91,27 @@ camera.mapGesture(Gesture.SCROLL_HORIZONTAL, GestureAction.FILTER_CONTROL_1);
camera.mapGesture(Gesture.SCROLL_VERTICAL, GestureAction.FILTER_CONTROL_2); camera.mapGesture(Gesture.SCROLL_VERTICAL, GestureAction.FILTER_CONTROL_2);
``` ```
### MultiFilter
CameraView provides a special filter called `MultiFilter` which can be used to group different filters
together, and apply them in sequence to the input frame, in order to process it more than once.
```java
camera.setFilter(new MultiFilter(firstFilter, secondFilter, thirdFilter));
```
You can even add new filters to the group at any time, using `MultiFilter.addFilter()`.
The `MultiFilter` will also try to dispatch [filter controls](#filters-controls) (e.g. from gestures)
to its children.
There are some technical caveats when using a `MultiFilter`:
- Using a large number of child filters can consume the available graphic memory
- For [advanced users](#advanced-usage), child filters need to read from `GLES20.GL_TEXTURE_2D`
instead of the typical `GLES11Ext.GL_TEXTURE_EXTERNAL_OES`. To achieve this, we get your fragment
shader String and replace any `"samplerExternalOES"` with `"sampler2D"`. This is a hack
that might cause issues with specific shader implementations.
### Advanced usage ### Advanced usage
Advanced users with OpenGL experience can create their own filters by implementing the `Filter` interface Advanced users with OpenGL experience can create their own filters by implementing the `Filter` interface

Loading…
Cancel
Save