diff options
author | Jorge Ruesga <jorge@ruesga.com> | 2013-08-06 01:47:05 +0200 |
---|---|---|
committer | Jorge Ruesga <jorge@ruesga.com> | 2013-08-06 01:47:05 +0200 |
commit | 6ab3912f76d8886ccfc88def25c18819a0594f07 (patch) | |
tree | b18b0800e82bdf4251c2bee8d892fcdfa9baf553 | |
parent | 660adfa9453ada61b8753dcac1adc5b9b0972b62 (diff) | |
download | android_packages_wallpapers_PhotoPhase-6ab3912f76d8886ccfc88def25c18819a0594f07.tar.gz android_packages_wallpapers_PhotoPhase-6ab3912f76d8886ccfc88def25c18819a0594f07.tar.bz2 android_packages_wallpapers_PhotoPhase-6ab3912f76d8886ccfc88def25c18819a0594f07.zip |
Support fot GPU image effects (#2)
Initial support of android.media.effects.
Note: Transitions are broken now, and must be fixed
Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
19 files changed, 195 insertions, 396 deletions
diff --git a/res/values/arrays.xml b/res/values/arrays.xml index ecfbb65..05157d7 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -65,7 +65,7 @@ <string-array name="effects_labels" translatable="false"> <item>@string/effects_none</item> <item>@string/effects_random</item> - <item>@string/effects_black_and_white</item> + <item>@string/effects_grayscale</item> <item>@string/effects_sepia</item> </string-array> diff --git a/res/values/strings.xml b/res/values/strings.xml index aff0185..dadde80 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -111,7 +111,7 @@ <!-- Effects --> <string name="effects_none">None</string> <string name="effects_random">Random</string> - <string name="effects_black_and_white">Black & White</string> + <string name="effects_grayscale">Grayscale</string> <string name="effects_sepia">Sepia</string> <!-- ColorPickerDialog --> diff --git a/src/org/cyanogenmod/wallpapers/photophase/GLESUtil.java b/src/org/cyanogenmod/wallpapers/photophase/GLESUtil.java index 25fe366..a6de6fd 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/GLESUtil.java +++ b/src/org/cyanogenmod/wallpapers/photophase/GLESUtil.java @@ -21,12 +21,11 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Rect; +import android.media.effect.Effect; import android.opengl.GLES20; import android.opengl.GLUtils; import android.util.Log; -import org.cyanogenmod.wallpapers.photophase.effects.Effect; - import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -305,12 +304,13 @@ public final class GLESUtil { * * @param file The image file * @param dimensions The desired dimensions - * @param effect The effect to apply to the image + * @param effect The effect to apply to the image or null if no effect is needed + * @param screenDim The screen dimensions * @param recycle If the bitmap should be recycled * @return GLESTextureInfo The texture info */ public static GLESTextureInfo loadTexture( - File file, Rect dimensions, Effect effect, boolean recycle) { + File file, Rect dimensions, Effect effect, Rect screenDim, boolean recycle) { Bitmap bitmap = null; try { // Decode and associate the bitmap (invert the desired dimensions) @@ -320,10 +320,9 @@ public final class GLESUtil { if (DEBUG) Log.e(TAG, msg); return new GLESTextureInfo(); } - bitmap = effect.apply(bitmap); if (DEBUG) Log.d(TAG, "image: " + file.getAbsolutePath()); - GLESTextureInfo ti = loadTexture(bitmap); + GLESTextureInfo ti = loadTexture(bitmap, effect, screenDim); ti.path = file; return ti; @@ -345,12 +344,13 @@ public final class GLESUtil { * * @param ctx The current context * @param resourceId The resource identifier - * @param effect The effect to apply to the image + * @param effect The effect to apply to the image or null if no effect is needed + * @param screenDim The screen dimensions * @param recycle If the bitmap should be recycled * @return GLESTextureInfo The texture info */ public static GLESTextureInfo loadTexture( - Context ctx, int resourceId, Effect effect, boolean recycle) { + Context ctx, int resourceId, Effect effect, Rect screenDim, boolean recycle) { Bitmap bitmap = null; InputStream raw = null; try { @@ -364,7 +364,7 @@ public final class GLESUtil { } if (DEBUG) Log.d(TAG, "resourceId: " + resourceId); - GLESTextureInfo ti = loadTexture(bitmap); + GLESTextureInfo ti = loadTexture(bitmap, effect, screenDim); return ti; } catch (Exception e) { @@ -392,18 +392,22 @@ public final class GLESUtil { * Method that loads texture from a bitmap reference. * * @param bitmap The bitmap reference + * @param effect The effect to apply to the image or null if no effect is needed + * @param screenDim The screen dimensions * @return GLESTextureInfo The texture info */ - public static GLESTextureInfo loadTexture(Bitmap bitmap) { + public static GLESTextureInfo loadTexture(Bitmap bitmap, Effect effect, Rect screenDim) { // Check that we have a valid image name reference if (bitmap == null) { return new GLESTextureInfo(); } - int[] textureNames = new int[1]; - GLES20.glGenTextures(1, textureNames, 0); + int num = effect == null ? 1 : 2; + + int[] textureNames = new int[num]; + GLES20.glGenTextures(num, textureNames, 0); GLESUtil.glesCheckError("glGenTextures"); - if (textureNames[0] <= 0) { + if (textureNames[0] <= 0 || (effect != null && textureNames[1] <= 0)) { String msg = "Failed to generate a valid texture"; if (DEBUG) Log.e(TAG, msg); return new GLESTextureInfo(); @@ -431,9 +435,23 @@ public final class GLESUtil { return new GLESTextureInfo(); } + // Has a effect? + int handle = textureNames[0]; + if (effect != null) { + // Apply the effect + effect.apply(textureNames[0], screenDim.width(), screenDim.height(), textureNames[1]); + effect.release(); + handle = textureNames[1]; + + // Delete the unused texture + int[] textures = {textureNames[0]}; + GLES20.glDeleteTextures(1, textures, 0); + GLESUtil.glesCheckError("glTexParameteri"); + } + // Return the texture handle identifier and the associated info GLESTextureInfo ti = new GLESTextureInfo(); - ti.handle = textureNames[0]; + ti.handle = handle; ti.bitmap = bitmap; ti.path = null; return ti; diff --git a/src/org/cyanogenmod/wallpapers/photophase/PhotoFrame.java b/src/org/cyanogenmod/wallpapers/photophase/PhotoFrame.java index 3cac77f..7e29a5a 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/PhotoFrame.java +++ b/src/org/cyanogenmod/wallpapers/photophase/PhotoFrame.java @@ -25,7 +25,6 @@ import org.cyanogenmod.wallpapers.photophase.GLESUtil.GLESTextureInfo; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; -import java.nio.ShortBuffer; /** @@ -38,26 +37,21 @@ public class PhotoFrame implements TextureRequestor { */ public static final int COORDS_PER_VERTER = 3; - // The photo frame is always a rectangle, so here applies 2 triangle order - private static final short[] VERTEX_ORDER = { 0, 1, 2, 0, 2, 3 }; - // The default texture coordinates (fit to frame) private static final float[] DEFAULT_TEXTURE_COORDS = { - 0, 0, // top left - 0, 1, // bottom left - 1, 1, // bottom right - 1, 0 // top right + 0.0f, 1.0f, + 1.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f }; + private final TextureManager mTextureManager; private final float mFrameWidth, mFrameHeight; - private final float mPictureWidth, mPictureHeight; private final float[] mFrameVertex; - private final float[] mPictureVertex; - private FloatBuffer mPictureVertexBuffer; - private ShortBuffer mVertexOrderBuffer; + private FloatBuffer mPositionBuffer; private FloatBuffer mTextureBuffer; private GLESTextureInfo mTextureInfo; @@ -74,11 +68,10 @@ public class PhotoFrame implements TextureRequestor { * @param ctx The current context * @param textureManager The texture manager * @param frameVertex A 4 dimension array with the coordinates per vertex plus padding - * @param pictureVertex A 4 dimension array with the coordinates per vertex * @param color Background color */ public PhotoFrame(Context ctx, TextureManager textureManager, - float[] frameVertex, float[] pictureVertex, GLColor color) { + float[] frameVertex, GLColor color) { super(); mLoaded = false; mBackgroundColor = color; @@ -86,25 +79,15 @@ public class PhotoFrame implements TextureRequestor { // Save dimensions mFrameVertex = frameVertex; - mFrameWidth = frameVertex[9] - frameVertex[0]; - mFrameHeight = frameVertex[4] - frameVertex[1]; - mPictureVertex = pictureVertex; - mPictureWidth = pictureVertex[9] - pictureVertex[0]; - mPictureHeight = pictureVertex[4] - pictureVertex[1]; + mFrameWidth = frameVertex[6] - frameVertex[4]; + mFrameHeight = frameVertex[1] - frameVertex[5]; // Initialize vertex byte buffer for shape coordinates - ByteBuffer bb = ByteBuffer.allocateDirect(pictureVertex.length * 4); // (# of coordinate values * 4 bytes per float) - bb.order(ByteOrder.nativeOrder()); - mPictureVertexBuffer = bb.asFloatBuffer(); - mPictureVertexBuffer.put(pictureVertex); - mPictureVertexBuffer.position(0); - - // Initialize vertex byte buffer for shape coordinates order - bb = ByteBuffer.allocateDirect(VERTEX_ORDER.length * 2); // (# of coordinate values * 2 bytes per short) + ByteBuffer bb = ByteBuffer.allocateDirect(frameVertex.length * 4); // (# of coordinate values * 4 bytes per float) bb.order(ByteOrder.nativeOrder()); - mVertexOrderBuffer = bb.asShortBuffer(); - mVertexOrderBuffer.put(VERTEX_ORDER); - mVertexOrderBuffer.position(0); + mPositionBuffer = bb.asFloatBuffer(); + mPositionBuffer.put(frameVertex); + mPositionBuffer.position(0); // Load the texture mTextureInfo = null; @@ -147,7 +130,7 @@ public class PhotoFrame implements TextureRequestor { ByteBuffer bb = ByteBuffer.allocateDirect(textureCoords.length * 4); // (# of coordinate values * 4 bytes per float) bb.order(ByteOrder.nativeOrder()); synchronized (mSync) { - // Synchronize buffer swap + // Swap buffers mTextureBuffer = bb.asFloatBuffer(); mTextureBuffer.put(textureCoords); mTextureBuffer.position(0); @@ -165,30 +148,12 @@ public class PhotoFrame implements TextureRequestor { } /** - * Method that returns the picture vertex + * Method that returns the position vertex buffer * - * @return float[] The picture vertex + * @return FloatBuffer The position vertex buffer */ - public float[] getPictureVertex() { - return mPictureVertex; - } - - /** - * Method that returns the picture vertex buffer - * - * @return FloatBuffer The picture vertex buffer - */ - public FloatBuffer getPictureVertexBuffer() { - return mPictureVertexBuffer; - } - - /** - * Method that returns the vertex order buffer - * - * @return ShortBuffer The vertex order buffer - */ - public ShortBuffer getVertexOrderBuffer() { - return mVertexOrderBuffer; + public FloatBuffer getPositionBuffer() { + return mPositionBuffer; } /** @@ -242,24 +207,6 @@ public class PhotoFrame implements TextureRequestor { } /** - * Method that returns the picture width - * - * @return float The picture width - */ - public float getPictureWidth() { - return mPictureWidth; - } - - /** - * Method that returns the picture height - * - * @return float The picture height - */ - public float getPictureHeight() { - return mPictureHeight; - } - - /** * Method that returns the background color of the frame * * @return GLColor The background color @@ -288,17 +235,13 @@ public class PhotoFrame implements TextureRequestor { } mTextureInfo = null; - if (mPictureVertexBuffer != null) { - mPictureVertexBuffer.clear(); - } - if (mVertexOrderBuffer != null) { - mVertexOrderBuffer.clear(); + if (mPositionBuffer != null) { + mPositionBuffer.clear(); } if (mTextureBuffer != null) { mTextureBuffer.clear(); } - mPictureVertexBuffer = null; - mVertexOrderBuffer = null; + mPositionBuffer = null; mTextureBuffer = null; } } diff --git a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseRenderer.java b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseRenderer.java index c1b40e7..5c2e2bf 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseRenderer.java +++ b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseRenderer.java @@ -27,6 +27,7 @@ import android.content.res.Configuration; import android.content.res.Resources.NotFoundException; import android.graphics.PointF; import android.graphics.Rect; +import android.media.effect.EffectContext; import android.net.Uri; import android.opengl.GLES20; import android.opengl.GLException; @@ -56,19 +57,20 @@ public class PhotoPhaseRenderer implements GLSurfaceView.Renderer { private final long mInstance; private static long sInstances; - final Context mContext; + /*package*/ final Context mContext; + /*package*/ EffectContext mEffectContext; private final Handler mHandler; - final GLESSurfaceDispatcher mDispatcher; - TextureManager mTextureManager; + /*package*/ final GLESSurfaceDispatcher mDispatcher; + /*package*/ TextureManager mTextureManager; - PhotoPhaseWallpaperWorld mWorld; - ColorShape mOverlay; + /*package*/ PhotoPhaseWallpaperWorld mWorld; + /*package*/ ColorShape mOverlay; - long mLastRunningTransition; + /*package*/ long mLastRunningTransition; - int mWidth = -1; - int mHeight = -1; - int mMeasuredHeight = -1; + /*package*/ int mWidth = -1; + /*package*/ int mHeight = -1; + /*package*/ int mMeasuredHeight = -1; private final float[] mMVPMatrix = new float[16]; private final float[] mProjMatrix = new float[16]; @@ -76,7 +78,7 @@ public class PhotoPhaseRenderer implements GLSurfaceView.Renderer { private final Object mDrawing = new Object(); - final Object mMediaSync = new Object(); + /*package*/ final Object mMediaSync = new Object(); private PendingIntent mMediaScanIntent; private final BroadcastReceiver mSettingsChangedReceiver = new BroadcastReceiver() { @@ -216,6 +218,10 @@ public class PhotoPhaseRenderer implements GLSurfaceView.Renderer { // Register a receiver to listen for media reload request mContext.unregisterReceiver(mSettingsChangedReceiver); recycle(); + if (mEffectContext != null) { + mEffectContext.release(); + } + mEffectContext = null; mWidth = -1; mHeight = -1; mMeasuredHeight = -1; @@ -401,6 +407,12 @@ public class PhotoPhaseRenderer implements GLSurfaceView.Renderer { GLES20.glDepthFunc(GLES20.GL_LEQUAL); GLESUtil.glesCheckError("glDepthFunc"); + // Create an effect context + if (mEffectContext != null) { + mEffectContext.release(); + } + mEffectContext = EffectContext.createWithCurrentGlContext(); + // Create the texture manager and recycle the old one if (mTextureManager == null) { // Precalculate the window size for the TextureManager. In onSurfaceChanged @@ -415,8 +427,10 @@ public class PhotoPhaseRenderer implements GLSurfaceView.Renderer { ? PreferencesProvider.Preferences.Layout.getPortraitDisposition().size() : PreferencesProvider.Preferences.Layout.getLandscapeDisposition().size(); + // Recycle the current texture manager and create a new one recycle(); - mTextureManager = new TextureManager(mContext, mDispatcher, cc, dimensions); + mTextureManager = new TextureManager( + mContext, mEffectContext, mDispatcher, cc, dimensions); } } diff --git a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaper.java b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaper.java index ea65f9d..0c9f23c 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaper.java +++ b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaper.java @@ -140,7 +140,7 @@ public class PhotoPhaseWallpaper public void run() { // Only if the wallpaper is visible after a long press and // not in preview mode - if(isVisible() && !isPreview()) { + if (isVisible() && !isPreview()) { List<ActivityManager.RunningTaskInfo> taskInfo = mActivityManager.getRunningTasks(1); String topActivity = taskInfo.get(0).topActivity.getClassName(); diff --git a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java index 8fc5934..2f31617 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java +++ b/src/org/cyanogenmod/wallpapers/photophase/PhotoPhaseWallpaperWorld.java @@ -327,13 +327,12 @@ public class PhotoPhaseWallpaperWorld { for (Disposition disposition : dispositions) { // Create the photo frame float[] frameVertices = getVerticesFromDisposition(disposition, cellw, cellh); - float[] pictureVertices = getFramePadding(frameVertices, portrait ? w : h, portrait ? h : w); + frameVertices = getFramePadding(frameVertices, portrait ? w : h, portrait ? h : w); PhotoFrame frame = new PhotoFrame( mContext, mTextureManager, frameVertices, - pictureVertices, Colors.getBackground()); mPhotoFrames.add(frame); @@ -395,25 +394,21 @@ public class PhotoPhaseWallpaperWorld { Disposition disposition, float cellw, float cellh) { return new float[] { - // top left - -1.0f + (disposition.x * cellw), - 1.0f - (disposition.y * cellh), - 0.0f, - - // bottom left + // bottom left -1.0f + (disposition.x * cellw), 1.0f - ((disposition.y * cellh) + (disposition.h * cellh)), - 0.0f, - // bottom right + // bottom right -1.0f + ((disposition.x * cellw) + (disposition.w * cellw)), 1.0f - ((disposition.y * cellh) + (disposition.h * cellh)), - 0.0f, - // top right - -1.0f + ((disposition.x * cellw) + (disposition.w * cellw)), + // top left + -1.0f + (disposition.x * cellw), 1.0f - (disposition.y * cellh), - 0.0f + + // top right + -1.0f + ((disposition.x * cellw) + (disposition.w * cellw)), + 1.0f - (disposition.y * cellh) }; } @@ -431,13 +426,13 @@ public class PhotoPhaseWallpaperWorld { final float pxw = (1 / (float)screenWidth) * PHOTO_FRAME_PADDING; final float pxh = (1 / (float)screenHeight) * PHOTO_FRAME_PADDING; paddingCoords[0] += pxw; - paddingCoords[1] -= pxh; - paddingCoords[3] += pxw; - paddingCoords[4] += pxh; + paddingCoords[1] += pxh; + paddingCoords[2] -= pxw; + paddingCoords[3] += pxh; + paddingCoords[4] += pxw; + paddingCoords[5] -= pxh; paddingCoords[6] -= pxw; - paddingCoords[7] += pxh; - paddingCoords[9] -= pxw; - paddingCoords[10] -= pxh; + paddingCoords[7] -= pxh; return paddingCoords; } } diff --git a/src/org/cyanogenmod/wallpapers/photophase/TextureManager.java b/src/org/cyanogenmod/wallpapers/photophase/TextureManager.java index ac05b77..9c0d3d0 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/TextureManager.java +++ b/src/org/cyanogenmod/wallpapers/photophase/TextureManager.java @@ -18,6 +18,7 @@ package org.cyanogenmod.wallpapers.photophase; import android.content.Context; import android.graphics.Rect; +import android.media.effect.EffectContext; import android.opengl.GLES20; import android.util.Log; @@ -44,6 +45,7 @@ public class TextureManager implements OnMediaPictureDiscoveredListener { static final List<GLESTextureInfo> sRecycledBitmaps = new ArrayList<GLESTextureInfo>(); final Context mContext; + final EffectContext mEffectContext; final Object mSync; final List<TextureRequestor> mPendingRequests; final FixedQueue<GLESTextureInfo> mQueue = new FixedQueue<GLESTextureInfo>(QUEUE_SIZE); @@ -74,12 +76,14 @@ public class TextureManager implements OnMediaPictureDiscoveredListener { if (sRecycledBitmaps.size() > 0) { // Bind to the GLES context GLESTextureInfo oldTextureInfo = sRecycledBitmaps.remove(0); - ti = GLESUtil.loadTexture(oldTextureInfo.bitmap); + ti = GLESUtil.loadTexture(oldTextureInfo.bitmap, + Effects.getNextEffect(mEffectContext), mDimensions); ti.path = oldTextureInfo.path; oldTextureInfo.bitmap = null; } else { // Load and bind to the GLES context - ti = GLESUtil.loadTexture(mImage, mDimensions, Effects.getNextEffect(), false); + ti = GLESUtil.loadTexture(mImage, mDimensions, + Effects.getNextEffect(mEffectContext), mDimensions, false); } synchronized (mSync) { @@ -111,13 +115,16 @@ public class TextureManager implements OnMediaPictureDiscoveredListener { * Constructor of <code>TextureManager</code> * * @param ctx The current context + * @param effectCtx The current effect context * @param dispatcher The GLES dispatcher * @param requestors The number of requestors * @param dimensions The desired dimensions for the decoded bitmaps */ - public TextureManager(final Context ctx, GLESSurfaceDispatcher dispatcher, int requestors, Rect dimensions) { + public TextureManager(final Context ctx, final EffectContext effectCtx, + GLESSurfaceDispatcher dispatcher, int requestors, Rect dimensions) { super(); mContext = ctx; + mEffectContext = effectCtx; mDispatcher = dispatcher; mDimensions = dimensions; mSync = new Object(); diff --git a/src/org/cyanogenmod/wallpapers/photophase/effects/BlackAndWhiteEffect.java b/src/org/cyanogenmod/wallpapers/photophase/effects/BlackAndWhiteEffect.java deleted file mode 100644 index dbda330..0000000 --- a/src/org/cyanogenmod/wallpapers/photophase/effects/BlackAndWhiteEffect.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.ColorMatrix; -import android.graphics.ColorMatrixColorFilter; -import android.graphics.Paint; - -/** - * This effect converts the source image to black and white color scheme. - */ -public class BlackAndWhiteEffect extends Effect { - - /** - * {@inheritDoc} - */ - @Override - public Bitmap apply(Bitmap src) { - try { - final int height = src.getHeight(); - final int width = src.getWidth(); - - Bitmap dst = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - final Canvas c = new Canvas(dst); - final Paint paint = new Paint(); - final ColorMatrix cm = new ColorMatrix(); - cm.setSaturation(0); - final ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm); - paint.setColorFilter(f); - c.drawBitmap(src, 0, 0, paint); - return dst; - } finally { - src.recycle(); - } - } - -} diff --git a/src/org/cyanogenmod/wallpapers/photophase/effects/Effect.java b/src/org/cyanogenmod/wallpapers/photophase/effects/Effect.java deleted file mode 100644 index 4ab4695..0000000 --- a/src/org/cyanogenmod/wallpapers/photophase/effects/Effect.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.graphics.Bitmap; - -/** - * The base class for all image effects. - */ -public abstract class Effect { - - /** - * Method that applies the effect - * - * @param src The source bitmap - * @return Bitmap The bitmap with the effect applied - */ - public abstract Bitmap apply(Bitmap src); -} diff --git a/src/org/cyanogenmod/wallpapers/photophase/effects/Effects.java b/src/org/cyanogenmod/wallpapers/photophase/effects/Effects.java index f8fd90d..c6a739d 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/effects/Effects.java +++ b/src/org/cyanogenmod/wallpapers/photophase/effects/Effects.java @@ -16,6 +16,10 @@ package org.cyanogenmod.wallpapers.photophase.effects; +import android.media.effect.Effect; +import android.media.effect.EffectContext; +import android.media.effect.EffectFactory; + import org.cyanogenmod.wallpapers.photophase.preferences.PreferencesProvider.Preferences; /** @@ -32,15 +36,15 @@ public class Effects { */ RANDOM, /** - * @see NullEffect + * No effect */ NO_EFFECT, /** - * @see BlackAndWhiteEffect + * @see EffectFactory#EFFECT_GRAYSCALE */ - BLACK_AND_WHITE, + GRAYSCALE, /** - * @see SepiaEffect + * @see EffectFactory#EFFECT_SEPIA */ SEPIA; } @@ -48,21 +52,32 @@ public class Effects { /** * Method that return the next effect to use with the picture. * - * @return Effect The next effect to use + * @param effectContext The android media effects context + * @return Effect The next effect to use or null if no need to apply any effect */ - public static Effect getNextEffect() { + public static Effect getNextEffect(EffectContext effectContext) { + // Get a new instance of a effect factory + EffectFactory effectFactory = effectContext.getFactory(); + + // Get an effect based on the user preference int effect = Preferences.General.Effects.getEffectTypes(); if (effect == EFFECTS.RANDOM.ordinal()) { int low = EFFECTS.NO_EFFECT.ordinal(); int hight = EFFECTS.values().length - 1; effect = low + (int)(Math.random() * ((hight - low) + 1)); } - if (effect == EFFECTS.BLACK_AND_WHITE.ordinal()) { - return new BlackAndWhiteEffect(); + + // Select the effect if is available + if (effect == EFFECTS.GRAYSCALE.ordinal()) { + if (EffectFactory.isEffectSupported(EffectFactory.EFFECT_GRAYSCALE)) { + return effectFactory.createEffect(EffectFactory.EFFECT_GRAYSCALE); + } } if (effect == EFFECTS.SEPIA.ordinal()) { - return new SepiaEffect(); + if (EffectFactory.isEffectSupported(EffectFactory.EFFECT_SEPIA)) { + return effectFactory.createEffect(EffectFactory.EFFECT_SEPIA); + } } - return new NullEffect(); + return null; } } diff --git a/src/org/cyanogenmod/wallpapers/photophase/effects/NullEffect.java b/src/org/cyanogenmod/wallpapers/photophase/effects/NullEffect.java deleted file mode 100644 index 0cd5e10..0000000 --- a/src/org/cyanogenmod/wallpapers/photophase/effects/NullEffect.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.graphics.Bitmap; - -/** - * A <code>null</code> effect. This class doesn't apply any filter to the bitmap - */ -public class NullEffect extends Effect { - - /** - * {@inheritDoc} - */ - @Override - public Bitmap apply(Bitmap bitmap) { - return bitmap; - } - -} diff --git a/src/org/cyanogenmod/wallpapers/photophase/effects/SepiaEffect.java b/src/org/cyanogenmod/wallpapers/photophase/effects/SepiaEffect.java deleted file mode 100644 index 15aa894..0000000 --- a/src/org/cyanogenmod/wallpapers/photophase/effects/SepiaEffect.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.ColorMatrix; -import android.graphics.ColorMatrixColorFilter; -import android.graphics.Paint; - -/** - * This effect converts the source image to sepia color scheme. - */ -public class SepiaEffect extends Effect { - - /** - * {@inheritDoc} - */ - @Override - public Bitmap apply(Bitmap src) { - try { - final int height = src.getHeight(); - final int width = src.getWidth(); - - Bitmap dst = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - final Canvas c = new Canvas(dst); - final Paint paint = new Paint(); - final ColorMatrix cmA = new ColorMatrix(); - cmA.setSaturation(0); - final ColorMatrix cmB = new ColorMatrix(); - cmB.setScale(1f, .95f, .82f, 1.0f); - cmA.setConcat(cmB, cmA); - final ColorMatrixColorFilter f = new ColorMatrixColorFilter(cmA); - paint.setColorFilter(f); - c.drawBitmap(src, 0, 0, paint); - return dst; - } finally { - src.recycle(); - } - } - -} diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/FadeTransition.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/FadeTransition.java index d88aafc..c314a88 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/transitions/FadeTransition.java +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/FadeTransition.java @@ -88,7 +88,7 @@ public class FadeTransition extends NullTransition { @Override public void select(PhotoFrame target) { super.select(target); - mOverlay = new ColorShape(mContext, target.getPictureVertex(), Colors.getBackground()); + mOverlay = new ColorShape(mContext, target.getFrameVertex()/*target.getPictureVertex()*/, Colors.getBackground()); mOverlay.setAlpha(0); } @@ -99,15 +99,13 @@ public class FadeTransition extends NullTransition { public void apply(float[] matrix) throws GLException { // Check internal vars if (mTarget == null || - mTarget.getPictureVertexBuffer() == null || - mTarget.getTextureBuffer() == null || - mTarget.getVertexOrderBuffer() == null) { + mTarget.getPositionBuffer() == null || + mTarget.getTextureBuffer() == null) { return; } if (mTransitionTarget == null || - mTransitionTarget.getPictureVertexBuffer() == null || - mTransitionTarget.getTextureBuffer() == null || - mTransitionTarget.getVertexOrderBuffer() == null) { + mTransitionTarget.getPositionBuffer() == null || + mTransitionTarget.getTextureBuffer() == null) { return; } diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/NullTransition.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/NullTransition.java index 0332bc5..e88689d 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/transitions/NullTransition.java +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/NullTransition.java @@ -101,9 +101,8 @@ public class NullTransition extends Transition { public void apply(float[] matrix) throws GLException { // Check internal vars if (mTarget == null || - mTarget.getPictureVertexBuffer() == null || - mTarget.getTextureBuffer() == null || - mTarget.getVertexOrderBuffer() == null) { + mTarget.getPositionBuffer() == null || + mTarget.getTextureBuffer() == null) { return; } @@ -114,54 +113,50 @@ public class NullTransition extends Transition { /** * Method that draws the picture texture * - * @param target + * @param target The target to draw * @param matrix The model-view-projection matrix */ protected void draw(PhotoFrame target, float[] matrix) { - // Set the program + // Bind default FBO + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); + + // Use our shader program useProgram(0); - // Bind the texture - int textureHandle = target.getTextureHandle(); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLESUtil.glesCheckError("glActiveTexture"); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle); - GLESUtil.glesCheckError("glBindTexture"); + // Disable blending + GLES20.glDisable(GLES20.GL_BLEND); - // Position - FloatBuffer vertexBuffer = target.getPictureVertexBuffer(); - vertexBuffer.position(0); - GLES20.glVertexAttribPointer( - mPositionHandlers[0], - PhotoFrame.COORDS_PER_VERTER, - GLES20.GL_FLOAT, - false, - PhotoFrame.COORDS_PER_VERTER * 4, - vertexBuffer); - GLESUtil.glesCheckError("glVertexAttribPointer"); - GLES20.glEnableVertexAttribArray(mPositionHandlers[0]); - GLESUtil.glesCheckError("glEnableVertexAttribArray"); + // Apply the projection and view transformation + GLES20.glUniformMatrix4fv(mMVPMatrixHandlers[0], 1, false, matrix, 0); + GLESUtil.glesCheckError("glUniformMatrix4fv"); // Texture FloatBuffer textureBuffer = target.getTextureBuffer(); textureBuffer.position(0); - GLES20.glVertexAttribPointer( - mTextureCoordHandlers[0], - 2, - GLES20.GL_FLOAT, - false, - 2 * 4, - textureBuffer); + GLES20.glVertexAttribPointer(mTextureCoordHandlers[0], 2, GLES20.GL_FLOAT, false, 0, textureBuffer); GLESUtil.glesCheckError("glVertexAttribPointer"); GLES20.glEnableVertexAttribArray(mTextureCoordHandlers[0]); GLESUtil.glesCheckError("glEnableVertexAttribArray"); - // Apply the projection and view transformation - GLES20.glUniformMatrix4fv(mMVPMatrixHandlers[0], 1, false, matrix, 0); - GLESUtil.glesCheckError("glUniformMatrix4fv"); + // Position + FloatBuffer positionBuffer = target.getPositionBuffer(); + positionBuffer.position(0); + GLES20.glVertexAttribPointer(mPositionHandlers[0], 2, GLES20.GL_FLOAT, false, 0, positionBuffer); + GLESUtil.glesCheckError("glVertexAttribPointer"); + GLES20.glEnableVertexAttribArray(mPositionHandlers[0]); + GLESUtil.glesCheckError("glEnableVertexAttribArray"); + + // Set the input texture + int textureHandle = target.getTextureHandle(); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLESUtil.glesCheckError("glActiveTexture"); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle); + GLESUtil.glesCheckError("glBindTexture"); + GLES20.glUniform1i(mTextureHandlers[0], 0); + GLESUtil.glesCheckError("glBindTexture"); - // Draw the photo frame - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4); + // Draw + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); GLESUtil.glesCheckError("glDrawElements"); // Disable attributes diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/SwapTransition.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/SwapTransition.java index d100110..d5cf15f 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/transitions/SwapTransition.java +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/SwapTransition.java @@ -84,15 +84,13 @@ public class SwapTransition extends NullTransition { public void apply(float[] matrix) throws GLException { // Check internal vars if (mTarget == null || - mTarget.getPictureVertexBuffer() == null || - mTarget.getTextureBuffer() == null || - mTarget.getVertexOrderBuffer() == null) { + mTarget.getPositionBuffer() == null || + mTarget.getTextureBuffer() == null) { return; } if (mTransitionTarget == null || - mTransitionTarget.getPictureVertexBuffer() == null || - mTransitionTarget.getTextureBuffer() == null || - mTransitionTarget.getVertexOrderBuffer() == null) { + mTransitionTarget.getPositionBuffer() == null || + mTransitionTarget.getTextureBuffer() == null) { return; } diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/Transition.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/Transition.java index 315a9f8..cd24b54 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/transitions/Transition.java +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/Transition.java @@ -35,6 +35,7 @@ public abstract class Transition { private final TextureManager mTextureManager; protected int[] mProgramHandlers; + protected int[] mTextureHandlers; protected int[] mPositionHandlers; protected int[] mTextureCoordHandlers; protected int[] mMVPMatrixHandlers; @@ -64,6 +65,7 @@ public abstract class Transition { assert mVertexShader.length != mFragmentShader.length; int cc = mVertexShader.length; mProgramHandlers = new int[cc]; + mTextureHandlers = new int[cc]; mPositionHandlers = new int[cc]; mTextureCoordHandlers = new int[cc]; mMVPMatrixHandlers = new int[cc]; @@ -86,7 +88,6 @@ public abstract class Transition { mContext, mTextureManager, mTarget.getFrameVertex(), - mTarget.getPictureVertex(), mTarget.getBackgroundColor()); } } @@ -157,6 +158,8 @@ public abstract class Transition { mProgramHandlers[index] = GLESUtil.createProgram( mContext.getResources(), mVertexShader[index], mFragmentShader[index]); + mTextureHandlers[index] = + GLES20.glGetAttribLocation(mProgramHandlers[index], "sTexture"); mPositionHandlers[index] = GLES20.glGetAttribLocation(mProgramHandlers[index], "aPosition"); GLESUtil.glesCheckError("glGetAttribLocation"); @@ -192,6 +195,7 @@ public abstract class Transition { GLESUtil.glesCheckError("glDeleteProgram"); } mProgramHandlers[i] = 0; + mTextureHandlers[i] = 0; mPositionHandlers[i] = 0; mTextureCoordHandlers[i] = 0; mMVPMatrixHandlers[i] = 0; diff --git a/src/org/cyanogenmod/wallpapers/photophase/transitions/TranslateTransition.java b/src/org/cyanogenmod/wallpapers/photophase/transitions/TranslateTransition.java index 4e32a4a..33e69d7 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/transitions/TranslateTransition.java +++ b/src/org/cyanogenmod/wallpapers/photophase/transitions/TranslateTransition.java @@ -29,7 +29,6 @@ import org.cyanogenmod.wallpapers.photophase.TextureManager; import org.cyanogenmod.wallpapers.photophase.transitions.Transitions.TRANSITIONS; import java.nio.FloatBuffer; -import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -120,16 +119,16 @@ public class TranslateTransition extends Transition { new ArrayList<TranslateTransition.TRANSLATE_MODES>( Arrays.asList(TRANSLATE_MODES.values())); float[] vertex = target.getFrameVertex(); - if (vertex[0] != -1.0f) { + if (vertex[4] != -1.0f) { modes.remove(TRANSLATE_MODES.RIGHT_TO_LEFT); } - if (vertex[9] != 1.0f) { + if (vertex[6] != 1.0f) { modes.remove(TRANSLATE_MODES.LEFT_TO_RIGHT); } - if (vertex[1] != 1.0f) { + if (vertex[5] != 1.0f) { modes.remove(TRANSLATE_MODES.DOWN_TO_UP); } - if (vertex[4] != -1.0f) { + if (vertex[1] != -1.0f) { modes.remove(TRANSLATE_MODES.UP_TO_DOWN); } @@ -145,8 +144,8 @@ public class TranslateTransition extends Transition { @Override public boolean isSelectable(PhotoFrame frame) { float[] vertex = frame.getFrameVertex(); - if (vertex[0] == -1.0f || vertex[9] == 1.0f || - vertex[1] == 1.0f || vertex[4] == -1.0f) { + if (vertex[4] == -1.0f || vertex[6] == 1.0f || + vertex[5] == 1.0f || vertex[1] == -1.0f) { return true; } return false; @@ -168,15 +167,13 @@ public class TranslateTransition extends Transition { public void apply(float[] matrix) throws GLException { // Check internal vars if (mTarget == null || - mTarget.getPictureVertexBuffer() == null || - mTarget.getTextureBuffer() == null || - mTarget.getVertexOrderBuffer() == null) { + mTarget.getPositionBuffer() == null || + mTarget.getTextureBuffer() == null) { return; } if (mTransitionTarget == null || - mTransitionTarget.getPictureVertexBuffer() == null || - mTransitionTarget.getTextureBuffer() == null || - mTransitionTarget.getVertexOrderBuffer() == null) { + mTransitionTarget.getPositionBuffer() == null || + mTransitionTarget.getTextureBuffer() == null) { return; } @@ -218,7 +215,7 @@ public class TranslateTransition extends Transition { GLESUtil.glesCheckError("glBindTexture"); // Position - FloatBuffer vertexBuffer = mTarget.getPictureVertexBuffer(); + FloatBuffer vertexBuffer = mTarget.getPositionBuffer(); vertexBuffer.position(0); GLES20.glVertexAttribPointer( mPositionHandlers[0], @@ -248,8 +245,8 @@ public class TranslateTransition extends Transition { // Calculate the delta distance float distance = (mMode.compareTo(TRANSLATE_MODES.LEFT_TO_RIGHT) == 0 || mMode.compareTo(TRANSLATE_MODES.RIGHT_TO_LEFT) == 0) - ? mTarget.getPictureWidth() - : mTarget.getPictureHeight(); + ? mTarget.getFrameWidth() + : mTarget.getFrameHeight(); if (mMode.compareTo(TRANSLATE_MODES.RIGHT_TO_LEFT) == 0 || mMode.compareTo(TRANSLATE_MODES.DOWN_TO_UP) == 0) { distance *= -1; } @@ -267,13 +264,7 @@ public class TranslateTransition extends Transition { GLESUtil.glesCheckError("glUniformMatrix4fv"); // Draw the photo frame - ShortBuffer vertexOrderBuffer = mTarget.getVertexOrderBuffer(); - vertexOrderBuffer.position(0); - GLES20.glDrawElements( - GLES20.GL_TRIANGLE_FAN, - 6, - GLES20.GL_UNSIGNED_SHORT, - vertexOrderBuffer); + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); GLESUtil.glesCheckError("glDrawElements"); // Disable attributes @@ -301,7 +292,7 @@ public class TranslateTransition extends Transition { GLESUtil.glesCheckError("glBindTexture"); // Position - FloatBuffer vertexBuffer = mTransitionTarget.getPictureVertexBuffer(); + FloatBuffer vertexBuffer = mTransitionTarget.getPositionBuffer(); vertexBuffer.position(0); GLES20.glVertexAttribPointer( mPositionHandlers[1], @@ -335,13 +326,7 @@ public class TranslateTransition extends Transition { GLESUtil.glesCheckError("glUniformMatrix4fv"); // Draw the photo frame - ShortBuffer vertexOrderBuffer = mTransitionTarget.getVertexOrderBuffer(); - vertexOrderBuffer.position(0); - GLES20.glDrawElements( - GLES20.GL_TRIANGLE_FAN, - 6, - GLES20.GL_UNSIGNED_SHORT, - vertexOrderBuffer); + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); GLESUtil.glesCheckError("glDrawElements"); // Disable attributes diff --git a/src/org/cyanogenmod/wallpapers/photophase/utils/MERAlgorithm.java b/src/org/cyanogenmod/wallpapers/photophase/utils/MERAlgorithm.java index bd29235..8e793ae 100644 --- a/src/org/cyanogenmod/wallpapers/photophase/utils/MERAlgorithm.java +++ b/src/org/cyanogenmod/wallpapers/photophase/utils/MERAlgorithm.java @@ -23,6 +23,9 @@ import java.util.Stack; * The maximal empty rectangle algorithm that allows to find the rectangle with the maximal * area that could be create in empty areas (in this case 0 in a byte matrix) */ +// +// Based on the source discussed at http://discuss.leetcode.com/questions/260/maximal-rectangle +// public final class MERAlgorithm { /** |