Home | History | Annotate | Download | only in mediaeffects
      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
     56     public void onCreate(Bundle savedInstanceState) {
     57         super.onCreate(savedInstanceState);
     58         setHasOptionsMenu(true);
     59     }
     60 
     61     @Override
     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
     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
     81     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
     82         inflater.inflate(R.menu.media_effects, menu);
     83     }
     84 
     85     @Override
     86     public boolean onOptionsItemSelected(MenuItem item) {
     87         setCurrentEffect(item.getItemId());
     88         mEffectView.requestRender();
     89         return true;
     90     }
     91 
     92     @Override
     93     public void onSaveInstanceState(Bundle outState) {
     94         outState.putInt(STATE_CURRENT_EFFECT, mCurrentEffect);
     95     }
     96 
     97     @Override
     98     public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) {
     99         // Nothing to do here
    100     }
    101 
    102     @Override
    103     public void onSurfaceChanged(GL10 gl, int width, int height) {
    104         if (mTexRenderer != null) {
    105             mTexRenderer.updateViewSize(width, height);
    106         }
    107     }
    108 
    109     @Override
    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 
    126     private void setCurrentEffect(int effect) {
    127         mCurrentEffect = effect;
    128     }
    129 
    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 
    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 
    273     private void applyEffect() {
    274         mEffect.apply(mTextures[0], mImageWidth, mImageHeight, mTextures[1]);
    275     }
    276 
    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