aboutsummaryrefslogtreecommitdiffstats
path: root/src/org/cyanogenmod
diff options
context:
space:
mode:
authorJorge Ruesga <jorge@ruesga.com>2013-08-14 18:09:23 +0200
committerJorge Ruesga <jorge@ruesga.com>2013-08-14 18:09:23 +0200
commit8c07c923cf89fb633c042e0851a1cd82827133ca (patch)
treecab898338b99a5119bebb0d8ffeff8bbff1b2a3a /src/org/cyanogenmod
parent39e18f77c7821ff476ad443c07c9e381473131f4 (diff)
downloadandroid_packages_wallpapers_PhotoPhase-8c07c923cf89fb633c042e0851a1cd82827133ca.tar.gz
android_packages_wallpapers_PhotoPhase-8c07c923cf89fb633c042e0851a1cd82827133ca.tar.bz2
android_packages_wallpapers_PhotoPhase-8c07c923cf89fb633c042e0851a1cd82827133ca.zip
Support for MCA own effects + Halftone effects
Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
Diffstat (limited to 'src/org/cyanogenmod')
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/effects/Effects.java9
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/effects/HalftoneEffect.java218
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/effects/PhotoPhaseEffect.java123
-rw-r--r--src/org/cyanogenmod/wallpapers/photophase/effects/PhotoPhaseEffectFactory.java38
4 files changed, 388 insertions, 0 deletions
diff --git a/src/org/cyanogenmod/wallpapers/photophase/effects/Effects.java b/src/org/cyanogenmod/wallpapers/photophase/effects/Effects.java
index 04866c0..cf9ff79 100644
--- a/src/org/cyanogenmod/wallpapers/photophase/effects/Effects.java
+++ b/src/org/cyanogenmod/wallpapers/photophase/effects/Effects.java
@@ -52,6 +52,10 @@ public class Effects {
*/
DOCUMENTARY,
/**
+ * @see PhotoPhaseEffectFactory#EFFECT_HALFTONE
+ */
+ HALFTONE,
+ /**
* @see EffectFactory#EFFECT_DUOTONE
*/
DUOTONE,
@@ -156,6 +160,11 @@ public class Effects {
if (EffectFactory.isEffectSupported(EffectFactory.EFFECT_DOCUMENTARY)) {
effect = effectFactory.createEffect(EffectFactory.EFFECT_DOCUMENTARY);
}
+ } else if (nextEffect.compareTo(EFFECTS.HALFTONE) == 0) {
+ if (EffectFactory.isEffectSupported(PhotoPhaseEffectFactory.EFFECT_HALFTONE)) {
+ effect = effectFactory.createEffect(PhotoPhaseEffectFactory.EFFECT_HALFTONE);
+ effect.setParameter("strength", 30.0f);
+ }
} else if (nextEffect.compareTo(EFFECTS.DUOTONE) == 0) {
if (EffectFactory.isEffectSupported(EffectFactory.EFFECT_DUOTONE)) {
effect = effectFactory.createEffect(EffectFactory.EFFECT_DUOTONE);
diff --git a/src/org/cyanogenmod/wallpapers/photophase/effects/HalftoneEffect.java b/src/org/cyanogenmod/wallpapers/photophase/effects/HalftoneEffect.java
new file mode 100644
index 0000000..b09696f
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/effects/HalftoneEffect.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2008 Max Maischein
+ * Copyright (C) 2013 The CyanogenMod 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.
+ */
+//
+// Based in the shaders of Max Maischein of App-VideoMixer:
+// http://cpansearch.perl.org/src/CORION/App-VideoMixer-0.02/filters/halftone.glsl
+//
+
+package org.cyanogenmod.wallpapers.photophase.effects;
+
+import android.media.effect.EffectContext;
+import android.opengl.GLES20;
+import android.util.Log;
+
+import org.cyanogenmod.wallpapers.photophase.utils.GLESUtil;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+/**
+ * A halftone effect<br/>
+ * <table>
+ * <tr><td>Parameter name</td><td>Meaning</td><td>Valid values</td></tr>
+ * <tr>
+ * <td><code>strength</code></td>
+ * <td>The halftone steps multiplier.</td>
+ * <td>Positive float (>0). Higher numbers produce smallest points;</td>
+ * </tr>
+ * </table>
+ */
+public class HalftoneEffect extends PhotoPhaseEffect {
+
+ private static final String TAG = "HalftoneEffect";
+
+ /**
+ * The halftone steps multiplier parameter key
+ */
+ public static final String STRENGTH_PARAMETER = "strength";
+
+ private static final int FLOAT_SIZE_BYTES = 4;
+
+ private static final String VERTEX_SHADER =
+ "attribute vec4 a_position;\n" +
+ "attribute vec2 a_texcoord;\n" +
+ "varying vec2 v_texcoord;\n" +
+ "void main() {\n" +
+ " gl_Position = vec4(a_position.xy, 0.0, 1.0);\n" +
+ " gl_Position = sign(gl_Position);\n" +
+ " v_texcoord = a_texcoord;\n" +
+ "}\n";
+ private static final String FRAGMENT_SHADER =
+ "precision mediump float;\n" +
+ "uniform sampler2D tex_sampler;\n" +
+ "varying vec2 v_texcoord;\n" +
+ "uniform float steps\n;" +
+ "float dotsize = 1.0 / steps ;\n" +
+ "float half_step = dotsize / 2.0;\n" +
+ "void main() {\n" +
+ " vec2 center = v_texcoord - vec2(mod(v_texcoord.x, dotsize),mod(v_texcoord.y, dotsize)) + half_step;\n" +
+ " vec4 pel = texture2D( tex_sampler, center);\n" +
+ " float size = length(pel);\n" +
+ " if (distance(v_texcoord,center) <= dotsize*size/4.0) {\n" +
+ " gl_FragColor = pel;\n" +
+ " } else {\n" +
+ " gl_FragColor = vec4(0.0,0.0,0.0,0.0);\n" +
+ " };\n" +
+ "}\n";
+
+ private static final float[] TEX_VERTICES = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};
+ private static final float[] POS_VERTICES = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f};
+
+ private float mStrength = 32.0f;
+
+ private int mProgram;
+ private int mTexSamplerHandle;
+ private int mTexCoordHandle;
+ private int mPosCoordHandle;
+ private int mStepsHandle;
+
+ private FloatBuffer mTexVertices;
+ private FloatBuffer mPosVertices;
+
+ /**
+ * An abstract contructor of <code>Effect</code> to follow the rules
+ * defined by {@see EffectFactory}.
+ *
+ * @param ctx The effect context
+ * @param name The effect name
+ */
+ public HalftoneEffect(EffectContext ctx, String name) {
+ super(ctx, HalftoneEffect.class.getName());
+ init();
+ }
+
+ /**
+ * Method that initializes the effect
+ */
+ private void init() {
+ // Create program
+ mProgram = GLESUtil.createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
+
+ // Bind attributes and uniforms
+ mTexSamplerHandle = GLES20.glGetUniformLocation(mProgram, "tex_sampler");
+ GLESUtil.glesCheckError("glGetUniformLocation");
+ mTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texcoord");
+ GLESUtil.glesCheckError("glGetAttribLocation");
+ mPosCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_position");
+ GLESUtil.glesCheckError("glGetAttribLocation");
+ mStepsHandle = GLES20.glGetUniformLocation(mProgram, "steps");
+ GLESUtil.glesCheckError("glGetUniformLocation");
+
+ // Setup coordinate buffers
+ mTexVertices = ByteBuffer.allocateDirect(
+ TEX_VERTICES.length * FLOAT_SIZE_BYTES)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mTexVertices.put(TEX_VERTICES).position(0);
+ mPosVertices = ByteBuffer.allocateDirect(
+ POS_VERTICES.length * FLOAT_SIZE_BYTES)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mPosVertices.put(POS_VERTICES).position(0);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ void apply(int inputTexId) {
+ // Use our shader program
+ GLES20.glUseProgram(mProgram);
+ GLESUtil.glesCheckError("glUseProgram");
+
+ // Disable blending
+ GLES20.glDisable(GLES20.GL_BLEND);
+ GLESUtil.glesCheckError("glDisable");
+
+ // Set the vertex attributes
+ GLES20.glVertexAttribPointer(mTexCoordHandle, 2, GLES20.GL_FLOAT, false, 0, mTexVertices);
+ GLESUtil.glesCheckError("glVertexAttribPointer");
+ GLES20.glEnableVertexAttribArray(mTexCoordHandle);
+ GLESUtil.glesCheckError("glEnableVertexAttribArray");
+ GLES20.glVertexAttribPointer(mPosCoordHandle, 2, GLES20.GL_FLOAT, false, 0, mPosVertices);
+ GLESUtil.glesCheckError("glVertexAttribPointer");
+ GLES20.glEnableVertexAttribArray(mPosCoordHandle);
+ GLESUtil.glesCheckError("glEnableVertexAttribArray");
+
+ // Set parameters
+ GLES20.glUniform1f(mStepsHandle, mStrength);
+ GLESUtil.glesCheckError("glUniform1f");
+
+ // Set the input texture
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, inputTexId);
+ GLESUtil.glesCheckError("glBindTexture");
+ GLES20.glUniform1i(mTexSamplerHandle, 0);
+ GLESUtil.glesCheckError("glUniform1i");
+
+ // Draw
+ GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ GLESUtil.glesCheckError("glClearColor");
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+ GLESUtil.glesCheckError("glClear");
+ GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
+ GLESUtil.glesCheckError("glDrawArrays");
+
+ // Disable attributes
+ GLES20.glDisableVertexAttribArray(mTexCoordHandle);
+ GLESUtil.glesCheckError("glDisableVertexAttribArray");
+ GLES20.glDisableVertexAttribArray(mPosCoordHandle);
+ GLESUtil.glesCheckError("glDisableVertexAttribArray");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setParameter(String parameterKey, Object value) {
+ if (parameterKey.compareTo(STRENGTH_PARAMETER) == 0) {
+ try {
+ float strength = Float.parseFloat(value.toString());
+ if (strength <= 0) {
+ Log.w(TAG, "strength parameter must be >= 0");
+ return;
+ }
+ mStrength = strength;
+ } catch (NumberFormatException ex) {
+ // Ignore
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void release() {
+ if (GLES20.glIsProgram(mProgram)) {
+ GLES20.glDeleteProgram(mProgram);
+ GLESUtil.glesCheckError("glDeleteProgram");
+ }
+ mTexVertices = null;
+ mPosVertices = null;
+ }
+
+}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/effects/PhotoPhaseEffect.java b/src/org/cyanogenmod/wallpapers/photophase/effects/PhotoPhaseEffect.java
new file mode 100644
index 0000000..83f461d
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/effects/PhotoPhaseEffect.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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 org.cyanogenmod.wallpapers.photophase.effects;
+
+import android.media.effect.Effect;
+import android.media.effect.EffectContext;
+import android.opengl.GLES20;
+import android.opengl.GLUtils;
+
+import org.cyanogenmod.wallpapers.photophase.utils.GLESUtil;
+
+import java.nio.IntBuffer;
+
+/**
+ * An abstract class definition for all the PhotoPhase custom effects
+ */
+public abstract class PhotoPhaseEffect extends Effect {
+
+ private final EffectContext mEffectContext;
+ private final String mName;
+
+ /**
+ * An abstract contructor of <code>Effect</code> to follow the rules
+ * defined by {@see EffectFactory}.
+ *
+ * @param ctx The effect context
+ * @param name The effect name
+ */
+ public PhotoPhaseEffect(EffectContext ctx, String name) {
+ super();
+ mEffectContext = ctx;
+ mName = name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Method that returns the effect context
+ *
+ * @return EffectContext The effect context
+ */
+ public EffectContext getEffectContext() {
+ return mEffectContext;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final void apply(int inputTexId, int width, int height, int outputTexId) {
+ // Create a framebuffer object and call the effect apply method to draw the effect
+ int[] fb = new int[1];
+ GLES20.glGenFramebuffers(1, fb, 0);
+ GLESUtil.glesCheckError("glGenFramebuffers");
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);
+ GLESUtil.glesCheckError("glBindFramebuffer");
+
+ // Render on the whole framebuffer,
+ GLES20.glViewport(0, 0, width, height);
+ GLESUtil.glesCheckError("glViewport");
+
+ // Create a new output texturure
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, outputTexId);
+ GLESUtil.glesCheckError("glBindTexture");
+ IntBuffer texBuffer = IntBuffer.wrap(new int[width * height]);
+ GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, width, height, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, texBuffer);
+ GLESUtil.glesCheckError("glTexImage2D");
+
+ // Set the
+ GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
+ GLESUtil.glesCheckError("glTexParameteri");
+ GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
+ GLESUtil.glesCheckError("glTexParameteri");
+
+ // Create the framebuffer
+ GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20. GL_TEXTURE_2D, outputTexId, 0);
+ GLESUtil.glesCheckError("glFramebufferTexture2D");
+
+ // Check if the buffer was built successfully
+ if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE) {
+ // Something when wrong. Throw an exception
+ GLESUtil.glesCheckError("glCheckFramebufferStatus");
+ int error = GLES20.glGetError();
+ throw new android.opengl.GLException(error, GLUtils.getEGLErrorString(error));
+ }
+
+ // Bind the framebuffer
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);
+
+ // Apply the effect
+ apply(inputTexId);
+
+ // Unbind the framebuffer
+ GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
+ }
+
+ /**
+ * Method that applies the effect.
+ *
+ * @param inputTexId The input texture
+ */
+ abstract void apply(int inputTexId);
+}
diff --git a/src/org/cyanogenmod/wallpapers/photophase/effects/PhotoPhaseEffectFactory.java b/src/org/cyanogenmod/wallpapers/photophase/effects/PhotoPhaseEffectFactory.java
new file mode 100644
index 0000000..eaa5f32
--- /dev/null
+++ b/src/org/cyanogenmod/wallpapers/photophase/effects/PhotoPhaseEffectFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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 org.cyanogenmod.wallpapers.photophase.effects;
+
+/**
+ * A class that defines the own PhotoPhase's effects implementation. This class follows the
+ * rules of the MCA aosp library.
+ */
+public class PhotoPhaseEffectFactory {
+
+ /**
+ * <p>Applies halftone effect to the image.</p>
+ * <p>Available parameters:</p>
+ * <table>
+ * <tr><td>Parameter name</td><td>Meaning</td><td>Valid values</td></tr>
+ * <tr>
+ * <td><code>strength</code></td>
+ * <td>The halftone steps multiplier.</td>
+ * <td>Positive float (>0). Higher numbers produce smallest points;</td>
+ * </tr>
+ * </table>
+ */
+ public static final String EFFECT_HALFTONE = "org.cyanogenmod.wallpapers.photophase.effects.HalftoneEffect";
+}