import com.android.gallery3d.data.DownloadCache;
import com.android.gallery3d.data.ImageCacheService;
import com.android.gallery3d.gadget.WidgetUtils;
-import com.android.gallery3d.photoeditor.PhotoEditor;
import com.android.gallery3d.picasasource.PicasaSource;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.LightCycleHelper;
GalleryUtils.initialize(this);
WidgetUtils.initialize(this);
PicasaSource.initialize(this);
- int state = ApiHelper.ENABLE_PHOTO_EDITOR
- ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
- getPackageManager().setComponentEnabledSetting(
- new ComponentName(this, PhotoEditor.class),
- state, PackageManager.DONT_KILL_APP);
mStitchingProgressManager = LightCycleHelper.createStitchingManagerInstance(this);
if (mStitchingProgressManager != null) {
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.util.AttributeSet;
-import android.widget.ViewSwitcher;
-
-import com.android.gallery3d.R;
-
-/**
- * Action bar that contains buttons such as undo, redo, save, etc.
- */
-public class ActionBar extends RestorableView {
-
- public ActionBar(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected int childLayoutId() {
- return R.layout.photoeditor_actionbar;
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
-
- // Show the action-bar title only when there's still room for it; otherwise, hide it.
- int width = 0;
- for (int i = 0; i < getChildCount(); i++) {
- width += getChildAt(i).getWidth();
- }
- findViewById(R.id.action_bar_title).setVisibility(((width > r - l)) ? INVISIBLE: VISIBLE);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- updateButtons(false, false);
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- showSaveOrShare();
- }
-
- /**
- * Save/share button may need being switched when undo/save enabled status is changed/restored.
- */
- private void showSaveOrShare() {
- // Show share-button only after photo is edited and saved; otherwise, show save-button.
- boolean showShare = findViewById(R.id.undo_button).isEnabled()
- && !findViewById(R.id.save_button).isEnabled();
- ViewSwitcher switcher = (ViewSwitcher) findViewById(R.id.save_share_buttons);
- int next = switcher.getNextView().getId();
- if ((showShare && (next == R.id.share_button))
- || (!showShare && (next == R.id.save_button))) {
- switcher.showNext();
- }
- }
-
- public void updateButtons(boolean canUndo, boolean canRedo) {
- setViewEnabled(R.id.undo_button, canUndo);
- setViewEnabled(R.id.redo_button, canRedo);
- setViewEnabled(R.id.save_button, canUndo);
- showSaveOrShare();
- }
-
- public void updateSave(boolean canSave) {
- setViewEnabled(R.id.save_button, canSave);
- showSaveOrShare();
- }
-
- public void clickBack() {
- findViewById(R.id.action_bar_back).performClick();
- }
-
- public boolean canSave() {
- return findViewById(R.id.save_button).isEnabled();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
-import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.provider.MediaStore.Images.ImageColumns;
-import android.util.Log;
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Utils for bitmap operations.
- */
-public class BitmapUtils {
-
- private static final String TAG = "BitmapUtils";
- private static final int DEFAULT_COMPRESS_QUALITY = 90;
- private static final int INDEX_ORIENTATION = 0;
-
- private static final String[] IMAGE_PROJECTION = new String[] {
- ImageColumns.ORIENTATION
- };
-
- private final Context context;
-
- public BitmapUtils(Context context) {
- this.context = context;
- }
-
- private static Bitmap createBitmap(Bitmap source, Matrix m) {
- return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), m, true);
- }
-
- private void closeStream(Closeable stream) {
- if (stream != null) {
- try {
- stream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- private Rect getBitmapBounds(Uri uri) {
- Rect bounds = new Rect();
- InputStream is = null;
-
- try {
- is = context.getContentResolver().openInputStream(uri);
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(is, null, options);
-
- bounds.right = options.outWidth;
- bounds.bottom = options.outHeight;
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } finally {
- closeStream(is);
- }
-
- return bounds;
- }
-
- private int getOrientation(Uri uri) {
- int orientation = 0;
- Cursor cursor = null;
- try {
- cursor = context.getContentResolver().query(uri, IMAGE_PROJECTION, null, null, null);
- if ((cursor != null) && cursor.moveToNext()) {
- orientation = cursor.getInt(INDEX_ORIENTATION);
- }
- } catch (Exception e) {
- // Ignore error for no orientation column; just use the default orientation value 0.
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return orientation;
- }
-
- /**
- * Decodes bitmap that keeps aspect-ratio and spans most within the bounds.
- */
- private Bitmap decodeBitmap(Uri uri, int width, int height) {
- InputStream is = null;
- Bitmap bitmap = null;
-
- try {
- // TODO: Take max pixels allowed into account for calculation to avoid possible OOM.
- Rect bounds = getBitmapBounds(uri);
- int sampleSize = Math.max(bounds.width() / width, bounds.height() / height);
- sampleSize = Math.min(sampleSize,
- Math.max(bounds.width() / height, bounds.height() / width));
-
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = Math.max(sampleSize, 1);
- options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-
- is = context.getContentResolver().openInputStream(uri);
- bitmap = BitmapFactory.decodeStream(is, null, options);
- } catch (FileNotFoundException e) {
- Log.e(TAG, "FileNotFoundException: " + uri);
- } finally {
- closeStream(is);
- }
-
- // Ensure bitmap in 8888 format, good for editing as well as GL compatible.
- if ((bitmap != null) && (bitmap.getConfig() != Bitmap.Config.ARGB_8888)) {
- Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, true);
- bitmap.recycle();
- bitmap = copy;
- }
-
- if (bitmap != null) {
- // Scale down the sampled bitmap if it's still larger than the desired dimension.
- float scale = Math.min((float) width / bitmap.getWidth(),
- (float) height / bitmap.getHeight());
- scale = Math.max(scale, Math.min((float) height / bitmap.getWidth(),
- (float) width / bitmap.getHeight()));
- if (scale < 1) {
- Matrix m = new Matrix();
- m.setScale(scale, scale);
- Bitmap transformed = createBitmap(bitmap, m);
- bitmap.recycle();
- return transformed;
- }
- }
- return bitmap;
- }
-
- /**
- * Gets decoded bitmap (maybe immutable) that keeps orientation as well.
- */
- public Bitmap getBitmap(Uri uri, int width, int height) {
- Bitmap bitmap = decodeBitmap(uri, width, height);
-
- // Rotate the decoded bitmap according to its orientation if it's necessary.
- if (bitmap != null) {
- int orientation = getOrientation(uri);
- if (orientation != 0) {
- Matrix m = new Matrix();
- m.setRotate(orientation);
- Bitmap transformed = createBitmap(bitmap, m);
- bitmap.recycle();
- return transformed;
- }
- }
- return bitmap;
- }
-
- /**
- * Saves the bitmap by given directory, filename, and format; if the directory is given null,
- * then saves it under the cache directory.
- */
- public File saveBitmap(Bitmap bitmap, File directory, String filename, CompressFormat format) {
-
- if (directory == null) {
- directory = context.getCacheDir();
- } else {
- // Check if the given directory exists or try to create it.
- if (!directory.isDirectory() && !directory.mkdirs()) {
- return null;
- }
- }
-
- File file = null;
- OutputStream os = null;
-
- try {
- filename = (format == CompressFormat.PNG) ? filename + ".png" : filename + ".jpg";
- file = new File(directory, filename);
- os = new FileOutputStream(file);
- bitmap.compress(format, DEFAULT_COMPRESS_QUALITY, os);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } finally {
- closeStream(os);
- }
- return file;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.photoeditor.actions.EffectAction;
-
-/**
- * Effects bar that contains all effects and shows them in categorized views.
- */
-public class EffectsBar extends LinearLayout {
-
- private final LayoutInflater inflater;
- private FilterStack filterStack;
- private EffectsMenu effectsMenu;
- private View effectsGallery;
- private EffectAction activeEffect;
-
- public EffectsBar(Context context, AttributeSet attrs) {
- super(context, attrs);
- inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- public void initialize(FilterStack filterStack) {
- this.filterStack = filterStack;
-
- effectsMenu = (EffectsMenu) findViewById(R.id.effects_menu);
- effectsMenu.setOnToggleListener(new EffectsMenu.OnToggleListener() {
-
- @Override
- public boolean onToggle(boolean isSelected, final int effectsId) {
- // Create and show effects-gallery only if the clicked toggle isn't selected or it's
- // selected but showing an active effect instead of effects-gallery. Set the clicked
- // toggle selected only when its effects-gallery will be created and shown.
- boolean select = !isSelected || (effectsGallery == null);
- exit(select ? new Runnable() {
-
- @Override
- public void run() {
- createEffectsGallery(effectsId);
- }
- } : null);
- return select;
- }
- });
- }
-
- private void createEffectsGallery(int effectsId) {
- // Inflate scrollable effects-gallery and desired effects into effects-bar.
- effectsGallery = inflater.inflate(R.layout.photoeditor_effects_gallery, this, false);
- ViewGroup scrollView = (ViewGroup) effectsGallery.findViewById(R.id.scroll_view);
- ViewGroup effects = (ViewGroup) inflater.inflate(effectsId, scrollView, false);
- for (int i = effects.getChildCount()-1; i >= 0; i--) {
- EffectAction effect = (EffectAction) effects.getChildAt(i);
- if( !effect.isPresent() ){
- effects.removeViewAt(i);
- continue;
- }
- setupEffect(effect);
- }
- scrollView.addView(effects);
- scrollView.scrollTo(0, 0);
- addView(effectsGallery, 0);
- }
-
- private void setupEffect(final EffectAction effect) {
- effect.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (isEnabled()) {
- // Set the clicked effect active before exiting effects-gallery.
- activeEffect = effect;
- exitEffectsGallery();
- EffectAction.ActionListener listener = new EffectAction.ActionListener() {
-
- @Override
- public void onOk() {
- exit(null);
- }
- };
- activeEffect.begin(getRootView(), filterStack, listener);
- }
- }
- });
- }
-
- private boolean exitEffectsGallery() {
- if (effectsGallery != null) {
- if (activeEffect != null) {
- // Detach the active effect to prevent it stopping effects-gallery from gc.
- ((ViewGroup) activeEffect.getParent()).removeView(activeEffect);
- }
- removeView(effectsGallery);
- effectsGallery = null;
- return true;
- }
- return false;
- }
-
- private boolean exitActiveEffect(final Runnable runnableOnDone) {
- if (activeEffect != null) {
- final Toolbar toolbar = (Toolbar) getRootView().findViewById(R.id.toolbar);
- toolbar.showSpinner();
- activeEffect.end(new Runnable() {
-
- @Override
- public void run() {
- toolbar.dismissSpinner();
- activeEffect = null;
- if (runnableOnDone != null) {
- runnableOnDone.run();
- }
- }
- });
- return true;
- }
- return false;
- }
-
- /**
- * Exits from effects gallery or the active effect; then executes the runnable if applicable.
- *
- * @return true if exiting from effects gallery or the active effect; otherwise, false.
- */
- public boolean exit(final Runnable runnableOnDone) {
- // Exit effects-menu selected states.
- effectsMenu.clearSelected();
-
- if (exitActiveEffect(runnableOnDone)) {
- return true;
- }
-
- boolean exited = exitEffectsGallery();
- if (runnableOnDone != null) {
- runnableOnDone.run();
- }
- return exited;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.gallery3d.R;
-
-/**
- * Effects menu that contains toggles mapping to corresponding groups of effects.
- */
-public class EffectsMenu extends RestorableView {
-
- /**
- * Listener of toggle changes.
- */
- public interface OnToggleListener {
-
- /**
- * Listens to the selected status and mapped effects-id of the clicked toggle.
- *
- * @return true to make the toggle selected; otherwise, make it unselected.
- */
- boolean onToggle(boolean isSelected, int effectsId);
- }
-
- public EffectsMenu(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected int childLayoutId() {
- return R.layout.photoeditor_effects_menu;
- }
-
- public void setOnToggleListener(OnToggleListener listener) {
- setToggleRunnable(listener, R.id.exposure_button, R.layout.photoeditor_effects_exposure);
- setToggleRunnable(listener, R.id.artistic_button, R.layout.photoeditor_effects_artistic);
- setToggleRunnable(listener, R.id.color_button, R.layout.photoeditor_effects_color);
- setToggleRunnable(listener, R.id.fix_button, R.layout.photoeditor_effects_fix);
- }
-
- private void setToggleRunnable(final OnToggleListener listener, final int toggleId,
- final int effectsId) {
- setClickRunnable(toggleId, new Runnable() {
-
- @Override
- public void run() {
- boolean selected = findViewById(toggleId).isSelected();
- setViewSelected(toggleId, listener.onToggle(selected, effectsId));
- }
- });
- }
-
- public void clearSelected() {
- ViewGroup menu = (ViewGroup) findViewById(R.id.toggles);
- for (int i = 0; i < menu.getChildCount(); i++) {
- View toggle = menu.getChildAt(i);
- if (toggle.isSelected()) {
- setViewSelected(toggle.getId(), false);
- }
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.graphics.Bitmap;
-import android.os.Bundle;
-
-import com.android.gallery3d.photoeditor.filters.Filter;
-
-import java.util.ArrayList;
-import java.util.Stack;
-
-/**
- * A stack of filters to be applied onto a photo.
- */
-public class FilterStack {
-
- /**
- * Listener of stack changes.
- */
- public interface StackListener {
-
- void onStackChanged(boolean canUndo, boolean canRedo);
- }
-
- private static final String APPLIED_STACK_KEY = "applied_stack";
- private static final String REDO_STACK_KEY = "redo_stack";
-
- private final Stack<Filter> appliedStack = new Stack<Filter>();
- private final Stack<Filter> redoStack = new Stack<Filter>();
-
- // Use two photo buffers as in and out in turns to apply filters in the stack.
- private final Photo[] buffers = new Photo[2];
- private final PhotoView photoView;
- private final StackListener stackListener;
-
- private Photo source;
- private Runnable queuedTopFilterChange;
- private boolean outputTopFilter;
- private volatile boolean paused;
-
- public FilterStack(PhotoView photoView, StackListener stackListener, Bundle savedState) {
- this.photoView = photoView;
- this.stackListener = stackListener;
- if (savedState != null) {
- appliedStack.addAll(getFilters(savedState, APPLIED_STACK_KEY));
- redoStack.addAll(getFilters(savedState, REDO_STACK_KEY));
- outputTopFilter = true;
- stackListener.onStackChanged(!appliedStack.empty(), !redoStack.empty());
- }
- }
-
- private ArrayList<Filter> getFilters(Bundle savedState, String key) {
- // Infer Filter array-list from the Parcelable array-list by the specified returned type.
- return savedState.getParcelableArrayList(key);
- }
-
- public void saveStacks(Bundle outState) {
- outState.putParcelableArrayList(APPLIED_STACK_KEY, new ArrayList<Filter>(appliedStack));
- outState.putParcelableArrayList(REDO_STACK_KEY, new ArrayList<Filter>(redoStack));
- }
-
- private void reallocateBuffer(int target) {
- int other = target ^ 1;
- buffers[target] = Photo.create(buffers[other].width(), buffers[other].height());
- }
-
- private void invalidate() {
- // In/out buffers need redrawn by re-applying filters on source photo.
- for (int i = 0; i < buffers.length; i++) {
- if (buffers[i] != null) {
- buffers[i].clear();
- buffers[i] = null;
- }
- }
- if (source != null) {
- buffers[0] = Photo.create(source.width(), source.height());
- reallocateBuffer(1);
-
- // Source photo will be displayed if there is no filter stacked.
- Photo photo = source;
- int size = outputTopFilter ? appliedStack.size() : appliedStack.size() - 1;
- for (int i = 0; i < size && !paused; i++) {
- photo = runFilter(i);
- }
- // Clear photo-view transformation when the top filter will be outputted.
- photoView.setPhoto(photo, outputTopFilter);
- }
- }
-
- private void invalidateTopFilter() {
- if (!appliedStack.empty()) {
- outputTopFilter = true;
- photoView.setPhoto(runFilter(appliedStack.size() - 1), true);
- }
- }
-
- private Photo runFilter(int filterIndex) {
- int out = getOutBufferIndex(filterIndex);
- Photo input = (filterIndex > 0) ? buffers[out ^ 1] : source;
- if ((input != null) && (buffers[out] != null)) {
- if (!buffers[out].matchDimension(input)) {
- buffers[out].clear();
- reallocateBuffer(out);
- }
- appliedStack.get(filterIndex).process(input, buffers[out]);
- nativeEglSetFenceAndWait();
- return buffers[out];
- }
- return null;
- }
-
- private int getOutBufferIndex(int filterIndex) {
- // buffers[0] and buffers[1] are swapped in turns as the in/out buffers for
- // processing stacked filters. For example, the first filter reads buffer[0] and
- // writes buffer[1]; the second filter then reads buffer[1] and writes buffer[0].
- // The returned index should only be used when the applied filter stack isn't empty.
- return (filterIndex + 1) % 2;
- }
-
- private void callbackDone(final OnDoneCallback callback) {
- // GL thread calls back to report UI thread the task is done.
- photoView.post(new Runnable() {
-
- @Override
- public void run() {
- callback.onDone();
- }
- });
- }
-
- private void stackChanged() {
- // GL thread calls back to report UI thread the stack is changed.
- final boolean canUndo = !appliedStack.empty();
- final boolean canRedo = !redoStack.empty();
- photoView.post(new Runnable() {
-
- @Override
- public void run() {
- stackListener.onStackChanged(canUndo, canRedo);
- }
- });
- }
-
- public void getOutputBitmap(final OnDoneBitmapCallback callback) {
- photoView.queue(new Runnable() {
-
- @Override
- public void run() {
- int filterIndex = appliedStack.size() - (outputTopFilter ? 1 : 2);
- Photo photo = (filterIndex < 0) ? source : buffers[getOutBufferIndex(filterIndex)];
- final Bitmap bitmap = (photo != null) ? photo.save() : null;
- photoView.post(new Runnable() {
-
- @Override
- public void run() {
- callback.onDone(bitmap);
- }
- });
- }
- });
- }
-
- public void setPhotoSource(final Bitmap bitmap, final OnDoneCallback callback) {
- photoView.queue(new Runnable() {
-
- @Override
- public void run() {
- source = Photo.create(bitmap);
- invalidate();
- callbackDone(callback);
- }
- });
- }
-
- private void pushFilterInternal(Filter filter) {
- appliedStack.push(filter);
- outputTopFilter = false;
- stackChanged();
- }
-
- public void pushFilter(final Filter filter) {
- photoView.queue(new Runnable() {
-
- @Override
- public void run() {
- while (!redoStack.empty()) {
- redoStack.pop().release();
- }
- pushFilterInternal(filter);
- }
- });
- }
-
- public void undo(final OnDoneCallback callback) {
- photoView.queue(new Runnable() {
-
- @Override
- public void run() {
- if (!appliedStack.empty()) {
- redoStack.push(appliedStack.pop());
- stackChanged();
- invalidate();
- }
- callbackDone(callback);
- }
- });
- }
-
- public void redo(final OnDoneCallback callback) {
- photoView.queue(new Runnable() {
-
- @Override
- public void run() {
- if (!redoStack.empty()) {
- pushFilterInternal(redoStack.pop());
- invalidateTopFilter();
- }
- callbackDone(callback);
- }
- });
- }
-
- public void topFilterChanged(final OnDoneCallback callback) {
- // Remove the outdated top-filter change before queuing a new one.
- if (queuedTopFilterChange != null) {
- photoView.remove(queuedTopFilterChange);
- }
- queuedTopFilterChange = new Runnable() {
-
- @Override
- public void run() {
- invalidateTopFilter();
- callbackDone(callback);
- }
- };
- photoView.queue(queuedTopFilterChange);
- }
-
- public void onPause() {
- // Flush pending queued operations and release effect-context before GL context is lost.
- // Use the flag to break from lengthy invalidate() in GL thread for not blocking onPause().
- paused = true;
- photoView.flush();
- photoView.queueEvent(new Runnable() {
-
- @Override
- public void run() {
- Filter.releaseContext();
- // Textures will be automatically deleted when GL context is lost.
- photoView.setPhoto(null, false);
- source = null;
- for (int i = 0; i < buffers.length; i++) {
- buffers[i] = null;
- }
- }
- });
- photoView.onPause();
- }
-
- public void onResume() {
- photoView.onResume();
- paused = false;
- }
-
- static {
- System.loadLibrary("jni_eglfence");
- }
-
- private native void nativeEglSetFenceAndWait();
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.ImageButton;
-
-/**
- * Image buttons used in Action-bar and Effects-menu that can be grayed out when set disabled.
- * (Text buttons are automatically grayed out when disabled; however, image buttons are not.)
- */
-public class ImageActionButton extends ImageButton {
-
- private static final float ENABLED_ALPHA = 1;
- private static final float DISABLED_ALPHA = 0.28f;
-
- public ImageActionButton(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
- setAlpha(enabled ? ENABLED_ALPHA : DISABLED_ALPHA);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.view.Gravity;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-
-/**
- * Asynchronous task for loading source photo screennail.
- */
-public class LoadScreennailTask extends AsyncTask<Uri, Void, Bitmap> {
-
- /**
- * Callback for the completed asynchronous task.
- */
- public interface Callback {
-
- void onComplete(Bitmap result);
- }
-
- private static final int SCREENNAIL_WIDTH = 1280;
- private static final int SCREENNAIL_HEIGHT = 960;
-
- private final Context context;
- private final Callback callback;
-
- public LoadScreennailTask(Context context, Callback callback) {
- this.context = context;
- this.callback = callback;
- }
-
- /**
- * The task should be executed with one given source photo uri.
- */
- @Override
- protected Bitmap doInBackground(Uri... params) {
- if (params[0] == null) {
- return null;
- }
- return new BitmapUtils(context).getBitmap(params[0], SCREENNAIL_WIDTH, SCREENNAIL_HEIGHT);
- }
-
- @Override
- protected void onPostExecute(Bitmap result) {
- if (result == null) {
- Toast toast = Toast.makeText(context, R.string.loading_failure, Toast.LENGTH_SHORT);
- toast.setGravity(Gravity.CENTER, 0, 0);
- toast.show();
- }
- callback.onComplete(result);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.graphics.Bitmap;
-
-/**
- * Callback that will only be called back in UI thread to notify that a bitmap is done.
- */
-public interface OnDoneBitmapCallback {
-
- void onDone(Bitmap bitmap);
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-/**
- * Callback that will only be called back in UI thread to notify that an operation has been done.
- */
-public interface OnDoneCallback {
-
- void onDone();
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.graphics.Bitmap;
-
-/**
- * Photo that holds a GL texture and all its methods must be only accessed from the GL thread.
- */
-public class Photo {
-
- private int texture;
- private int width;
- private int height;
-
- /**
- * Factory method to ensure every Photo instance holds a valid texture.
- */
- public static Photo create(Bitmap bitmap) {
- return (bitmap != null) ? new Photo(
- RendererUtils.createTexture(bitmap), bitmap.getWidth(), bitmap.getHeight()) : null;
- }
-
- public static Photo create(int width, int height) {
- return new Photo(RendererUtils.createTexture(), width, height);
- }
-
- private Photo(int texture, int width, int height) {
- this.texture = texture;
- this.width = width;
- this.height = height;
- }
-
- public int texture() {
- return texture;
- }
-
- public boolean matchDimension(Photo photo) {
- return ((photo.width == width) && (photo.height == height));
- }
-
- public void changeDimension(int width, int height) {
- this.width = width;
- this.height = height;
- RendererUtils.clearTexture(texture);
- texture = RendererUtils.createTexture();
- }
-
- public int width() {
- return width;
- }
-
- public int height() {
- return height;
- }
-
- public Bitmap save() {
- return RendererUtils.saveTexture(texture, width, height);
- }
-
- /**
- * Clears the texture; this instance should not be used after its clear() is called.
- */
- public void clear() {
- RendererUtils.clearTexture(texture);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.Bundle;
-
-import com.android.gallery3d.R;
-
-/**
- * Main activity of the photo editor that opens a photo and prepares tools for photo editing.
- */
-public class PhotoEditor extends Activity {
-
- private static final String SAVE_URI_KEY = "save_uri";
-
- private Uri sourceUri;
- private Uri saveUri;
- private FilterStack filterStack;
- private ActionBar actionBar;
- private EffectsBar effectsBar;
- private Toolbar toolbar;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.photoeditor_main);
-
- Intent intent = getIntent();
- if (Intent.ACTION_EDIT.equalsIgnoreCase(intent.getAction())) {
- sourceUri = intent.getData();
- }
-
- toolbar = (Toolbar) findViewById(R.id.toolbar);
- actionBar = (ActionBar) findViewById(R.id.action_bar);
- filterStack = new FilterStack((PhotoView) findViewById(R.id.photo_view),
- new FilterStack.StackListener() {
-
- @Override
- public void onStackChanged(boolean canUndo, boolean canRedo) {
- actionBar.updateButtons(canUndo, canRedo);
- }
- }, savedInstanceState);
- if (savedInstanceState != null) {
- saveUri = savedInstanceState.getParcelable(SAVE_URI_KEY);
- actionBar.updateSave(saveUri == null);
- }
-
- // Effects-bar is initially disabled until photo is successfully loaded.
- effectsBar = (EffectsBar) findViewById(R.id.effects_bar);
- effectsBar.initialize(filterStack);
- effectsBar.setEnabled(false);
-
- actionBar.setClickRunnable(R.id.undo_button, createUndoRedoRunnable(true));
- actionBar.setClickRunnable(R.id.redo_button, createUndoRedoRunnable(false));
- actionBar.setClickRunnable(R.id.save_button, createSaveRunnable());
- actionBar.setClickRunnable(R.id.share_button, createShareRunnable());
- actionBar.setClickRunnable(R.id.action_bar_back, createBackRunnable());
- }
-
- private void openPhoto() {
- toolbar.showSpinner();
- LoadScreennailTask.Callback callback = new LoadScreennailTask.Callback() {
-
- @Override
- public void onComplete(final Bitmap result) {
- filterStack.setPhotoSource(result, new OnDoneCallback() {
-
- @Override
- public void onDone() {
- toolbar.dismissSpinner();
- effectsBar.setEnabled(result != null);
- }
- });
- }
- };
- new LoadScreennailTask(this, callback).execute(sourceUri);
- }
-
- private Runnable createUndoRedoRunnable(final boolean undo) {
- return new Runnable() {
-
- @Override
- public void run() {
- effectsBar.exit(new Runnable() {
-
- @Override
- public void run() {
- toolbar.showSpinner();
- OnDoneCallback callback = new OnDoneCallback() {
-
- @Override
- public void onDone() {
- toolbar.dismissSpinner();
- }
- };
- if (undo) {
- filterStack.undo(callback);
- } else {
- filterStack.redo(callback);
- }
- }
- });
- }
- };
- }
-
- private Runnable createSaveRunnable() {
- return new Runnable() {
-
- @Override
- public void run() {
- effectsBar.exit(new Runnable() {
-
- @Override
- public void run() {
- toolbar.showSpinner();
- filterStack.getOutputBitmap(new OnDoneBitmapCallback() {
-
- @Override
- public void onDone(Bitmap bitmap) {
- SaveCopyTask.Callback callback = new SaveCopyTask.Callback() {
-
- @Override
- public void onComplete(Uri result) {
- toolbar.dismissSpinner();
- saveUri = result;
- actionBar.updateSave(saveUri == null);
- }
- };
- new SaveCopyTask(PhotoEditor.this, sourceUri, callback).execute(
- bitmap);
- }
- });
- }
- });
- }
- };
- }
-
- private Runnable createShareRunnable() {
- return new Runnable() {
-
- @Override
- public void run() {
- effectsBar.exit(new Runnable() {
-
- @Override
- public void run() {
- if (saveUri != null) {
- Intent intent = new Intent(Intent.ACTION_SEND);
- intent.putExtra(Intent.EXTRA_STREAM, saveUri);
- intent.setType("image/*");
- startActivity(intent);
- }
- }
- });
- }
- };
- }
-
- private Runnable createBackRunnable() {
- return new Runnable() {
-
- @Override
- public void run() {
- // Exit effects or go back to the previous activity on pressing back button.
- if (!effectsBar.exit(null)) {
- // Pop-up a dialog if there are unsaved changes.
- if (actionBar.canSave()) {
- new YesCancelDialogBuilder(PhotoEditor.this, new Runnable() {
-
- @Override
- public void run() {
- // Discard unsaved photo for the result.
- finish();
- }
- }, R.string.discard_unsaved_photo).show();
- } else {
- setResult(RESULT_OK, new Intent().setData(saveUri));
- finish();
- }
- }
- }
- };
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- filterStack.saveStacks(outState);
- outState.putParcelable(SAVE_URI_KEY, saveUri);
- }
-
- @Override
- public void onBackPressed() {
- actionBar.clickBack();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- filterStack.onPause();
- // Dismiss any running progress dialog as all operations are paused.
- toolbar.dismissSpinner();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- filterStack.onResume();
- openPhoto();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.content.Context;
-import android.graphics.RectF;
-import android.opengl.GLSurfaceView;
-import android.util.AttributeSet;
-
-import java.util.Vector;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * Renders and displays photo in the surface view.
- */
-public class PhotoView extends GLSurfaceView {
-
- private final PhotoRenderer renderer;
-
- public PhotoView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- renderer = new PhotoRenderer();
- setEGLContextClientVersion(2);
- setRenderer(renderer);
- setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
- }
-
- public RectF getPhotoBounds() {
- RectF photoBounds;
- synchronized (renderer.photoBounds) {
- photoBounds = new RectF(renderer.photoBounds);
- }
- return photoBounds;
- }
-
- /**
- * Queues a runnable and renders a frame after execution. Queued runnables could be later
- * removed by remove() or flush().
- */
- public void queue(Runnable r) {
- renderer.queue.add(r);
- requestRender();
- }
-
- /**
- * Removes the specified queued runnable.
- */
- public void remove(Runnable runnable) {
- renderer.queue.remove(runnable);
- }
-
- /**
- * Flushes all queued runnables to cancel their execution.
- */
- public void flush() {
- renderer.queue.clear();
- }
-
- /**
- * Sets photo for display; this method must be queued for GL thread.
- */
- public void setPhoto(Photo photo, boolean clearTransform) {
- renderer.setPhoto(photo, clearTransform);
- }
-
- /**
- * Rotates displayed photo; this method must be queued for GL thread.
- */
- public void rotatePhoto(float degrees) {
- renderer.rotatePhoto(degrees);
- }
-
- /**
- * Flips displayed photo; this method must be queued for GL thread.
- */
- public void flipPhoto(float horizontalDegrees, float verticalDegrees) {
- renderer.flipPhoto(horizontalDegrees, verticalDegrees);
- }
-
- /**
- * Renderer that renders the GL surface-view and only be called from the GL thread.
- */
- private class PhotoRenderer implements GLSurfaceView.Renderer {
-
- final Vector<Runnable> queue = new Vector<Runnable>();
- final RectF photoBounds = new RectF();
- RendererUtils.RenderContext renderContext;
- Photo photo;
- int viewWidth;
- int viewHeight;
- float rotatedDegrees;
- float flippedHorizontalDegrees;
- float flippedVerticalDegrees;
-
- void setPhoto(Photo photo, boolean clearTransform) {
- int width = (photo != null) ? photo.width() : 0;
- int height = (photo != null) ? photo.height() : 0;
- boolean changed;
- synchronized (photoBounds) {
- changed = (photoBounds.width() != width) || (photoBounds.height() != height);
- if (changed) {
- photoBounds.set(0, 0, width, height);
- }
- }
- this.photo = photo;
- updateSurface(clearTransform, changed);
- }
-
- void updateSurface(boolean clearTransform, boolean sizeChanged) {
- boolean flipped = (flippedHorizontalDegrees != 0) || (flippedVerticalDegrees != 0);
- boolean transformed = (rotatedDegrees != 0) || flipped;
- if ((clearTransform && transformed) || (sizeChanged && !transformed)) {
- // Fit photo when clearing existing transforms or changing surface/photo sizes.
- if (photo != null) {
- RendererUtils.setRenderToFit(renderContext, photo.width(), photo.height(),
- viewWidth, viewHeight);
- rotatedDegrees = 0;
- flippedHorizontalDegrees = 0;
- flippedVerticalDegrees = 0;
- }
- } else {
- // Restore existing transformations for orientation changes or awaking from sleep.
- if (rotatedDegrees != 0) {
- rotatePhoto(rotatedDegrees);
- } else if (flipped) {
- flipPhoto(flippedHorizontalDegrees, flippedVerticalDegrees);
- }
- }
- }
-
- void rotatePhoto(float degrees) {
- if (photo != null) {
- RendererUtils.setRenderToRotate(renderContext, photo.width(), photo.height(),
- viewWidth, viewHeight, degrees);
- rotatedDegrees = degrees;
- }
- }
-
- void flipPhoto(float horizontalDegrees, float verticalDegrees) {
- if (photo != null) {
- RendererUtils.setRenderToFlip(renderContext, photo.width(), photo.height(),
- viewWidth, viewHeight, horizontalDegrees, verticalDegrees);
- flippedHorizontalDegrees = horizontalDegrees;
- flippedVerticalDegrees = verticalDegrees;
- }
- }
-
- @Override
- public void onDrawFrame(GL10 gl) {
- Runnable r = null;
- synchronized (queue) {
- if (!queue.isEmpty()) {
- r = queue.remove(0);
- }
- }
- if (r != null) {
- r.run();
- }
- if (!queue.isEmpty()) {
- requestRender();
- }
- RendererUtils.renderBackground();
- if (photo != null) {
- RendererUtils.renderTexture(renderContext, photo.texture(), viewWidth, viewHeight);
- }
- }
-
- @Override
- public void onSurfaceChanged(GL10 gl, int width, int height) {
- viewWidth = width;
- viewHeight = height;
- updateSurface(false, true);
- }
-
- @Override
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
- renderContext = RendererUtils.createProgram();
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.graphics.Bitmap;
-import android.opengl.GLES20;
-import android.opengl.GLUtils;
-import android.util.FloatMath;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
-/**
- * Utils for GL renderer.
- */
-public class RendererUtils {
-
- public static class RenderContext {
- private int shaderProgram;
- private int texSamplerHandle;
- private int texCoordHandle;
- private int posCoordHandle;
- private FloatBuffer texVertices;
- private FloatBuffer posVertices;
- }
-
- private static final float[] TEX_VERTICES = {
- 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f
- };
-
- private static final float[] POS_VERTICES = {
- -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f
- };
-
- 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 = a_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" +
- "void main() {\n" +
- " gl_FragColor = texture2D(tex_sampler, v_texcoord);\n" +
- "}\n";
-
- private static final int FLOAT_SIZE_BYTES = 4;
- private static final float DEGREE_TO_RADIAN = (float) Math.PI / 180.0f;
-
- public static int createTexture() {
- int[] textures = new int[1];
- GLES20.glGenTextures(textures.length, textures, 0);
- checkGlError("glGenTextures");
- return textures[0];
- }
-
- public static int createTexture(Bitmap bitmap) {
- int texture = createTexture();
-
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
- GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
- GLES20.glTexParameteri(
- GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
- GLES20.glTexParameteri(
- GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
- GLES20.glTexParameteri(
- GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
- GLES20.glTexParameteri(
- GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
- checkGlError("texImage2D");
-
- return texture;
- }
-
- public static Bitmap saveTexture(int texture, int width, int height) {
- int[] frame = new int[1];
- GLES20.glGenFramebuffers(1, frame, 0);
- checkGlError("glGenFramebuffers");
- GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frame[0]);
- checkGlError("glBindFramebuffer");
- GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
- GLES20.GL_TEXTURE_2D, texture, 0);
- checkGlError("glFramebufferTexture2D");
-
- ByteBuffer buffer = ByteBuffer.allocate(width * height * 4);
- GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer);
- checkGlError("glReadPixels");
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- bitmap.copyPixelsFromBuffer(buffer);
-
- GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
- checkGlError("glBindFramebuffer");
- GLES20.glDeleteFramebuffers(1, frame, 0);
- checkGlError("glDeleteFramebuffer");
- return bitmap;
- }
-
- public static void clearTexture(int texture) {
- int[] textures = new int[1];
- textures[0] = texture;
- GLES20.glDeleteTextures(textures.length, textures, 0);
- checkGlError("glDeleteTextures");
- }
-
- private static float[] getFitVertices(int srcWidth, int srcHeight, int dstWidth,
- int dstHeight) {
- float srcAspectRatio = ((float) srcWidth) / srcHeight;
- float dstAspectRatio = ((float) dstWidth) / dstHeight;
- float relativeAspectRatio = dstAspectRatio / srcAspectRatio;
-
- float[] vertices = new float[8];
- System.arraycopy(POS_VERTICES, 0, vertices, 0, vertices.length);
- if (relativeAspectRatio > 1.0f) {
- // Screen is wider than the camera, scale down X
- vertices[0] /= relativeAspectRatio;
- vertices[2] /= relativeAspectRatio;
- vertices[4] /= relativeAspectRatio;
- vertices[6] /= relativeAspectRatio;
- } else {
- vertices[1] *= relativeAspectRatio;
- vertices[3] *= relativeAspectRatio;
- vertices[5] *= relativeAspectRatio;
- vertices[7] *= relativeAspectRatio;
- }
- return vertices;
- }
-
- public static void setRenderToFit(RenderContext context, int srcWidth, int srcHeight,
- int dstWidth, int dstHeight) {
- context.posVertices = createVerticesBuffer(
- getFitVertices(srcWidth, srcHeight, dstWidth, dstHeight));
- }
-
- public static void setRenderToRotate(RenderContext context, int srcWidth, int srcHeight,
- int dstWidth, int dstHeight, float degrees) {
- float radian = -degrees * DEGREE_TO_RADIAN;
- float cosTheta = FloatMath.cos(radian);
- float sinTheta = FloatMath.sin(radian);
- float cosWidth = cosTheta * srcWidth;
- float sinWidth = sinTheta * srcWidth;
- float cosHeight = cosTheta * srcHeight;
- float sinHeight = sinTheta * srcHeight;
-
- float[] vertices = new float[8];
- vertices[0] = -cosWidth + sinHeight;
- vertices[1] = -sinWidth - cosHeight;
- vertices[2] = cosWidth + sinHeight;
- vertices[3] = sinWidth - cosHeight;
- vertices[4] = -vertices[2];
- vertices[5] = -vertices[3];
- vertices[6] = -vertices[0];
- vertices[7] = -vertices[1];
-
- float maxWidth = Math.max(Math.abs(vertices[0]), Math.abs(vertices[2]));
- float maxHeight = Math.max(Math.abs(vertices[1]), Math.abs(vertices[3]));
- float scale = Math.min(dstWidth / maxWidth, dstHeight / maxHeight);
-
- for (int i = 0; i < 8; i += 2) {
- vertices[i] *= scale / dstWidth;
- vertices[i + 1] *= scale / dstHeight;
- }
- context.posVertices = createVerticesBuffer(vertices);
- }
-
- public static void setRenderToFlip(RenderContext context, int srcWidth, int srcHeight,
- int dstWidth, int dstHeight, float horizontalDegrees, float verticalDegrees) {
- // Calculate the base flip coordinates.
- float[] base = getFitVertices(srcWidth, srcHeight, dstWidth, dstHeight);
- int horizontalRounds = (int) horizontalDegrees / 180;
- if (horizontalRounds % 2 != 0) {
- base[0] = -base[0];
- base[4] = base[0];
- base[2] = -base[2];
- base[6] = base[2];
- }
- int verticalRounds = (int) verticalDegrees / 180;
- if (verticalRounds % 2 != 0) {
- base[1] = -base[1];
- base[3] = base[1];
- base[5] = -base[5];
- base[7] = base[5];
- }
-
- float length = 5;
- float[] vertices = new float[8];
- System.arraycopy(base, 0, vertices, 0, vertices.length);
- if (horizontalDegrees % 180f != 0) {
- float radian = (horizontalDegrees - horizontalRounds * 180) * DEGREE_TO_RADIAN;
- float cosTheta = FloatMath.cos(radian);
- float sinTheta = FloatMath.sin(radian);
-
- float scale = length / (length + sinTheta * base[0]);
- vertices[0] = cosTheta * base[0] * scale;
- vertices[1] = base[1] * scale;
- vertices[4] = vertices[0];
- vertices[5] = base[5] * scale;
-
- scale = length / (length + sinTheta * base[2]);
- vertices[2] = cosTheta * base[2] * scale;
- vertices[3] = base[3] * scale;
- vertices[6] = vertices[2];
- vertices[7] = base[7] * scale;
- }
-
- if (verticalDegrees % 180f != 0) {
- float radian = (verticalDegrees - verticalRounds * 180) * DEGREE_TO_RADIAN;
- float cosTheta = FloatMath.cos(radian);
- float sinTheta = FloatMath.sin(radian);
-
- float scale = length / (length + sinTheta * base[1]);
- vertices[0] = base[0] * scale;
- vertices[1] = cosTheta * base[1] * scale;
- vertices[2] = base[2] * scale;
- vertices[3] = vertices[1];
-
- scale = length / (length + sinTheta * base[5]);
- vertices[4] = base[4] * scale;
- vertices[5] = cosTheta * base[5] * scale;
- vertices[6] = base[6] * scale;
- vertices[7] = vertices[5];
- }
- context.posVertices = createVerticesBuffer(vertices);
- }
-
- public static void renderBackground() {
- GLES20.glClearColor(0, 0, 0, 1);
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- }
-
- public static void renderTexture(
- RenderContext context, int texture, int viewWidth, int viewHeight) {
- // Use our shader program
- GLES20.glUseProgram(context.shaderProgram);
- checkGlError("glUseProgram");
-
- // Set viewport
- GLES20.glViewport(0, 0, viewWidth, viewHeight);
- checkGlError("glViewport");
-
- // Disable blending
- GLES20.glDisable(GLES20.GL_BLEND);
-
- // Set the vertex attributes
- GLES20.glVertexAttribPointer(
- context.texCoordHandle, 2, GLES20.GL_FLOAT, false, 0, context.texVertices);
- GLES20.glEnableVertexAttribArray(context.texCoordHandle);
- GLES20.glVertexAttribPointer(
- context.posCoordHandle, 2, GLES20.GL_FLOAT, false, 0, context.posVertices);
- GLES20.glEnableVertexAttribArray(context.posCoordHandle);
- checkGlError("vertex attribute setup");
-
- // Set the input texture
- GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
- checkGlError("glActiveTexture");
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
- checkGlError("glBindTexture");
- GLES20.glUniform1i(context.texSamplerHandle, 0);
-
- // Draw!
- GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
- }
-
- public static RenderContext createProgram() {
- int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER);
- if (vertexShader == 0) {
- return null;
- }
- int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
- if (pixelShader == 0) {
- return null;
- }
-
- int program = GLES20.glCreateProgram();
- if (program != 0) {
- GLES20.glAttachShader(program, vertexShader);
- checkGlError("glAttachShader");
- GLES20.glAttachShader(program, pixelShader);
- checkGlError("glAttachShader");
- GLES20.glLinkProgram(program);
- int[] linkStatus = new int[1];
- GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
- if (linkStatus[0] != GLES20.GL_TRUE) {
- String info = GLES20.glGetProgramInfoLog(program);
- GLES20.glDeleteProgram(program);
- program = 0;
- throw new RuntimeException("Could not link program: " + info);
- }
- }
-
- // Bind attributes and uniforms
- RenderContext context = new RenderContext();
- context.texSamplerHandle = GLES20.glGetUniformLocation(program, "tex_sampler");
- context.texCoordHandle = GLES20.glGetAttribLocation(program, "a_texcoord");
- context.posCoordHandle = GLES20.glGetAttribLocation(program, "a_position");
- context.texVertices = createVerticesBuffer(TEX_VERTICES);
- context.posVertices = createVerticesBuffer(POS_VERTICES);
-
- context.shaderProgram = program;
- return context;
- }
-
- private static int loadShader(int shaderType, String source) {
- int shader = GLES20.glCreateShader(shaderType);
- if (shader != 0) {
- GLES20.glShaderSource(shader, source);
- GLES20.glCompileShader(shader);
- int[] compiled = new int[1];
- GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
- if (compiled[0] == 0) {
- String info = GLES20.glGetShaderInfoLog(shader);
- GLES20.glDeleteShader(shader);
- shader = 0;
- throw new RuntimeException("Could not compile shader " + shaderType + ":" + info);
- }
- }
- return shader;
- }
-
- private static FloatBuffer createVerticesBuffer(float[] vertices) {
- if (vertices.length != 8) {
- throw new RuntimeException("Number of vertices should be four.");
- }
-
- FloatBuffer buffer = ByteBuffer.allocateDirect(
- vertices.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
- buffer.put(vertices).position(0);
- return buffer;
- }
-
- private static void checkGlError(String op) {
- int error;
- while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
- throw new RuntimeException(op + ": glError " + error);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map.Entry;
-
-/**
- * View that holds a single child and could be recreated/restored after orientation changes.
- */
-public abstract class RestorableView extends FrameLayout {
-
- private final HashMap<Integer, Runnable> clickRunnables = new HashMap<Integer, Runnable>();
- private final HashSet<Integer> changedViews = new HashSet<Integer>();
- private final LayoutInflater inflater;
-
- public RestorableView(Context context, AttributeSet attrs) {
- super(context, attrs);
- inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- protected abstract int childLayoutId();
-
- private void recreateChildView() {
- if (getChildCount() != 0) {
- removeAllViews();
- }
- inflater.inflate(childLayoutId(), this, true);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- recreateChildView();
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
-
- // Remember the removing child before recreating the child.
- View view = getChildAt(0);
- recreateChildView();
-
- // Restore its runnables and status of views that have been changed.
- for (Entry<Integer, Runnable> entry : clickRunnables.entrySet()) {
- setClickRunnable(entry.getKey(), entry.getValue());
- }
- for (int id : changedViews) {
- View changed = view.findViewById(id);
- setViewEnabled(id, changed.isEnabled());
- setViewSelected(id, changed.isSelected());
- }
- }
-
- public void setClickRunnable(int id, final Runnable r) {
- findViewById(id).setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if (isEnabled()) {
- r.run();
- }
- }
- });
- clickRunnables.put(id, r);
- }
-
- public void setViewEnabled(int id, boolean enabled) {
- findViewById(id).setEnabled(enabled);
- // Track views whose enabled status has been updated.
- changedViews.add(id);
- }
-
- public void setViewSelected(int id, boolean selected) {
- findViewById(id).setSelected(selected);
- // Track views whose selected status has been updated.
- changedViews.add(id);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Environment;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Images.ImageColumns;
-import android.view.Gravity;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.util.BucketNames;
-
-import java.io.File;
-import java.sql.Date;
-import java.text.SimpleDateFormat;
-
-/**
- * Asynchronous task for saving edited photo as a new copy.
- */
-public class SaveCopyTask extends AsyncTask<Bitmap, Void, Uri> {
-
- /**
- * Callback for the completed asynchronous task.
- */
- public interface Callback {
-
- void onComplete(Uri result);
- }
-
- private interface ContentResolverQueryCallback {
-
- void onCursorResult(Cursor cursor);
- }
-
- private static final String TIME_STAMP_NAME = "'IMG'_yyyyMMdd_HHmmss";
-
- private final Context context;
- private final Uri sourceUri;
- private final Callback callback;
- private final String saveFileName;
- private String saveFolderName;
-
- public SaveCopyTask(Context context, Uri sourceUri, Callback callback) {
- this.context = context;
- this.sourceUri = sourceUri;
- this.callback = callback;
-
- saveFileName = new SimpleDateFormat(TIME_STAMP_NAME).format(
- new Date(System.currentTimeMillis()));
- }
-
- /**
- * The task should be executed with one given bitmap to be saved.
- */
- @Override
- protected Uri doInBackground(Bitmap... params) {
- // TODO: Support larger dimensions for photo saving.
- if (params[0] == null) {
- return null;
- }
- // Use the default save directory if the source directory cannot be saved.
- File saveDirectory = getSaveDirectory();
- if ((saveDirectory == null) || !saveDirectory.canWrite()) {
- saveDirectory = new File(Environment.getExternalStorageDirectory(),
- BucketNames.DOWNLOAD);
- saveFolderName = context.getString(R.string.folder_download);
- } else {
- saveFolderName = saveDirectory.getName();
- }
-
- Bitmap bitmap = params[0];
- File file = new BitmapUtils(context).saveBitmap(
- bitmap, saveDirectory, saveFileName, Bitmap.CompressFormat.JPEG);
- Uri uri = (file != null) ? insertContent(file) : null;
- bitmap.recycle();
- return uri;
- }
-
- @Override
- protected void onPostExecute(Uri result) {
- String message = (result == null) ? context.getString(R.string.saving_failure)
- : context.getString(R.string.photo_saved, saveFolderName);
- Toast toast = Toast.makeText(context, message, Toast.LENGTH_SHORT);
- toast.setGravity(Gravity.CENTER, 0, 0);
- toast.show();
-
- callback.onComplete(result);
- }
-
- private void querySource(String[] projection, ContentResolverQueryCallback callback) {
- ContentResolver contentResolver = context.getContentResolver();
- Cursor cursor = null;
- try {
- cursor = contentResolver.query(sourceUri, projection, null, null, null);
- if ((cursor != null) && cursor.moveToNext()) {
- callback.onCursorResult(cursor);
- }
- } catch (Exception e) {
- // Ignore error for lacking the data column from the source.
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
-
- private File getSaveDirectory() {
- final File[] dir = new File[1];
- querySource(new String[] { ImageColumns.DATA }, new ContentResolverQueryCallback () {
-
- @Override
- public void onCursorResult(Cursor cursor) {
- dir[0] = new File(cursor.getString(0)).getParentFile();
- }
- });
- return dir[0];
- }
-
- /**
- * Insert the content (saved file) with proper source photo properties.
- */
- private Uri insertContent(File file) {
- long now = System.currentTimeMillis() / 1000;
-
- final ContentValues values = new ContentValues();
- values.put(Images.Media.TITLE, saveFileName);
- values.put(Images.Media.DISPLAY_NAME, file.getName());
- values.put(Images.Media.MIME_TYPE, "image/jpeg");
- values.put(Images.Media.DATE_TAKEN, now);
- values.put(Images.Media.DATE_MODIFIED, now);
- values.put(Images.Media.DATE_ADDED, now);
- values.put(Images.Media.ORIENTATION, 0);
- values.put(Images.Media.DATA, file.getAbsolutePath());
- values.put(Images.Media.SIZE, file.length());
-
- String[] projection = new String[] {
- ImageColumns.DATE_TAKEN,
- ImageColumns.LATITUDE,
- ImageColumns.LONGITUDE,
- };
- querySource(projection, new ContentResolverQueryCallback() {
-
- @Override
- public void onCursorResult(Cursor cursor) {
- values.put(Images.Media.DATE_TAKEN, cursor.getLong(0));
-
- double latitude = cursor.getDouble(1);
- double longitude = cursor.getDouble(2);
- // TODO: Change || to && after the default location issue is fixed.
- if ((latitude != 0f) || (longitude != 0f)) {
- values.put(Images.Media.LATITUDE, latitude);
- values.put(Images.Media.LONGITUDE, longitude);
- }
- }
- });
-
- return context.getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.ProgressBar;
-
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Spinner model progress dialog that disables all tools for user interaction after it shows up and
- * and re-enables them after it dismisses.
- */
-public class SpinnerProgressDialog extends Dialog {
-
- /**
- * Listener of touch events.
- */
- public interface OnTouchListener {
-
- public boolean onTouch(DialogInterface dialog, MotionEvent event);
- }
-
- private final List<View> enabledTools = new ArrayList<View>();
- private final OnTouchListener listener;
-
- public SpinnerProgressDialog(Context context, List<View> tools, OnTouchListener listener) {
- super(context, R.style.SpinnerProgressDialog);
- addContentView(new ProgressBar(context), new LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- setCancelable(false);
-
- for (View view : tools) {
- if (view.isEnabled()) {
- enabledTools.add(view);
- }
- }
- this.listener = listener;
- }
-
- @Override
- public void show() {
- super.show();
- // Disable enabled tools when showing spinner progress dialog.
- for (View view : enabledTools) {
- view.setEnabled(false);
- }
- }
-
- @Override
- public void dismiss() {
- super.dismiss();
- // Enable tools that were disabled by this spinner progress dialog.
- for (View view : enabledTools) {
- view.setEnabled(true);
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- return listener.onTouch(this, event);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor;
-
-import android.content.Context;
-import android.content.DialogInterface;
-import android.os.Handler;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.widget.RelativeLayout;
-
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Toolbar that contains all tools and controls their idle/awake behaviors from UI thread.
- */
-public class Toolbar extends RelativeLayout {
-
- private final ToolbarIdleHandler idleHandler;
- private final List<View> tools = new ArrayList<View>();
- private SpinnerProgressDialog spinner;
-
- public Toolbar(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- setOnHierarchyChangeListener(new OnHierarchyChangeListener() {
-
- @Override
- public void onChildViewAdded(View parent, View child) {
- // Photo-view isn't treated as a tool that responds to user events.
- if (child.getId() != R.id.photo_view) {
- tools.add(child);
- }
- }
-
- @Override
- public void onChildViewRemoved(View parent, View child) {
- tools.remove(child);
- }
- });
-
- idleHandler = new ToolbarIdleHandler(context, tools);
- idleHandler.killIdle();
- }
-
- public void showSpinner() {
- // There should be only one progress spinner running at a time.
- if (spinner == null) {
- spinner = new SpinnerProgressDialog(getContext(), tools,
- new SpinnerProgressDialog.OnTouchListener() {
-
- @Override
- public boolean onTouch(DialogInterface dialog, MotionEvent event) {
- // Kill idle even when the progress dialog is shown.
- idleHandler.killIdle();
- return true;
- }
- });
- spinner.show();
- }
- }
-
- public void dismissSpinner() {
- if (spinner != null) {
- spinner.dismiss();
- spinner = null;
- }
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- idleHandler.killIdle();
- return super.dispatchTouchEvent(ev);
- }
-
- private static class ToolbarIdleHandler {
-
- private static final int MAKE_IDLE = 1;
- private static final int TIMEOUT_IDLE = 8000;
-
- private final List<View> tools;
- private final Handler mainHandler;
- private final Animation fadeIn;
- private final Animation fadeOut;
- private boolean idle;
-
- public ToolbarIdleHandler(Context context, final List<View> tools) {
- this.tools = tools;
- mainHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MAKE_IDLE:
- if (!idle) {
- idle = true;
- for (View view : tools) {
- view.startAnimation(fadeOut);
- }
- }
- break;
- }
- }
- };
-
- fadeIn = AnimationUtils.loadAnimation(context, R.anim.photoeditor_fade_in);
- fadeOut = AnimationUtils.loadAnimation(context, R.anim.photoeditor_fade_out);
- }
-
- public void killIdle() {
- mainHandler.removeMessages(MAKE_IDLE);
- if (idle) {
- idle = false;
- for (View view : tools) {
- view.startAnimation(fadeIn);
- }
- }
- mainHandler.sendEmptyMessageDelayed(MAKE_IDLE, TIMEOUT_IDLE);
- }
- }
-}
+++ /dev/null
-package com.android.gallery3d.photoeditor;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-
-import com.android.gallery3d.R;
-
-/**
- * Alert dialog builder that builds a simple Yes/Cancel dialog.
- */
-public class YesCancelDialogBuilder extends AlertDialog.Builder {
-
- public YesCancelDialogBuilder(Context context, final Runnable yes, int messageId) {
- super(context);
- setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- yes.run();
- }
- })
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // no-op
- }
- }).setMessage(messageId);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.widget.SeekBar;
-
-import com.android.gallery3d.R;
-
-/**
- * Seek-bar base that implements a draggable thumb that fits seek-bar's track height.
- */
-abstract class AbstractSeekBar extends SeekBar {
-
- public AbstractSeekBar(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- // Scale the thumb to fit seek-bar's track height.
- Resources res = getResources();
- Drawable thumb = res.getDrawable(R.drawable.photoeditor_seekbar_thumb);
- int height = h - getPaddingTop() - getPaddingBottom();
- int scaledWidth = thumb.getIntrinsicWidth() * height / thumb.getIntrinsicHeight();
-
- Bitmap bitmap = Bitmap.createBitmap(scaledWidth, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- thumb.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
- thumb.draw(canvas);
-
- // The thumb should not extend out of the track per UX design.
- setThumb(new BitmapDrawable(res, bitmap));
- setThumbOffset(0);
-
- // The thumb position is updated here after the thumb is changed.
- super.onSizeChanged(w, h, oldw, oldh);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.AutoFixFilter;
-
-/**
- * An action handling auto-fix effect.
- */
-public class AutoFixAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0.5f;
-
- public AutoFixAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- AutoFixFilter filter = new AutoFixFilter();
- filter.setScale(DEFAULT_SCALE);
- notifyChanged(filter);
- notifyOk();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Region.Op;
-import android.graphics.drawable.BitmapDrawable;
-import android.util.AttributeSet;
-import android.widget.SeekBar;
-
-import com.android.gallery3d.R;
-
-/**
- * Seek-bar that has a draggable thumb to set and get the color from predefined color set.
- */
-class ColorSeekBar extends AbstractSeekBar {
-
- /**
- * Listens to color changes.
- */
- public interface OnColorChangeListener {
-
- void onColorChanged(int color, boolean fromUser);
- }
-
- private final int[] colors;
- private Bitmap progressDrawable;
-
- public ColorSeekBar(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- // Set up the predefined colors that could be indexed in the seek-bar.
- TypedArray a = getResources().obtainTypedArray(R.array.color_picker_colors);
- colors = new int[a.length()];
- for (int i = 0; i < a.length(); i++) {
- colors[i] = a.getColor(i, 0x000000);
- }
- a.recycle();
- setMax(colors.length - 1);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- if (progressDrawable != null) {
- progressDrawable.recycle();
- }
- int width = w - getPaddingLeft() - getPaddingRight();
- int height = h - getPaddingTop() - getPaddingBottom();
- progressDrawable = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(progressDrawable);
-
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setStyle(Paint.Style.FILL);
-
- // Draw two half circles in the first and last colors at the left/right ends.
- int radius = height / 2;
- float left = radius;
- float right = width - radius;
-
- canvas.save();
- canvas.clipRect(left, 0, right, height, Op.DIFFERENCE);
- paint.setColor(colors[0]);
- canvas.drawCircle(left, radius, radius, paint);
- paint.setColor(colors[colors.length - 1]);
- canvas.drawCircle(right, radius, radius, paint);
- canvas.restore();
-
- // Draw color strips that make the thumb stop at every strip's center during seeking.
- float strip = (right - left) / (colors.length - 1);
- right = left + strip / 2;
- paint.setColor(colors[0]);
- canvas.drawRect(left, 0, right, height, paint);
- left = right;
- for (int i = 1; i < colors.length - 1; i++) {
- right = left + strip;
- paint.setColor(colors[i]);
- canvas.drawRect(left, 0, right, height, paint);
- left = right;
- }
- right = left + strip / 2;
- paint.setColor(colors[colors.length - 1]);
- canvas.drawRect(left, 0, right, height, paint);
-
- setProgressDrawable(new BitmapDrawable(getResources(), progressDrawable));
- }
-
- public void setOnColorChangeListener(final OnColorChangeListener listener) {
- setOnSeekBarChangeListener((listener == null) ? null : new OnSeekBarChangeListener() {
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- listener.onColorChanged(colors[progress], fromUser);
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- }
- });
- }
-
- public void setColorIndex(int colorIndex) {
- setProgress(colorIndex);
- }
-
- public int getColor() {
- return colors[getProgress()];
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.ColorTemperatureFilter;
-
-/**
- * An action handling color temperature effect.
- */
-public class ColorTemperatureAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0.5f;
-
- public ColorTemperatureAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final ColorTemperatureFilter filter = new ColorTemperatureFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.COLOR);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.CropFilter;
-
-/**
- * An action handling crop effect.
- */
-public class CropAction extends EffectAction {
-
- private static final float DEFAULT_CROP = 0.2f;
-
- public CropAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- // Cropped results wouldn't be previewed for changed crop bounds.
- final CropFilter filter = new CropFilter();
- disableFilterOutput();
-
- CropView cropView = toolKit.addCropView();
- cropView.setOnCropChangeListener(new CropView.OnCropChangeListener() {
-
- @Override
- public void onCropChanged(RectF cropBounds, boolean fromUser) {
- if (fromUser) {
- filter.setCropBounds(cropBounds);
- notifyChanged(filter);
- }
- }
- });
-
- RectF bounds = new RectF(DEFAULT_CROP, DEFAULT_CROP, 1 - DEFAULT_CROP, 1 - DEFAULT_CROP);
- cropView.setCropBounds(bounds);
- filter.setCropBounds(bounds);
- notifyChanged(filter);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.R;
-
-/**
- * A view that tracks touch motions and adjusts crop bounds accordingly.
- */
-class CropView extends FullscreenToolView {
-
- /**
- * Listener of crop bounds.
- */
- public interface OnCropChangeListener {
-
- void onCropChanged(RectF cropBounds, boolean fromUser);
- }
-
- private static final int MOVE_LEFT = 1;
- private static final int MOVE_TOP = 2;
- private static final int MOVE_RIGHT = 4;
- private static final int MOVE_BOTTOM = 8;
- private static final int MOVE_BLOCK = 16;
-
- private static final int MIN_CROP_WIDTH_HEIGHT = 2;
- private static final int TOUCH_TOLERANCE = 25;
- private static final int SHADOW_ALPHA = 160;
-
- private final Paint borderPaint;
- private final Drawable cropIndicator;
- private final int indicatorSize;
- private final RectF cropBounds = new RectF(0, 0, 1, 1);
-
- private float lastX;
- private float lastY;
- private int movingEdges;
- private OnCropChangeListener listener;
-
- public CropView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- Resources resources = context.getResources();
- cropIndicator = resources.getDrawable(R.drawable.camera_crop_holo);
- indicatorSize = (int) resources.getDimension(R.dimen.crop_indicator_size);
- int borderColor = resources.getColor(R.color.opaque_cyan);
-
- borderPaint = new Paint();
- borderPaint.setStyle(Paint.Style.STROKE);
- borderPaint.setColor(borderColor);
- borderPaint.setStrokeWidth(2f);
- }
-
- public void setOnCropChangeListener(OnCropChangeListener listener) {
- this.listener = listener;
- }
-
- private void refreshByCropChange(boolean fromUser) {
- if (listener != null) {
- listener.onCropChanged(new RectF(cropBounds), fromUser);
- }
- invalidate();
- }
-
- /**
- * Sets cropped bounds; modifies the bounds if it's smaller than the allowed dimensions.
- */
- public void setCropBounds(RectF bounds) {
- // Avoid cropping smaller than minimum width or height.
- if (bounds.width() * getPhotoWidth() < MIN_CROP_WIDTH_HEIGHT) {
- bounds.set(0, bounds.top, 1, bounds.bottom);
- }
- if (bounds.height() * getPhotoHeight() < MIN_CROP_WIDTH_HEIGHT) {
- bounds.set(bounds.left, 0, bounds.right, 1);
- }
- cropBounds.set(bounds);
- refreshByCropChange(false);
- }
-
- private RectF getCropBoundsDisplayed() {
- float width = displayBounds.width();
- float height = displayBounds.height();
- RectF cropped = new RectF(cropBounds.left * width, cropBounds.top * height,
- cropBounds.right * width, cropBounds.bottom * height);
- cropped.offset(displayBounds.left, displayBounds.top);
- return cropped;
- }
-
- private void detectMovingEdges(float x, float y) {
- RectF cropped = getCropBoundsDisplayed();
- movingEdges = 0;
-
- // Check left or right.
- float left = Math.abs(x - cropped.left);
- float right = Math.abs(x - cropped.right);
- if ((left <= TOUCH_TOLERANCE) && (left < right)) {
- movingEdges |= MOVE_LEFT;
- }
- else if (right <= TOUCH_TOLERANCE) {
- movingEdges |= MOVE_RIGHT;
- }
-
- // Check top or bottom.
- float top = Math.abs(y - cropped.top);
- float bottom = Math.abs(y - cropped.bottom);
- if ((top <= TOUCH_TOLERANCE) & (top < bottom)) {
- movingEdges |= MOVE_TOP;
- }
- else if (bottom <= TOUCH_TOLERANCE) {
- movingEdges |= MOVE_BOTTOM;
- }
-
- // Check inside block.
- if (cropped.contains(x, y) && (movingEdges == 0)) {
- movingEdges = MOVE_BLOCK;
- }
- invalidate();
- }
-
- private void moveEdges(float deltaX, float deltaY) {
- RectF cropped = getCropBoundsDisplayed();
- if (movingEdges == MOVE_BLOCK) {
- // Move the whole cropped bounds within the photo display bounds.
- deltaX = (deltaX > 0) ? Math.min(displayBounds.right - cropped.right, deltaX)
- : Math.max(displayBounds.left - cropped.left, deltaX);
- deltaY = (deltaY > 0) ? Math.min(displayBounds.bottom - cropped.bottom, deltaY)
- : Math.max(displayBounds.top - cropped.top, deltaY);
- cropped.offset(deltaX, deltaY);
- } else {
- // Adjust cropped bound dimensions within the photo display bounds.
- float minWidth = MIN_CROP_WIDTH_HEIGHT * displayBounds.width() / getPhotoWidth();
- float minHeight = MIN_CROP_WIDTH_HEIGHT * displayBounds.height() / getPhotoHeight();
- if ((movingEdges & MOVE_LEFT) != 0) {
- cropped.left = Math.min(cropped.left + deltaX, cropped.right - minWidth);
- }
- if ((movingEdges & MOVE_TOP) != 0) {
- cropped.top = Math.min(cropped.top + deltaY, cropped.bottom - minHeight);
- }
- if ((movingEdges & MOVE_RIGHT) != 0) {
- cropped.right = Math.max(cropped.right + deltaX, cropped.left + minWidth);
- }
- if ((movingEdges & MOVE_BOTTOM) != 0) {
- cropped.bottom = Math.max(cropped.bottom + deltaY, cropped.top + minHeight);
- }
- cropped.intersect(displayBounds);
- }
- mapPhotoRect(cropped, cropBounds);
- refreshByCropChange(true);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- super.onTouchEvent(event);
-
- if (isEnabled()) {
- float x = event.getX();
- float y = event.getY();
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- detectMovingEdges(x, y);
- lastX = x;
- lastY = y;
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (movingEdges != 0) {
- moveEdges(x - lastX, y - lastY);
- }
- lastX = x;
- lastY = y;
- break;
-
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- movingEdges = 0;
- invalidate();
- break;
- }
- }
- return true;
- }
-
- private void drawIndicator(Canvas canvas, Drawable indicator, float centerX, float centerY) {
- int left = (int) centerX - indicatorSize / 2;
- int top = (int) centerY - indicatorSize / 2;
- indicator.setBounds(left, top, left + indicatorSize, top + indicatorSize);
- indicator.draw(canvas);
- }
-
- private void drawShadow(Canvas canvas, float left, float top, float right, float bottom) {
- canvas.save();
- canvas.clipRect(left, top, right, bottom);
- canvas.drawARGB(SHADOW_ALPHA, 0, 0, 0);
- canvas.restore();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- // Draw shadow on non-cropped bounds and the border around cropped bounds.
- RectF cropped = getCropBoundsDisplayed();
- drawShadow(canvas, displayBounds.left, displayBounds.top, displayBounds.right, cropped.top);
- drawShadow(canvas, displayBounds.left, cropped.top, cropped.left, displayBounds.bottom);
- drawShadow(canvas, cropped.right, cropped.top, displayBounds.right, displayBounds.bottom);
- drawShadow(canvas, cropped.left, cropped.bottom, cropped.right, displayBounds.bottom);
- canvas.drawRect(cropped, borderPaint);
-
- boolean notMoving = movingEdges == 0;
- if (((movingEdges & MOVE_TOP) != 0) || notMoving) {
- drawIndicator(canvas, cropIndicator, cropped.centerX(), cropped.top);
- }
- if (((movingEdges & MOVE_BOTTOM) != 0) || notMoving) {
- drawIndicator(canvas, cropIndicator, cropped.centerX(), cropped.bottom);
- }
- if (((movingEdges & MOVE_LEFT) != 0) || notMoving) {
- drawIndicator(canvas, cropIndicator, cropped.left, cropped.centerY());
- }
- if (((movingEdges & MOVE_RIGHT) != 0) || notMoving) {
- drawIndicator(canvas, cropIndicator, cropped.right, cropped.centerY());
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.CrossProcessFilter;
-
-/**
- * An action handling cross-process effect.
- */
-public class CrossProcessAction extends EffectAction {
-
- public CrossProcessAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- notifyChanged(new CrossProcessFilter());
- notifyOk();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.DocumentaryFilter;
-
-/**
- * An action handling the preset "Documentary" effect.
- */
-public class DocumentaryAction extends EffectAction {
-
- public DocumentaryAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- notifyChanged(new DocumentaryFilter());
- notifyOk();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PointF;
-import android.graphics.RectF;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Vector;
-
-/**
- * Doodle that consists of a color and doodling path for drawing.
- */
-public class Doodle implements Parcelable {
-
- private final int color;
- private final Path normalizedPath = new Path();
- private final Vector<PointF> points = new Vector<PointF>();
-
- /**
- * Creates paint for doodles.
- */
- public static Paint createPaint() {
- Paint paint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG);
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeJoin(Paint.Join.ROUND);
- paint.setStrokeCap(Paint.Cap.ROUND);
- paint.setStrokeWidth(15);
- return paint;
- }
-
- public Doodle(int color, PointF startPoint) {
- this.color = Color.argb(192, Color.red(color), Color.green(color), Color.blue(color));
- normalizedPath.moveTo(startPoint.x, startPoint.y);
- points.add(startPoint);
- }
-
- /**
- * Checks if the constructed doodle path is in (0, 0, 1, 1) bounds.
- */
- public boolean inBounds() {
- RectF r = new RectF();
- normalizedPath.computeBounds(r, false);
- return r.intersects(0, 0, 1, 1);
- }
-
- /**
- * Adds control points whose coordinates range from 0 to 1 to construct the doodle path.
- */
- public void addControlPoint(PointF point) {
- PointF last = points.lastElement();
- normalizedPath.quadTo(last.x, last.y, (last.x + point.x) / 2, (last.y + point.y) / 2);
- points.add(point);
- }
-
- public int getColor() {
- return color;
- }
-
- public boolean isEmpty() {
- return normalizedPath.isEmpty();
- }
-
- /**
- * Gets the drawing path from the normalized doodle path.
- */
- public void getDrawingPath(Matrix matrix, Path path) {
- path.set(normalizedPath);
- path.transform(matrix);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(color);
- dest.writeInt(points.size());
- for (PointF point : points) {
- dest.writeParcelable(point, 0);
- }
- }
-
- public static final Parcelable.Creator<Doodle> CREATOR = new Parcelable.Creator<Doodle>() {
-
- @Override
- public Doodle createFromParcel(Parcel source) {
- int color = source.readInt();
- int size = source.readInt();
- if (size > 0) {
- Doodle doodle = new Doodle(color, (PointF) source.readParcelable(null));
- for (int i = 1; i < size; i++) {
- doodle.addControlPoint((PointF) source.readParcelable(null));
- }
- return doodle;
- }
- return new Doodle(color, new PointF(0, 0));
- }
-
- @Override
- public Doodle[] newArray(int size) {
- return new Doodle[size];
- }};
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.DoodleFilter;
-
-/**
- * An action handling doodle effect.
- */
-public class DoodleAction extends EffectAction {
-
- private static final int DEFAULT_COLOR_INDEX = 4;
-
- public DoodleAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- // Directly draw on doodle-view because running the doodle filter isn't fast enough.
- final DoodleFilter filter = new DoodleFilter();
- disableFilterOutput();
-
- final DoodleView doodleView = toolKit.addDoodleView();
- doodleView.setOnDoodleChangeListener(new DoodleView.OnDoodleChangeListener() {
-
- @Override
- public void onDoodleChanged(Doodle doodle) {
- // Check if the user draws within photo bounds and makes visible changes on photo.
- if (doodle.inBounds()) {
- notifyChanged(filter);
- }
- }
-
- @Override
- public void onDoodleFinished(Doodle doodle) {
- if (doodle.inBounds()) {
- filter.addDoodle(doodle);
- notifyChanged(filter);
- }
- }
- });
-
- ColorSeekBar colorPicker = toolKit.addColorPicker();
- colorPicker.setOnColorChangeListener(new ColorSeekBar.OnColorChangeListener() {
-
- @Override
- public void onColorChanged(int color, boolean fromUser) {
- if (fromUser) {
- doodleView.setColor(color);
- }
- }
- });
- colorPicker.setColorIndex(DEFAULT_COLOR_INDEX);
- doodleView.setColor(colorPicker.getColor());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PointF;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-/**
- * A view that tracks touch motions as paths and paints them as doodles.
- */
-class DoodleView extends FullscreenToolView {
-
- /**
- * Listener of doodle paths.
- */
- public interface OnDoodleChangeListener {
-
- void onDoodleChanged(Doodle doodle);
-
- void onDoodleFinished(Doodle doodle);
- }
-
- private final Paint bitmapPaint = new Paint(Paint.DITHER_FLAG);
- private final Paint doodlePaint = Doodle.createPaint();
- private final PointF lastPoint = new PointF();
- private final Path drawingPath = new Path();
- private final Matrix drawingMatrix = new Matrix();
- private final Matrix displayMatrix = new Matrix();
-
- private Bitmap bitmap;
- private Canvas bitmapCanvas;
- private Doodle doodle;
- private int color;
- private OnDoodleChangeListener listener;
-
- public DoodleView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void setOnDoodleChangeListener(OnDoodleChangeListener listener) {
- this.listener = listener;
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- RectF r = new RectF(0, 0, getPhotoWidth(), getPhotoHeight());
- if ((bitmap == null) && !r.isEmpty()) {
- bitmap = Bitmap.createBitmap((int) r.width(), (int) r.height(),
- Bitmap.Config.ARGB_8888);
- bitmapCanvas = new Canvas(bitmap);
-
- // Set up a matrix that maps back normalized paths to be drawn on the bitmap or canvas.
- drawingMatrix.setRectToRect(new RectF(0, 0, 1, 1), r, Matrix.ScaleToFit.FILL);
- }
- displayMatrix.setRectToRect(r, displayBounds, Matrix.ScaleToFit.FILL);
- }
-
- private void drawDoodle(Canvas canvas) {
- if ((canvas != null) && (doodle != null)) {
- doodlePaint.setColor(doodle.getColor());
- doodle.getDrawingPath(drawingMatrix, drawingPath);
- canvas.drawPath(drawingPath, doodlePaint);
- }
- }
-
- public void setColor(int color) {
- // Restart doodle to draw in a new color.
- this.color = color;
- finishDoodle();
- startDoodle();
- }
-
- private void startDoodle() {
- doodle = new Doodle(color, new PointF(lastPoint.x, lastPoint.y));
- }
-
- private void finishDoodle() {
- if ((doodle != null) && !doodle.isEmpty()) {
- // Update the finished non-empty doodle to the bitmap.
- drawDoodle(bitmapCanvas);
- if (listener != null) {
- listener.onDoodleFinished(doodle);
- }
- invalidate();
- }
- doodle = null;
- }
-
- private void addLastPointIntoDoodle() {
- if (doodle != null) {
- doodle.addControlPoint(new PointF(lastPoint.x, lastPoint.y));
- if (listener != null) {
- listener.onDoodleChanged(doodle);
- }
- invalidate();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- super.onTouchEvent(event);
-
- if (isEnabled()) {
- float x = event.getX();
- float y = event.getY();
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mapPhotoPoint(x, y, lastPoint);
- startDoodle();
- break;
-
- case MotionEvent.ACTION_MOVE:
- mapPhotoPoint(x, y, lastPoint);
- addLastPointIntoDoodle();
- break;
-
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- // Line to last position with offset to draw at least dots for single clicks.
- mapPhotoPoint(x + 1, y + 1, lastPoint);
- addLastPointIntoDoodle();
- finishDoodle();
- break;
- }
- }
- return true;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- canvas.save();
- canvas.clipRect(displayBounds);
- canvas.concat(displayMatrix);
- if (bitmap != null) {
- canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
- }
- drawDoodle(canvas);
- canvas.restore();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.DuotoneFilter;
-
-/**
- * An action handling duo-tone effect.
- */
-public class DuotoneAction extends EffectAction {
-
- private static final int DEFAULT_FIRST_COLOR = 0x004488;
- private static final int DEFAULT_SECOND_COLOR = 0xffff00;
-
- public DuotoneAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- // TODO: Add several sets of duo-tone colors to select from.
- DuotoneFilter filter = new DuotoneFilter();
- filter.setDuotone(DEFAULT_FIRST_COLOR, DEFAULT_SECOND_COLOR);
- notifyChanged(filter);
- notifyOk();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.photoeditor.FilterStack;
-import com.android.gallery3d.photoeditor.OnDoneCallback;
-import com.android.gallery3d.photoeditor.filters.Filter;
-
-/**
- * An action binding UI controls and effect operation for editing photo.
- */
-public abstract class EffectAction extends LinearLayout {
-
- /**
- * Listener of effect action.
- */
- public interface ActionListener {
-
- /**
- * Invoked when the action is okayed (effect is applied and completed).
- */
- void onOk();
- }
-
- protected EffectToolKit toolKit;
- private Toast tooltip;
- private FilterStack filterStack;
- private boolean pushedFilter;
- private boolean disableFilterOutput;
- private FilterChangedCallback lastFilterChangedCallback;
- private ActionListener listener;
-
- public EffectAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void begin(View root, FilterStack filterStack, ActionListener listener) {
- // This view is already detached from UI view hierarchy by reaching here; findViewById()
- // could only access its own child views from here.
- toolKit = new EffectToolKit(root, ((TextView) findViewById(R.id.effect_label)).getText());
- this.filterStack = filterStack;
- this.listener = listener;
-
- // Shows the tooltip if it's available.
- if (getTag() != null) {
- tooltip = Toast.makeText(getContext(), (String) getTag(), Toast.LENGTH_SHORT);
- tooltip.setGravity(Gravity.CENTER, 0, 0);
- tooltip.show();
- }
- prepare();
- }
-
- /**
- * Subclasses should create a specific filter and bind the filter to necessary UI controls here
- * when the action is about to begin.
- */
- protected abstract void prepare();
-
- /**
- * Ends the effect and then executes the runnable after the effect is finished.
- */
- public void end(final Runnable runnableOnODone) {
- // Cancel the tooltip if it's still showing.
- if ((tooltip != null) && (tooltip.getView().getParent() != null)) {
- tooltip.cancel();
- tooltip = null;
- }
- // End tool editing by canceling unfinished touch events.
- toolKit.cancel();
- // Output the pushed filter if it wasn't outputted.
- if (pushedFilter && disableFilterOutput) {
- outputFilter();
- }
-
- // Wait till last output callback is done before finishing.
- if ((lastFilterChangedCallback == null) || lastFilterChangedCallback.done) {
- finish(runnableOnODone);
- } else {
- lastFilterChangedCallback.runnableOnReady = new Runnable() {
-
- @Override
- public void run() {
- finish(runnableOnODone);
- }
- };
- }
- }
-
- private void finish(Runnable runnableOnDone) {
- toolKit.close();
- pushedFilter = false;
- disableFilterOutput = false;
- lastFilterChangedCallback = null;
-
- runnableOnDone.run();
- }
-
- protected void disableFilterOutput() {
- // Filter output won't be outputted until this effect has done editing its filter.
- disableFilterOutput = true;
- }
-
- protected void outputFilter() {
- // Notify the stack to execute the changed top filter and output the results.
- lastFilterChangedCallback = new FilterChangedCallback();
- filterStack.topFilterChanged(lastFilterChangedCallback);
- }
-
- protected void notifyChanged(Filter filter) {
- if (!pushedFilter) {
- filterStack.pushFilter(filter);
- pushedFilter = true;
- }
- if (pushedFilter && !disableFilterOutput) {
- outputFilter();
- }
- }
-
- protected void notifyOk() {
- listener.onOk();
- }
-
- /**
- * Checks if the action effect is present in the system.
- *
- * @return boolean true if an action effect is present in the system and can be loaded
- */
- public boolean isPresent() {
- return true;
- }
-
- /**
- * Done callback for executing top filter changes.
- */
- private class FilterChangedCallback implements OnDoneCallback {
-
- private boolean done;
- private Runnable runnableOnReady;
-
- @Override
- public void onDone() {
- done = true;
-
- if (runnableOnReady != null) {
- runnableOnReady.run();
- }
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.os.SystemClock;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.photoeditor.PhotoView;
-
-/**
- * Tool kit used by effect actions to retrieve tools, including managing tool creation/removal.
- */
-public class EffectToolKit {
-
- public enum ScaleType {
- LIGHT, SHADOW, COLOR, GENERIC
- }
-
- private final LayoutInflater inflater;
- private final PhotoView photoView;
- private final ViewGroup toolPanel;
- private final ViewGroup toolFullscreen;
-
- public EffectToolKit(View root, CharSequence label) {
- inflater = (LayoutInflater) root.getContext().getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
-
- // Create effect tool panel as the first child of effects-bar.
- ViewGroup effectsBar = (ViewGroup) root.findViewById(R.id.effects_bar);
- toolPanel = (ViewGroup) inflater.inflate(
- R.layout.photoeditor_effect_tool_panel, effectsBar, false);
- ((TextView) toolPanel.findViewById(R.id.effect_label)).setText(label);
- effectsBar.addView(toolPanel, 0);
-
- // Create effect tool full-screen on top of photo-view and place it within the same
- // view group that contains photo-view.
- photoView = (PhotoView) root.findViewById(R.id.photo_view);
- ViewGroup parent = (ViewGroup) photoView.getParent();
- toolFullscreen = (ViewGroup) inflater.inflate(
- R.layout.photoeditor_effect_tool_fullscreen, parent, false);
- parent.addView(toolFullscreen, parent.indexOfChild(photoView) + 1);
- }
-
- public PhotoView getPhotoView() {
- return photoView;
- }
-
- /**
- * Cancel pending touch events and stop dispatching further touch events to tools.
- */
- public void cancel() {
- long now = SystemClock.uptimeMillis();
- MotionEvent cancelEvent = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
- toolFullscreen.dispatchTouchEvent(cancelEvent);
- toolPanel.dispatchTouchEvent(cancelEvent);
- cancelEvent.recycle();
- View.OnTouchListener listener = new View.OnTouchListener() {
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- // Consume all further touch events and don't dispatch them.
- return true;
- }
- };
- toolFullscreen.setOnTouchListener(listener);
- toolPanel.setOnTouchListener(listener);
- }
-
- /**
- * Close to remove all created tools.
- */
- public void close() {
- ((ViewGroup) toolFullscreen.getParent()).removeView(toolFullscreen);
- ((ViewGroup) toolPanel.getParent()).removeView(toolPanel);
- }
-
- private View addFullscreenTool(int toolId) {
- FullscreenToolView tool = (FullscreenToolView) inflater.inflate(
- toolId, toolFullscreen, false);
- tool.setPhotoBounds(getPhotoView().getPhotoBounds());
- toolFullscreen.addView(tool);
- return tool;
- }
-
- private View addPanelTool(int toolId) {
- // Add the tool right above the effect-label in the panel.
- View tool = inflater.inflate(toolId, toolPanel, false);
- toolPanel.addView(tool, toolPanel.indexOfChild(toolPanel.findViewById(R.id.effect_label)));
- return tool;
- }
-
- private Drawable getScalePickerProgressDrawable(Resources res, ScaleType type) {
- switch (type) {
- case LIGHT:
- return res.getDrawable(R.drawable.photoeditor_scale_seekbar_light);
-
- case SHADOW:
- return res.getDrawable(R.drawable.photoeditor_scale_seekbar_shadow);
-
- case COLOR:
- return res.getDrawable(R.drawable.photoeditor_scale_seekbar_color);
- }
- return res.getDrawable(R.drawable.photoeditor_scale_seekbar_generic);
- }
-
- public ScaleSeekBar addScalePicker(ScaleType type) {
- ScaleSeekBar scalePicker = (ScaleSeekBar) addPanelTool(
- R.layout.photoeditor_scale_seekbar);
- scalePicker.setProgressDrawable(getScalePickerProgressDrawable(
- toolPanel.getResources(), type));
- return scalePicker;
- }
-
- public ColorSeekBar addColorPicker() {
- return (ColorSeekBar) addPanelTool(R.layout.photoeditor_color_seekbar);
- }
-
- public DoodleView addDoodleView() {
- return (DoodleView) addFullscreenTool(R.layout.photoeditor_doodle_view);
- }
-
- public TouchView addTouchView() {
- return (TouchView) addFullscreenTool(R.layout.photoeditor_touch_view);
- }
-
- public FlipView addFlipView() {
- return (FlipView) addFullscreenTool(R.layout.photoeditor_flip_view);
- }
-
- public RotateView addRotateView() {
- return (RotateView) addFullscreenTool(R.layout.photoeditor_rotate_view);
- }
-
- public CropView addCropView() {
- return (CropView) addFullscreenTool(R.layout.photoeditor_crop_view);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.FaceTanFilter;
-
-/**
- * An action handling face tanning effect.
- */
-public class FaceTanAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0.5f;
-
- public FaceTanAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final FaceTanFilter filter = new FaceTanFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.GENERIC);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
-
- filter.setScale(DEFAULT_SCALE);
- notifyChanged(filter);
- }
-
- @Override
- public boolean isPresent() {
- return FaceTanFilter.isPresent();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.FaceliftFilter;
-
-/**
- * An action handling facelift effect.
- */
-public class FaceliftAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0.5f;
-
- public FaceliftAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final FaceliftFilter filter = new FaceliftFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.GENERIC);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
-
- filter.setScale(DEFAULT_SCALE);
- notifyChanged(filter);
- }
-
- @Override
- public boolean isPresent() {
- return FaceliftFilter.isPresent();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.FillLightFilter;
-
-/**
- * An action handling fill-light effect.
- */
-public class FillLightAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0f;
-
- public FillLightAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final FillLightFilter filter = new FillLightFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.LIGHT);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.FisheyeFilter;
-
-/**
- * An action handling fisheye effect.
- */
-public class FisheyeAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0.5f;
-
- public FisheyeAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final FisheyeFilter filter = new FisheyeFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.GENERIC);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
-
- filter.setScale(DEFAULT_SCALE);
- notifyChanged(filter);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.PhotoView;
-import com.android.gallery3d.photoeditor.filters.FlipFilter;
-
-/**
- * An action handling flip effect.
- */
-public class FlipAction extends EffectAction {
-
- private static final float DEFAULT_ANGLE = 0.0f;
- private static final float DEFAULT_FLIP_SPAN = 180.0f;
-
- public FlipAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- // Disable outputting flipped results and directly flip photo-view for animations.
- final FlipFilter filter = new FlipFilter();
- disableFilterOutput();
-
- final FlipView flipView = toolKit.addFlipView();
- flipView.setOnFlipChangeListener(new FlipView.OnFlipChangeListener() {
-
- float horizontalDegrees;
- float verticalDegrees;
- Runnable queuedTransform;
- PhotoView photoView = toolKit.getPhotoView();
-
- @Override
- public void onAngleChanged(float horizontalDegrees, float verticalDegrees,
- boolean fromUser) {
- if (fromUser) {
- this.horizontalDegrees = horizontalDegrees;
- this.verticalDegrees = verticalDegrees;
- transformPhotoView(horizontalDegrees, verticalDegrees);
- notifyChanged(filter);
- }
- }
-
- @Override
- public void onStartTrackingTouch() {
- // no-op
- }
-
- @Override
- public void onStopTrackingTouch() {
- // Round flip degrees to multiples of 180 degrees.
- horizontalDegrees = roundTo180(horizontalDegrees);
- verticalDegrees = roundTo180(verticalDegrees);
- transformPhotoView(horizontalDegrees, verticalDegrees);
- flipView.setFlippedAngles(horizontalDegrees, verticalDegrees);
-
- // Flip the filter according to the flipped directions of flip-view.
- filter.setFlip(((int) horizontalDegrees / 180) % 2 != 0,
- ((int) verticalDegrees / 180) % 2 != 0);
- notifyChanged(filter);
- }
-
- private float roundTo180(float degrees) {
- if (degrees % 180 != 0) {
- degrees = Math.round(degrees / 180) * 180;
- }
- return degrees;
- }
-
- private void transformPhotoView(final float horizontalDegrees,
- final float verticalDegrees) {
- // Remove the outdated flip change before queuing a new one.
- if (queuedTransform != null) {
- photoView.remove(queuedTransform);
- }
- queuedTransform = new Runnable() {
-
- @Override
- public void run() {
- photoView.flipPhoto(horizontalDegrees, verticalDegrees);
- }
- };
- photoView.queue(queuedTransform);
- }
- });
- flipView.setFlippedAngles(DEFAULT_ANGLE, DEFAULT_ANGLE);
- flipView.setFlipSpan(DEFAULT_FLIP_SPAN);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-/**
- * View that handles touch-events to track flipping directions and angles.
- */
-class FlipView extends FullscreenToolView {
-
- /**
- * Listens to flip changes.
- */
- public interface OnFlipChangeListener {
-
- void onAngleChanged(float horizontalDegrees, float verticalDegrees, boolean fromUser);
-
- void onStartTrackingTouch();
-
- void onStopTrackingTouch();
- }
-
- private static final float FIXED_DIRECTION_THRESHOLD = 20;
-
- private OnFlipChangeListener listener;
- private float maxFlipSpan;
- private float touchStartX;
- private float touchStartY;
- private float currentHorizontalDegrees;
- private float currentVerticalDegrees;
- private float lastHorizontalDegrees;
- private float lastVerticalDegrees;
- private boolean fixedDirection;
- private boolean fixedDirectionHorizontal;
-
- public FlipView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void setOnFlipChangeListener(OnFlipChangeListener listener) {
- this.listener = listener;
- }
-
- public void setFlippedAngles(float horizontalDegrees, float verticalDegrees) {
- refreshAngle(horizontalDegrees, verticalDegrees, false);
- }
-
- /**
- * Sets allowed degrees for every flip before flipping the view.
- */
- public void setFlipSpan(float degrees) {
- // Flip-span limits allowed flipping degrees of every flip for usability purpose; the max.
- // flipped angles could be accumulated and larger than allowed flip-span.
- maxFlipSpan = degrees;
- }
-
- private float calculateAngle(boolean flipHorizontal, float x, float y) {
- // Use partial length along the moving direction to calculate the flip angle.
- float maxDistance = (flipHorizontal ? getWidth() : getHeight()) * 0.35f;
- float moveDistance = flipHorizontal ? (x - touchStartX) : (touchStartY - y);
-
- if (Math.abs(moveDistance) > maxDistance) {
- moveDistance = (moveDistance > 0) ? maxDistance : -maxDistance;
-
- if (flipHorizontal) {
- touchStartX = x - moveDistance;
- } else {
- touchStartY = moveDistance + y;
- }
- }
- return (moveDistance / maxDistance) * maxFlipSpan;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- super.onTouchEvent(ev);
-
- if (isEnabled()) {
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- fixedDirection = false;
- lastHorizontalDegrees = currentHorizontalDegrees;
- lastVerticalDegrees = currentVerticalDegrees;
- touchStartX = ev.getX();
- touchStartY = ev.getY();
-
- if (listener != null) {
- listener.onStartTrackingTouch();
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- // Allow only one direction for flipping during movements, and make the
- // direction fixed once it exceeds threshold.
- float x = ev.getX();
- float y = ev.getY();
- boolean flipHorizontal = fixedDirection ? fixedDirectionHorizontal
- : (Math.abs(x - touchStartX) >= Math.abs(y - touchStartY));
- float degrees = calculateAngle(flipHorizontal, x, y);
- if (!fixedDirection && (Math.abs(degrees) > FIXED_DIRECTION_THRESHOLD)) {
- fixedDirection = true;
- fixedDirectionHorizontal = flipHorizontal;
- }
-
- if (flipHorizontal) {
- refreshAngle(lastHorizontalDegrees + degrees, lastVerticalDegrees, true);
- } else {
- refreshAngle(lastHorizontalDegrees, lastVerticalDegrees + degrees, true);
- }
- break;
-
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- if (listener != null) {
- listener.onStopTrackingTouch();
- }
- break;
- }
- }
- return true;
- }
-
- private void refreshAngle(float horizontalDegrees, float verticalDegrees, boolean fromUser) {
- currentHorizontalDegrees = horizontalDegrees;
- currentVerticalDegrees = verticalDegrees;
- if (listener != null) {
- listener.onAngleChanged(horizontalDegrees, verticalDegrees, fromUser);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.graphics.Matrix;
-import android.graphics.PointF;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-import android.view.View;
-
-/**
- * Full-screen tool view that gets photo display bounds and maps positions on photo display bounds
- * back to exact coordinates on photo.
- */
-abstract class FullscreenToolView extends View {
-
- protected final RectF displayBounds = new RectF();
- private final Matrix photoMatrix = new Matrix();
- private RectF photoBounds;
-
- public FullscreenToolView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * Photo bounds must be set before onSizeChanged() and all other instance methods are invoked.
- */
- public void setPhotoBounds(RectF photoBounds) {
- this.photoBounds = photoBounds;
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- displayBounds.setEmpty();
- photoMatrix.reset();
- if (photoBounds.isEmpty()) {
- return;
- }
-
- // Assumes photo-view is also full-screen as this tool-view and centers/scales photo to fit.
- Matrix matrix = new Matrix();
- if (matrix.setRectToRect(photoBounds, new RectF(0, 0, w, h), Matrix.ScaleToFit.CENTER)) {
- matrix.mapRect(displayBounds, photoBounds);
- }
-
- matrix.invert(photoMatrix);
- }
-
- protected float getPhotoWidth() {
- return photoBounds.width();
- }
-
- protected float getPhotoHeight() {
- return photoBounds.height();
- }
-
- protected void mapPhotoPoint(float x, float y, PointF dst) {
- if (photoBounds.isEmpty()) {
- dst.set(0, 0);
- } else {
- float[] point = new float[] {x, y};
- photoMatrix.mapPoints(point);
- dst.set(point[0] / photoBounds.width(), point[1] / photoBounds.height());
- }
- }
-
- protected void mapPhotoRect(RectF src, RectF dst) {
- if (photoBounds.isEmpty()) {
- dst.setEmpty();
- } else {
- photoMatrix.mapRect(dst, src);
- dst.set(dst.left / photoBounds.width(), dst.top / photoBounds.height(),
- dst.right / photoBounds.width(), dst.bottom / photoBounds.height());
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.GrainFilter;
-
-/**
- * An action handling the film-grain effect.
- */
-public class GrainAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0.5f;
-
- public GrainAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final GrainFilter filter = new GrainFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.GENERIC);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
-
- filter.setScale(DEFAULT_SCALE);
- notifyChanged(filter);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.GrayscaleFilter;
-
-/**
- * An action handling grayscale effect.
- */
-public class GrayscaleAction extends EffectAction {
-
- public GrayscaleAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- notifyChanged(new GrayscaleFilter());
- notifyOk();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.HighlightFilter;
-
-/**
- * An action handling highlight effect.
- */
-public class HighlightAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0f;
-
- public HighlightAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final HighlightFilter filter = new HighlightFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.LIGHT);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.LomoishFilter;
-
-/**
- * An action handling the preset "Lomo-ish" effect.
- */
-public class LomoishAction extends EffectAction {
-
- public LomoishAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- notifyChanged(new LomoishFilter());
- notifyOk();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.NegativeFilter;
-
-/**
- * An action handling negative effect.
- */
-public class NegativeAction extends EffectAction {
-
- public NegativeAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- notifyChanged(new NegativeFilter());
- notifyOk();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.PosterizeFilter;
-
-/**
- * An action handling the "Posterize" effect.
- */
-public class PosterizeAction extends EffectAction {
-
- public PosterizeAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- notifyChanged(new PosterizeFilter());
- notifyOk();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.graphics.PointF;
-import android.graphics.RectF;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.RedEyeFilter;
-
-/**
- * An action handling red-eye removal.
- */
-public class RedEyeAction extends EffectAction {
-
- public RedEyeAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final RedEyeFilter filter = new RedEyeFilter();
-
- TouchView touchView = toolKit.addTouchView();
- touchView.setSingleTapListener(new TouchView.SingleTapListener() {
-
- final RectF bounds = new RectF(0, 0, 1, 1);
-
- @Override
- public void onSingleTap(PointF point) {
- // Check if the user taps within photo bounds to remove red eye on photo.
- if (bounds.contains(point.x, point.y)) {
- filter.addRedEyePosition(point);
- notifyChanged(filter);
- }
- }
- });
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.PhotoView;
-import com.android.gallery3d.photoeditor.filters.RotateFilter;
-
-/**
- * An action handling rotate effect.
- */
-public class RotateAction extends EffectAction {
-
- private static final float DEFAULT_ANGLE = 0.0f;
- private static final float DEFAULT_ROTATE_SPAN = 360.0f;
-
- public RotateAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- // Disable outputting rotated results and directly rotate photo-view for animations.
- final RotateFilter filter = new RotateFilter();
- disableFilterOutput();
-
- final RotateView rotateView = toolKit.addRotateView();
- rotateView.setOnRotateChangeListener(new RotateView.OnRotateChangeListener() {
-
- float rotateDegrees;
- Runnable queuedTransform;
- PhotoView photoView = toolKit.getPhotoView();
-
- @Override
- public void onAngleChanged(float degrees, boolean fromUser) {
- if (fromUser) {
- rotateDegrees = degrees;
- transformPhotoView(rotateDegrees);
- notifyChanged(filter);
- }
- }
-
- @Override
- public void onStartTrackingTouch() {
- // no-op
- }
-
- @Override
- public void onStopTrackingTouch() {
- // Round rotate degrees to multiples of 90 degrees.
- if (rotateDegrees % 90 != 0) {
- rotateDegrees = Math.round(rotateDegrees / 90) * 90;
- }
- transformPhotoView(rotateDegrees);
- rotateView.setRotatedAngle(rotateDegrees);
- filter.setAngle(rotateDegrees);
- notifyChanged(filter);
- }
-
- private void transformPhotoView(final float degrees) {
- // Remove the outdated rotation change before queuing a new one.
- if (queuedTransform != null) {
- photoView.remove(queuedTransform);
- }
- queuedTransform = new Runnable() {
-
- @Override
- public void run() {
- photoView.rotatePhoto(degrees);
- }
- };
- photoView.queue(queuedTransform);
- }
- });
- rotateView.setRotatedAngle(DEFAULT_ANGLE);
- rotateView.setRotateSpan(DEFAULT_ROTATE_SPAN);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.DashPathEffect;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-
-import com.android.gallery3d.R;
-
-/**
- * View that shows grids and handles touch-events to adjust angle of rotation.
- */
-class RotateView extends FullscreenToolView {
-
- /**
- * Listens to rotate changes.
- */
- public interface OnRotateChangeListener {
-
- void onAngleChanged(float degrees, boolean fromUser);
-
- void onStartTrackingTouch();
-
- void onStopTrackingTouch();
- }
-
- // All angles used are defined between PI and -PI.
- private static final float MATH_PI = (float) Math.PI;
- private static final float MATH_HALF_PI = MATH_PI / 2;
- private static final float RADIAN_TO_DEGREE = 180f / MATH_PI;
-
- private final Paint dashStrokePaint;
- private final Path grids = new Path();
- private final Path referenceLine = new Path();
- private final int gridsColor;
- private final int referenceColor;
-
- private OnRotateChangeListener listener;
- private boolean drawGrids;
- private int centerX;
- private int centerY;
- private float maxRotatedAngle;
- private float minRotatedAngle;
- private float currentRotatedAngle;
- private float lastRotatedAngle;
- private float touchStartAngle;
-
- public RotateView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- dashStrokePaint = new Paint();
- dashStrokePaint.setAntiAlias(true);
- dashStrokePaint.setStyle(Paint.Style.STROKE);
- dashStrokePaint.setPathEffect(new DashPathEffect(new float[] {15.0f, 5.0f}, 1.0f));
- dashStrokePaint.setStrokeWidth(2f);
- gridsColor = context.getResources().getColor(R.color.translucent_white);
- referenceColor = context.getResources().getColor(R.color.translucent_cyan);
- }
-
- public void setRotatedAngle(float degrees) {
- refreshAngle(degrees, false);
- }
-
- /**
- * Sets allowed degrees for rotation span before rotating the view.
- */
- public void setRotateSpan(float degrees) {
- if (degrees >= 360f) {
- maxRotatedAngle = Float.POSITIVE_INFINITY;
- } else {
- maxRotatedAngle = (degrees / RADIAN_TO_DEGREE) / 2;
- }
- minRotatedAngle = -maxRotatedAngle;
- }
-
- public void setOnRotateChangeListener(OnRotateChangeListener listener) {
- this.listener = listener;
- }
-
- public void setDrawGrids(boolean drawGrids) {
- this.drawGrids = drawGrids;
- invalidate();
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- centerX = w / 2;
- centerY = h / 2;
-
- // Make reference line long enough to cross the bounds diagonally after being rotated.
- referenceLine.reset();
- float radius = (float) Math.hypot(centerX, centerY);
- float delta = radius - centerX;
- referenceLine.moveTo(-delta, centerY);
- referenceLine.lineTo(getWidth() + delta, centerY);
- delta = radius - centerY;
- referenceLine.moveTo(centerX, -delta);
- referenceLine.lineTo(centerX, getHeight() + delta);
-
- // Set grids inside photo display bounds.
- grids.reset();
- delta = displayBounds.width() / 4.0f;
- for (float x = displayBounds.left + delta; x < displayBounds.right; x += delta) {
- grids.moveTo(x, displayBounds.top);
- grids.lineTo(x, displayBounds.bottom);
- }
- delta = displayBounds.height() / 4.0f;
- for (float y = displayBounds.top + delta; y < displayBounds.bottom; y += delta) {
- grids.moveTo(displayBounds.left, y);
- grids.lineTo(displayBounds.right, y);
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (drawGrids) {
- canvas.save();
- canvas.clipRect(displayBounds);
- dashStrokePaint.setColor(gridsColor);
- canvas.drawPath(grids, dashStrokePaint);
-
- canvas.rotate(-currentRotatedAngle * RADIAN_TO_DEGREE, centerX, centerY);
- dashStrokePaint.setColor(referenceColor);
- canvas.drawPath(referenceLine, dashStrokePaint);
- canvas.restore();
- }
- }
-
- private float calculateAngle(MotionEvent ev) {
- float x = ev.getX() - centerX;
- float y = centerY - ev.getY();
-
- float angle;
- if (x == 0) {
- angle = (y >= 0) ? MATH_HALF_PI : -MATH_HALF_PI;
- } else {
- angle = (float) Math.atan(y / x);
- }
-
- if ((angle >= 0) && (x < 0)) {
- angle = angle - MATH_PI;
- } else if ((angle < 0) && (x < 0)) {
- angle = MATH_PI + angle;
- }
- return angle;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- super.onTouchEvent(ev);
-
- if (isEnabled()) {
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- lastRotatedAngle = currentRotatedAngle;
- touchStartAngle = calculateAngle(ev);
-
- if (listener != null) {
- listener.onStartTrackingTouch();
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- float touchAngle = calculateAngle(ev);
- float rotatedAngle = touchAngle - touchStartAngle + lastRotatedAngle;
-
- if ((rotatedAngle > maxRotatedAngle) || (rotatedAngle < minRotatedAngle)) {
- // Angles are out of range; restart rotating.
- // TODO: Fix discontinuity around boundary.
- lastRotatedAngle = currentRotatedAngle;
- touchStartAngle = touchAngle;
- } else {
- refreshAngle(-rotatedAngle * RADIAN_TO_DEGREE, true);
- }
- break;
-
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- if (listener != null) {
- listener.onStopTrackingTouch();
- }
- break;
- }
- }
- return true;
- }
-
- private void refreshAngle(float degrees, boolean fromUser) {
- currentRotatedAngle = -degrees / RADIAN_TO_DEGREE;
- if (listener != null) {
- listener.onAngleChanged(degrees, fromUser);
- }
- invalidate();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.SaturationFilter;
-
-/**
- * An action handling saturation effect.
- */
-public class SaturationAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0.5f;
-
- public SaturationAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final SaturationFilter filter = new SaturationFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.COLOR);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.SeekBar;
-
-/**
- * Seek-bar that has a draggable thumb to set and get the normalized scale value from 0 to 1.
- */
-class ScaleSeekBar extends AbstractSeekBar {
-
- /**
- * Listens to scale changes.
- */
- public interface OnScaleChangeListener {
-
- void onProgressChanged(float progress, boolean fromUser);
- }
-
- public ScaleSeekBar(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- setMax(100);
- }
-
- public void setOnScaleChangeListener(final OnScaleChangeListener listener) {
- setOnSeekBarChangeListener((listener == null) ? null : new OnSeekBarChangeListener() {
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- listener.onProgressChanged((float) progress / getMax(), fromUser);
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- }
- });
- }
-
- public void setProgress(float progress) {
- setProgress((int) (progress * getMax()));
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.SepiaFilter;
-
-/**
- * An action handling sepia effect.
- */
-public class SepiaAction extends EffectAction {
-
- public SepiaAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- notifyChanged(new SepiaFilter());
- notifyOk();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.ShadowFilter;
-
-/**
- * An action handling shadow effect.
- */
-public class ShadowAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0f;
-
- public ShadowAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final ShadowFilter filter = new ShadowFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.SHADOW);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.SharpenFilter;
-
-/**
- * An action handling sharpen effect.
- */
-public class SharpenAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0.5f;
-
- public SharpenAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final SharpenFilter filter = new SharpenFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.GENERIC);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
-
- filter.setScale(DEFAULT_SCALE);
- notifyChanged(filter);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.StraightenFilter;
-
-/**
- * An action handling straighten effect.
- */
-public class StraightenAction extends EffectAction {
-
- private static final float DEFAULT_ANGLE = 0.0f;
- private static final float DEFAULT_ROTATE_SPAN = StraightenFilter.MAX_DEGREES * 2;
-
- public StraightenAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final StraightenFilter filter = new StraightenFilter();
-
- RotateView rotateView = toolKit.addRotateView();
- rotateView.setOnRotateChangeListener(new RotateView.OnRotateChangeListener() {
-
- @Override
- public void onAngleChanged(float degrees, boolean fromUser){
- if (fromUser) {
- filter.setAngle(degrees);
- notifyChanged(filter);
- }
- }
-
- @Override
- public void onStartTrackingTouch() {
- // no-op
- }
-
- @Override
- public void onStopTrackingTouch() {
- // no-op
- }
- });
- rotateView.setDrawGrids(true);
- rotateView.setRotatedAngle(DEFAULT_ANGLE);
- rotateView.setRotateSpan(DEFAULT_ROTATE_SPAN);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.TintFilter;
-
-/**
- * An action handling tint effect.
- */
-public class TintAction extends EffectAction {
-
- private static final int DEFAULT_COLOR_INDEX = 13;
-
- public TintAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final TintFilter filter = new TintFilter();
-
- ColorSeekBar colorPicker = toolKit.addColorPicker();
- colorPicker.setOnColorChangeListener(new ColorSeekBar.OnColorChangeListener() {
-
- @Override
- public void onColorChanged(int color, boolean fromUser) {
- if (fromUser) {
- filter.setTint(color);
- notifyChanged(filter);
- }
- }
- });
- colorPicker.setColorIndex(DEFAULT_COLOR_INDEX);
-
- filter.setTint(colorPicker.getColor());
- notifyChanged(filter);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.graphics.PointF;
-import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-
-/**
- * A view that detects user gestures and touch motions.
- */
-class TouchView extends FullscreenToolView {
-
- /**
- * Listener of single tap on a point (relative to photo coordinates).
- */
- public interface SingleTapListener {
-
- void onSingleTap(PointF point);
- }
-
- private final GestureDetector gestureDetector;
- private SingleTapListener singleTapListener;
-
- public TouchView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- gestureDetector = new GestureDetector(
- context, new GestureDetector.SimpleOnGestureListener() {
-
- @Override
- public boolean onDown(MotionEvent e) {
- // GestureDetector onTouchEvent returns true only for events whose preceding
- // down-events have been consumed.
- return true;
- }
-
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- if (singleTapListener != null) {
- PointF point = new PointF();
- mapPhotoPoint(e.getX(), e.getY(), point);
- singleTapListener.onSingleTap(point);
- }
- return true;
- }
- });
- gestureDetector.setIsLongpressEnabled(false);
- }
-
- public void setSingleTapListener(SingleTapListener listener) {
- singleTapListener = listener;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- return isEnabled() && gestureDetector.onTouchEvent(event);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.actions;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-import com.android.gallery3d.photoeditor.filters.VignetteFilter;
-
-/**
- * An action handling vignette effect.
- */
-public class VignetteAction extends EffectAction {
-
- private static final float DEFAULT_SCALE = 0.5f;
-
- public VignetteAction(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- public void prepare() {
- final VignetteFilter filter = new VignetteFilter();
-
- ScaleSeekBar scalePicker = toolKit.addScalePicker(EffectToolKit.ScaleType.GENERIC);
- scalePicker.setOnScaleChangeListener(new ScaleSeekBar.OnScaleChangeListener() {
-
- @Override
- public void onProgressChanged(float progress, boolean fromUser) {
- if (fromUser) {
- filter.setScale(progress);
- notifyChanged(filter);
- }
- }
- });
- scalePicker.setProgress(DEFAULT_SCALE);
-
- filter.setScale(DEFAULT_SCALE);
- notifyChanged(filter);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.os.Parcel;
-
-/**
- * Filter base that has a scale value ranging from 0 to 1 for adjustments and can persist states.
- */
-public abstract class AbstractScaleFilter extends Filter {
-
- protected float scale;
-
- /**
- * Sets the scale from 0 to 1.
- */
- public void setScale(float scale) {
- this.scale = scale;
- }
-
- @Override
- protected void writeToParcel(Parcel out) {
- out.writeFloat(scale);
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- scale = in.readFloat();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Auto-fix filter applied to the image.
- */
-public class AutoFixFilter extends AbstractScaleFilter {
-
- public static final Creator<AutoFixFilter> CREATOR = creatorOf(AutoFixFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_AUTOFIX);
- effect.setParameter("scale", scale);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Color temperature filter applied to the image.
- */
-public class ColorTemperatureFilter extends AbstractScaleFilter {
-
- public static final Creator<ColorTemperatureFilter> CREATOR = creatorOf(
- ColorTemperatureFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_TEMPERATURE);
- effect.setParameter("scale", scale);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.graphics.RectF;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-import android.os.Parcel;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Crop filter applied to the image.
- */
-public class CropFilter extends Filter {
-
- public static final Creator<CropFilter> CREATOR = creatorOf(CropFilter.class);
-
- private RectF bounds;
-
- /**
- * The rect coordinates used here should range from 0 to 1.
- */
- public void setCropBounds(RectF bounds) {
- this.bounds = bounds;
- }
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- dst.changeDimension(Math.round(bounds.width() * src.width()),
- Math.round(bounds.height() * src.height()));
-
- Effect effect = getEffect(EffectFactory.EFFECT_CROP);
- effect.setParameter("xorigin", Math.round(bounds.left * src.width()));
- effect.setParameter("yorigin", Math.round(bounds.top * src.height()));
- effect.setParameter("width", dst.width());
- effect.setParameter("height", dst.height());
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-
- @Override
- protected void writeToParcel(Parcel out) {
- out.writeParcelable(bounds, 0);
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- bounds = in.readParcelable(null);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Cross-process filter applied to the image.
- */
-public class CrossProcessFilter extends Filter {
-
- public static final Creator<CrossProcessFilter> CREATOR = creatorOf(CrossProcessFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- getEffect(EffectFactory.EFFECT_CROSSPROCESS).apply(
- src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Documentary filter applied to the image.
- */
-public class DocumentaryFilter extends Filter {
-
- public static final Creator<DocumentaryFilter> CREATOR = creatorOf(DocumentaryFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- getEffect(EffectFactory.EFFECT_DOCUMENTARY).apply(
- src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.RectF;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-import android.os.Parcel;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-import com.android.gallery3d.photoeditor.actions.Doodle;
-
-import java.util.Vector;
-
-/**
- * Doodle filter applied to the image.
- */
-public class DoodleFilter extends Filter {
-
- public static final Creator<DoodleFilter> CREATOR = creatorOf(DoodleFilter.class);
-
- private final Vector<Doodle> doodles = new Vector<Doodle>();
-
- public void addDoodle(Doodle doodle) {
- doodles.add(doodle);
- }
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Bitmap bitmap = Bitmap.createBitmap(src.width(), src.height(), Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
-
- Matrix matrix = new Matrix();
- matrix.setRectToRect(new RectF(0, 0, 1, 1),
- new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()), Matrix.ScaleToFit.FILL);
-
- Path drawingPath = new Path();
- Paint paint = Doodle.createPaint();
- for (Doodle doodle : doodles) {
- paint.setColor(doodle.getColor());
- doodle.getDrawingPath(matrix, drawingPath);
- canvas.drawPath(drawingPath, paint);
- }
-
- Effect effect = getEffect(EffectFactory.EFFECT_BITMAPOVERLAY);
- effect.setParameter("bitmap", bitmap);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-
- @Override
- protected void writeToParcel(Parcel out) {
- out.writeInt(doodles.size());
- for (Doodle doodle : doodles) {
- out.writeParcelable(doodle, 0);
- }
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- int size = in.readInt();
- for (int i = 0; i < size; i++) {
- doodles.add((Doodle) in.readParcelable(Doodle.class.getClassLoader()));
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-import android.os.Parcel;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Duotone filter applied to the image.
- */
-public class DuotoneFilter extends Filter {
-
- public static final Creator<DuotoneFilter> CREATOR = creatorOf(DuotoneFilter.class);
-
- private int firstColor;
- private int secondColor;
-
- public void setDuotone(int firstColor, int secondColor) {
- this.firstColor = firstColor;
- this.secondColor = secondColor;
- }
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_DUOTONE);
- effect.setParameter("first_color", firstColor);
- effect.setParameter("second_color", secondColor);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-
- @Override
- protected void writeToParcel(Parcel out) {
- out.writeInt(firstColor);
- out.writeInt(secondColor);
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- firstColor = in.readInt();
- secondColor = in.readInt();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Face tanning filter applied to the image.
- */
-public class FaceTanFilter extends AbstractScaleFilter {
-
- public static final Creator<FaceTanFilter> CREATOR = creatorOf(FaceTanFilter.class);
-
- private static final String EFFECT_FACE_TANNING = "com.google.android.media.effect.effects.FaceTanningEffect";
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EFFECT_FACE_TANNING);
- effect.setParameter("blend", scale);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-
- /**
- * Checks if the effect is present in the system.
- *
- * @return boolean true if an effect is present in the system and can be loaded
- */
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public static boolean isPresent() {
- return EffectFactory.isEffectSupported(EFFECT_FACE_TANNING);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Facelift filter applied to the image.
- */
-public class FaceliftFilter extends AbstractScaleFilter {
-
- public static final Creator<FaceliftFilter> CREATOR = creatorOf(FaceliftFilter.class);
-
- private static final String EFFECT_FACELIFT = "com.google.android.media.effect.effects.FaceliftEffect";
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EFFECT_FACELIFT);
- effect.setParameter("blend", scale);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-
- /**
- * Checks if the effect is present in the system.
- *
- * @return boolean true if an effect is present in the system and can be loaded
- */
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public static boolean isPresent() {
- return EffectFactory.isEffectSupported(EFFECT_FACELIFT);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Fill-light filter applied to the image.
- */
-public class FillLightFilter extends AbstractScaleFilter {
-
- public static final Creator<FillLightFilter> CREATOR = creatorOf(FillLightFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_FILLLIGHT);
- effect.setParameter("strength", scale);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectContext;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-import java.util.HashMap;
-
-/**
- * Image filter for photo editing; all of its methods must be called from a single GL thread.
- */
-@TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
-public abstract class Filter implements Parcelable {
-
- // TODO: This should be set in MFF instead.
- private static final int DEFAULT_TILE_SIZE = 640;
-
- private static final HashMap<Filter, Effect> effects = new HashMap<Filter, Effect>();
- private static EffectContext context;
-
- /**
- * Filter context should be released before the current GL context is lost.
- */
- public static void releaseContext() {
- if (context != null) {
- // Release all effects created with the releasing context.
- for (Effect effect : effects.values()) {
- effect.release();
- }
- effects.clear();
- context.release();
- context = null;
- }
- }
-
- public void release() {
- Effect effect = effects.remove(this);
- if (effect != null) {
- effect.release();
- }
- }
-
- protected Effect getEffect(String name) {
- Effect effect = effects.get(this);
- if (effect == null) {
- if (context == null) {
- context = EffectContext.createWithCurrentGlContext();
- }
- effect = context.getFactory().createEffect(name);
- effect.setParameter("tile_size", DEFAULT_TILE_SIZE);
- effects.put(this, effect);
- }
- return effect;
- }
-
- /**
- * Processes the source bitmap and matrix and output the destination bitmap and matrix.
- *
- * @param src source photo as the input.
- * @param dst destination photo having the same dimension as source photo as the output.
- */
- public abstract void process(Photo src, Photo dst);
-
- /**
- * Instantiates CREATOR of subclasses for Parcelable implementations.
- */
- protected static <T extends Filter> Parcelable.Creator<T> creatorOf(Class<T> filterClass) {
- return new FilterCreator<T>(filterClass);
- }
-
- /**
- * Saves states for restoring filter later; subclasses can override this to persist states.
- */
- protected void writeToParcel(Parcel out) {
- }
-
- /**
- * Restores filter from the saved states; subclasses can override this to persist states.
- */
- protected void readFromParcel(Parcel in) {
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- writeToParcel(dest);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.reflect.Array;
-
-/**
- * Creator that creates the specific parcelable filter from the parcel.
- */
-public class FilterCreator<T extends Filter> implements Parcelable.Creator<T> {
-
- private final Class<T> filterClass;
-
- public FilterCreator(Class<T> filterClass) {
- this.filterClass = filterClass;
- }
-
- @Override
- public T createFromParcel(Parcel source) {
- try {
- T filter = filterClass.newInstance();
- filter.readFromParcel(source);
- return filter;
- } catch (InstantiationException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public T[] newArray(int size) {
- return (T[]) Array.newInstance(filterClass, size);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Fisheye filter applied to the image.
- */
-public class FisheyeFilter extends AbstractScaleFilter {
-
- public static final Creator<FisheyeFilter> CREATOR = creatorOf(FisheyeFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_FISHEYE);
- effect.setParameter("scale", scale);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-import android.os.Parcel;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Flip filter applied to the image.
- */
-public class FlipFilter extends Filter {
-
- public static final Creator<FlipFilter> CREATOR = creatorOf(FlipFilter.class);
-
- private final boolean[] flips = new boolean[2];
-
- public void setFlip(boolean flipHorizontal, boolean flipVertical) {
- flips[0] = flipHorizontal;
- flips[1] = flipVertical;
- }
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_FLIP);
- effect.setParameter("horizontal", flips[0]);
- effect.setParameter("vertical", flips[1]);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-
- @Override
- protected void writeToParcel(Parcel out) {
- out.writeBooleanArray(flips);
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- in.readBooleanArray(flips);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Film grain filter applied to the image.
- */
-public class GrainFilter extends AbstractScaleFilter {
-
- public static final Creator<GrainFilter> CREATOR = creatorOf(GrainFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_GRAIN);
- effect.setParameter("strength", scale);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Grayscale filter applied to the image.
- */
-public class GrayscaleFilter extends Filter {
-
- public static final Creator<GrayscaleFilter> CREATOR = creatorOf(GrayscaleFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- getEffect(EffectFactory.EFFECT_GRAYSCALE).apply(
- src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Highlight filter applied to the image.
- */
-public class HighlightFilter extends AbstractScaleFilter {
-
- public static final Creator<HighlightFilter> CREATOR = creatorOf(HighlightFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_BLACKWHITE);
- effect.setParameter("black", 0f);
- effect.setParameter("white", 1f - scale * 0.5f);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Lomo-ish filter applied to the image.
- */
-public class LomoishFilter extends Filter {
-
- public static final Creator<LomoishFilter> CREATOR = creatorOf(LomoishFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- getEffect(EffectFactory.EFFECT_LOMOISH).apply(
- src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Negative filter applied to the image.
- */
-public class NegativeFilter extends Filter {
-
- public static final Creator<NegativeFilter> CREATOR = creatorOf(NegativeFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- getEffect(EffectFactory.EFFECT_NEGATIVE).apply(
- src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Posterize filter applied to the image.
- */
-public class PosterizeFilter extends Filter {
-
- public static final Creator<PosterizeFilter> CREATOR = creatorOf(PosterizeFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- getEffect(EffectFactory.EFFECT_POSTERIZE).apply(
- src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.graphics.PointF;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-import android.os.Parcel;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-import java.util.Vector;
-
-/**
- * Red-eye removal filter applied to the image.
- */
-public class RedEyeFilter extends Filter {
-
- public static final Creator<RedEyeFilter> CREATOR = creatorOf(RedEyeFilter.class);
-
- private final Vector<PointF> redeyes = new Vector<PointF>();
-
- /**
- * The point coordinates used here should range from 0 to 1.
- */
- public void addRedEyePosition(PointF point) {
- redeyes.add(point);
- }
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_REDEYE);
- float[] centers = new float[redeyes.size() * 2];
- int i = 0;
- for (PointF eye : redeyes) {
- centers[i++] = eye.x;
- centers[i++] = eye.y;
- }
- effect.setParameter("centers", centers);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-
- @Override
- protected void writeToParcel(Parcel out) {
- out.writeInt(redeyes.size());
- for (PointF eye : redeyes) {
- out.writeParcelable(eye, 0);
- }
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- int size = in.readInt();
- for (int i = 0; i < size; i++) {
- redeyes.add((PointF) in.readParcelable(null));
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-import android.os.Parcel;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Rotate filter applied to the image.
- */
-public class RotateFilter extends Filter {
-
- public static final Creator<RotateFilter> CREATOR = creatorOf(RotateFilter.class);
-
- private float degrees;
-
- /**
- * Sets rotation angle which must be multiples of 90 degrees.
- */
- public void setAngle(float degrees) {
- this.degrees = degrees;
- }
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- if (degrees % 180 != 0) {
- dst.changeDimension(src.height(), src.width());
- }
- Effect effect = getEffect(EffectFactory.EFFECT_ROTATE);
- effect.setParameter("angle", (int) degrees);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-
- @Override
- protected void writeToParcel(Parcel out) {
- out.writeFloat(degrees);
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- degrees = in.readFloat();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Saturation filter applied to the image.
- */
-public class SaturationFilter extends AbstractScaleFilter {
-
- public static final Creator<SaturationFilter> CREATOR = creatorOf(SaturationFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_SATURATE);
- effect.setParameter("scale", (scale - 0.5f) * 2);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Sepia filter applied to the image.
- */
-public class SepiaFilter extends Filter {
-
- public static final Creator<SepiaFilter> CREATOR = creatorOf(SepiaFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- getEffect(EffectFactory.EFFECT_SEPIA).apply(
- src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Shadow filter applied to the image.
- */
-public class ShadowFilter extends AbstractScaleFilter {
-
- public static final Creator<ShadowFilter> CREATOR = creatorOf(ShadowFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_BLACKWHITE);
- effect.setParameter("black", scale * 0.5f);
- effect.setParameter("white", 1f);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Sharpen filter applied to the image.
- */
-public class SharpenFilter extends AbstractScaleFilter {
-
- public static final Creator<SharpenFilter> CREATOR = creatorOf(SharpenFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_SHARPEN);
- effect.setParameter("scale", scale);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-import android.os.Parcel;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Straighten filter applied to the image.
- */
-public class StraightenFilter extends Filter {
-
- public static final Creator<StraightenFilter> CREATOR = creatorOf(StraightenFilter.class);
- public static final float MAX_DEGREES = 45.0f;
-
- private float degrees;
-
- public void setAngle(float degrees) {
- this.degrees = degrees;
- }
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_STRAIGHTEN);
- effect.setParameter("maxAngle", MAX_DEGREES);
- effect.setParameter("angle", -degrees);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-
- @Override
- protected void writeToParcel(Parcel out) {
- out.writeFloat(degrees);
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- degrees = in.readFloat();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-import android.os.Parcel;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Tint filter applied to the image.
- */
-public class TintFilter extends Filter {
-
- public static final Creator<TintFilter> CREATOR = creatorOf(TintFilter.class);
-
- private int color;
-
- public void setTint(int color) {
- this.color = color;
- }
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_TINT);
- effect.setParameter("tint", color);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-
- @Override
- protected void writeToParcel(Parcel out) {
- out.writeInt(color);
- }
-
- @Override
- protected void readFromParcel(Parcel in) {
- color = in.readInt();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source 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 com.android.gallery3d.photoeditor.filters;
-
-import android.annotation.TargetApi;
-import android.media.effect.Effect;
-import android.media.effect.EffectFactory;
-
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.photoeditor.Photo;
-
-/**
- * Vignette filter applied to the image.
- */
-public class VignetteFilter extends AbstractScaleFilter {
-
- public static final Creator<VignetteFilter> CREATOR = creatorOf(VignetteFilter.class);
-
- @Override
- @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
- public void process(Photo src, Photo dst) {
- Effect effect = getEffect(EffectFactory.EFFECT_VIGNETTE);
- effect.setParameter("scale", scale);
- effect.apply(src.texture(), src.width(), src.height(), dst.texture());
- }
-}