1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.mediaeffects; 18 19 import android.graphics.Bitmap; 20 import android.graphics.BitmapFactory; 21 import android.graphics.Color; 22 import android.media.effect.Effect; 23 import android.media.effect.EffectContext; 24 import android.media.effect.EffectFactory; 25 import android.opengl.GLES20; 26 import android.opengl.GLSurfaceView; 27 import android.opengl.GLUtils; 28 import android.os.Bundle; 29 import android.support.annotation.Nullable; 30 import android.support.v4.app.Fragment; 31 import android.view.LayoutInflater; 32 import android.view.Menu; 33 import android.view.MenuInflater; 34 import android.view.MenuItem; 35 import android.view.View; 36 import android.view.ViewGroup; 37 38 import javax.microedition.khronos.egl.EGLConfig; 39 import javax.microedition.khronos.opengles.GL10; 40 41 public class MediaEffectsFragment extends Fragment implements GLSurfaceView.Renderer { 42 43 private static final String STATE_CURRENT_EFFECT = "current_effect"; 44 45 private GLSurfaceView mEffectView; 46 private int[] mTextures = new int[2]; 47 private EffectContext mEffectContext; 48 private Effect mEffect; 49 private TextureRenderer mTexRenderer = new TextureRenderer(); 50 private int mImageWidth; 51 private int mImageHeight; 52 private boolean mInitialized = false; 53 private int mCurrentEffect; 54 55 @Override onCreate(Bundle savedInstanceState)56 public void onCreate(Bundle savedInstanceState) { 57 super.onCreate(savedInstanceState); 58 setHasOptionsMenu(true); 59 } 60 61 @Override onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)62 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 63 @Nullable Bundle savedInstanceState) { 64 return inflater.inflate(R.layout.fragment_media_effects, container, false); 65 } 66 67 @Override onViewCreated(View view, @Nullable Bundle savedInstanceState)68 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 69 mEffectView = (GLSurfaceView) view.findViewById(R.id.effectsview); 70 mEffectView.setEGLContextClientVersion(2); 71 mEffectView.setRenderer(this); 72 mEffectView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 73 if (null != savedInstanceState && savedInstanceState.containsKey(STATE_CURRENT_EFFECT)) { 74 setCurrentEffect(savedInstanceState.getInt(STATE_CURRENT_EFFECT)); 75 } else { 76 setCurrentEffect(R.id.none); 77 } 78 } 79 80 @Override onCreateOptionsMenu(Menu menu, MenuInflater inflater)81 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 82 inflater.inflate(R.menu.media_effects, menu); 83 } 84 85 @Override onOptionsItemSelected(MenuItem item)86 public boolean onOptionsItemSelected(MenuItem item) { 87 setCurrentEffect(item.getItemId()); 88 mEffectView.requestRender(); 89 return true; 90 } 91 92 @Override onSaveInstanceState(Bundle outState)93 public void onSaveInstanceState(Bundle outState) { 94 outState.putInt(STATE_CURRENT_EFFECT, mCurrentEffect); 95 } 96 97 @Override onSurfaceCreated(GL10 gl, EGLConfig eglConfig)98 public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) { 99 // Nothing to do here 100 } 101 102 @Override onSurfaceChanged(GL10 gl, int width, int height)103 public void onSurfaceChanged(GL10 gl, int width, int height) { 104 if (mTexRenderer != null) { 105 mTexRenderer.updateViewSize(width, height); 106 } 107 } 108 109 @Override onDrawFrame(GL10 gl)110 public void onDrawFrame(GL10 gl) { 111 if (!mInitialized) { 112 //Only need to do this once 113 mEffectContext = EffectContext.createWithCurrentGlContext(); 114 mTexRenderer.init(); 115 loadTextures(); 116 mInitialized = true; 117 } 118 if (mCurrentEffect != R.id.none) { 119 //if an effect is chosen initialize it and apply it to the texture 120 initEffect(); 121 applyEffect(); 122 } 123 renderResult(); 124 } 125 setCurrentEffect(int effect)126 private void setCurrentEffect(int effect) { 127 mCurrentEffect = effect; 128 } 129 loadTextures()130 private void loadTextures() { 131 // Generate textures 132 GLES20.glGenTextures(2, mTextures, 0); 133 134 // Load input bitmap 135 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.puppy); 136 mImageWidth = bitmap.getWidth(); 137 mImageHeight = bitmap.getHeight(); 138 mTexRenderer.updateTextureSize(mImageWidth, mImageHeight); 139 140 // Upload to texture 141 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]); 142 GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 143 144 // Set texture parameters 145 GLToolbox.initTexParams(); 146 } 147 initEffect()148 private void initEffect() { 149 EffectFactory effectFactory = mEffectContext.getFactory(); 150 if (mEffect != null) { 151 mEffect.release(); 152 } 153 // Initialize the correct effect based on the selected menu/action item 154 switch (mCurrentEffect) { 155 156 case R.id.none: 157 break; 158 159 case R.id.autofix: 160 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_AUTOFIX); 161 mEffect.setParameter("scale", 0.5f); 162 break; 163 164 case R.id.bw: 165 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_BLACKWHITE); 166 mEffect.setParameter("black", .1f); 167 mEffect.setParameter("white", .7f); 168 break; 169 170 case R.id.brightness: 171 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_BRIGHTNESS); 172 mEffect.setParameter("brightness", 2.0f); 173 break; 174 175 case R.id.contrast: 176 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_CONTRAST); 177 mEffect.setParameter("contrast", 1.4f); 178 break; 179 180 case R.id.crossprocess: 181 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_CROSSPROCESS); 182 break; 183 184 case R.id.documentary: 185 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_DOCUMENTARY); 186 break; 187 188 case R.id.duotone: 189 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_DUOTONE); 190 mEffect.setParameter("first_color", Color.YELLOW); 191 mEffect.setParameter("second_color", Color.DKGRAY); 192 break; 193 194 case R.id.filllight: 195 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FILLLIGHT); 196 mEffect.setParameter("strength", .8f); 197 break; 198 199 case R.id.fisheye: 200 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FISHEYE); 201 mEffect.setParameter("scale", .5f); 202 break; 203 204 case R.id.flipvert: 205 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FLIP); 206 mEffect.setParameter("vertical", true); 207 break; 208 209 case R.id.fliphor: 210 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_FLIP); 211 mEffect.setParameter("horizontal", true); 212 break; 213 214 case R.id.grain: 215 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_GRAIN); 216 mEffect.setParameter("strength", 1.0f); 217 break; 218 219 case R.id.grayscale: 220 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_GRAYSCALE); 221 break; 222 223 case R.id.lomoish: 224 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_LOMOISH); 225 break; 226 227 case R.id.negative: 228 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_NEGATIVE); 229 break; 230 231 case R.id.posterize: 232 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_POSTERIZE); 233 break; 234 235 case R.id.rotate: 236 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_ROTATE); 237 mEffect.setParameter("angle", 180); 238 break; 239 240 case R.id.saturate: 241 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SATURATE); 242 mEffect.setParameter("scale", .5f); 243 break; 244 245 case R.id.sepia: 246 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SEPIA); 247 break; 248 249 case R.id.sharpen: 250 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_SHARPEN); 251 break; 252 253 case R.id.temperature: 254 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_TEMPERATURE); 255 mEffect.setParameter("scale", .9f); 256 break; 257 258 case R.id.tint: 259 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_TINT); 260 mEffect.setParameter("tint", Color.MAGENTA); 261 break; 262 263 case R.id.vignette: 264 mEffect = effectFactory.createEffect(EffectFactory.EFFECT_VIGNETTE); 265 mEffect.setParameter("scale", .5f); 266 break; 267 268 default: 269 break; 270 } 271 } 272 applyEffect()273 private void applyEffect() { 274 mEffect.apply(mTextures[0], mImageWidth, mImageHeight, mTextures[1]); 275 } 276 renderResult()277 private void renderResult() { 278 if (mCurrentEffect != R.id.none) { 279 // if no effect is chosen, just render the original bitmap 280 mTexRenderer.renderTexture(mTextures[1]); 281 } else { 282 // render the result of applyEffect() 283 mTexRenderer.renderTexture(mTextures[0]); 284 } 285 } 286 287 } 288