Skip to content

Commit

Permalink
Optimize and compact
Browse files Browse the repository at this point in the history
  • Loading branch information
nekocode committed Aug 12, 2016
1 parent 689503d commit bb3261d
Show file tree
Hide file tree
Showing 55 changed files with 618 additions and 645 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ android {
applicationId "cn.nekocode.camerafilter"
minSdkVersion 15
targetSdkVersion 23
versionCode 150
versionName "1.5"
versionCode 200
versionName "2.0"
}
buildTypes {
release {
Expand Down
30 changes: 15 additions & 15 deletions app/src/main/java/cn/nekocode/camerafilter/CameraRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.util.Log;
import android.util.Pair;
Expand All @@ -42,7 +43,6 @@
import cn.nekocode.camerafilter.filter.CrosshatchFilter;
import cn.nekocode.camerafilter.filter.EMInterferenceFilter;
import cn.nekocode.camerafilter.filter.EdgeDetectionFilter;
import cn.nekocode.camerafilter.filter.JFAVoronoiFilter;
import cn.nekocode.camerafilter.filter.LegofiedFilter;
import cn.nekocode.camerafilter.filter.LichtensteinEsqueFilter;
import cn.nekocode.camerafilter.filter.MappingFilter;
Expand Down Expand Up @@ -76,7 +76,7 @@ public class CameraRenderer extends Thread implements TextureView.SurfaceTexture
private Camera camera;
private SurfaceTexture cameraSurfaceTexture;
private int cameraTextureId;
private CameraFilter cameraFilter;
private CameraFilter selectedFilter;
private SparseArray<CameraFilter> cameraFilterMap = new SparseArray<>();

private boolean exit = false;
Expand All @@ -101,13 +101,15 @@ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
camera.release();
}
exit = true;
CameraFilter.release();

return true;
}

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
surfaceTexture = surface;
GLES20.glViewport(0, 0, gwidth = width, gheight = height);

// Open camera
Pair<Camera.CameraInfo, Integer> backCamera = getBackCamera();
Expand All @@ -118,22 +120,16 @@ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int hei
start();
}

