/* * Copyright (C) 2014 The Android Open Source Project * * 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 com.example.android.mediaeffects; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.media.effect.Effect; import android.media.effect.EffectContext; import android.media.effect.EffectFactory; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.opengl.GLUtils; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class MediaEffectsFragment extends Fragment implements GLSurfaceView.Renderer { private static final String STATE_CURRENT_EFFECT = "current_effect"; private GLSurfaceView mEffectView; private int[] mTextures = new int[2]; private EffectContext mEffectContext; private Effect mEffect; private TextureRenderer mTexRenderer = new TextureRenderer(); private int mImageWidth; private int mImageHeight; private boolean mInitialized = false; private int mCurrentEffect; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_media_effects, container, false); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { mEffectView = (GLSurfaceView) view.findViewById(R.id.effectsview); mEffectView.setEGLContextClientVersion(2); mEffectView.setRenderer(this); mEffectView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); if (null != savedInstanceState && savedInstanceState.containsKey(STATE_CURRENT_EFFECT)) { setCurrentEffect(savedInstanceState.getInt(STATE_CURRENT_EFFECT)); } else { setCurrentEffect(R.id.none); } } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.media_effects, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { setCurrentEffect(item.getItemId()); mEffectView.requestRender(); return true; } @Override public void onSaveInstanceState(Bundle outState) { outState.putInt(STATE_CURRENT_EFFECT, mCurrentEffect); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) { // Nothing to do here } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { if (mTexRenderer != null) { mTexRenderer.updateViewSize(width, height); } } @Override public void onDrawFrame(GL10 gl) { if (!mInitialized) { //Only need to do this once mEffectContext = EffectContext.createWithCurrentGlContext(); mTexRenderer.init(); loadTextures(); mInitialized = true; } if (mCurrentEffect != R.id.none) { //if an effect is chosen initialize it and apply it to the texture initEffect(); applyEffect(); } renderResult(); } private void setCurrentEffect(int effect) { mCurrentEffect = effect; } private void loadTextures() { // Generate textures GLES20.glGenTextures(2, mTextures, 0); // Load input bitmap Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.puppy); mImageWidth = bitmap.getWidth(); mImageHeight = bitmap.getHeight(); mTexRenderer.updateTextureSize(mImageWidth, mImageHeight); // Upload to texture GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]); GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); // Set texture parameters GLToolbox.initTexParams(); } private void initEffect() { EffectFactory effectFactory = mEffectContext.getFactory(); if (mEffect != null) { mEffect.release(); } // Initialize the correct effect based on the selected menu/action item switch (mCurrentEffect) { case R.id.none: break; case R.id.autofix: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_AUTOFIX); mEffect.setParameter("scale", 0.5f); break; case R.id.bw: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_BLACKWHITE); mEffect.setParameter("black", .1f); mEffect.setParameter("white", .7f); break; case R.id.brightness: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_BRIGHTNESS); mEffect.setParameter("brightness", 2.0f); break; case R.id.contrast: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_CONTRAST); mEffect.setParameter("contrast", 1.4f); break; case R.id.crossprocess: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_CROSSPROCESS); break; case R.id.documentary: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_DOCUMENTARY); break; case R.id.duotone: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_DUOTONE); mEffect.setParameter("first_color", Color.YELLOW); mEffect.setParameter("second_color", Color.DKGRAY); break; case R.id.filllight: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FILLLIGHT); mEffect.setParameter("strength", .8f); break; case R.id.fisheye: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FISHEYE); mEffect.setParameter("scale", .5f); break; case R.id.flipvert: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FLIP); mEffect.setParameter("vertical", true); break; case R.id.fliphor: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FLIP); mEffect.setParameter("horizontal", true); break; case R.id.grain: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_GRAIN); mEffect.setParameter("strength", 1.0f); break; case R.id.grayscale: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_GRAYSCALE); break; case R.id.lomoish: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_LOMOISH); break; case R.id.negative: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_NEGATIVE); break; case R.id.posterize: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_POSTERIZE); break; case R.id.rotate: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_ROTATE); mEffect.setParameter("angle", 180); break; case R.id.saturate: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SATURATE); mEffect.setParameter("scale", .5f); break; case R.id.sepia: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SEPIA); break; case R.id.sharpen: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SHARPEN); break; case R.id.temperature: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_TEMPERATURE); mEffect.setParameter("scale", .9f); break; case R.id.tint: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_TINT); mEffect.setParameter("tint", Color.MAGENTA); break; case R.id.vignette: mEffect = effectFactory.createEffect(EffectFactory.EFFECT_VIGNETTE); mEffect.setParameter("scale", .5f); break; default: break; } } private void applyEffect() { mEffect.apply(mTextures[0], mImageWidth, mImageHeight, mTextures[1]); } private void renderResult() { if (mCurrentEffect != R.id.none) { // if no effect is chosen, just render the original bitmap mTexRenderer.renderTexture(mTextures[1]); } else { // render the result of applyEffect() mTexRenderer.renderTexture(mTextures[0]); } } }