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