Android視訊編輯器(四)通過OpenGL給視訊增加不同濾鏡效果
阿新 • • 發佈:2019-02-07
然後定義繪製的畫面的寬高,由介面從外部進行設定private GPUImageFilter curFilter; private GPUImageFilter leftFilter; private GPUImageFilter rightFilter; public void init() { curFilter.init(); leftFilter.init(); rightFilter.init(); } private void onFilterSizeChanged(int width, int height) { curFilter.onInputSizeChanged(width, height); leftFilter.onInputSizeChanged(width, height); rightFilter.onInputSizeChanged(width, height); curFilter.onDisplaySizeChanged(width, height); leftFilter.onDisplaySizeChanged(width, height); rightFilter.onDisplaySizeChanged(width, height); }
然後再定義一個幀緩衝區和一個紋理,用於繪製圖像private int width, height; public void onSizeChanged(int width, int height) { this.width = width; this.height = height; GLES20.glGenFramebuffers(1, fFrame, 0); EasyGlUtils.genTexturesWithParameter(1, fTexture, 0, GLES20.GL_RGBA, width, height); onFilterSizeChanged(width, height); }
private int[] fFrame = new int[1];
private int[] fTexture = new int[1];
並且初始化一個Scroller,來完成滑動事件的響應,Scroller的使用可以見這篇文章 private Scroller scroller;
scroller = new Scroller(MyApplication.getContext());初始化一個當前的filter的index,也就是標記位,標識當前是哪一個filter。
然後,在建構函式裡面進行一些初始化private int curIndex = 0;
public SlideGpufilterGroup() {
initFilter();
scroller = new Scroller(MyApplication.getContext());
}
initFilter方法其實就是當前三種filter的初始化 public void initFilter() {
curFilter = getFilter(getCurIndex());
leftFilter = getFilter(getLeftIndex());
rightFilter = getFilter(getRightIndex());
}
getFilter其實就是根據filter的index進行filter物件的初始化 public GPUImageFilter getFilter(int index) {
GPUImageFilter filter = MagicFilterFactory.initFilters(types[index]);
if (filter == null) {
filter = new GPUImageFilter();
}
return filter;
}
而getCurIndex、getLeftIndex、getRightIndex這三個方法,就是分別獲取到當前filter的index和左邊、右邊的filter的index。 private int getCurIndex() {
return curIndex;
}
private int getLeftIndex() {
int leftIndex = curIndex - 1;
if (leftIndex < 0) {
leftIndex = types.length - 1;
}
return leftIndex;
}
private int getRightIndex() {
int rightIndex = curIndex + 1;
if (rightIndex >= types.length) {
rightIndex = 0;
}
return rightIndex;
}
當前的filter和左邊、右邊的filter我們都有了,現在還有兩個點,一個就是怎麼樣具體去繪製當前資料幀,另一個就是怎麼進行filter的切換。首先,我們來看看詳細的繪製規則,首先對外提供一個onDrawFrame方法
public void onDrawFrame(int textureId) {
EasyGlUtils.bindFrameTexture(fFrame[0], fTexture[0]);
if (direction == 0 && offset == 0) {
curFilter.onDrawFrame(textureId);
} else if (direction == 1) {
onDrawSlideLeft(textureId);
} else if (direction == -1) {
onDrawSlideRight(textureId);
}
EasyGlUtils.unBindFrameBuffer();
}
該方法,接受一個紋理id,就是我們當前要繪製的紋理。然後將幀緩衝和紋理進行繫結,下面就是一個if
else的判斷,這裡direction其實就是我們自己定義的,用來表示當前是什麼動作的一個int。 int direction;//0為靜止,-1為向左滑,1為向右滑
用這樣一個int,就可以區分當前的滑動是什麼樣的狀態,如果為0表示沒有滑動,那麼我們只用繪製curFilter就行了。而上面我們已經進行了curFilter的初始化,它也繼承自GPUImageFilter。我們只用呼叫onDrawFragme把當前的紋理id傳入進去就行了。而這個offset,其實就是我們記錄的當前的滑動量,如果offset其實=0的,那表示沒有偏移量,那肯定也只用繪製當前這個filter就行了。
如果,當前的狀態是向右滑動,也就是direction = 1,我們就呼叫onDrawSlideLeft函式。
private void onDrawSlideLeft(int textureId) {
if (locked && scroller.computeScrollOffset()) {
offset = scroller.getCurrX();
drawSlideLeft(textureId);
} else {
drawSlideLeft(textureId);
if (locked) {
if (needSwitch) {
reCreateRightFilter();
if (mListener != null) {
mListener.onFilterChange(types[curIndex]);
}
}
offset = 0;
direction = 0;
locked = false;
}
}
}
我們先來看看scroller的computeScrollOffset方法 官方註釋是 /**
* Call this when you want to know the new location. If it returns true,
* the animation is not yet finished.
*/
public boolean computeScrollOffset() {
其實就是如果還在滑動的話,就返回true。