public void setCameraFilter(int id) {
cameraFilter = cameraFilterMap.get(id);
if (id == R.id.filter20) ((JFAVoronoiFilter) cameraFilter).resetFrame();
public void setSelectedFilter(int id) {
selectedFilter = cameraFilterMap.get(id);
selectedFilter.onAttach();
}

@Override
public void run() {
initGL(surfaceTexture);

Camera.Size cameraSize = camera.getParameters().getPreviewSize();

// Create texture for camera preview
cameraTextureId = MyGLUtils.createCameraTexture();
cameraSurfaceTexture = new SurfaceTexture(cameraTextureId);

// Setup camera filter map
// Setup camera filters map
cameraFilterMap.append(R.id.filter0, new OriginalFilter(context));
cameraFilterMap.append(R.id.filter1, new EdgeDetectionFilter(context));
cameraFilterMap.append(R.id.filter2, new PixelizeFilter(context));
Expand All @@ -154,8 +150,12 @@ public void run() {
cameraFilterMap.append(R.id.filter17, new MoneyFilter(context));
cameraFilterMap.append(R.id.filter18, new CrackedFilter(context));
cameraFilterMap.append(R.id.filter19, new PolygonizationFilter(context));
cameraFilterMap.append(R.id.filter20, new JFAVoronoiFilter(context, cameraSize.width, cameraSize.height));
cameraFilter = cameraFilterMap.get(R.id.filter0);
// cameraFilterMap.append(R.id.filter20, new JFAVoronoiFilter(context));
setSelectedFilter(R.id.filter0);

// Create texture for camera preview
cameraTextureId = MyGLUtils.genTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
cameraSurfaceTexture = new SurfaceTexture(cameraTextureId);

// Start camera preview
try {
Expand All @@ -175,7 +175,7 @@ public void run() {
}

// Draw camera preview
cameraFilter.draw(cameraTextureId, gwidth, gheight);
selectedFilter.draw(cameraTextureId, gwidth, gheight);

// Flush
GLES20.glFlush();
Expand Down
62 changes: 35 additions & 27 deletions app/src/main/java/cn/nekocode/camerafilter/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ void setupCameraPreviewView() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
renderer.setCameraFilter(R.id.filter0);
renderer.setSelectedFilter(R.id.filter0);
break;

case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
renderer.setCameraFilter(filterId);
renderer.setSelectedFilter(filterId);
break;
}
return true;
Expand All @@ -123,37 +123,45 @@ public boolean onOptionsItemSelected(MenuItem item) {

// TODO: need tidy up
if (filterId == R.id.capture) {
String mPath = genSaveFileName(getTitle().toString() + "_", ".png");
File imageFile = new File(mPath);
if (imageFile.exists()) {
imageFile.delete();
}

// create bitmap screen capture
Bitmap bitmap = textureView.getBitmap();;
OutputStream outputStream = null;

try {
outputStream = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
outputStream.flush();
outputStream.close();

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

Toast.makeText(this, "The capture has been saved to your sdcard root path.", Toast.LENGTH_SHORT).show();

Toast.makeText(this,
caputre() ? "The capture has been saved to your sdcard root path." :
"Save failed!",
Toast.LENGTH_SHORT).show();
return true;
}

setTitle(item.getTitle());

if (renderer != null)
renderer.setCameraFilter(filterId);
renderer.setSelectedFilter(filterId);

return true;
}

private boolean caputre() {
String mPath = genSaveFileName(getTitle().toString() + "_", ".png");
File imageFile = new File(mPath);
if (imageFile.exists()) {
imageFile.delete();
}

// create bitmap screen capture
Bitmap bitmap = textureView.getBitmap();
OutputStream outputStream = null;

try {
outputStream = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
outputStream.flush();
outputStream.close();

} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}

return true;
}
Expand Down
62 changes: 37 additions & 25 deletions app/src/main/java/cn/nekocode/camerafilter/MyGLUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,37 +36,50 @@
public class MyGLUtils {
private static final String TAG = "MyGLUtils";

public static int createCameraTexture() {
int[] texture = new int[1];

GLES20.glGenTextures(1, texture, 0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture[0]);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);

return texture[0];
public static int genTexture() {
return genTexture(GLES20.GL_TEXTURE_2D);
}

public static int loadTexture(final Context context, final int resourceId) {
int[] texture = new int[1];
public static int genTexture(int textureType) {
int[] genBuf = new int[1];
GLES20.glGenTextures(1, genBuf, 0);
GLES20.glBindTexture(textureType, genBuf[0]);

// Set texture default draw parameters
if (textureType == GLES11Ext.GL_TEXTURE_EXTERNAL_OES) {
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);

} else {
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
}

GLES20.glGenTextures(1, texture, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
return genBuf[0];
}

final int textureHandle = texture[0];
public static int loadTexture(final Context context, final int resourceId, int[] size) {
final int texId = genTexture();

if (textureHandle != 0) {
if (texId != 0) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
options.inJustDecodeBounds = true;

// Just decode bounds
BitmapFactory.decodeResource(context.getResources(), resourceId, options);

// Set return size
size[0] = options.outWidth;
size[1] = options.outHeight;

// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
// Decode
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);

// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
Expand All @@ -75,8 +88,7 @@ public static int loadTexture(final Context context, final int resourceId) {
bitmap.recycle();
}

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
return textureHandle;
return texId;
}

public static int buildProgram(Context context, int vertexSourceRawId, int fragmentSourceRawId) {
Expand Down
100 changes: 100 additions & 0 deletions app/src/main/java/cn/nekocode/camerafilter/RenderBuffer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright 2016 nekocode
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.nekocode.camerafilter;

import android.opengl.GLES20;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import javax.microedition.khronos.opengles.GL10;

/**
* Created by nekocode on 16/8/12.
*/
public class RenderBuffer {
private int texId = 0;
private int activeTexUnit = 0;
private int renderBufferId = 0;
private int frameBufferId = 0;

private int width, height;

public RenderBuffer(int width, int height, int activeTexUnit) {
this.width = width;
this.height = height;
this.activeTexUnit = activeTexUnit;
int[] genbuf = new int[1];

// Generate and bind 2d texture
GLES20.glActiveTexture(activeTexUnit);
texId = MyGLUtils.genTexture();
IntBuffer texBuffer =
ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.nativeOrder()).asIntBuffer();
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, texBuffer);

GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);

// Generate frame buffer
GLES20.glGenFramebuffers(1, genbuf, 0);
frameBufferId = genbuf[0];
// Bind frame buffer
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId);

// Generate render buffer
GLES20.glGenRenderbuffers(1, genbuf, 0);
renderBufferId = genbuf[0];
// Bind render buffer
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, renderBufferId);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, width, height);

unbind();
}

public int getTexId() {
return texId;
}

public int getWidth() {
return width;
}

public int getHeight() {
return height;
}

public int getActiveTexUnit() {
return activeTexUnit;
}

public void bind() {
GLES20.glViewport(0, 0, width, height);

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, texId, 0);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
GLES20.GL_RENDERBUFFER, renderBufferId);
}

public void unbind() {
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
}
}
Loading

0 comments on commit bb3261d

Please sign in to comment.