summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/camera/CaptureAnimManager.java104
-rw-r--r--src/com/android/camera/ComboPreferences.java7
-rw-r--r--src/com/android/camera/FocusOverlayManager.java1
-rw-r--r--src/com/android/camera/MosaicFrameProcessor.java3
-rw-r--r--src/com/android/camera/MosaicPreviewRenderer.java3
-rw-r--r--src/com/android/camera/PhotoModule.java7
-rw-r--r--src/com/android/camera/VideoModule.java15
-rw-r--r--src/com/android/camera/ui/PieMenuButton.java61
-rw-r--r--src/com/android/gallery3d/app/CommonControllerOverlay.java4
-rw-r--r--src/com/android/gallery3d/app/PhotoPage.java2
-rw-r--r--src/com/android/gallery3d/filtershow/EditorPlaceHolder.java4
-rw-r--r--src/com/android/gallery3d/filtershow/FilterShowActivity.java265
-rw-r--r--src/com/android/gallery3d/filtershow/ImageStateAdapter.java7
-rw-r--r--src/com/android/gallery3d/filtershow/PanelController.java228
-rw-r--r--src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java242
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ImageLoader.java17
-rw-r--r--src/com/android/gallery3d/filtershow/cache/RenderingRequest.java106
-rw-r--r--src/com/android/gallery3d/filtershow/cache/RenderingRequestCaller.java21
-rw-r--r--src/com/android/gallery3d/filtershow/cache/TripleBufferBitmap.java14
-rw-r--r--src/com/android/gallery3d/filtershow/editors/BasicEditor.java51
-rw-r--r--src/com/android/gallery3d/filtershow/editors/Editor.java20
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorCurves.java17
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorDraw.java48
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorRedEye.java61
-rw-r--r--src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java54
-rw-r--r--src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java46
-rw-r--r--src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java113
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java128
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java113
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java54
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java29
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java158
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java108
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java91
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterPoint.java21
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java87
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java53
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java209
-rw-r--r--src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java65
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilter.java168
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java100
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java34
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java30
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java98
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java41
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java492
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java32
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java29
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java59
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java8
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterGradient.java114
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java43
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java48
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java34
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java84
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java30
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java146
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java27
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java34
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java37
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterStraighten.java8
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java74
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java29
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java34
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java27
-rw-r--r--src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java4
-rw-r--r--src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java46
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/GeometryListener.java21
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java4
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java55
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java6
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java103
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageRedEye.java (renamed from src/com/android/gallery3d/filtershow/imageshow/ImageRedEyes.java)112
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageShow.java57
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java27
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/MasterImage.java104
-rw-r--r--src/com/android/gallery3d/filtershow/presets/ImagePreset.java226
-rw-r--r--src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java2
-rw-r--r--src/com/android/gallery3d/filtershow/ui/FilterIconButton.java89
-rw-r--r--src/com/android/gallery3d/filtershow/ui/IconButton.java2
-rw-r--r--src/com/android/gallery3d/filtershow/ui/ImageCurves.java24
-rw-r--r--src/com/android/gallery3d/filtershow/ui/Spline.java6
-rw-r--r--src/com/android/gallery3d/ingest/IngestActivity.java230
-rw-r--r--src/com/android/gallery3d/ingest/IngestService.java24
-rw-r--r--src/com/android/gallery3d/ingest/MtpDeviceIndex.java105
-rw-r--r--src/com/android/gallery3d/ingest/adapter/CheckBroker.java56
-rw-r--r--src/com/android/gallery3d/ingest/adapter/MtpAdapter.java16
-rw-r--r--src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java102
-rw-r--r--src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java29
-rw-r--r--src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java99
-rw-r--r--src/com/android/gallery3d/ingest/ui/IngestGridView.java58
-rw-r--r--src/com/android/gallery3d/ingest/ui/MtpBitmapCache.java73
-rw-r--r--src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java115
-rw-r--r--src/com/android/gallery3d/ingest/ui/MtpImageView.java167
-rw-r--r--src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java90
-rw-r--r--src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java1
-rw-r--r--src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java34
-rwxr-xr-xtests/src/com/android/gallery3d/CameraTestRunner.java46
-rwxr-xr-xtests/src/com/android/gallery3d/StressTests.java47
-rw-r--r--tests/src/com/android/gallery3d/functional/CameraTest.java81
-rw-r--r--tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java148
-rw-r--r--tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java258
-rwxr-xr-xtests/src/com/android/gallery3d/power/ImageAndVideoCapture.java116
-rwxr-xr-xtests/src/com/android/gallery3d/stress/CameraLatency.java149
-rw-r--r--tests/src/com/android/gallery3d/stress/CameraStartUp.java157
-rwxr-xr-xtests/src/com/android/gallery3d/stress/CameraStressTestRunner.java61
-rwxr-xr-xtests/src/com/android/gallery3d/stress/ImageCapture.java121
-rw-r--r--tests/src/com/android/gallery3d/stress/ShotToShotLatency.java143
-rwxr-xr-xtests/src/com/android/gallery3d/stress/SwitchPreview.java117
-rw-r--r--tests/src/com/android/gallery3d/stress/TestUtil.java57
-rwxr-xr-xtests/src/com/android/gallery3d/stress/VideoCapture.java115
-rw-r--r--tests/src/com/android/gallery3d/unittest/CameraUnitTest.java107
112 files changed, 6066 insertions, 2241 deletions
diff --git a/src/com/android/camera/CaptureAnimManager.java b/src/com/android/camera/CaptureAnimManager.java
index 64383aff7..4643c379f 100644
--- a/src/com/android/camera/CaptureAnimManager.java
+++ b/src/com/android/camera/CaptureAnimManager.java
@@ -30,13 +30,18 @@ import com.android.gallery3d.glrenderer.RawTexture;
public class CaptureAnimManager {
@SuppressWarnings("unused")
private static final String TAG = "CAM_Capture";
+ // times mark endpoint of animation phase
private static final int TIME_FLASH = 200;
private static final int TIME_HOLD = 400;
- private static final int TIME_SLIDE = 400; // milliseconds.
+ private static final int TIME_SLIDE = 700;
+ private static final int TIME_HOLD2 = 1000;
+ private static final int TIME_SLIDE2 = 1200;
private static final int ANIM_BOTH = 0;
private static final int ANIM_FLASH = 1;
private static final int ANIM_SLIDE = 2;
+ private static final int ANIM_HOLD2 = 3;
+ private static final int ANIM_SLIDE2 = 4;
private final Interpolator mSlideInterpolator = new DecelerateInterpolator();
@@ -44,15 +49,22 @@ public class CaptureAnimManager {
private long mAnimStartTime; // milliseconds.
private float mX; // The center of the whole view including preview and review.
private float mY;
- private float mDelta;
private int mDrawWidth;
private int mDrawHeight;
private int mAnimType;
+ private int mHoldX;
+ private int mHoldY;
+ private int mHoldW;
+ private int mHoldH;
+
+ private int mOffset = 80;
+
/* preview: camera preview view.
* review: view of picture just taken.
*/
public CaptureAnimManager() {
+
}
public void setOrientation(int displayRotation) {
@@ -83,18 +95,24 @@ public class CaptureAnimManager {
mDrawHeight = h;
mX = x;
mY = y;
+ mHoldW = (int) (mDrawWidth * 0.7f);
+ mHoldH = (int) (mDrawHeight * 0.7f);
switch (mAnimOrientation) {
case 0: // Preview is on the left.
- mDelta = w;
+ mHoldX = x + w - mOffset;
+ mHoldY = y + (mDrawHeight - mHoldH) / 2;
break;
case 90: // Preview is below.
- mDelta = -h;
+ mHoldX = x + (mDrawWidth - mHoldW + 1) / 2;
+ mHoldY = y + mOffset- mHoldH;
break;
case 180: // Preview on the right.
- mDelta = -w;
+ mHoldX = x - w + mOffset;
+ mHoldY = y + (mDrawHeight - mHoldH) / 2;
break;
case 270: // Preview is above.
- mDelta = h;
+ mHoldX = x + (mDrawWidth - mHoldW + 1) / 2;
+ mHoldY = y + h - mOffset;
break;
}
}
@@ -104,14 +122,27 @@ public class CaptureAnimManager {
RawTexture review) {
long timeDiff = SystemClock.uptimeMillis() - mAnimStartTime;
// Check if the animation is over
- if (mAnimType == ANIM_SLIDE && timeDiff > TIME_SLIDE) return false;
- if (mAnimType == ANIM_BOTH && timeDiff > TIME_HOLD + TIME_SLIDE) return false;
+ if (mAnimType == ANIM_SLIDE && timeDiff > TIME_SLIDE2 - TIME_HOLD) return false;
+ if (mAnimType == ANIM_BOTH && timeDiff > TIME_SLIDE2) return false;
+ // determine phase and time in phase
int animStep = mAnimType;
- if (mAnimType == ANIM_BOTH) {
- animStep = (timeDiff < TIME_HOLD) ? ANIM_FLASH : ANIM_SLIDE;
- if (animStep == ANIM_SLIDE) {
+ if (mAnimType == ANIM_SLIDE) {
+ timeDiff += TIME_HOLD;
+ }
+ if (mAnimType == ANIM_SLIDE || mAnimType == ANIM_BOTH) {
+ if (timeDiff < TIME_HOLD) {
+ animStep = ANIM_FLASH;
+ } else if (timeDiff < TIME_SLIDE) {
+ animStep = ANIM_SLIDE;
timeDiff -= TIME_HOLD;
+ } else if (timeDiff < TIME_HOLD2) {
+ animStep = ANIM_HOLD2;
+ timeDiff -= TIME_SLIDE;
+ } else {
+ // SLIDE2
+ animStep = ANIM_SLIDE2;
+ timeDiff -= TIME_HOLD2;
}
}
@@ -123,24 +154,47 @@ public class CaptureAnimManager {
canvas.fillRect(mX, mY, mDrawWidth, mDrawHeight, color);
}
} else if (animStep == ANIM_SLIDE) {
- float fraction = (float) (timeDiff) / TIME_SLIDE;
+ float fraction = mSlideInterpolator.getInterpolation((float) (timeDiff) / (TIME_SLIDE - TIME_HOLD));
float x = mX;
float y = mY;
- if (mAnimOrientation == 0 || mAnimOrientation == 180) {
- x = x + mDelta * mSlideInterpolator.getInterpolation(fraction);
- } else {
- y = y + mDelta * mSlideInterpolator.getInterpolation(fraction);
+ float w = 0;
+ float h = 0;
+ x = interpolate(mX, mHoldX, fraction);
+ y = interpolate(mY, mHoldY, fraction);
+ w = interpolate(mDrawWidth, mHoldW, fraction);
+ h = interpolate(mDrawHeight, mHoldH, fraction);
+ preview.directDraw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight);
+ review.draw(canvas, (int) x, (int) y, (int) w, (int) h);
+ } else if (animStep == ANIM_HOLD2) {
+ preview.directDraw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight);
+ review.draw(canvas, mHoldX, mHoldY, mHoldW, mHoldH);
+ } else if (animStep == ANIM_SLIDE2) {
+ float fraction = (float)(timeDiff) / (TIME_SLIDE2 - TIME_HOLD2);
+ float x = mHoldX;
+ float y = mHoldY;
+ float d = mOffset * fraction;
+ switch (mAnimOrientation) {
+ case 0:
+ x = mHoldX + d;
+ break;
+ case 180:
+ x = mHoldX - d;
+ break;
+ case 90:
+ y = mHoldY - d;
+ break;
+ case 270:
+ y = mHoldY + d;
+ break;
}
- // float alpha = canvas.getAlpha();
- // canvas.setAlpha(fraction);
- preview.directDraw(canvas, (int) mX, (int) mY,
- mDrawWidth, mDrawHeight);
- // canvas.setAlpha(alpha);
-
- review.draw(canvas, (int) x, (int) y, mDrawWidth, mDrawHeight);
- } else {
- return false;
+ preview.directDraw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight);
+ review.draw(canvas, (int) x, (int) y, mHoldW, mHoldH);
}
return true;
}
+
+ private static float interpolate(float start, float end, float fraction) {
+ return start + (end - start) * fraction;
+ }
+
}
diff --git a/src/com/android/camera/ComboPreferences.java b/src/com/android/camera/ComboPreferences.java
index af1476eac..9155fb3eb 100644
--- a/src/com/android/camera/ComboPreferences.java
+++ b/src/com/android/camera/ComboPreferences.java
@@ -32,12 +32,14 @@ public class ComboPreferences implements
OnSharedPreferenceChangeListener {
private SharedPreferences mPrefGlobal; // global preferences
private SharedPreferences mPrefLocal; // per-camera preferences
- private BackupManager mBackupManager;
+ private String mPackageName;
private CopyOnWriteArrayList<OnSharedPreferenceChangeListener> mListeners;
+ // TODO: Remove this WeakHashMap in the camera code refactoring
private static WeakHashMap<Context, ComboPreferences> sMap =
new WeakHashMap<Context, ComboPreferences>();
public ComboPreferences(Context context) {
+ mPackageName = context.getPackageName();
mPrefGlobal = context.getSharedPreferences(
getGlobalSharedPreferencesName(context), Context.MODE_PRIVATE);
mPrefGlobal.registerOnSharedPreferenceChangeListener(this);
@@ -45,7 +47,6 @@ public class ComboPreferences implements
synchronized (sMap) {
sMap.put(context, this);
}
- mBackupManager = new BackupManager(context);
mListeners = new CopyOnWriteArrayList<OnSharedPreferenceChangeListener>();
// The global preferences was previously stored in the default
@@ -327,6 +328,6 @@ public class ComboPreferences implements
for (OnSharedPreferenceChangeListener listener : mListeners) {
listener.onSharedPreferenceChanged(this, key);
}
- mBackupManager.dataChanged();
+ BackupManager.dataChanged(mPackageName);
}
}
diff --git a/src/com/android/camera/FocusOverlayManager.java b/src/com/android/camera/FocusOverlayManager.java
index 2bec18760..9acf85de9 100644
--- a/src/com/android/camera/FocusOverlayManager.java
+++ b/src/com/android/camera/FocusOverlayManager.java
@@ -430,6 +430,7 @@ public class FocusOverlayManager {
public String getFocusMode() {
if (mOverrideFocusMode != null) return mOverrideFocusMode;
+ if (mParameters == null) return Parameters.FOCUS_MODE_AUTO;
List<String> supportedFocusModes = mParameters.getSupportedFocusModes();
if (mFocusAreaSupported && mFocusArea != null) {
diff --git a/src/com/android/camera/MosaicFrameProcessor.java b/src/com/android/camera/MosaicFrameProcessor.java
index c59e6b91b..efd4ad2ae 100644
--- a/src/com/android/camera/MosaicFrameProcessor.java
+++ b/src/com/android/camera/MosaicFrameProcessor.java
@@ -92,7 +92,8 @@ public class MosaicFrameProcessor {
mPreviewBufferSize = bufSize;
setupMosaicer(mPreviewWidth, mPreviewHeight, mPreviewBufferSize);
setStripType(Mosaic.STRIPTYPE_WIDE);
- reset();
+ // no need to call reset() here. reset() should be called by the client
+ // after this initialization before calling other methods of this object.
}
public void clear() {
diff --git a/src/com/android/camera/MosaicPreviewRenderer.java b/src/com/android/camera/MosaicPreviewRenderer.java
index e12fe432e..26ce733aa 100644
--- a/src/com/android/camera/MosaicPreviewRenderer.java
+++ b/src/com/android/camera/MosaicPreviewRenderer.java
@@ -90,6 +90,7 @@ public class MosaicPreviewRenderer {
break;
case MSG_RELEASE:
doRelease();
+ mEglThreadBlockVar.open();
break;
}
}
@@ -203,7 +204,7 @@ public class MosaicPreviewRenderer {
}
public void release() {
- mEglHandler.sendEmptyMessage(EGLHandler.MSG_RELEASE);
+ mEglHandler.sendMessageSync(EGLHandler.MSG_RELEASE);
}
public void showPreviewFrameSync() {
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index aa7783346..e52c83c3a 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -1438,7 +1438,11 @@ public class PhotoModule
}
mFocusManager.onShutterDown();
} else {
- mFocusManager.onShutterUp();
+ // for countdown mode, we need to postpone the shutter release
+ // i.e. lock the focus during countdown.
+ if (!mCountDownView.isCountingDown()) {
+ mFocusManager.onShutterUp();
+ }
}
}
@@ -2430,6 +2434,7 @@ public class PhotoModule
public void onCountDownFinished() {
mSnapshotOnIdle = false;
mFocusManager.doSnap();
+ mFocusManager.onShutterUp();
}
void setPreviewFrameLayoutAspectRatio() {
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index c136358e1..4d01bc320 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -652,7 +652,7 @@ public class VideoModule implements CameraModule,
if (mQuickCapture) {
doReturnToCaller(!recordFail);
} else if (!recordFail) {
- showAlert();
+ showCaptureResult();
}
}
} else if (!recordFail){
@@ -1658,14 +1658,14 @@ public class VideoModule implements CameraModule,
}
}
- private void showAlert() {
+ private void showCaptureResult() {
Bitmap bitmap = null;
if (mVideoFileDescriptor != null) {
bitmap = Thumbnail.createVideoThumbnailBitmap(mVideoFileDescriptor.getFileDescriptor(),
- mPreviewFrameLayout.getWidth());
+ mDesiredPreviewWidth);
} else if (mCurrentVideoFilename != null) {
bitmap = Thumbnail.createVideoThumbnailBitmap(mCurrentVideoFilename,
- mPreviewFrameLayout.getWidth());
+ mDesiredPreviewWidth);
}
if (bitmap != null) {
// MetadataRetriever already rotates the thumbnail. We should rotate
@@ -2053,7 +2053,7 @@ public class VideoModule implements CameraModule,
if (mQuickCapture) {
doReturnToCaller(true);
} else {
- showAlert();
+ showCaptureResult();
}
}
}
@@ -2176,6 +2176,7 @@ public class VideoModule implements CameraModule,
mShutterButton = mActivity.getShutterButton();
mShutterButton.setImageResource(R.drawable.btn_new_shutter_video);
mShutterButton.setOnShutterButtonListener(this);
+ mShutterButton.setVisibility(View.VISIBLE);
mShutterButton.requestFocus();
mShutterButton.enableTouch(true);
@@ -2203,7 +2204,6 @@ public class VideoModule implements CameraModule,
@Override
public void onConfigurationChanged(Configuration newConfig) {
setDisplayOrientation();
-
// Change layout in response to configuration change
LayoutInflater inflater = mActivity.getLayoutInflater();
((ViewGroup) mRootView).removeAllViews();
@@ -2223,6 +2223,9 @@ public class VideoModule implements CameraModule,
initializeZoom();
onFullScreenChanged(mActivity.isInCameraApp());
updateOnScreenIndicators();
+ if (mIsVideoCaptureIntent && mVideoFileDescriptor != null) {
+ showCaptureResult();
+ }
}
@Override
diff --git a/src/com/android/camera/ui/PieMenuButton.java b/src/com/android/camera/ui/PieMenuButton.java
new file mode 100644
index 000000000..e5719310a
--- /dev/null
+++ b/src/com/android/camera/ui/PieMenuButton.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 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.camera.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+public class PieMenuButton extends View {
+ private boolean mPressed;
+ private boolean mReadyToClick = false;
+ public PieMenuButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void drawableStateChanged() {
+ super.drawableStateChanged();
+ mPressed = isPressed();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (MotionEvent.ACTION_UP == event.getAction() && mPressed) {
+ // Perform a customized click as soon as the ACTION_UP event
+ // is received. The reason for doing this is that Framework
+ // delays the performClick() call after ACTION_UP. But we do not
+ // want the delay because it affects an important state change
+ // for PieRenderer.
+ mReadyToClick = true;
+ performClick();
+ }
+ return super.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean performClick() {
+ if (mReadyToClick) {
+ // We only respond to our customized click which happens right
+ // after ACTION_UP event is received, with no delay.
+ mReadyToClick = false;
+ return super.performClick();
+ }
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/src/com/android/gallery3d/app/CommonControllerOverlay.java b/src/com/android/gallery3d/app/CommonControllerOverlay.java
index 089872fa5..a5aa805ef 100644
--- a/src/com/android/gallery3d/app/CommonControllerOverlay.java
+++ b/src/com/android/gallery3d/app/CommonControllerOverlay.java
@@ -274,10 +274,6 @@ public abstract class CommonControllerOverlay extends FrameLayout implements
mBackground.layout(0, y - mTimeBar.getBarHeight(), w, y);
mTimeBar.layout(pl, y - mTimeBar.getPreferredHeight(), w - pr, y);
- // Needed, otherwise the framework will not re-layout in case only the
- // padding is changed
- mTimeBar.requestLayout();
-
// Put the play/pause/next/ previous button in the center of the screen
layoutCenteredView(mPlayPauseReplayView, 0, 0, w, h);
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
index b3a6040de..44ff62feb 100644
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ b/src/com/android/gallery3d/app/PhotoPage.java
@@ -670,7 +670,7 @@ public abstract class PhotoPage extends ActivityState implements
}
private void overrideTransitionToEditor() {
- ((Activity) mActivity).overridePendingTransition(android.R.anim.slide_in_left,
+ ((Activity) mActivity).overridePendingTransition(android.R.anim.fade_in,
android.R.anim.fade_out);
}
diff --git a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java b/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
index 1b6c5ea58..dee9d2e8d 100644
--- a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
+++ b/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
@@ -66,6 +66,10 @@ public class EditorPlaceHolder {
mOldViews = views;
}
+ public void hide() {
+ mContainer.setVisibility(View.GONE);
+ }
+
public void hideOldViews() {
for (View view : mOldViews) {
view.setVisibility(View.GONE);
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index 83ea06dc7..f7147eac1 100644
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -16,7 +16,6 @@
package com.android.gallery3d.filtershow;
-import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.app.ProgressDialog;
@@ -45,34 +44,25 @@ import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
-import android.widget.AdapterView;
+import android.widget.*;
import android.widget.AdapterView.OnItemClickListener;
-import android.widget.FrameLayout;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.SeekBar;
-import android.widget.ShareActionProvider;
import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
-import android.widget.Toast;
import com.android.gallery3d.R;
import com.android.gallery3d.data.LocalAlbum;
+import com.android.gallery3d.filtershow.cache.FilteringPipeline;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.editors.BasicEditor;
import com.android.gallery3d.filtershow.editors.EditorDraw;
import com.android.gallery3d.filtershow.editors.EditorManager;
-import com.android.gallery3d.filtershow.filters.FiltersManager;
-import com.android.gallery3d.filtershow.filters.ImageFilter;
-import com.android.gallery3d.filtershow.filters.ImageFilterBorder;
-import com.android.gallery3d.filtershow.filters.ImageFilterFx;
-import com.android.gallery3d.filtershow.filters.ImageFilterParametricBorder;
-import com.android.gallery3d.filtershow.filters.ImageFilterRS;
-import com.android.gallery3d.filtershow.filters.ImageFilterRedEye;
+import com.android.gallery3d.filtershow.editors.EditorRedEye;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
+import com.android.gallery3d.filtershow.filters.*;
import com.android.gallery3d.filtershow.imageshow.ImageCrop;
import com.android.gallery3d.filtershow.imageshow.ImageDraw;
import com.android.gallery3d.filtershow.imageshow.ImageFlip;
-import com.android.gallery3d.filtershow.imageshow.ImageRedEyes;
+import com.android.gallery3d.filtershow.imageshow.ImageRedEye;
import com.android.gallery3d.filtershow.imageshow.ImageRotate;
import com.android.gallery3d.filtershow.imageshow.ImageShow;
import com.android.gallery3d.filtershow.imageshow.ImageStraighten;
@@ -84,7 +74,6 @@ import com.android.gallery3d.filtershow.provider.SharedImageProvider;
import com.android.gallery3d.filtershow.tools.SaveCopyTask;
import com.android.gallery3d.filtershow.ui.FilterIconButton;
import com.android.gallery3d.filtershow.ui.FramedTextButton;
-import com.android.gallery3d.filtershow.ui.ImageCurves;
import com.android.gallery3d.filtershow.ui.Spline;
import com.android.gallery3d.util.GalleryUtils;
@@ -93,14 +82,14 @@ import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Vector;
-@TargetApi(16)
public class FilterShowActivity extends Activity implements OnItemClickListener,
OnShareTargetSelectedListener {
// fields for supporting crop action
public static final String CROP_ACTION = "com.android.camera.action.CROP";
private CropExtras mCropExtras = null;
- MasterImage mMasterImage = MasterImage.getImage();
+ private String mAction = "";
+ MasterImage mMasterImage = null;
public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET";
public static final String LAUNCH_FULLSCREEN = "launch-fullscreen";
@@ -108,7 +97,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
private final PanelController mPanelController = new PanelController();
private ImageLoader mImageLoader = null;
private ImageShow mImageShow = null;
- private ImageRedEyes mImageRedEyes = null;
private ImageDraw mImageDraw = null;
private ImageStraighten mImageStraighten = null;
private ImageCrop mImageCrop = null;
@@ -159,14 +147,17 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
private FilterIconButton mNullBorderFilter;
private int mIconSeedSize = 140;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setResources();
+ Resources res = getResources();
setupMasterImage();
ImageFilterRS.setRenderScriptContext(this);
- ImageShow.setDefaultBackgroundColor(getResources().getColor(R.color.background_screen));
+ ImageShow.setDefaultBackgroundColor(res.getColor(R.color.background_screen));
// TODO: get those values from XML.
ImageZoom.setZoomedSize(getPixelsFromDip(256));
FramedTextButton.setTextSize((int) getPixelsFromDip(14));
@@ -176,11 +167,11 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
ImageShow.setTextPadding((int) getPixelsFromDip(10));
ImageShow.setOriginalTextMargin((int) getPixelsFromDip(4));
ImageShow.setOriginalTextSize((int) getPixelsFromDip(18));
- ImageShow.setOriginalText(getResources().getString(R.string.original_picture_text));
- mIconSeedSize = getResources().getDimensionPixelSize(R.dimen.thumbnail_size);
+ ImageShow.setOriginalText(res.getString(R.string.original_picture_text));
+ mIconSeedSize = res.getDimensionPixelSize(R.dimen.thumbnail_size);
- Drawable curveHandle = getResources().getDrawable(R.drawable.camera_crop);
- int curveHandleSize = (int) getResources().getDimension(R.dimen.crop_indicator_size);
+ Drawable curveHandle = res.getDrawable(R.drawable.camera_crop);
+ int curveHandleSize = (int) res.getDimension(R.dimen.crop_indicator_size);
Spline.setCurveHandle(curveHandle, curveHandleSize);
Spline.setCurveWidth((int) getPixelsFromDip(3));
@@ -209,7 +200,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mImageRotate = (ImageRotate) findViewById(R.id.imageRotate);
mImageFlip = (ImageFlip) findViewById(R.id.imageFlip);
mImageTinyPlanet = (ImageTinyPlanet) findViewById(R.id.imageTinyPlanet);
- mImageRedEyes = (ImageRedEyes) findViewById(R.id.imageRedEyes);
mImageDraw = (ImageDraw) findViewById(R.id.imageDraw);
mImageCrop.setAspectTextSize((int) getPixelsFromDip(18));
@@ -221,15 +211,19 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mImageViews.add(mImageRotate);
mImageViews.add(mImageFlip);
mImageViews.add(mImageTinyPlanet);
- mImageViews.add(mImageRedEyes);
mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer));
mEditorPlaceHolder.addEditor(new EditorDraw());
mEditorPlaceHolder.addEditor(new BasicEditor());
+ mEditorPlaceHolder.addEditor(new ImageOnlyEditor());
+ mEditorPlaceHolder.addEditor(new EditorTinyPlanet());
+ mEditorPlaceHolder.addEditor(new EditorRedEye());
EditorManager.addEditors(mEditorPlaceHolder);
mEditorPlaceHolder.setOldViews(mImageViews);
mEditorPlaceHolder.setImageLoader(mImageLoader);
+ mEditorPlaceHolder.hide();
+
mListFx = findViewById(R.id.fxList);
mListBorders = findViewById(R.id.bordersList);
mListGeometry = findViewById(R.id.geometryList);
@@ -257,7 +251,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mImageRotate.setImageLoader(mImageLoader);
mImageFlip.setImageLoader(mImageLoader);
mImageTinyPlanet.setImageLoader(mImageLoader);
- mImageRedEyes.setImageLoader(mImageLoader);
mImageDraw.setImageLoader(mImageLoader);
mPanelController.setActivity(this);
@@ -269,7 +262,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mPanelController.addImageView(findViewById(R.id.imageRotate));
mPanelController.addImageView(findViewById(R.id.imageFlip));
mPanelController.addImageView(findViewById(R.id.imageTinyPlanet));
- mPanelController.addImageView(findViewById(R.id.imageRedEyes));
mPanelController.addImageView(findViewById(R.id.imageDraw));
mPanelController.addPanel(mFxButton, mListFx, 0);
@@ -280,19 +272,17 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mPanelController.addComponent(mGeometryButton, findViewById(R.id.cropButton));
mPanelController.addComponent(mGeometryButton, findViewById(R.id.rotateButton));
mPanelController.addComponent(mGeometryButton, findViewById(R.id.flipButton));
- mPanelController.addComponent(mGeometryButton, findViewById(R.id.redEyeButton));
mPanelController.addPanel(mColorsButton, mListColors, 3);
- Vector<ImageFilter> filters = new Vector<ImageFilter>();
- FiltersManager.addFilters(filters, mImageLoader);
+ Vector<FilterRepresentation> filtersRepresentations = new Vector<FilterRepresentation>();
+
+ FiltersManager filtersManager = FiltersManager.getManager();
+ filtersManager.addEffects(filtersRepresentations);
- for (ImageFilter filter : filters) {
- filter.setParameter(filter.getDefaultParameter());
- filter.setName(getString(filter.getTextId()));
- setupFilterButton(filter, listColors, mColorsButton);
+ for (FilterRepresentation representation : filtersRepresentations) {
+ setupFilterRepresentationButton(representation, listColors, mColorsButton);
}
- mPanelController.addFilter(new ImageFilterRedEye());
mPanelController.addView(findViewById(R.id.applyEffect));
findViewById(R.id.resetOperationsButton).setOnClickListener(
@@ -309,11 +299,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
LoadBordersTask loadBorders = new LoadBordersTask(listBorders);
loadBorders.execute();
- SeekBar seekBar = (SeekBar) findViewById(R.id.filterSeekBar);
- seekBar.setMax(SEEK_BAR_MAX);
-
- mImageShow.setSeekBar(seekBar);
- mImageTinyPlanet.setSeekBar(seekBar);
mPanelController.setRowPanel(findViewById(R.id.secondRowPanel));
mPanelController.setUtilityPanel(this, findViewById(R.id.filterButtonsList),
findViewById(R.id.panelAccessoryViewList),
@@ -325,6 +310,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
+ mAction = intent.getAction();
+
if (intent.getData() != null) {
startLoadBitmap(intent.getData());
} else {
@@ -332,8 +319,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
}
// Handle behavior for various actions
- String action = intent.getAction();
- if (action.equalsIgnoreCase(CROP_ACTION)) {
+ if (mAction.equalsIgnoreCase(CROP_ACTION)) {
Bundle extras = intent.getExtras();
if (extras != null) {
mCropExtras = new CropExtras(extras.getInt(CropExtras.KEY_OUTPUT_X, 0),
@@ -362,17 +348,17 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mPanelController.setFixedAspect(mCropExtras.getAspectX() > 0
&& mCropExtras.getAspectY() > 0);
}
- mPanelController.showComponent(findViewById(R.id.cropButton));
- } else if (action.equalsIgnoreCase(TINY_PLANET_ACTION)) {
- mPanelController.showComponent(findViewById(R.id.tinyplanetButton));
}
}
private void startLoadBitmap(Uri uri) {
final View filters = findViewById(R.id.filtersPanel);
final View loading = findViewById(R.id.loading);
- loading.setVisibility(View.VISIBLE);
+ final View imageShow = findViewById(R.id.imageShow);
+ imageShow.setVisibility(View.INVISIBLE);
filters.setVisibility(View.INVISIBLE);
+ loading.setVisibility(View.VISIBLE);
+
View tinyPlanetView = findViewById(R.id.tinyplanetButton);
if (tinyPlanetView != null) {
tinyPlanetView.setVisibility(View.GONE);
@@ -382,37 +368,29 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
}
private class LoadBordersTask extends AsyncTask<Void, Boolean, Boolean> {
- Vector<ImageFilter> mBorders;
+ Vector<FilterRepresentation> mBorders;
LinearLayout mList;
public LoadBordersTask(LinearLayout list) {
mList = list;
- mBorders = new Vector<ImageFilter>();
+ mBorders = new Vector<FilterRepresentation>();
}
@Override
protected Boolean doInBackground(Void... params) {
- mBorders.add(new ImageFilterBorder(null));
- Drawable npd1 = getResources().getDrawable(R.drawable.filtershow_border_4x5);
- mBorders.add(new ImageFilterBorder(npd1));
- Drawable npd2 = getResources().getDrawable(R.drawable.filtershow_border_brush);
- mBorders.add(new ImageFilterBorder(npd2));
- Drawable npd3 = getResources().getDrawable(R.drawable.filtershow_border_grunge);
- mBorders.add(new ImageFilterBorder(npd3));
- Drawable npd4 = getResources().getDrawable(R.drawable.filtershow_border_sumi_e);
- mBorders.add(new ImageFilterBorder(npd4));
- Drawable npd5 = getResources().getDrawable(R.drawable.filtershow_border_tape);
- mBorders.add(new ImageFilterBorder(npd5));
- mBorders.add(new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize, 0));
- mBorders.add(new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize,
- mImageBorderSize));
- mBorders.add(new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize, 0));
- mBorders.add(new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize,
- mImageBorderSize));
+ mBorders.add(new FilterImageBorderRepresentation(0));
+ mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_4x5));
+ mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_brush));
+ mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_grunge));
+ mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_sumi_e));
+ mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_tape));
+ mBorders.add(new FilterColorBorderRepresentation(Color.BLACK, mImageBorderSize, 0));
+ mBorders.add(new FilterColorBorderRepresentation(Color.BLACK, mImageBorderSize, mImageBorderSize));
+ mBorders.add(new FilterColorBorderRepresentation(Color.WHITE, mImageBorderSize, 0));
+ mBorders.add(new FilterColorBorderRepresentation(Color.WHITE, mImageBorderSize, mImageBorderSize));
int creamColor = Color.argb(255, 237, 237, 227);
- mBorders.add(new ImageFilterParametricBorder(creamColor, mImageBorderSize, 0));
- mBorders.add(new ImageFilterParametricBorder(creamColor, mImageBorderSize,
- mImageBorderSize));
+ mBorders.add(new FilterColorBorderRepresentation(creamColor, mImageBorderSize, 0));
+ mBorders.add(new FilterColorBorderRepresentation(creamColor, mImageBorderSize, mImageBorderSize));
return true;
}
@@ -422,9 +400,12 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
return;
}
for (int i = 0; i < mBorders.size(); i++) {
- ImageFilter filter = mBorders.elementAt(i);
+ FilterRepresentation filter = mBorders.elementAt(i);
filter.setName(getString(R.string.borders));
- FilterIconButton b = setupFilterButton(filter, mList, mBorderButton);
+ if (i == 0) {
+ filter.setName(getString(R.string.none));
+ }
+ FilterIconButton b = setupFilterRepresentationButton(filter, mList, mBorderButton);
if (i == 0) {
mNullBorderFilter = b;
mNullBorderFilter.setSelected(true);
@@ -457,10 +438,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
if (isCancelled()) {
return;
}
- final View filters = findViewById(R.id.filtersPanel);
- final View loading = findViewById(R.id.loading);
- loading.setVisibility(View.GONE);
- filters.setVisibility(View.VISIBLE);
if (values[0]) {
mTinyPlanetButton.setVisibility(View.VISIBLE);
}
@@ -468,13 +445,33 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
@Override
protected void onPostExecute(Boolean result) {
+
if (isCancelled()) {
return;
}
+
if (!result) {
cannotLoadImage();
}
+ final View loading = findViewById(R.id.loading);
+ loading.setVisibility(View.GONE);
+ final View filters = findViewById(R.id.filtersPanel);
+ filters.setVisibility(View.VISIBLE);
+ if (PanelController.useAnimations()) {
+ float y = filters.getY();
+ filters.setY(y + filters.getHeight());
+ filters.animate().setDuration(600).y(y).withLayer().start();
+ }
+ final View imageShow = findViewById(R.id.imageShow);
+ imageShow.setVisibility(View.VISIBLE);
+
+ Bitmap largeBitmap = mImageLoader.getOriginalBitmapLarge();
+ FilteringPipeline pipeline = FilteringPipeline.getPipeline();
+ pipeline.setOriginal(largeBitmap);
+ float previewScale = (float) largeBitmap.getWidth() / (float) mImageLoader.getOriginalBounds().width();
+ pipeline.setPreviewScaleFactor(previewScale);
+
Bitmap bmap = mImageLoader.getOriginalBitmapSmall();
if (bmap != null && bmap.getWidth() > 0 && bmap.getHeight() > 0) {
float w = bmap.getWidth();
@@ -505,6 +502,13 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
}
mLoadBitmapTask = null;
+
+ if (mAction == CROP_ACTION) {
+ mPanelController.showComponent(findViewById(R.id.cropButton));
+ } else if (mAction == TINY_PLANET_ACTION) {
+ mPanelController.showComponent(findViewById(R.id.tinyplanetButton));
+ }
+
super.onPostExecute(result);
}
@@ -704,19 +708,22 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mSaveButton.setEnabled(enable);
}
- public FilterIconButton setupFilterButton(ImageFilter filter, LinearLayout panel, View button) {
+ public FilterIconButton setupFilterRepresentationButton(FilterRepresentation representation, LinearLayout panel, View button) {
LayoutInflater inflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
FilterIconButton icon = (FilterIconButton) inflater.inflate(R.layout.filtericonbutton,
panel, false);
- String text = filter.getName();
- if (filter instanceof ImageFilterBorder || filter instanceof ImageFilterParametricBorder) {
- text = "";
+ if (representation.getTextId() != 0) {
+ representation.setName(getString(representation.getTextId()));
+ }
+ String text = representation.getName();
+ icon.setup(text, mPanelController, panel);
+ icon.setFilterRepresentation(representation);
+ if (representation instanceof FilterTinyPlanetRepresentation) {
+ // needed to hide tinyplanet on startup
+ icon.setId(R.id.tinyplanetButton);
}
- icon.setup(text, filter, this, panel);
- icon.setId(filter.getButtonId());
mPanelController.addComponent(button, icon);
- mPanelController.addFilter(filter);
panel.addView(icon);
return icon;
}
@@ -725,7 +732,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
// TODO: use listview
// TODO: load the filters straight from the filesystem
- ImageFilterFx[] fxArray = new ImageFilterFx[18];
+ FilterFxRepresentation[] fxArray = new FilterFxRepresentation[18];
int p = 0;
int[] drawid = {
@@ -760,15 +767,23 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
for (int i = 0; i < drawid.length; i++) {
Bitmap b = BitmapFactory.decodeResource(getResources(), drawid[i], o);
- fxArray[p++] = new ImageFilterFx(b, getString(fxNameid[i]), fxNameid[i]);
+ FilterFxRepresentation fx = new FilterFxRepresentation(getString(fxNameid[i]), drawid[i], fxNameid[i]);
+ fx.setFxBitmap(b);
+ fxArray[p++] = fx;
}
- ImageFilterFx nullFilter = new ImageFilterFx(null, getString(R.string.none), R.string.none);
- mNullFxFilter = setupFilterButton(nullFilter, listFilters, mFxButton);
+ FilterFxRepresentation nullFx = new FilterFxRepresentation(getString(R.string.none), 0, R.string.none);
+ mNullFxFilter = setupFilterRepresentationButton(nullFx, listFilters, mFxButton);
mNullFxFilter.setSelected(true);
+ Vector<FilterRepresentation> filtersRepresentations = new Vector<FilterRepresentation>();
+ FiltersManager.getManager().addLooks(filtersRepresentations);
+ for (FilterRepresentation representation : filtersRepresentations) {
+ setupFilterRepresentationButton(representation, listFilters, mFxButton);
+ }
+
for (int i = 0; i < p; i++) {
- setupFilterButton(fxArray[i], listFilters, mFxButton);
+ setupFilterRepresentationButton(fxArray[i], listFilters, mFxButton);
}
// Default preset (original)
@@ -803,6 +818,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
for (View view : mImageViews) {
view.setVisibility(View.GONE);
}
+ mEditorPlaceHolder.hide();
}
public void unselectBottomPanelButtons() {
@@ -852,7 +868,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
int translate = translateMainPanel(viewList);
if (!mShowingImageStatePanel) {
mShowingImageStatePanel = true;
- view.animate().setDuration(200).x(translate)
+ if (PanelController.useAnimations()) {
+ view.animate().setDuration(200).x(translate)
.withLayer().withEndAction(new Runnable() {
@Override
public void run() {
@@ -862,11 +879,22 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
.alpha(1.0f).start();
}
}).start();
+ } else {
+ view.setX(translate);
+ viewList.setAlpha(0);
+ viewList.setVisibility(View.VISIBLE);
+ viewList.animate().setDuration(100)
+ .alpha(1.0f).start();
+ }
} else {
mShowingImageStatePanel = false;
viewList.setVisibility(View.INVISIBLE);
- view.animate().setDuration(200).x(0).withLayer()
+ if (PanelController.useAnimations()) {
+ view.animate().setDuration(200).x(0).withLayer()
.start();
+ } else {
+ view.setX(0);
+ }
}
invalidateOptionsMenu();
}
@@ -875,6 +903,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
+ setResources();
if (mShowingHistoryPanel) {
toggleHistoryPanel();
}
@@ -887,6 +916,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
ImageStateAdapter mImageStateAdapter = new ImageStateAdapter(this,
R.layout.filtershow_imagestate_row);
+ MasterImage.reset();
+ mMasterImage = MasterImage.getImage();
mMasterImage.setHistoryAdapter(mHistoryAdapter);
mMasterImage.setStateAdapter(mImageStateAdapter);
mMasterImage.setActivity(this);
@@ -907,7 +938,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
int translate = translateMainPanel(viewList);
if (!mShowingHistoryPanel) {
mShowingHistoryPanel = true;
- view.animate().setDuration(200).x(translate)
+ if (PanelController.useAnimations()) {
+ view.animate().setDuration(200).x(translate)
.withLayer().withEndAction(new Runnable() {
@Override
public void run() {
@@ -917,11 +949,22 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
.alpha(1.0f).start();
}
}).start();
+ } else {
+ view.setX(translate);
+ viewList.setAlpha(0);
+ viewList.setVisibility(View.VISIBLE);
+ viewList.animate().setDuration(100)
+ .alpha(1.0f).start();
+ }
} else {
mShowingHistoryPanel = false;
viewList.setVisibility(View.INVISIBLE);
- view.animate().setDuration(200).x(0).withLayer()
+ if (PanelController.useAnimations()) {
+ view.animate().setDuration(200).x(0).withLayer()
.start();
+ } else {
+ view.setX(0);
+ }
}
invalidateOptionsMenu();
}
@@ -973,23 +1016,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
r.getDisplayMetrics());
}
- public void useFilter(ImageFilter filter) {
- if (mMasterImage.getCurrentFilter() == filter) {
- return;
- }
- ImagePreset oldPreset = mMasterImage.getPreset();
- ImagePreset copy = new ImagePreset(oldPreset);
-
- ImageFilter existingFilter = copy.getFilter(filter.getName());
- if (existingFilter == null) {
- copy.add(filter);
- }
- existingFilter = copy.getFilter(filter.getName());
- mMasterImage.setPreset(copy, true);
- mMasterImage.setCurrentFilter(existingFilter);
- invalidateViews();
- }
-
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
@@ -1018,31 +1044,31 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
private boolean mSaveToExtraUri = false;
private boolean mSaveAsWallpaper = false;
private boolean mReturnAsExtra = false;
- private boolean outputted = false;
+ private boolean mOutputted = false;
public void saveImage() {
if (mCropExtras != null) {
if (mCropExtras.getExtraOutput() != null) {
mSaveToExtraUri = true;
- outputted = true;
+ mOutputted = true;
}
if (mCropExtras.getSetAsWallpaper()) {
mSaveAsWallpaper = true;
- outputted = true;
+ mOutputted = true;
}
if (mCropExtras.getReturnData()) {
mReturnAsExtra = true;
- outputted = true;
+ mOutputted = true;
}
- if (outputted) {
+ if (mOutputted) {
mImageShow.getImagePreset().mGeoData.setUseCropExtrasFlag(true);
showSavingProgress(null);
mImageShow.returnFilteredResult(this);
}
}
- if (!outputted) {
+ if (!mOutputted) {
if (mImageShow.hasModifications()) {
// Get the name of the album, to which the image will be saved
File saveDir = SaveCopyTask.getFinalSaveDirectory(this, mImageLoader.getUri());
@@ -1092,12 +1118,17 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
}
public void done() {
- if (outputted) {
+ if (mOutputted) {
hideSavingProgress();
}
finish();
}
+ private void setResources() {
+ ImageFilterBorder filterBorder = (ImageFilterBorder) FiltersManager.getManager().getFilter(ImageFilterBorder.class);
+ filterBorder.setResources(getResources());
+ }
+
static {
System.loadLibrary("jni_filtershow_filters");
}
diff --git a/src/com/android/gallery3d/filtershow/ImageStateAdapter.java b/src/com/android/gallery3d/filtershow/ImageStateAdapter.java
index 44b94e45e..58e0035bc 100644
--- a/src/com/android/gallery3d/filtershow/ImageStateAdapter.java
+++ b/src/com/android/gallery3d/filtershow/ImageStateAdapter.java
@@ -24,9 +24,10 @@ import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.ImageFilter;
-public class ImageStateAdapter extends ArrayAdapter<ImageFilter> {
+public class ImageStateAdapter extends ArrayAdapter<FilterRepresentation> {
private static final String LOGTAG = "ImageStateAdapter";
public ImageStateAdapter(Context context, int textViewResourceId) {
@@ -41,12 +42,12 @@ public class ImageStateAdapter extends ArrayAdapter<ImageFilter> {
Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.filtershow_imagestate_row, null);
}
- ImageFilter filter = getItem(position);
+ FilterRepresentation filter = getItem(position);
if (filter != null) {
TextView itemLabel = (TextView) view.findViewById(R.id.imagestate_label);
itemLabel.setText(filter.getName());
TextView itemParameter = (TextView) view.findViewById(R.id.imagestate_parameter);
- itemParameter.setText("" + filter.getParameter());
+ itemParameter.setText(filter.getStateRepresentation());
}
return view;
}
diff --git a/src/com/android/gallery3d/filtershow/PanelController.java b/src/com/android/gallery3d/filtershow/PanelController.java
index a0b13fb84..18a9585a6 100644
--- a/src/com/android/gallery3d/filtershow/PanelController.java
+++ b/src/com/android/gallery3d/filtershow/PanelController.java
@@ -16,9 +16,9 @@
package com.android.gallery3d.filtershow;
+import android.annotation.TargetApi;
import android.content.Context;
import android.text.Html;
-import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewPropertyAnimator;
@@ -27,6 +27,7 @@ import android.widget.TextView;
import com.android.gallery3d.R;
import com.android.gallery3d.filtershow.editors.Editor;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.ImageFilter;
import com.android.gallery3d.filtershow.filters.ImageFilterTinyPlanet;
import com.android.gallery3d.filtershow.imageshow.ImageCrop;
@@ -34,7 +35,6 @@ import com.android.gallery3d.filtershow.imageshow.ImageShow;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
import com.android.gallery3d.filtershow.presets.ImagePreset;
import com.android.gallery3d.filtershow.ui.FilterIconButton;
-import com.android.gallery3d.filtershow.ui.FramedTextButton;
import java.util.HashMap;
import java.util.Vector;
@@ -49,6 +49,14 @@ public class PanelController implements OnClickListener {
private boolean mDisableFilterButtons = false;
private boolean mFixedAspect = false;
+ public static boolean useAnimations() {
+ int currentapiVersion = android.os.Build.VERSION.SDK_INT;
+ if (currentapiVersion >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
+ return true;
+ }
+ return false;
+ }
+
public void setFixedAspect(boolean t) {
mFixedAspect = t;
}
@@ -87,16 +95,28 @@ public class PanelController implements OnClickListener {
} else {
delta = w;
}
- anim.x(delta);
+ if (PanelController.useAnimations()) {
+ anim.x(delta);
+ } else {
+ mContainer.setX(delta);
+ }
} else if (move == VERTICAL_MOVE) {
- anim.y(h);
- }
- anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
- @Override
- public void run() {
- mContainer.setVisibility(View.GONE);
+ if (PanelController.useAnimations()) {
+ anim.y(h);
+ } else {
+ mContainer.setY(h);
}
- });
+ }
+ if (PanelController.useAnimations()) {
+ anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mContainer.setVisibility(View.GONE);
+ }
+ });
+ } else {
+ mContainer.setVisibility(View.GONE);
+ }
return anim;
}
@@ -108,18 +128,20 @@ public class PanelController implements OnClickListener {
ViewPropertyAnimator anim = mContainer.animate();
int w = mRowPanel.getWidth();
int h = mRowPanel.getHeight();
- if (move == HORIZONTAL_MOVE) {
- if (oldPos < mPosition) {
- mContainer.setX(w);
- } else {
- mContainer.setX(-w);
+ if (useAnimations()) {
+ if (move == HORIZONTAL_MOVE) {
+ if (oldPos < mPosition) {
+ mContainer.setX(w);
+ } else {
+ mContainer.setX(-w);
+ }
+ anim.x(0);
+ } else if (move == VERTICAL_MOVE) {
+ mContainer.setY(h);
+ anim.y(0);
}
- anim.x(0);
- } else if (move == VERTICAL_MOVE) {
- mContainer.setY(h);
- anim.y(0);
+ anim.setDuration(ANIM_DURATION).withLayer();
}
- anim.setDuration(ANIM_DURATION).withLayer();
return anim;
}
}
@@ -187,12 +209,16 @@ public class PanelController implements OnClickListener {
mView.setY(0);
int h = mRowPanel.getHeight();
anim.y(-h);
- anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
- @Override
- public void run() {
- mView.setVisibility(View.GONE);
- }
- });
+ if (PanelController.useAnimations()) {
+ anim.setDuration(ANIM_DURATION).withLayer().withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mView.setVisibility(View.GONE);
+ }
+ });
+ } else {
+ mView.setVisibility(View.GONE);
+ }
mSelected = false;
return anim;
}
@@ -203,10 +229,13 @@ public class PanelController implements OnClickListener {
mView.setX(0);
mView.setY(-h);
updateText();
+ mSelected = true;
ViewPropertyAnimator anim = mView.animate();
anim.y(0);
- anim.setDuration(ANIM_DURATION).withLayer();
- mSelected = true;
+ anim.setDuration(ANIM_DURATION);
+ if (PanelController.useAnimations()) {
+ anim.withLayer();
+ }
return anim;
}
@@ -233,7 +262,6 @@ public class PanelController implements OnClickListener {
private View mCurrentPanel = null;
private View mRowPanel = null;
private UtilityPanel mUtilityPanel = null;
- private MasterImage mMasterImage = MasterImage.getImage();
private ImageShow mCurrentImage = null;
private Editor mCurrentEditor = null;
private FilterShowActivity mActivity = null;
@@ -294,9 +322,9 @@ public class PanelController implements OnClickListener {
if (mUtilityPanel == null || !mUtilityPanel.selected()) {
return true;
}
- HistoryAdapter adapter = mMasterImage.getHistory();
+ HistoryAdapter adapter = MasterImage.getImage().getHistory();
int position = adapter.undo();
- mMasterImage.onHistoryItemClick(position);
+ MasterImage.getImage().onHistoryItemClick(position);
showPanel(mCurrentPanel);
mCurrentImage.select();
if (mCurrentEditor != null) {
@@ -345,6 +373,7 @@ public class PanelController implements OnClickListener {
public ImageShow showImageView(int id) {
ImageShow image = null;
+ mActivity.hideImageViews();
for (View view : mImageViews) {
if (view.getId() == id) {
view.setVisibility(View.VISIBLE);
@@ -358,7 +387,8 @@ public class PanelController implements OnClickListener {
public void showDefaultImageView() {
showImageView(R.id.imageShow).setShowControls(false);
- mMasterImage.setCurrentFilter(null);
+ MasterImage.getImage().setCurrentFilter(null);
+ MasterImage.getImage().setCurrentFilterRepresentation(null);
}
public void showPanel(View view) {
@@ -368,10 +398,14 @@ public class PanelController implements OnClickListener {
if (mUtilityPanel != null && mUtilityPanel.selected()) {
ViewPropertyAnimator anim1 = mUtilityPanel.unselect();
removedUtilityPanel = true;
- anim1.start();
+ if (anim1 != null) {
+ anim1.start();
+ }
if (mCurrentPanel == view) {
ViewPropertyAnimator anim2 = current.select(-1, VERTICAL_MOVE);
- anim2.start();
+ if (anim2 != null) {
+ anim2.start();
+ }
showDefaultImageView();
}
}
@@ -387,77 +421,75 @@ public class PanelController implements OnClickListener {
currentPos = current.getPosition();
}
ViewPropertyAnimator anim1 = panel.select(currentPos, HORIZONTAL_MOVE);
- anim1.start();
+ if (anim1 != null) {
+ anim1.start();
+ }
if (current != null) {
ViewPropertyAnimator anim2 = current.unselect(panel.getPosition(), HORIZONTAL_MOVE);
- anim2.start();
+ if (anim2 != null) {
+ anim2.start();
+ }
}
} else {
ViewPropertyAnimator anim = panel.select(-1, VERTICAL_MOVE);
- anim.start();
+ if (anim != null) {
+ anim.start();
+ }
}
+
showDefaultImageView();
mCurrentPanel = view;
}
public ImagePreset getImagePreset() {
- return mMasterImage.getPreset();
- }
-
- public ImageFilter setImagePreset(ImageFilter filter, String name) {
- ImagePreset copy = new ImagePreset(getImagePreset());
- copy.add(filter);
- copy.setHistoryName(name);
- copy.setIsFx(false);
- mMasterImage.setPreset(copy, true);
- return filter;
+ return MasterImage.getImage().getPreset();
}
- // TODO: remove this.
- public void ensureFilter(String name) {
- ImagePreset preset = getImagePreset();
- ImageFilter filter = preset.getFilter(name);
- if (filter != null) {
- // If we already have a filter, we might still want
- // to push it onto the history stack.
- ImagePreset copy = new ImagePreset(getImagePreset());
- copy.setHistoryName(name);
- mMasterImage.setPreset(copy, true);
- filter = copy.getFilter(name);
- }
-
- if (filter == null) {
- ImageFilter filterInstance = mFilters.get(name);
- if (filterInstance != null) {
- try {
- ImageFilter newFilter = filterInstance.clone();
- newFilter.reset();
- filter = setImagePreset(newFilter, name);
- } catch (CloneNotSupportedException e) {
- e.printStackTrace();
- }
- }
+ public void useFilterRepresentation(FilterRepresentation filterRepresentation) {
+ if (filterRepresentation == null) {
+ return;
}
- if (filter != null) {
- mMasterImage.setCurrentFilter(filter);
+ if (MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) {
+ return;
}
+ ImagePreset oldPreset = MasterImage.getImage().getPreset();
+ ImagePreset copy = new ImagePreset(oldPreset);
+ FilterRepresentation representation = copy.getRepresentation(filterRepresentation);
+ if (representation == null) {
+ copy.addFilter(filterRepresentation);
+ } else {
+ if (filterRepresentation.allowsMultipleInstances()) {
+ representation.updateTempParametersFrom(filterRepresentation);
+ copy.setHistoryName(filterRepresentation.getName());
+ }
+ filterRepresentation = representation;
+ }
+ MasterImage.getImage().setPreset(copy, true);
+ MasterImage.getImage().setCurrentFilterRepresentation(filterRepresentation);
}
public void showComponent(View view) {
boolean doPanelTransition = true;
if (view instanceof FilterIconButton) {
- ImageFilter f = ((FilterIconButton) view).getImageFilter();
- doPanelTransition = f.showUtilityPanel();
+ FilterRepresentation f = ((FilterIconButton) view).getFilterRepresentation();
+ if (f != null) {
+ // FIXME: this check shouldn't be necessary (f shouldn't be null)
+ doPanelTransition = f.showUtilityPanel();
+ }
}
- if (mUtilityPanel != null && !mUtilityPanel.selected() && doPanelTransition ) {
+ if (mUtilityPanel != null && !mUtilityPanel.selected() && doPanelTransition) {
Panel current = mPanels.get(mCurrentPanel);
ViewPropertyAnimator anim1 = current.unselect(-1, VERTICAL_MOVE);
- anim1.start();
+ if (anim1 != null) {
+ anim1.start();
+ }
if (mUtilityPanel != null) {
ViewPropertyAnimator anim2 = mUtilityPanel.select();
- anim2.start();
+ if (anim2 != null) {
+ anim2.start();
+ }
}
}
@@ -469,22 +501,23 @@ public class PanelController implements OnClickListener {
if (view instanceof FilterIconButton) {
mCurrentEditor = null;
FilterIconButton component = (FilterIconButton) view;
- ImageFilter filter = component.getImageFilter();
- if (filter.getEditingViewId() != 0) {
- if (mEditorPlaceHolder.contains(filter.getEditingViewId())) {
- mCurrentEditor = mEditorPlaceHolder.showEditor(filter.getEditingViewId());
- mCurrentImage = mCurrentEditor.getImageShow();
- mCurrentEditor.setPanelController(this);
- } else {
- mCurrentImage = showImageView(filter.getEditingViewId());
+ FilterRepresentation representation = component.getFilterRepresentation();
+ if (representation != null) {
+ mUtilityPanel.setEffectName(representation.getName());
+ mUtilityPanel.setShowParameter(representation.showParameterValue());
+
+ if (representation.getEditorId() != 0) {
+ if (mEditorPlaceHolder.contains(representation.getEditorId())) {
+ mCurrentEditor = mEditorPlaceHolder.showEditor(representation.getEditorId());
+ mCurrentImage = mCurrentEditor.getImageShow();
+ mCurrentEditor.setPanelController(this);
+ } else {
+ mCurrentImage = showImageView(representation.getEditorId());
+ }
}
- mCurrentImage.setShowControls(filter.showEditingControls());
- String ename = mCurrentImage.getContext().getString(filter.getTextId());
- mUtilityPanel.setEffectName(ename);
+ mCurrentImage.setShowControls(representation.showEditingControls());
+ mUtilityPanel.setShowParameter(representation.showParameterValue());
- mUtilityPanel.setShowParameter(filter.showParameterValue());
- ImageFilter currentFilter = mMasterImage.getPreset().getFilter(filter.getName());
- mMasterImage.setCurrentFilter(currentFilter);
mCurrentImage.select();
if (mCurrentEditor != null) {
mCurrentEditor.reflectCurrentFilter();
@@ -503,7 +536,6 @@ public class PanelController implements OnClickListener {
mCurrentImage = showImageView(R.id.imageTinyPlanet).setShowControls(true);
String ename = mCurrentImage.getContext().getString(R.string.tinyplanet);
mUtilityPanel.setEffectName(ename);
- ensureFilter(ename);
if (!mDisableFilterButtons) {
mActivity.disableFilterButtons();
mDisableFilterButtons = true;
@@ -541,15 +573,8 @@ public class PanelController implements OnClickListener {
mUtilityPanel.setShowParameter(false);
break;
}
- case R.id.redEyeButton: {
- mCurrentImage = showImageView(R.id.imageRedEyes).setShowControls(true);
- String ename = mCurrentImage.getContext().getString(R.string.redeye);
- mUtilityPanel.setEffectName(ename);
- ensureFilter(ename);
- break;
- }
case R.id.applyEffect: {
- if (mMasterImage.getCurrentFilter() instanceof ImageFilterTinyPlanet) {
+ if (MasterImage.getImage().getCurrentFilter() instanceof ImageFilterTinyPlanet) {
mActivity.saveImage();
} else {
if (mCurrentImage instanceof ImageCrop) {
@@ -557,6 +582,7 @@ public class PanelController implements OnClickListener {
}
showPanel(mCurrentPanel);
}
+ MasterImage.getImage().invalidateFiltersOnly();
break;
}
}
diff --git a/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java b/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java
index d415250a4..419abe85d 100644
--- a/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java
+++ b/src/com/android/gallery3d/filtershow/cache/FilteringPipeline.java
@@ -22,6 +22,8 @@ import android.os.Process;
import android.support.v8.renderscript.*;
import android.util.Log;
+import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.filters.ImageFilterRS;
import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
@@ -31,7 +33,6 @@ public class FilteringPipeline implements Handler.Callback {
private final static FilteringPipeline gPipeline = new FilteringPipeline();
private static final String LOGTAG = "FilteringPipeline";
- private ImagePreset mPreviousPreset = null;
private ImagePreset mPreviousGeometryPreset = null;
private ImagePreset mPreviousFiltersPreset = null;
private GeometryMetadata mPreviousGeometry = null;
@@ -44,11 +45,9 @@ public class FilteringPipeline implements Handler.Callback {
private HandlerThread mHandlerThread = null;
private final static int NEW_PRESET = 0;
- private final static int NEW_GEOMETRY_PRESET = 1;
- private final static int NEW_FILTERS_PRESET = 2;
- private final static int COMPUTE_PRESET = 3;
- private final static int COMPUTE_GEOMETRY_PRESET = 4;
- private final static int COMPUTE_FILTERS_PRESET = 5;
+ private final static int NEW_RENDERING_REQUEST = 1;
+ private final static int COMPUTE_PRESET = 2;
+ private final static int COMPUTE_RENDERING_REQUEST = 3;
private Handler mProcessingHandler = null;
private final Handler mUIHandler = new Handler() {
@@ -61,16 +60,9 @@ public class FilteringPipeline implements Handler.Callback {
MasterImage.getImage().notifyObservers();
break;
}
- case NEW_GEOMETRY_PRESET: {
- TripleBufferBitmap buffer = MasterImage.getImage().getGeometryOnlyBuffer();
- buffer.swapConsumer();
- MasterImage.getImage().notifyObservers();
- break;
- }
- case NEW_FILTERS_PRESET: {
- TripleBufferBitmap buffer = MasterImage.getImage().getFiltersOnlyBuffer();
- buffer.swapConsumer();
- MasterImage.getImage().notifyObservers();
+ case NEW_RENDERING_REQUEST: {
+ RenderingRequest request = (RenderingRequest) msg.obj;
+ request.markAvailable();
break;
}
}
@@ -89,21 +81,11 @@ public class FilteringPipeline implements Handler.Callback {
mUIHandler.sendMessage(uimsg);
break;
}
- case COMPUTE_GEOMETRY_PRESET: {
- ImagePreset preset = (ImagePreset) msg.obj;
- TripleBufferBitmap buffer = MasterImage.getImage().getGeometryOnlyBuffer();
- compute(buffer, preset, COMPUTE_GEOMETRY_PRESET);
- buffer.swapProducer();
- Message uimsg = mUIHandler.obtainMessage(NEW_GEOMETRY_PRESET);
- mUIHandler.sendMessage(uimsg);
- break;
- }
- case COMPUTE_FILTERS_PRESET: {
- ImagePreset preset = (ImagePreset) msg.obj;
- TripleBufferBitmap buffer = MasterImage.getImage().getFiltersOnlyBuffer();
- compute(buffer, preset, COMPUTE_FILTERS_PRESET);
- buffer.swapProducer();
- Message uimsg = mUIHandler.obtainMessage(NEW_FILTERS_PRESET);
+ case COMPUTE_RENDERING_REQUEST: {
+ RenderingRequest request = (RenderingRequest) msg.obj;
+ render(request);
+ Message uimsg = mUIHandler.obtainMessage(NEW_RENDERING_REQUEST);
+ uimsg.obj = request;
mUIHandler.sendMessage(uimsg);
break;
}
@@ -116,7 +98,6 @@ public class FilteringPipeline implements Handler.Callback {
private float mResizeFactor = 1.0f;
private long mResizeTime = 0;
- private Allocation mOriginalBitmapAllocation = null;
private Allocation mOriginalAllocation = null;
private Allocation mFiltersOnlyOriginalAllocation = null;
@@ -136,8 +117,6 @@ public class FilteringPipeline implements Handler.Callback {
Log.v(LOGTAG,"setOriginal, size " + bitmap.getWidth() + " x " + bitmap.getHeight());
updateOriginalAllocation(MasterImage.getImage().getPreset());
updatePreviewBuffer();
- updateFiltersOnlyPreviewBuffer();
- updateGeometryOnlyPreviewBuffer();
}
public synchronized boolean updateOriginalAllocation(ImagePreset preset) {
@@ -153,10 +132,16 @@ public class FilteringPipeline implements Handler.Callback {
}
mResizedOriginalBitmap = Bitmap.createScaledBitmap(mOriginalBitmap, w, h, true);
*/
+
GeometryMetadata geometry = preset.getGeometry();
if (mPreviousGeometry != null && geometry.equals(mPreviousGeometry)) {
return false;
}
+
+ if (DEBUG) {
+ Log.v(LOGTAG, "geometry has changed");
+ }
+
RenderScript RS = ImageFilterRS.getRenderScriptContext();
if (mFiltersOnlyOriginalAllocation != null) {
mFiltersOnlyOriginalAllocation.destroy();
@@ -169,83 +154,113 @@ public class FilteringPipeline implements Handler.Callback {
mResizedOriginalBitmap = preset.applyGeometry(mOriginalBitmap);
mOriginalAllocation = Allocation.createFromBitmap(RS, mResizedOriginalBitmap,
Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
+
mPreviousGeometry = new GeometryMetadata(geometry);
+
+ FiltersManager.getManager().resetBitmapsRS();
return true;
}
- public synchronized void updatePreviewBuffer() {
+ public void postRenderingRequest(RenderingRequest request) {
if (mOriginalAllocation == null) {
return;
}
- if (!needsRepaint()) {
- return;
- }
- if (mProcessingHandler.hasMessages(COMPUTE_PRESET)) {
- mProcessingHandler.removeMessages(COMPUTE_PRESET);
- }
- Message msg = mProcessingHandler.obtainMessage(COMPUTE_PRESET);
- ImagePreset preset = new ImagePreset(MasterImage.getImage().getPreset());
- setPresetParameters(preset);
- msg.obj = preset;
+ Message msg = mProcessingHandler.obtainMessage(COMPUTE_RENDERING_REQUEST);
+ msg.obj = request;
mProcessingHandler.sendMessage(msg);
}
- public void updateGeometryOnlyPreviewBuffer() {
+ public synchronized void updatePreviewBuffer() {
if (mOriginalAllocation == null) {
return;
}
- if (!needsGeometryRepaint()) {
+ if (mProcessingHandler.hasMessages(COMPUTE_PRESET)) {
return;
}
- if (mProcessingHandler.hasMessages(COMPUTE_GEOMETRY_PRESET)) {
- mProcessingHandler.removeMessages(COMPUTE_GEOMETRY_PRESET);
- }
- Message msg = mProcessingHandler.obtainMessage(COMPUTE_GEOMETRY_PRESET);
- ImagePreset preset = new ImagePreset(MasterImage.getImage().getGeometryPreset());
- setPresetParameters(preset);
- msg.obj = preset;
- mProcessingHandler.sendMessage(msg);
- }
-
- public void updateFiltersOnlyPreviewBuffer() {
- if (mOriginalAllocation == null) {
+ if (!needsRepaint()) {
return;
}
- if (!needsFiltersRepaint()) {
+ if (MasterImage.getImage().getPreset() == null) {
return;
}
- if (mProcessingHandler.hasMessages(COMPUTE_FILTERS_PRESET)) {
- mProcessingHandler.removeMessages(COMPUTE_FILTERS_PRESET);
- }
- Message msg = mProcessingHandler.obtainMessage(COMPUTE_FILTERS_PRESET);
- ImagePreset preset = new ImagePreset(MasterImage.getImage().getFiltersOnlyPreset());
- setPresetParameters(preset);
-
- msg.obj = preset;
+ Message msg = mProcessingHandler.obtainMessage(COMPUTE_PRESET);
+ msg.obj = MasterImage.getImage().getPreset();
mProcessingHandler.sendMessage(msg);
}
private void setPresetParameters(ImagePreset preset) {
preset.setScaleFactor(mPreviewScaleFactor);
if (mPreviewScaleFactor < 1.0f) {
- preset.setIsHighQuality(false);
+ preset.setQuality(ImagePreset.QUALITY_PREVIEW);
} else {
- preset.setIsHighQuality(true);
+ preset.setQuality(ImagePreset.QUALITY_PREVIEW);
+ }
+ }
+
+ private String getType(RenderingRequest request) {
+ if (request.getType() == RenderingRequest.ICON_RENDERING) {
+ return "ICON_RENDERING";
+ }
+ if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
+ return "FILTERS_RENDERING";
+ }
+ if (request.getType() == RenderingRequest.FULL_RENDERING) {
+ return "FULL_RENDERING";
+ }
+ if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
+ return "GEOMETRY_RENDERING";
+ }
+ return "UNKNOWN TYPE!";
+ }
+
+ private void render(RenderingRequest request) {
+ if (request.getBitmap() == null
+ || request.getImagePreset() == null) {
+ return;
+ }
+ if (DEBUG) {
+ Log.v(LOGTAG, "render image of type " + getType(request));
+ }
+
+ Bitmap bitmap = request.getBitmap();
+ ImagePreset preset = request.getImagePreset();
+ setPresetParameters(preset);
+ if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
+ FiltersManager.getManager().resetBitmapsRS();
+ }
+
+ if (request.getType() != RenderingRequest.ICON_RENDERING) {
+ updateOriginalAllocation(preset);
+ }
+ if (DEBUG) {
+ Log.v(LOGTAG, "after update, req bitmap (" + bitmap.getWidth() + "x" + bitmap.getHeight()
+ +" ? resizeOriginal (" + mResizedOriginalBitmap.getWidth() + "x"
+ + mResizedOriginalBitmap.getHeight());
+ }
+ if (request.getType() == RenderingRequest.FULL_RENDERING
+ || request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
+ mOriginalAllocation.copyTo(bitmap);
+ } else if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
+ mFiltersOnlyOriginalAllocation.copyTo(bitmap);
+ }
+ if (request.getType() == RenderingRequest.FULL_RENDERING
+ || request.getType() == RenderingRequest.FILTERS_RENDERING
+ || request.getType() == RenderingRequest.ICON_RENDERING) {
+ Bitmap bmp = preset.apply(bitmap);
+ request.setBitmap(bmp);
+ }
+ if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
+ FiltersManager.getManager().resetBitmapsRS();
}
}
private void compute(TripleBufferBitmap buffer, ImagePreset preset, int type) {
- String thread = Thread.currentThread().getName();
- if (type == COMPUTE_PRESET && preset.same(mPreviousPreset)) {
- mPreviousPreset.usePreset(preset);
- preset = mPreviousPreset;
- } else if (type == COMPUTE_GEOMETRY_PRESET && preset.same(mPreviousGeometryPreset)) {
- mPreviousGeometryPreset.usePreset(preset);
- preset = mPreviousGeometryPreset;
- } else if (type == COMPUTE_FILTERS_PRESET && preset.same(mPreviousFiltersPreset)) {
- mPreviousFiltersPreset.usePreset(preset);
- preset = mPreviousFiltersPreset;
+ if (DEBUG) {
+ Log.v(LOGTAG, "compute preset " + preset);
+ preset.showFilters();
}
+
+ String thread = Thread.currentThread().getName();
long time = System.currentTimeMillis();
if (updateOriginalAllocation(preset)) {
buffer.updateBitmaps(mResizedOriginalBitmap);
@@ -253,30 +268,15 @@ public class FilteringPipeline implements Handler.Callback {
Bitmap bitmap = buffer.getProducer();
long time2 = System.currentTimeMillis();
- if (type != COMPUTE_FILTERS_PRESET) {
- if (bitmap == null || (bitmap.getWidth() != mResizedOriginalBitmap.getWidth())
- || (bitmap.getHeight() != mResizedOriginalBitmap.getHeight())) {
- buffer.updateBitmaps(mResizedOriginalBitmap);
- bitmap = buffer.getProducer();
- }
- mOriginalAllocation.copyTo(bitmap);
- } else {
- if (bitmap == null || (bitmap.getWidth() != mOriginalBitmap.getWidth())
- || (bitmap.getHeight() != mOriginalBitmap.getHeight())) {
- buffer.updateBitmaps(mOriginalBitmap);
- bitmap = buffer.getProducer();
- }
- mFiltersOnlyOriginalAllocation.copyTo(bitmap);
- }
-
- if (mOriginalAllocation == null || bitmap == null) {
- Log.v(LOGTAG, "exiting compute because mOriginalAllocation: " + mOriginalAllocation + " or bitmap: " + bitmap);
- return;
+ if (bitmap == null || (bitmap.getWidth() != mResizedOriginalBitmap.getWidth())
+ || (bitmap.getHeight() != mResizedOriginalBitmap.getHeight())) {
+ buffer.updateBitmaps(mResizedOriginalBitmap);
+ bitmap = buffer.getProducer();
}
+ mOriginalAllocation.copyTo(bitmap);
- if (type != COMPUTE_GEOMETRY_PRESET) {
- bitmap = preset.apply(bitmap);
- }
+ setPresetParameters(preset);
+ bitmap = preset.apply(bitmap);
time = System.currentTimeMillis() - time;
time2 = System.currentTimeMillis() - time2;
@@ -286,50 +286,16 @@ public class FilteringPipeline implements Handler.Callback {
+ ") took " + time + " ms, " + time2 + " ms for the filter, on thread " + thread);
}
if (type == COMPUTE_PRESET) {
- mPreviousPreset = preset;
if (mResizeFactor > 0.6 && time > MAX_PROCESS_TIME && (System.currentTimeMillis() + 1000 > mResizeTime)) {
mResizeTime = System.currentTimeMillis();
mResizeFactor *= RESIZE_FACTOR;
}
- } else if (type == COMPUTE_GEOMETRY_PRESET) {
- mPreviousGeometryPreset = preset;
- } else if (type == COMPUTE_FILTERS_PRESET) {
- mPreviousFiltersPreset = preset;
}
}
private synchronized boolean needsRepaint() {
- ImagePreset preset = MasterImage.getImage().getPreset();
- if (preset == null || mPreviousPreset == null) {
- return true;
- }
- if (preset.equals(mPreviousPreset)) {
- return false;
- }
- return true;
- }
-
- private synchronized boolean needsGeometryRepaint() {
- ImagePreset preset = MasterImage.getImage().getPreset();
- if (preset == null || mPreviousGeometry == null || mPreviousGeometryPreset == null) {
- return true;
- }
- GeometryMetadata geometry = preset.getGeometry();
- if (geometry.equals(mPreviousGeometryPreset.getGeometry())) {
- return false;
- }
- return true;
- }
-
- private synchronized boolean needsFiltersRepaint() {
- ImagePreset preset = MasterImage.getImage().getPreset();
- if (preset == null || mPreviousFiltersPreset == null) {
- return true;
- }
- if (preset.equals(mPreviousFiltersPreset)) {
- return false;
- }
- return true;
+ TripleBufferBitmap buffer = MasterImage.getImage().getDoubleBuffer();
+ return buffer.checkRepaintNeeded();
}
public void setPreviewScaleFactor(float previewScaleFactor) {
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
index ade775d09..698992ac9 100644
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
@@ -212,13 +212,13 @@ public class ImageLoader {
mOriginalBitmapLarge = rotateToPortrait(mOriginalBitmapLarge, mOrientation);
}
mZoomOrientation = mOrientation;
- FilteringPipeline pipeline = FilteringPipeline.getPipeline();
- pipeline.setOriginal(mOriginalBitmapLarge);
- float previewScale = (float) mOriginalBitmapLarge.getWidth() / (float) getOriginalBounds().width();
- pipeline.setPreviewScaleFactor(previewScale);
warnListeners();
}
+ public Bitmap decodeImage(int id, BitmapFactory.Options options) {
+ return BitmapFactory.decodeResource(mContext.getResources(), id, options);
+ }
+
public static Bitmap rotateToPortrait(Bitmap bitmap, int ori) {
Matrix matrix = new Matrix();
int w = bitmap.getWidth();
@@ -280,7 +280,7 @@ public class ImageLoader {
return null;
}
- static final int MAX_BITMAP_DIM = 2048;
+ static final int MAX_BITMAP_DIM = 900;
private Bitmap loadScaledBitmap(Uri uri, int size) {
InputStream is = null;
@@ -392,7 +392,7 @@ public class ImageLoader {
public void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity,
File destination) {
- preset.setIsHighQuality(true);
+ preset.setQuality(ImagePreset.QUALITY_FINAL);
preset.setScaleFactor(1.0f);
new SaveCopyTask(mContext, mUri, destination, new SaveCopyTask.Callback() {
@@ -432,7 +432,7 @@ public class ImageLoader {
public void returnFilteredResult(ImagePreset preset,
final FilterShowActivity filterShowActivity) {
- preset.setIsHighQuality(true);
+ preset.setQuality(ImagePreset.QUALITY_FINAL);
preset.setScaleFactor(1.0f);
BitmapTask.Callbacks<ImagePreset> cb = new BitmapTask.Callbacks<ImagePreset>() {
@@ -448,7 +448,7 @@ public class ImageLoader {
@Override
public Bitmap onExecute(ImagePreset param) {
- if (param == null) {
+ if (param == null || mUri == null) {
return null;
}
Bitmap bitmap = loadMutableBitmap(mContext, mUri);
@@ -456,6 +456,7 @@ public class ImageLoader {
Log.w(LOGTAG, "Failed to save image!");
return null;
}
+ bitmap = param.applyGeometry(bitmap);
return param.apply(bitmap);
}
};
diff --git a/src/com/android/gallery3d/filtershow/cache/RenderingRequest.java b/src/com/android/gallery3d/filtershow/cache/RenderingRequest.java
new file mode 100644
index 000000000..1e9f6b83a
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/cache/RenderingRequest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2013 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.filtershow.cache;
+
+import android.graphics.Bitmap;
+import com.android.gallery3d.app.Log;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.presets.ImagePreset;
+
+public class RenderingRequest {
+ private static final String LOGTAG = "RenderingRequest";
+ private boolean mIsDirect = false;
+ private Bitmap mBitmap = null;
+ private ImagePreset mImagePreset = null;
+ private RenderingRequestCaller mCaller = null;
+ private int mType = FULL_RENDERING;
+ public static int FULL_RENDERING = 0;
+ public static int FILTERS_RENDERING = 1;
+ public static int GEOMETRY_RENDERING = 2;
+ public static int ICON_RENDERING = 3;
+ private static final Bitmap.Config mConfig = Bitmap.Config.ARGB_8888;
+
+ public static void post(Bitmap source, ImagePreset preset, int type,
+ RenderingRequestCaller caller) {
+ if (source == null || preset == null || caller == null) {
+ Log.v(LOGTAG, "something null: source: " + source + " or preset: " + preset + " or caller: " + caller);
+ return;
+ }
+ RenderingRequest request = new RenderingRequest();
+ Bitmap bitmap = null;
+ if (type == FULL_RENDERING || type == GEOMETRY_RENDERING || type == ICON_RENDERING) {
+ bitmap = preset.applyGeometry(source);
+ } else {
+ bitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), mConfig);
+ }
+ request.setBitmap(bitmap);
+ ImagePreset passedPreset = new ImagePreset(preset);
+ passedPreset.setImageLoader(MasterImage.getImage().getImageLoader());
+ request.setImagePreset(passedPreset);
+ request.setType(type);
+ request.setCaller(caller);
+ request.post();
+ }
+
+ public void post() {
+ FilteringPipeline.getPipeline().postRenderingRequest(this);
+ }
+
+ public void markAvailable() {
+ if (mBitmap == null || mImagePreset == null
+ || mCaller == null) {
+ return;
+ }
+ mCaller.available(this);
+ }
+
+ public boolean isDirect() {
+ return mIsDirect;
+ }
+
+ public void setDirect(boolean isDirect) {
+ mIsDirect = isDirect;
+ }
+
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+
+ public void setBitmap(Bitmap bitmap) {
+ mBitmap = bitmap;
+ }
+
+ public ImagePreset getImagePreset() {
+ return mImagePreset;
+ }
+
+ public void setImagePreset(ImagePreset imagePreset) {
+ mImagePreset = imagePreset;
+ }
+
+ public int getType() {
+ return mType;
+ }
+
+ public void setType(int type) {
+ mType = type;
+ }
+
+ public void setCaller(RenderingRequestCaller caller) {
+ mCaller = caller;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/cache/RenderingRequestCaller.java b/src/com/android/gallery3d/filtershow/cache/RenderingRequestCaller.java
new file mode 100644
index 000000000..240eb8f44
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/cache/RenderingRequestCaller.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 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.filtershow.cache;
+
+public interface RenderingRequestCaller {
+ public void available(RenderingRequest request);
+}
diff --git a/src/com/android/gallery3d/filtershow/cache/TripleBufferBitmap.java b/src/com/android/gallery3d/filtershow/cache/TripleBufferBitmap.java
index c4837ad4a..cc14bf65f 100644
--- a/src/com/android/gallery3d/filtershow/cache/TripleBufferBitmap.java
+++ b/src/com/android/gallery3d/filtershow/cache/TripleBufferBitmap.java
@@ -30,6 +30,7 @@ public class TripleBufferBitmap {
private boolean mNeedsSwap = false;
private final Bitmap.Config mBitmapConfig = Bitmap.Config.ARGB_8888;
+ private boolean mNeedsRepaint = true;
public TripleBufferBitmap() {
@@ -68,4 +69,17 @@ public class TripleBufferBitmap {
mConsumer = intermediate;
mNeedsSwap = false;
}
+
+ public synchronized void invalidate() {
+ mNeedsRepaint = true;
+ }
+
+ public synchronized boolean checkRepaintNeeded() {
+ if (mNeedsRepaint) {
+ mNeedsRepaint = false;
+ return true;
+ }
+ return false;
+ }
+
}
diff --git a/src/com/android/gallery3d/filtershow/editors/BasicEditor.java b/src/com/android/gallery3d/filtershow/editors/BasicEditor.java
index 1ea0da700..48aa5925a 100644
--- a/src/com/android/gallery3d/filtershow/editors/BasicEditor.java
+++ b/src/com/android/gallery3d/filtershow/editors/BasicEditor.java
@@ -17,15 +17,15 @@
package com.android.gallery3d.filtershow.editors;
import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.filters.ImageFilter;
+import com.android.gallery3d.filtershow.filters.*;
import android.content.Context;
-import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.presets.ImagePreset;
/**
* The basic editor that all the one parameter filters
@@ -47,8 +47,8 @@ public class BasicEditor extends Editor implements OnSeekBarChangeListener {
protected BasicEditor(int id, int layoutID, int viewID) {
super(id);
- int mLayoutID = layoutID;
- int mViewID = viewID;
+ mLayoutID = layoutID;
+ mViewID = viewID;
}
@Override
@@ -61,35 +61,32 @@ public class BasicEditor extends Editor implements OnSeekBarChangeListener {
@Override
public void reflectCurrentFilter() {
- ImageFilter filter = mImageShow.getCurrentFilter();
- if (filter == null) {
- return;
+ super.reflectCurrentFilter();
+ if (getLocalRepresentation() != null && getLocalRepresentation() instanceof FilterBasicRepresentation) {
+ FilterBasicRepresentation interval = (FilterBasicRepresentation) getLocalRepresentation();
+ boolean f = interval.showParameterValue();
+ mSeekBar.setVisibility((f) ? View.VISIBLE : View.GONE);
+ int value = interval.getValue();
+ int min = interval.getMinimum();
+ int max = interval.getMaximum();
+ mSeekBar.setMax(max - min);
+ mSeekBar.setProgress(value - min);
}
- boolean f = filter.showParameterValue();
- mSeekBar.setVisibility((f) ? View.VISIBLE : View.INVISIBLE);
- int parameter = filter.getParameter();
- int maxp = filter.getMaxParameter();
- int minp = filter.getMinParameter();
- mSeekBar.setMax(maxp - minp);
- mSeekBar.setProgress(parameter - minp);
}
@Override
public void onProgressChanged(SeekBar sbar, int progress, boolean arg2) {
- ImageFilter filter = mImageShow.getCurrentFilter();
- if (filter == null) {
- return;
+ if (getLocalRepresentation() != null && getLocalRepresentation() instanceof FilterBasicRepresentation) {
+ FilterBasicRepresentation interval = (FilterBasicRepresentation) getLocalRepresentation();
+ int value = progress + interval.getMinimum();
+ interval.setValue(value);
+ mImageShow.onNewValue(value);
+ mView.invalidate();
+ if (interval.showParameterValue()) {
+ mPanelController.onNewValue(value);
+ }
+ commitLocalRepresentation();
}
- int minp = filter.getMinParameter();
- int value = progress + minp;
- mImageShow.onNewValue(value);
- mView.invalidate();
- if (filter.showParameterValue()) {
- mPanelController.onNewValue(value);
- }
-
- Log.v(LOGTAG, " #### progress=" + value);
- MasterImage.getImage().updateBuffers();
}
@Override
diff --git a/src/com/android/gallery3d/filtershow/editors/Editor.java b/src/com/android/gallery3d/filtershow/editors/Editor.java
index a9b2fd425..bea591c63 100644
--- a/src/com/android/gallery3d/filtershow/editors/Editor.java
+++ b/src/com/android/gallery3d/filtershow/editors/Editor.java
@@ -25,7 +25,10 @@ import android.widget.LinearLayout;
import com.android.gallery3d.filtershow.PanelController;
import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.imageshow.ImageShow;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.presets.ImagePreset;
/**
* Base class for Editors Must contain a mImageShow and a top level view
@@ -38,6 +41,7 @@ public class Editor {
protected PanelController mPanelController;
protected int mID;
private final String LOGTAG = "Editor";
+ protected FilterRepresentation mLocalRepresentation = null;
public void setPanelController(PanelController panelController) {
this.mPanelController = panelController;
@@ -53,6 +57,7 @@ public class Editor {
public void createEditor(Context context,FrameLayout frameLayout) {
mContext = context;
mFrameLayout = frameLayout;
+ mLocalRepresentation = null;
}
protected void unpack(int viewid, int layoutid) {
@@ -105,10 +110,25 @@ public class Editor {
mView.setVisibility(visible);
}
+ public FilterRepresentation getLocalRepresentation() {
+ if (mLocalRepresentation == null) {
+ ImagePreset preset = MasterImage.getImage().getPreset();
+ FilterRepresentation filterRepresentation = MasterImage.getImage().getCurrentFilterRepresentation();
+ mLocalRepresentation = preset.getFilterRepresentationCopyFrom(filterRepresentation);
+ }
+ return mLocalRepresentation;
+ }
+
+ public void commitLocalRepresentation() {
+ ImagePreset preset = MasterImage.getImage().getPreset();
+ preset.updateFilterRepresentation(getLocalRepresentation());
+ }
+
/**
* called after the filter is set and the select is called
*/
public void reflectCurrentFilter() {
+ mLocalRepresentation = null;
}
public boolean useUtilityPanel() {
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorCurves.java b/src/com/android/gallery3d/filtershow/editors/EditorCurves.java
index a3360483a..b6e7b2bd7 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorCurves.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorCurves.java
@@ -20,11 +20,13 @@ import android.content.Context;
import android.widget.FrameLayout;
import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.filters.FilterCurvesRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.ui.ImageCurves;
public class EditorCurves extends Editor {
public static final int ID = R.id.imageCurves;
-
+ ImageCurves mImageCurves;
public EditorCurves() {
super(ID);
}
@@ -32,6 +34,17 @@ public class EditorCurves extends Editor {
@Override
public void createEditor(Context context, FrameLayout frameLayout) {
super.createEditor(context, frameLayout);
- mView = mImageShow = new ImageCurves(context);
+ mView = mImageShow = mImageCurves = new ImageCurves(context);
+ mImageCurves.setEditor(this);
+ }
+
+ @Override
+ public void reflectCurrentFilter() {
+ super.reflectCurrentFilter();
+ FilterRepresentation rep = getLocalRepresentation();
+ if (rep != null && getLocalRepresentation() instanceof FilterCurvesRepresentation) {
+ FilterCurvesRepresentation drawRep = (FilterCurvesRepresentation) rep;
+ mImageCurves.setFilterDrawRepresentation(drawRep);
+ }
}
}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDraw.java b/src/com/android/gallery3d/filtershow/editors/EditorDraw.java
index abd4ae475..aa5ec61e8 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorDraw.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDraw.java
@@ -18,12 +18,10 @@ package com.android.gallery3d.filtershow.editors;
import android.app.Dialog;
import android.content.Context;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
-import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
@@ -35,16 +33,16 @@ import com.android.gallery3d.R;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.colorpicker.ColorGridDialog;
import com.android.gallery3d.filtershow.colorpicker.RGBListener;
+import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.ImageFilterDraw;
import com.android.gallery3d.filtershow.imageshow.ImageDraw;
import com.android.gallery3d.filtershow.ui.FramedTextButton;
-/**
- * TODO: Insert description here. (generated by hoford)
- */
public class EditorDraw extends Editor {
private static final String LOGTAG = "EditorDraw";
public static final int ID = R.id.editorDraw;
+ public ImageDraw mImageDraw;
public EditorDraw() {
super(ID);
@@ -53,7 +51,9 @@ public class EditorDraw extends Editor {
@Override
public void createEditor(Context context, FrameLayout frameLayout) {
super.createEditor(context, frameLayout);
- mView = mImageShow = new ImageDraw(context);
+ mView = mImageShow = mImageDraw = new ImageDraw(context);
+ mImageDraw.setEditor(this);
+
}
@Override
@@ -62,6 +62,17 @@ public class EditorDraw extends Editor {
}
@Override
+ public void reflectCurrentFilter() {
+ super.reflectCurrentFilter();
+ FilterRepresentation rep = getLocalRepresentation();
+
+ if (rep != null && getLocalRepresentation() instanceof FilterDrawRepresentation) {
+ FilterDrawRepresentation drawRep = (FilterDrawRepresentation) getLocalRepresentation();
+ mImageDraw.setFilterDrawRepresentation(drawRep);
+ }
+ }
+
+ @Override
public void openUtilityPanel(final LinearLayout accessoryViewList) {
View view = accessoryViewList.findViewById(R.id.drawUtilityButton);
if (view == null) {
@@ -70,7 +81,8 @@ public class EditorDraw extends Editor {
view = inflater.inflate(R.layout.filtershow_draw_button, accessoryViewList, false);
accessoryViewList.addView(view, view.getLayoutParams());
view.setOnClickListener(new OnClickListener() {
- @Override
+
+ @Override
public void onClick(View arg0) {
showPopupMenu(accessoryViewList);
}
@@ -88,25 +100,30 @@ public class EditorDraw extends Editor {
if (button == null) {
return;
}
- PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), button);
+ final PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), button);
popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_draw, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+
@Override
public boolean onMenuItemClick(MenuItem item) {
ImageFilterDraw filter = (ImageFilterDraw) mImageShow.getCurrentFilter();
- int minp = filter.getMinParameter();
- int parameter = filter.getParameter();
if (item.getItemId() == R.id.draw_menu_color) {
showColorGrid(item);
} else if (item.getItemId() == R.id.draw_menu_size) {
showSizeDialog(item);
- } else if (item.getItemId() == R.id.draw_menu_style_brush) {
+ } else if (item.getItemId() == R.id.draw_menu_style_brush_marker) {
+ ImageDraw idraw = (ImageDraw) mImageShow;
+ idraw.setStyle(ImageFilterDraw.BRUSH_STYLE_MARKER);
+ } else if (item.getItemId() == R.id.draw_menu_style_brush_spatter) {
ImageDraw idraw = (ImageDraw) mImageShow;
- idraw.setStyle(ImageFilterDraw.BRUSH_STYLE);
+ idraw.setStyle(ImageFilterDraw.BRUSH_STYLE_SPATTER);
} else if (item.getItemId() == R.id.draw_menu_style_line) {
ImageDraw idraw = (ImageDraw) mImageShow;
idraw.setStyle(ImageFilterDraw.SIMPLE_STYLE);
-
+ } else if (item.getItemId() == R.id.draw_menu_clear) {
+ ImageDraw idraw = (ImageDraw) mImageShow;
+ idraw.resetParameter();
+ commitLocalRepresentation();
}
mView.invalidate();
return true;
@@ -126,6 +143,7 @@ public class EditorDraw extends Editor {
Button button = (Button) dialog.findViewById(R.id.sizeAcceptButton);
button.setOnClickListener(new OnClickListener() {
+ @Override
public void onClick(View arg0) {
int p = bar.getProgress();
ImageDraw idraw = (ImageDraw) mImageShow;
@@ -135,9 +153,10 @@ public class EditorDraw extends Editor {
});
dialog.show();
}
+
public void showColorGrid(final MenuItem item) {
RGBListener cl = new RGBListener() {
- @Override
+ @Override
public void setColor(int rgb) {
ImageDraw idraw = (ImageDraw) mImageShow;
idraw.setColor(rgb);
@@ -147,5 +166,4 @@ public class EditorDraw extends Editor {
cpd.show();
LayoutParams params = cpd.getWindow().getAttributes();
}
-
}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java b/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java
new file mode 100644
index 000000000..c37102b37
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 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.filtershow.editors;
+
+import android.content.Context;
+import android.util.Log;
+import android.widget.FrameLayout;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.filters.FilterRedEyeRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.ImageRedEye;
+
+/**
+ * The editor with no slider for filters without UI
+ */
+public class EditorRedEye extends Editor {
+ public static int ID = R.id.editorRedEye;
+ private final String LOGTAG = "EditorRedEye";
+ ImageRedEye mImageRedEyes;
+
+ public EditorRedEye() {
+ super(ID);
+ }
+
+ protected EditorRedEye(int id) {
+ super(id);
+ }
+
+ @Override
+ public void createEditor(Context context, FrameLayout frameLayout) {
+ super.createEditor(context, frameLayout);
+ mView = mImageShow = mImageRedEyes= new ImageRedEye(context);
+ mImageRedEyes.setEditor(this);
+ }
+
+ @Override
+ public void reflectCurrentFilter() {
+ super.reflectCurrentFilter();
+ FilterRepresentation rep = getLocalRepresentation();
+ if (rep != null && getLocalRepresentation() instanceof FilterRedEyeRepresentation) {
+ FilterRedEyeRepresentation redEyeRep = (FilterRedEyeRepresentation) rep;
+
+ mImageRedEyes.setRepresentation(redEyeRep);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java b/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java
new file mode 100644
index 000000000..d21950912
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 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.filtershow.editors;
+
+import android.content.Context;
+import android.util.Log;
+import android.widget.FrameLayout;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation;
+import com.android.gallery3d.filtershow.imageshow.ImageTinyPlanet;
+
+public class EditorTinyPlanet extends BasicEditor {
+ public static final int ID = R.id.tinyPlanetEditor;
+ private static final String LOGTAG = "EditorTinyPlanet";
+ ImageTinyPlanet mImageTinyPlanet;
+
+ public EditorTinyPlanet() {
+ super(ID, R.layout.filtershow_tiny_planet_editor, R.id.imageTinyPlanet);
+ }
+
+ @Override
+ public void createEditor(Context context, FrameLayout frameLayout) {
+ super.createEditor(context, frameLayout);
+ mImageTinyPlanet = (ImageTinyPlanet) mImageShow;
+ mImageTinyPlanet.setEditor(this);
+ }
+
+ @Override
+ public void reflectCurrentFilter() {
+ super.reflectCurrentFilter();
+
+ FilterRepresentation rep = getLocalRepresentation();
+ if (rep != null && getLocalRepresentation() instanceof FilterTinyPlanetRepresentation) {
+ FilterTinyPlanetRepresentation drawRep = (FilterTinyPlanetRepresentation) rep;
+ mImageTinyPlanet.setRepresentation(drawRep);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java b/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java
new file mode 100644
index 000000000..a3fc5aab4
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 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.filtershow.editors;
+
+import android.content.Context;
+import android.widget.FrameLayout;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.imageshow.ImageShow;
+
+/**
+ * The editor with no slider for filters without UI
+ */
+public class ImageOnlyEditor extends Editor {
+ public static int ID = R.id.imageOnlyEditor;
+ private final String LOGTAG = "ImageOnlyEditor";
+
+ public ImageOnlyEditor() {
+ super(ID);
+ }
+
+ protected ImageOnlyEditor(int id) {
+ super(id);
+ }
+
+ @Override
+ public void createEditor(Context context, FrameLayout frameLayout) {
+ super.createEditor(context, frameLayout);
+ mView = mImageShow = new ImageShow(context);
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
new file mode 100644
index 000000000..43660d6a0
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+
+import java.util.HashMap;
+import java.util.Vector;
+
+public class BaseFiltersManager {
+
+ private static final String LOGTAG = "BaseFiltersManager";
+ private static HashMap<Class, ImageFilter> mFilters = new HashMap<Class, ImageFilter>();
+
+ protected BaseFiltersManager() {
+ Vector<ImageFilter> filters = new Vector<ImageFilter>();
+ addFilters(filters);
+ for (ImageFilter filter : filters) {
+ mFilters.put(filter.getClass(), filter);
+ }
+ }
+
+ protected void addFilters(Vector<ImageFilter> filters) {
+ filters.add(new ImageFilterTinyPlanet());
+ filters.add(new ImageFilterRedEye());
+ filters.add(new ImageFilterWBalance());
+ filters.add(new ImageFilterExposure());
+ filters.add(new ImageFilterVignette());
+ filters.add(new ImageFilterContrast());
+ filters.add(new ImageFilterShadows());
+ filters.add(new ImageFilterVibrance());
+ filters.add(new ImageFilterSharpen());
+ filters.add(new ImageFilterCurves());
+ filters.add(new ImageFilterDraw());
+ filters.add(new ImageFilterHue());
+ filters.add(new ImageFilterSaturated());
+ filters.add(new ImageFilterBwFilter());
+ filters.add(new ImageFilterNegative());
+ filters.add(new ImageFilterEdge());
+ filters.add(new ImageFilterKMeans());
+ filters.add(new ImageFilterFx());
+ filters.add(new ImageFilterBorder());
+ filters.add(new ImageFilterParametricBorder());
+ }
+
+ public ImageFilter getFilter(Class c) {
+ return mFilters.get(c);
+ }
+
+ public ImageFilter getFilterForRepresentation(FilterRepresentation representation) {
+ return mFilters.get(representation.getFilterClass());
+ }
+
+ public void addFilter(Class filterClass, ImageFilter filter) {
+ mFilters.put(filterClass, filter);
+ }
+
+ public FilterRepresentation getRepresentation(Class c) {
+ ImageFilter filter = mFilters.get(c);
+ if (filter != null) {
+ return filter.getDefaultRepresentation();
+ }
+ return null;
+ }
+
+ public void addLooks(Vector<FilterRepresentation> representations) {
+ // subclass can add representations
+ }
+
+ public void addEffects(Vector<FilterRepresentation> representations) {
+ representations.add(getRepresentation(ImageFilterTinyPlanet.class));
+ representations.add(getRepresentation(ImageFilterRedEye.class));
+ representations.add(getRepresentation(ImageFilterWBalance.class));
+ representations.add(getRepresentation(ImageFilterExposure.class));
+ representations.add(getRepresentation(ImageFilterVignette.class));
+ representations.add(getRepresentation(ImageFilterContrast.class));
+ representations.add(getRepresentation(ImageFilterShadows.class));
+ representations.add(getRepresentation(ImageFilterVibrance.class));
+ representations.add(getRepresentation(ImageFilterSharpen.class));
+ representations.add(getRepresentation(ImageFilterCurves.class));
+ representations.add(getRepresentation(ImageFilterDraw.class));
+ representations.add(getRepresentation(ImageFilterHue.class));
+ representations.add(getRepresentation(ImageFilterSaturated.class));
+ representations.add(getRepresentation(ImageFilterBwFilter.class));
+ representations.add(getRepresentation(ImageFilterNegative.class));
+ representations.add(getRepresentation(ImageFilterEdge.class));
+ representations.add(getRepresentation(ImageFilterKMeans.class));
+ }
+
+ public void resetBitmapsRS() {
+ for (Class c : mFilters.keySet()) {
+ ImageFilter filter = mFilters.get(c);
+ if (filter instanceof ImageFilterRS) {
+ ImageFilterRS filterRS = (ImageFilterRS) filter;
+ filterRS.resetBitmap();
+ }
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java
new file mode 100644
index 000000000..2410ebe72
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+import com.android.gallery3d.app.Log;
+
+public class FilterBasicRepresentation extends FilterRepresentation {
+ private static final String LOGTAG = "FilterBasicRepresentation";
+ private int mMinimum;
+ private int mValue;
+ private int mMaximum;
+ private int mDefaultValue;
+ private int mPreviewValue;
+
+ public FilterBasicRepresentation(String name, int minimum, int value, int maximum) {
+ super(name);
+ mMinimum = minimum;
+ mMaximum = maximum;
+ setValue(value);
+ }
+
+ public String toString() {
+ return getName() + " : " + mMinimum + " < " + mValue + " < " + mMaximum;
+ }
+
+ @Override
+ public FilterRepresentation clone() throws CloneNotSupportedException {
+ FilterBasicRepresentation representation = (FilterBasicRepresentation) super.clone();
+ representation.setMinimum(getMinimum());
+ representation.setMaximum(getMaximum());
+ representation.setValue(getValue());
+ Log.v(LOGTAG, "cloning from <" + this + "> to <" + representation + ">");
+ return representation;
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterBasicRepresentation) {
+ FilterBasicRepresentation representation = (FilterBasicRepresentation) a;
+ setMinimum(representation.getMinimum());
+ setMaximum(representation.getMaximum());
+ setValue(representation.getValue());
+ setDefaultValue(representation.getDefaultValue());
+ setPreviewValue(representation.getPreviewValue());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterBasicRepresentation) {
+ FilterBasicRepresentation basic = (FilterBasicRepresentation) representation;
+ if (basic.mMinimum == mMinimum
+ && basic.mMaximum == mMaximum
+ && basic.mValue == mValue
+ && basic.mDefaultValue == mDefaultValue
+ && basic.mPreviewValue == mPreviewValue) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int getMinimum() {
+ return mMinimum;
+ }
+
+ public void setMinimum(int minimum) {
+ mMinimum = minimum;
+ }
+
+ public int getValue() {
+ return mValue;
+ }
+
+ public void setValue(int value) {
+ mValue = value;
+ if (mValue < mMinimum) {
+ mValue = mMinimum;
+ }
+ if (mValue > mMaximum) {
+ mValue = mMaximum;
+ }
+ }
+
+ public int getMaximum() {
+ return mMaximum;
+ }
+
+ public void setMaximum(int maximum) {
+ mMaximum = maximum;
+ }
+
+ public void setDefaultValue(int defaultValue) {
+ mDefaultValue = defaultValue;
+ }
+
+ public int getDefaultValue() {
+ return mDefaultValue;
+ }
+
+ public int getPreviewValue() {
+ return mPreviewValue;
+ }
+
+ public void setPreviewValue(int previewValue) {
+ mPreviewValue = previewValue;
+ }
+
+ public String getStateRepresentation() {
+ return "" + getValue();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
new file mode 100644
index 000000000..b2664a30f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+
+public class FilterColorBorderRepresentation extends FilterRepresentation {
+ private int mColor;
+ private int mBorderSize;
+ private int mBorderRadius;
+
+ public FilterColorBorderRepresentation(int color, int size, int radius) {
+ super("ColorBorder");
+ mColor = color;
+ mBorderSize = size;
+ mBorderRadius = radius;
+ setFilterClass(ImageFilterParametricBorder.class);
+ setPriority(FilterRepresentation.TYPE_BORDER);
+ setTextId(R.string.borders);
+ setEditorId(ImageOnlyEditor.ID);
+ setShowEditingControls(false);
+ setShowParameterValue(false);
+ setShowUtilityPanel(false);
+ }
+
+ public String toString() {
+ return "FilterBorder: " + getName();
+ }
+
+ @Override
+ public FilterRepresentation clone() throws CloneNotSupportedException {
+ FilterColorBorderRepresentation representation = (FilterColorBorderRepresentation) super.clone();
+ representation.setName(getName());
+ representation.setColor(getColor());
+ representation.setBorderSize(getBorderSize());
+ representation.setBorderRadius(getBorderRadius());
+ return representation;
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterColorBorderRepresentation) {
+ FilterColorBorderRepresentation representation = (FilterColorBorderRepresentation) a;
+ setName(representation.getName());
+ setColor(representation.getColor());
+ setBorderSize(representation.getBorderSize());
+ setBorderRadius(representation.getBorderRadius());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterColorBorderRepresentation) {
+ FilterColorBorderRepresentation border = (FilterColorBorderRepresentation) representation;
+ if (border.mColor == mColor
+ && border.mBorderSize == mBorderSize
+ && border.mBorderRadius == mBorderRadius) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean allowsMultipleInstances() {
+ return true;
+ }
+
+ @Override
+ public int getTextId() {
+ return R.string.borders;
+ }
+
+ public int getColor() {
+ return mColor;
+ }
+
+ public void setColor(int color) {
+ mColor = color;
+ }
+
+ public int getBorderSize() {
+ return mBorderSize;
+ }
+
+ public void setBorderSize(int borderSize) {
+ mBorderSize = borderSize;
+ }
+
+ public int getBorderRadius() {
+ return mBorderRadius;
+ }
+
+ public void setBorderRadius(int borderRadius) {
+ mBorderRadius = borderRadius;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java
new file mode 100644
index 000000000..6c831708e
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java
@@ -0,0 +1,54 @@
+package com.android.gallery3d.filtershow.filters;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.ui.Spline;
+
+/**
+ * TODO: Insert description here. (generated by hoford)
+ */
+public class FilterCurvesRepresentation extends FilterRepresentation {
+ private Spline[] mSplines = new Spline[4];
+
+ public FilterCurvesRepresentation() {
+ super("Curves");
+ setFilterClass(ImageFilterCurves.class);
+ setTextId(R.string.curvesRGB);
+ setButtonId(R.id.curvesButtonRGB);
+ setOverlayId(R.drawable.filtershow_button_colors_curve);
+ setEditorId(R.id.imageCurves);
+ setShowEditingControls(false);
+ setShowParameterValue(false);
+ setShowUtilityPanel(true);
+ for (int i = 0; i < mSplines.length; i++) {
+ mSplines[i] = new Spline();
+ mSplines[i].reset();
+ }
+ }
+
+ public boolean isNil() {
+ for (int i = 0; i < 4; i++) {
+ if (getSpline(i) != null && !getSpline(i).isOriginal()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void reset() {
+ Spline spline = new Spline();
+
+ spline.addPoint(0.0f, 1.0f);
+ spline.addPoint(1.0f, 0.0f);
+
+ for (int i = 0; i < 4; i++) {
+ mSplines[i] = new Spline(spline);
+ }
+ }
+
+ public void setSpline(int splineIndex, Spline s) {
+ mSplines[splineIndex] = s;
+ }
+ public Spline getSpline(int splineIndex) {
+ return mSplines[splineIndex];
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java
new file mode 100644
index 000000000..3807ee1f5
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+public class FilterDirectRepresentation extends FilterRepresentation {
+
+ public FilterDirectRepresentation(String name) {
+ super(name);
+ }
+
+ public boolean isNil() {
+ return true;
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java
new file mode 100644
index 000000000..e41f0a622
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+import android.graphics.Path;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorDraw;
+
+import java.util.Vector;
+
+public class FilterDrawRepresentation extends FilterRepresentation {
+ private static final String LOGTAG = "FilterDrawRepresentation";
+
+ public static class StrokeData implements Cloneable {
+ public byte mType;
+ public Path mPath;
+ public float mRadius;
+ public int mColor;
+ public int noPoints = 0;
+ @Override
+ public String toString() {
+ return "stroke(" + mType + ", path(" + (mPath) + "), " + mRadius + " , "
+ + Integer.toHexString(mColor) + ")";
+ }
+ @Override
+ public StrokeData clone() throws CloneNotSupportedException {
+ return (StrokeData) super.clone();
+ }
+ }
+
+ private Vector<StrokeData> mDrawing = new Vector<StrokeData>();
+ private StrokeData mCurrent; // used in the currently drawing style
+
+ public FilterDrawRepresentation() {
+ super("Draw");
+ setFilterClass(ImageFilterDraw.class);
+ setPriority(FilterRepresentation.TYPE_VIGNETTE);
+ setTextId(R.string.imageDraw);
+ setButtonId(R.id.drawOnImageButton);
+ setEditorId(EditorDraw.ID);
+ }
+
+ @Override
+ public String toString() {
+ return getName() + " : strokes=" + mDrawing.size()
+ + ((mCurrent == null) ? " no current "
+ : ("draw=" + mCurrent.mType + " " + mCurrent.noPoints));
+ }
+
+ public Vector<StrokeData> getDrawing() {
+ return mDrawing;
+ }
+
+ public StrokeData getCurrentDrawing() {
+ return mCurrent;
+ }
+
+ @Override
+ public FilterRepresentation clone() throws CloneNotSupportedException {
+ FilterDrawRepresentation representation = (FilterDrawRepresentation) super.clone();
+ return representation;
+ }
+
+ @Override
+ public boolean isNil() {
+ return getDrawing().isEmpty();
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterDrawRepresentation) {
+ FilterDrawRepresentation representation = (FilterDrawRepresentation) a;
+ try {
+ if (representation.mCurrent != null) {
+ mCurrent = (StrokeData) representation.mCurrent.clone();
+ } else {
+ mCurrent = null;
+ }
+ if (representation.mDrawing != null) {
+ mDrawing = (Vector<StrokeData>) representation.mDrawing.clone();
+ } else {
+ mDrawing = null;
+ }
+
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ } else {
+ Log.v(LOGTAG, "cannot use parameters from " + a);
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterDrawRepresentation) {
+ FilterDrawRepresentation fdRep = (FilterDrawRepresentation) representation;
+ if (fdRep.mDrawing.size() != mDrawing.size())
+ return false;
+ if (fdRep.mCurrent == null && mCurrent.mPath == null) {
+ return true;
+ }
+ if (fdRep.mCurrent != null && mCurrent.mPath != null) {
+ if (fdRep.mCurrent.noPoints == mCurrent.noPoints) {
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
+ }
+
+ public void startNewSection(byte type, int color, float size, float x, float y) {
+ mCurrent = new StrokeData();
+ mCurrent.mColor = color;
+ mCurrent.mRadius = size;
+ mCurrent.mType = type;
+ mCurrent.mPath = new Path();
+ mCurrent.mPath.moveTo(x, y);
+ mCurrent.noPoints = 0;
+ }
+
+ public void addPoint(float x, float y) {
+ mCurrent.noPoints++;
+ mCurrent.mPath.lineTo(x, y);
+ }
+
+ public void endSection(float x, float y) {
+ mCurrent.mPath.lineTo(x, y);
+ mCurrent.noPoints++;
+ mDrawing.add(mCurrent);
+ mCurrent = null;
+ }
+
+ public void clear() {
+ mCurrent = null;
+ mDrawing.clear();
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java
new file mode 100644
index 000000000..859bf327c
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+import android.graphics.Bitmap;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+
+public class FilterFxRepresentation extends FilterRepresentation {
+ private Bitmap mFxBitmap = null;
+ // TODO: When implementing serialization, we should find a unique way of
+ // specifying bitmaps / names (the resource IDs being random)
+ private int mBitmapResource = 0;
+ private int mNameResource = 0;
+
+ public FilterFxRepresentation(String name, int bitmapResource, int nameResource) {
+ super(name);
+ mBitmapResource = bitmapResource;
+ mNameResource = nameResource;
+ setFilterClass(ImageFilterFx.class);
+ setPriority(FilterRepresentation.TYPE_FX);
+ setTextId(nameResource);
+ setEditorId(ImageOnlyEditor.ID);
+ setShowEditingControls(false);
+ setShowParameterValue(false);
+ setShowUtilityPanel(false);
+ }
+
+ public String toString() {
+ return "FilterFx: " + getName();
+ }
+
+ @Override
+ public FilterRepresentation clone() throws CloneNotSupportedException {
+ FilterFxRepresentation representation = (FilterFxRepresentation) super.clone();
+ representation.setName(getName());
+ representation.setBitmapResource(getBitmapResource());
+ representation.setNameResource(getNameResource());
+ representation.setFxBitmap(getFxBitmap());
+ return representation;
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterFxRepresentation) {
+ FilterFxRepresentation representation = (FilterFxRepresentation) a;
+ setName(representation.getName());
+ setBitmapResource(representation.getBitmapResource());
+ setNameResource(representation.getNameResource());
+ setFxBitmap(representation.getFxBitmap());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterFxRepresentation) {
+ FilterFxRepresentation fx = (FilterFxRepresentation) representation;
+ if (fx.mNameResource == mNameResource
+ && fx.mBitmapResource == mBitmapResource) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean allowsMultipleInstances() {
+ return true;
+ }
+
+ public Bitmap getFxBitmap() {
+ return mFxBitmap;
+ }
+
+ public void setFxBitmap(Bitmap fxBitmap) {
+ mFxBitmap = fxBitmap;
+ }
+
+ public int getNameResource() {
+ return mNameResource;
+ }
+
+ public void setNameResource(int nameResource) {
+ mNameResource = nameResource;
+ }
+
+ public int getBitmapResource() {
+ return mBitmapResource;
+ }
+
+ public void setBitmapResource(int bitmapResource) {
+ mBitmapResource = bitmapResource;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
new file mode 100644
index 000000000..99c809148
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+
+public class FilterImageBorderRepresentation extends FilterRepresentation {
+ private int mDrawableResource = 0;
+
+ public FilterImageBorderRepresentation(int drawableResource) {
+ super("ImageBorder");
+ mDrawableResource = drawableResource;
+ setFilterClass(ImageFilterBorder.class);
+ setPriority(FilterRepresentation.TYPE_BORDER);
+ setTextId(R.string.borders);
+ setEditorId(ImageOnlyEditor.ID);
+ setShowEditingControls(false);
+ setShowParameterValue(false);
+ setShowUtilityPanel(false);
+ // load the drawable at init as we are in a background thread
+ // (see FilterShowActivity's LoadBordersTask)
+ ImageFilterBorder filter = (ImageFilterBorder) FiltersManager.getManager().getFilter(getFilterClass());
+ filter.getDrawable(getDrawableResource());
+ }
+
+ public String toString() {
+ return "FilterBorder: " + getName();
+ }
+
+ @Override
+ public FilterRepresentation clone() throws CloneNotSupportedException {
+ FilterImageBorderRepresentation representation = (FilterImageBorderRepresentation) super.clone();
+ representation.setName(getName());
+ representation.setDrawableResource(getDrawableResource());
+ return representation;
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterImageBorderRepresentation) {
+ FilterImageBorderRepresentation representation = (FilterImageBorderRepresentation) a;
+ setName(representation.getName());
+ setDrawableResource(representation.getDrawableResource());
+ }
+ }
+
+ @Override
+ public boolean equals(FilterRepresentation representation) {
+ if (!super.equals(representation)) {
+ return false;
+ }
+ if (representation instanceof FilterImageBorderRepresentation) {
+ FilterImageBorderRepresentation border = (FilterImageBorderRepresentation) representation;
+ if (border.mDrawableResource == mDrawableResource) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getTextId() {
+ return R.string.borders;
+ }
+
+ public boolean allowsMultipleInstances() {
+ return true;
+ }
+
+ public int getDrawableResource() {
+ return mDrawableResource;
+ }
+
+ public void setDrawableResource(int drawableResource) {
+ mDrawableResource = drawableResource;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterPoint.java b/src/com/android/gallery3d/filtershow/filters/FilterPoint.java
new file mode 100644
index 000000000..4520717a1
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterPoint.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+public interface FilterPoint {
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java
new file mode 100644
index 000000000..fc01650ae
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+import java.util.Vector;
+
+public abstract class FilterPointRepresentation extends FilterRepresentation {
+ private static final String LOGTAG = "FilterPointRepresentation";
+ private Vector<FilterPoint> mCandidates = new Vector<FilterPoint>();
+
+ public FilterPointRepresentation(String type, int textid, int editorID) {
+ super(type);
+ setFilterClass(ImageFilterRedEye.class);
+ setPriority(FilterRepresentation.TYPE_NORMAL);
+ setTextId(textid);
+ setEditorId(editorID);
+ }
+
+ @Override
+ public FilterRepresentation clone() throws CloneNotSupportedException {
+ FilterPointRepresentation representation = (FilterPointRepresentation) super
+ .clone();
+ representation.mCandidates = (Vector<FilterPoint>) mCandidates.clone();
+ return representation;
+ }
+
+ public boolean hasCandidates() {
+ return mCandidates != null;
+ }
+
+ public Vector<FilterPoint> getCandidates() {
+ return mCandidates;
+ }
+
+ @Override
+ public boolean isNil() {
+ if (getCandidates() != null && getCandidates().size() > 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public Object getCandidate(int index) {
+ return this.mCandidates.get(index);
+ }
+
+ public void addCandidate(FilterPoint c) {
+ this.mCandidates.add(c);
+ }
+
+ @Override
+ public void useParametersFrom(FilterRepresentation a) {
+ if (a instanceof FilterPointRepresentation) {
+ FilterPointRepresentation representation = (FilterPointRepresentation) a;
+ mCandidates.clear();
+ for (FilterPoint redEyeCandidate : representation.mCandidates) {
+ mCandidates.add(redEyeCandidate);
+ }
+ }
+ }
+
+ public void removeCandidate(RedEyeCandidate c) {
+ this.mCandidates.remove(c);
+ }
+
+ public void clearCandidates() {
+ this.mCandidates.clear();
+ }
+
+ public int getNumberOfCandidates() {
+ return mCandidates.size();
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java
new file mode 100644
index 000000000..70d016f69
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+import android.graphics.RectF;
+import android.util.Log;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorRedEye;
+
+import java.util.Vector;
+
+public class FilterRedEyeRepresentation extends FilterPointRepresentation {
+ private static final String LOGTAG = "FilterRedEyeRepresentation";
+
+ public FilterRedEyeRepresentation() {
+ super("RedEye",R.string.redeye,EditorRedEye.ID);
+ setFilterClass(ImageFilterRedEye.class);
+ setOverlayId(R.drawable.photoeditor_effect_redeye);
+ }
+
+ public void addRect(RectF rect, RectF bounds) {
+ Vector<RedEyeCandidate> intersects = new Vector<RedEyeCandidate>();
+ for (int i = 0; i < getCandidates().size(); i++) {
+ RedEyeCandidate r = (RedEyeCandidate) getCandidate(i);
+ if (r.intersect(rect)) {
+ intersects.add(r);
+ }
+ }
+ for (int i = 0; i < intersects.size(); i++) {
+ RedEyeCandidate r = intersects.elementAt(i);
+ rect.union(r.mRect);
+ bounds.union(r.mBounds);
+ removeCandidate(r);
+ }
+ addCandidate(new RedEyeCandidate(rect, bounds));
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
new file mode 100644
index 000000000..513cdcdef
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+import com.android.gallery3d.app.Log;
+import com.android.gallery3d.filtershow.editors.BasicEditor;
+import com.android.gallery3d.filtershow.presets.ImagePreset;
+
+public class FilterRepresentation implements Cloneable {
+ private static final String LOGTAG = "FilterRepresentation";
+ private String mName;
+ private int mPriority = TYPE_NORMAL;
+ private Class mFilterClass;
+ private int mTextId = 0;
+ private int mEditorId = BasicEditor.ID;
+ private int mButtonId = 0;
+ private int mOverlayId = 0;
+ private boolean mShowEditingControls = true;
+ private boolean mShowParameterValue = true;
+ private boolean mShowUtilityPanel = true;
+
+ public static final byte TYPE_BORDER = 1;
+ public static final byte TYPE_FX = 2;
+ public static final byte TYPE_WBALANCE = 3;
+ public static final byte TYPE_VIGNETTE = 4;
+ public static final byte TYPE_NORMAL = 5;
+ public static final byte TYPE_TINYPLANET = 6;
+
+ public FilterRepresentation mTempRepresentation = null;
+
+ public FilterRepresentation(String name) {
+ mName = name;
+ }
+
+ @Override
+ public FilterRepresentation clone() throws CloneNotSupportedException {
+ FilterRepresentation representation = (FilterRepresentation) super.clone();
+ representation.setName(getName());
+ representation.setPriority(getPriority());
+ representation.setFilterClass(getFilterClass());
+ representation.setTextId(getTextId());
+ representation.setEditorId(getEditorId());
+ representation.setButtonId(getButtonId());
+ representation.setOverlayId(getOverlayId());
+ representation.setShowEditingControls(showEditingControls());
+ representation.setShowParameterValue(showParameterValue());
+ representation.setShowUtilityPanel(showUtilityPanel());
+ Log.v(LOGTAG, "cloning from <" + this + "> to <" + representation + ">");
+ return representation;
+ }
+
+ public boolean equals(FilterRepresentation representation) {
+ if (representation == null) {
+ return false;
+ }
+ if (representation.mFilterClass == representation.mFilterClass
+ && representation.mName.equalsIgnoreCase(mName)
+ && representation.mPriority == mPriority
+ && representation.mTextId == mTextId
+ && representation.mEditorId == mEditorId
+ && representation.mButtonId == mButtonId
+ && representation.mOverlayId == mOverlayId
+ && representation.mShowEditingControls == mShowEditingControls
+ && representation.mShowParameterValue == mShowParameterValue
+ && representation.mShowUtilityPanel == mShowUtilityPanel) {
+ return true;
+ }
+ return false;
+ }
+
+ public String toString() {
+ return mName;
+ }
+
+ public void setName(String name) {
+ mName = name;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public void setPriority(int priority) {
+ mPriority = priority;
+ }
+
+ public int getPriority() {
+ return mPriority;
+ }
+
+ public boolean isNil() {
+ return false;
+ }
+
+ public void useParametersFrom(FilterRepresentation a) {
+ }
+
+ public synchronized void updateTempParametersFrom(FilterRepresentation representation) {
+ if (mTempRepresentation == null) {
+ try {
+ mTempRepresentation = representation.clone();
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ } else {
+ mTempRepresentation.useParametersFrom(representation);
+ }
+ }
+
+ public synchronized void synchronizeRepresentation() {
+ if (mTempRepresentation != null) {
+ useParametersFrom(mTempRepresentation);
+ }
+ }
+
+ public boolean allowsMultipleInstances() {
+ return false;
+ }
+
+ public Class getFilterClass() {
+ return mFilterClass;
+ }
+
+ public void setFilterClass(Class filterClass) {
+ mFilterClass = filterClass;
+ }
+
+ public boolean same(FilterRepresentation b) {
+ if (b == null) {
+ return false;
+ }
+ return getFilterClass() == b.getFilterClass();
+ }
+
+ public int getTextId() {
+ return mTextId;
+ }
+
+ public void setTextId(int textId) {
+ mTextId = textId;
+ }
+
+ public int getButtonId() {
+ return mButtonId;
+ }
+
+ public void setButtonId(int buttonId) {
+ mButtonId = buttonId;
+ }
+
+ public int getOverlayId() {
+ return mOverlayId;
+ }
+
+ public void setOverlayId(int overlayId) {
+ mOverlayId = overlayId;
+ }
+
+ public int getEditorId() {
+ return mEditorId;
+ }
+
+ public void setEditorId(int editorId) {
+ mEditorId = editorId;
+ }
+
+ public boolean showEditingControls() {
+ return mShowEditingControls;
+ }
+
+ public void setShowEditingControls(boolean showEditingControls) {
+ mShowEditingControls = showEditingControls;
+ }
+
+ public boolean showParameterValue() {
+ return mShowParameterValue;
+ }
+
+ public void setShowParameterValue(boolean showParameterValue) {
+ mShowParameterValue = showParameterValue;
+ }
+
+ public boolean showUtilityPanel() {
+ return mShowUtilityPanel;
+ }
+
+ public void setShowUtilityPanel(boolean showUtilityPanel) {
+ mShowUtilityPanel = showUtilityPanel;
+ }
+
+ public String getStateRepresentation() {
+ return "";
+ }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java
new file mode 100644
index 000000000..7b69ce9e0
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 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.filtershow.filters;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
+
+public class FilterTinyPlanetRepresentation extends FilterBasicRepresentation {
+ private static final String LOGTAG = "FilterTinyPlanetRepresentation";
+ private float mAngle = 0;
+
+ public FilterTinyPlanetRepresentation() {
+ super("TinyPlanet", 0, 50, 100);
+ setShowParameterValue(true);
+ setFilterClass(ImageFilterTinyPlanet.class);
+ setPriority(FilterRepresentation.TYPE_TINYPLANET);
+ setTextId(R.string.tinyplanet);
+ setButtonId(R.id.tinyplanetButton);
+ setEditorId(EditorTinyPlanet.ID);
+ }
+
+ @Override
+ public FilterRepresentation clone() throws CloneNotSupportedException {
+ FilterTinyPlanetRepresentation representation = (FilterTinyPlanetRepresentation) super
+ .clone();
+ representation.mAngle = mAngle;
+ representation.setZoom(getZoom());
+ return representation;
+ }
+
+ public void setAngle(float angle) {
+ mAngle = angle;
+ }
+
+ public float getAngle() {
+ return mAngle;
+ }
+
+ public int getZoom() {
+ return getValue();
+ }
+
+ public void setZoom(int zoom) {
+ setValue(zoom);
+ }
+
+ public boolean isNil() {
+ // TinyPlanet always has an effect
+ return false;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
index a261031c3..614c6a01d 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
@@ -17,94 +17,19 @@
package com.android.gallery3d.filtershow.filters;
import android.graphics.Bitmap;
+import android.graphics.Matrix;
import com.android.gallery3d.R;
import com.android.gallery3d.filtershow.editors.BasicEditor;
+import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
import com.android.gallery3d.filtershow.presets.ImagePreset;
-public class ImageFilter implements Cloneable {
+public abstract class ImageFilter implements Cloneable {
- public static int DEFAULT_MAX_PARAMETER = 100;
- public static int DEFAULT_MIN_PARAMETER = -100;
- public static int DEFAULT_INITIAL_PARAMETER = 0;
-
- protected int mMaxParameter = DEFAULT_MAX_PARAMETER;
- protected int mMinParameter = DEFAULT_MIN_PARAMETER;
- protected int mPreviewParameter = mMaxParameter;
- protected int mDefaultParameter = DEFAULT_INITIAL_PARAMETER;
- protected int mParameter = DEFAULT_INITIAL_PARAMETER;
private ImagePreset mImagePreset;
protected String mName = "Original";
private final String LOGTAG = "ImageFilter";
- public static final byte TYPE_BORDER = 1;
- public static final byte TYPE_FX = 2;
- public static final byte TYPE_WBALANCE = 3;
- public static final byte TYPE_VIGNETTE = 4;
- public static final byte TYPE_NORMAL = 5;
- public static final byte TYPE_TINYPLANET = 6;
- private byte filterType = TYPE_NORMAL;
-
- public byte getFilterType() {
- return filterType;
- }
-
- protected void setFilterType(byte type) {
- filterType = type;
- }
-
- public int getButtonId() {
- return 0;
- }
-
- public int getTextId() {
- return 0;
- }
-
- public int getOverlayBitmaps() {
- return 0;
- }
-
- public int getEditingViewId() {
- return BasicEditor.ID;
- }
-
- public boolean showEditingControls() {
- return true;
- }
-
- public boolean showParameterValue() {
- return true;
- }
-
- public boolean showUtilityPanel() {
- return true;
- }
-
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilter filter = (ImageFilter) super.clone();
- filter.setName(getName());
- filter.setParameter(getParameter());
- filter.setFilterType(filterType);
- filter.mMaxParameter = mMaxParameter;
- filter.mMinParameter = mMinParameter;
- filter.mImagePreset = mImagePreset;
- filter.mDefaultParameter = mDefaultParameter;
- filter.mPreviewParameter = mPreviewParameter;
- return filter;
- }
-
- public void reset() {
- setParameter(mDefaultParameter);
- }
-
- public boolean isNil() {
- if (mParameter == mDefaultParameter) {
- return true;
- }
- return false;
- }
public void setName(String name) {
mName = name;
@@ -114,7 +39,7 @@ public class ImageFilter implements Cloneable {
return mName;
}
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
// do nothing here, subclasses will implement filtering here
return bitmap;
}
@@ -123,86 +48,33 @@ public class ImageFilter implements Cloneable {
* Called on small bitmaps to create button icons for each filter.
* Override this to provide filter-specific button icons.
*/
- public Bitmap iconApply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
- int param = getParameter();
- setParameter(getPreviewParameter());
- bitmap = apply(bitmap, scaleFactor, highQuality);
- setParameter(param);
- return bitmap;
- }
-
- public int getParameter() {
- return mParameter;
- }
-
- public void setParameter(int value) {
- mParameter = value;
- }
-
- /**
- * The maximum allowed value (inclusive)
- * @return maximum value allowed as input to this filter
- */
- public int getMaxParameter() {
- return mMaxParameter;
- }
-
- /**
- * The parameter value to be used in previews.
- * @return parameter value to be used to preview the filter
- */
- public int getPreviewParameter() {
- return mPreviewParameter;
- }
-
- /**
- * The minimum allowed value (inclusive)
- * @return minimum value allowed as input to this filter
- */
- public int getMinParameter() {
- return mMinParameter;
- }
-
- /**
- * Returns the default value returned by this filter.
- * @return default value
- */
- public int getDefaultParameter() {
- return mDefaultParameter;
+ public Bitmap iconApply(Bitmap bitmap, float scaleFactor, int quality) {
+ return apply(bitmap, scaleFactor, quality);
}
public ImagePreset getImagePreset() {
return mImagePreset;
}
- public void setImagePreset(ImagePreset mPreset) {
- this.mImagePreset = mPreset;
- }
-
- public boolean equals(ImageFilter filter) {
- if (!same(filter)) {
- return false;
- }
- if (mParameter != filter.mParameter) {
- return false;
- }
- return true;
+ public void setImagePreset(ImagePreset imagePreset) {
+ mImagePreset = imagePreset;
}
- public boolean same(ImageFilter filter) {
- if (filter == null) {
- return false;
- }
- if (!filter.getName().equalsIgnoreCase(getName())) {
- return false;
- }
- return true;
- }
+ public abstract void useRepresentation(FilterRepresentation representation);
native protected void nativeApplyGradientFilter(Bitmap bitmap, int w, int h,
int[] redGradient, int[] greenGradient, int[] blueGradient);
- public void useFilter(ImageFilter a) {
- setParameter(a.getParameter());
+ public FilterRepresentation getDefaultRepresentation() {
+ return null;
+ }
+
+ protected Matrix getOriginalToScreenMatrix(int w, int h) {
+ GeometryMetadata geo = getImagePreset().mGeoData;
+ Matrix originalToScreen = geo.getOriginalToScreen(true,
+ getImagePreset().getImageLoader().getOriginalBounds().width(),
+ getImagePreset().getImageLoader().getOriginalBounds().height(),
+ w, h);
+ return originalToScreen;
}
}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
index 4fe308294..70e7f2220 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
@@ -16,78 +16,38 @@
package com.android.gallery3d.filtershow.filters;
+import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+
+import java.util.HashMap;
public class ImageFilterBorder extends ImageFilter {
private static final float NINEPATCH_ICON_SCALING = 10;
private static final float BITMAP_ICON_SCALING = 1 / 3.0f;
- Drawable mNinePatch = null;
+ private FilterImageBorderRepresentation mParameters = null;
+ private Resources mResources = null;
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilterBorder filter = (ImageFilterBorder) super.clone();
- filter.setDrawable(mNinePatch);
- return filter;
- }
+ private HashMap<Integer, Drawable> mDrawables = new HashMap<Integer, Drawable>();
- public ImageFilterBorder(Drawable ninePatch) {
- setFilterType(TYPE_BORDER);
+ public ImageFilterBorder() {
mName = "Border";
- mNinePatch = ninePatch;
- }
-
- @Override
- public boolean isNil() {
- if (mNinePatch == null) {
- return true;
- }
- return false;
- }
-
- @Override
- public int getTextId() {
- return R.string.borders;
- }
-
- @Override
- public boolean showParameterValue() {
- return false;
- }
-
- @Override
- public boolean showEditingControls() {
- return false;
- }
-
- @Override
- public boolean showUtilityPanel() {
- return false;
}
- @Override
- public boolean same(ImageFilter filter) {
- boolean isBorderFilter = super.same(filter);
- if (!isBorderFilter) {
- return false;
- }
- if (!(filter instanceof ImageFilterBorder)) {
- return false;
- }
- ImageFilterBorder borderFilter = (ImageFilterBorder) filter;
- if (mNinePatch != borderFilter.mNinePatch) {
- return false;
- }
- return true;
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterImageBorderRepresentation parameters = (FilterImageBorderRepresentation) representation;
+ mParameters = parameters;
}
- public void setDrawable(Drawable ninePatch) {
- // TODO: for now we only use nine patch
- mNinePatch = ninePatch;
+ public FilterImageBorderRepresentation getParameters() {
+ return mParameters;
}
public Bitmap applyHelper(Bitmap bitmap, float scale1, float scale2 ) {
@@ -96,14 +56,15 @@ public class ImageFilterBorder extends ImageFilter {
Rect bounds = new Rect(0, 0, (int) (w * scale1), (int) (h * scale1));
Canvas canvas = new Canvas(bitmap);
canvas.scale(scale2, scale2);
- mNinePatch.setBounds(bounds);
- mNinePatch.draw(canvas);
+ Drawable drawable = getDrawable(getParameters().getDrawableResource());
+ drawable.setBounds(bounds);
+ drawable.draw(canvas);
return bitmap;
}
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
- if (mNinePatch == null) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null || getParameters().getDrawableResource() == 0) {
return bitmap;
}
float scale2 = scaleFactor * 2.0f;
@@ -112,12 +73,29 @@ public class ImageFilterBorder extends ImageFilter {
}
@Override
- public Bitmap iconApply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
- if (mNinePatch == null) {
+ public Bitmap iconApply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null || getParameters().getDrawableResource() == 0) {
return bitmap;
}
float scale1 = NINEPATCH_ICON_SCALING;
float scale2 = BITMAP_ICON_SCALING;
return applyHelper(bitmap, scale1, scale2);
}
+
+ public void setResources(Resources resources) {
+ if (mResources != resources) {
+ mResources = resources;
+ mDrawables.clear();
+ }
+ }
+
+ public Drawable getDrawable(int rsc) {
+ Drawable drawable = mDrawables.get(rsc);
+ if (drawable == null && mResources != null && rsc != 0) {
+ drawable = new BitmapDrawable(mResources, BitmapFactory.decodeResource(mResources, rsc));
+ mDrawables.put(rsc, drawable);
+ }
+ return drawable;
+ }
+
}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
index 1bb5c76ac..c92ac012d 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
@@ -22,38 +22,34 @@ import android.graphics.Bitmap;
import android.graphics.Color;
-public class ImageFilterBwFilter extends ImageFilter {
+public class ImageFilterBwFilter extends SimpleImageFilter {
public ImageFilterBwFilter() {
mName = "BW Filter";
- mMaxParameter = 180;
- mMinParameter = -180;
}
- @Override
- public int getButtonId() {
- return R.id.bwfilterButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.bwfilter;
- }
-
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilterBwFilter filter = (ImageFilterBwFilter) super.clone();
- return filter;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("BW Filter");
+ representation.setFilterClass(ImageFilterBwFilter.class);
+ representation.setMaximum(180);
+ representation.setMinimum(-180);
+ representation.setTextId(R.string.bwfilter);
+ representation.setButtonId(R.id.bwfilterButton);
+ return representation;
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, int r, int g, int b);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
float[] hsv = new float[] {
- 180 + mParameter, 1, 1
+ 180 + getParameters().getValue(), 1, 1
};
int rgb = Color.HSVToColor(hsv);
int r = 0xFF & (rgb >> 16);
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
index 70e3d8589..2f94e3d17 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
@@ -20,30 +20,36 @@ import com.android.gallery3d.R;
import android.graphics.Bitmap;
-public class ImageFilterContrast extends ImageFilter {
+public class ImageFilterContrast extends SimpleImageFilter {
public ImageFilterContrast() {
mName = "Contrast";
}
- @Override
- public int getButtonId() {
- return R.id.contrastButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.contrast;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Contrast");
+ representation.setFilterClass(ImageFilterContrast.class);
+ representation.setTextId(R.string.contrast);
+ representation.setButtonId(R.id.contrastButton);
+
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ return representation;
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float strength);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- float p = mParameter;
- float value = p;
+ float value = getParameters().getValue();
nativeApplyFilter(bitmap, w, h, value);
return bitmap;
}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java
index b7e5c2ae6..aa4cf22e6 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java
@@ -25,82 +25,26 @@ import com.android.gallery3d.filtershow.ui.Spline;
public class ImageFilterCurves extends ImageFilter {
private static final String LOGTAG = "ImageFilterCurves";
- private Spline[] mSplines = new Spline[4];
-
- public ImageFilterCurves() {
- mName = "Curves";
- reset();
- }
-
- @Override
- public int getButtonId() {
- return R.id.curvesButtonRGB;
- }
-
- @Override
- public int getTextId() {
- return R.string.curvesRGB;
- }
-
- @Override
- public int getOverlayBitmaps() {
- return R.drawable.filtershow_button_colors_curve;
- }
-
- @Override
- public int getEditingViewId() {
- return R.id.imageCurves;
- }
+ FilterCurvesRepresentation mParameters = new FilterCurvesRepresentation();
@Override
- public boolean showParameterValue() {
- return false;
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterCurvesRepresentation();
}
@Override
- public boolean equals(ImageFilter filter) {
- return same(filter);
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterCurvesRepresentation parameters = (FilterCurvesRepresentation) representation;
+ mParameters = parameters;
}
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilterCurves filter = (ImageFilterCurves) super.clone();
- filter.mSplines = new Spline[4];
- for (int i = 0; i < 4; i++) {
- if (mSplines[i] != null) {
- filter.setSpline(mSplines[i], i);
- }
- }
- return filter;
- }
-
- @Override
- public boolean isNil() {
- for (int i = 0; i < 4; i++) {
- if (mSplines[i] != null && !mSplines[i].isOriginal()) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public boolean same(ImageFilter filter) {
- boolean isCurveFilter = super.same(filter);
- if (!isCurveFilter) {
- return false;
- }
- ImageFilterCurves curve = (ImageFilterCurves) filter;
- for (int i = 0; i < 4; i++) {
- if (mSplines[i] != curve.mSplines[i]) {
- return false;
- }
- }
- return true;
+ public ImageFilterCurves() {
+ mName = "Curves";
+ reset();
}
public void populateArray(int[] array, int curveIndex) {
- Spline spline = mSplines[curveIndex];
+ Spline spline = mParameters.getSpline(curveIndex);
if (spline == null) {
return;
}
@@ -111,8 +55,8 @@ public class ImageFilterCurves extends ImageFilter {
}
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
- if (!mSplines[Spline.RGB].isOriginal()) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (!mParameters.getSpline(Spline.RGB).isOriginal()) {
int[] rgbGradient = new int[256];
populateArray(rgbGradient, Spline.RGB);
nativeApplyGradientFilter(bitmap, bitmap.getWidth(), bitmap.getHeight(),
@@ -120,17 +64,17 @@ public class ImageFilterCurves extends ImageFilter {
}
int[] redGradient = null;
- if (!mSplines[Spline.RED].isOriginal()) {
+ if (!mParameters.getSpline(Spline.RED).isOriginal()) {
redGradient = new int[256];
populateArray(redGradient, Spline.RED);
}
int[] greenGradient = null;
- if (!mSplines[Spline.GREEN].isOriginal()) {
+ if (!mParameters.getSpline(Spline.GREEN).isOriginal()) {
greenGradient = new int[256];
populateArray(greenGradient, Spline.GREEN);
}
int[] blueGradient = null;
- if (!mSplines[Spline.BLUE].isOriginal()) {
+ if (!mParameters.getSpline(Spline.BLUE).isOriginal()) {
blueGradient = new int[256];
populateArray(blueGradient, Spline.BLUE);
}
@@ -141,14 +85,13 @@ public class ImageFilterCurves extends ImageFilter {
}
public void setSpline(Spline spline, int splineIndex) {
- mSplines[splineIndex] = new Spline(spline);
+ mParameters.setSpline(splineIndex, new Spline(spline));
}
public Spline getSpline(int splineIndex) {
- return mSplines[splineIndex];
+ return mParameters.getSpline(splineIndex);
}
- @Override
public void reset() {
Spline spline = new Spline();
@@ -156,16 +99,15 @@ public class ImageFilterCurves extends ImageFilter {
spline.addPoint(1.0f, 0.0f);
for (int i = 0; i < 4; i++) {
- mSplines[i] = new Spline(spline);
+ mParameters.setSpline(i, new Spline(spline));
}
}
- @Override
public void useFilter(ImageFilter a) {
ImageFilterCurves c = (ImageFilterCurves) a;
for (int i = 0; i < 4; i++) {
- if (c.mSplines[i] != null) {
- setSpline(c.mSplines[i], i);
+ if (c.mParameters.getSpline(i) != null) {
+ setSpline(c.mParameters.getSpline(i), i);
}
}
}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
index 784028a8d..906467344 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
@@ -23,40 +23,37 @@ import android.graphics.Rect;
import com.android.gallery3d.R;
import com.android.gallery3d.filtershow.cache.ImageLoader;
-public class ImageFilterDownsample extends ImageFilter {
+public class ImageFilterDownsample extends SimpleImageFilter {
private static final int ICON_DOWNSAMPLE_FRACTION = 8;
private ImageLoader mImageLoader;
public ImageFilterDownsample(ImageLoader loader) {
mName = "Downsample";
- mMaxParameter = 100;
- mMinParameter = 1;
- mPreviewParameter = 3;
- mDefaultParameter = 50;
- mParameter = 50;
mImageLoader = loader;
}
- @Override
- public int getButtonId() {
- return R.id.downsampleButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.downsample;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Downsample");
+ representation.setFilterClass(ImageFilterDownsample.class);
+ representation.setMaximum(100);
+ representation.setMinimum(1);
+ representation.setValue(50);
+ representation.setDefaultValue(50);
+ representation.setPreviewValue(3);
+ representation.setTextId(R.string.downsample);
+ representation.setButtonId(R.id.downsampleButton);
+ return representation;
}
@Override
- public boolean isNil() {
- return false;
- }
-
- @Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- int p = mParameter;
+ int p = getParameters().getValue();
// size of original precached image
Rect size = mImageLoader.getOriginalBounds();
@@ -82,7 +79,7 @@ public class ImageFilterDownsample extends ImageFilter {
}
@Override
- public Bitmap iconApply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap iconApply(Bitmap bitmap, float scaleFactor, int quality) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Bitmap ret = Bitmap.createScaledBitmap(bitmap, w / ICON_DOWNSAMPLE_FRACTION, h
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
index 3177d2473..6d7614ec9 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
@@ -17,6 +17,7 @@
package com.android.gallery3d.filtershow.filters;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
@@ -24,463 +25,252 @@ import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PathMeasure;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
+import android.util.Log;
import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.editors.EditorDraw;
+import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation.StrokeData;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.presets.ImagePreset;
-import java.util.Arrays;
+import java.util.Vector;
public class ImageFilterDraw extends ImageFilter {
private static final String LOGTAG = "ImageFilterDraw";
- public final static char SIMPLE_STYLE = 0;
- public final static char BRUSH_STYLE = 1;
+ public final static byte SIMPLE_STYLE = 0;
+ public final static byte BRUSH_STYLE_SPATTER = 1;
+ public final static byte BRUSH_STYLE_MARKER = 2;
+ public final static int NUMBER_OF_STYLES = 3;
Bitmap mOverlayBitmap; // this accelerates interaction
int mCachedStrokes = -1;
int mCurrentStyle = 0;
- DrawStyle[] mDrawings = new DrawStyle[] {
- new SimpleDraw(), new Brush() };
- public void setStyle(char style) {
- mCurrentStyle = style;
+ FilterDrawRepresentation mParameters = new FilterDrawRepresentation();
+
+ public ImageFilterDraw() {
+ mName = "Image Draw";
}
- public static interface DrawStyle {
- public DrawStyle clone();
- public void setSize(float radius);
- public void setColor(int color);
- public void startStroke(float x, float y);
- public void stroke(float x, float y);
- public void endStroke(float x, float y);
- public int getNumberOfStrokes();
- public void clearCurren();
- public void paintCurrentStroke(Canvas canvas, Matrix toScrMatrix, boolean highQuality);
- public int paintLast(int from, Canvas canvas, Matrix toScrMatrix, boolean highQuality);
- public boolean same(DrawStyle o);
- public boolean empty();
+ DrawStyle[] mDrawingsTypes = new DrawStyle[] {
+ new SimpleDraw(),
+ new Brush(R.drawable.brush_marker),
+ new Brush(R.drawable.brush_spatter)
};
+ {
+ for (int i = 0; i < mDrawingsTypes.length; i++) {
+ mDrawingsTypes[i].setType((byte) i);
+ }
- class SimpleDraw implements DrawStyle {
- private Path[] mPaths = new Path[0];
- private int[] mColors = new int[0];
- private float[] mRadius = new float[0];
- private int mStrokeCnt = 0;
+ }
- private Path mCurrentPath;
- private float mCurrentRadius;
- private int mCurrentColor;
+ @Override
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterDrawRepresentation();
+ }
- @Override
- public DrawStyle clone() {
- SimpleDraw ret = new SimpleDraw();
- ret.mPaths = new Path[mPaths.length];
- for (int i = 0; i < ret.mPaths.length; i++) {
- ret.mPaths[i] = new Path(mPaths[i]);
- }
- ret.mColors = Arrays.copyOf(mColors, mColors.length);
- ret.mRadius = Arrays.copyOf(mRadius, mRadius.length);
- ret.mStrokeCnt = mStrokeCnt;
- return ret;
- }
+ @Override
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterDrawRepresentation parameters = (FilterDrawRepresentation) representation;
+ mParameters = parameters;
+ }
- @Override
- public boolean empty() {
- return mStrokeCnt == -1;
- }
+ public void setStyle(byte style) {
+ mCurrentStyle = style % mDrawingsTypes.length;
+ }
- @Override
- public void setSize(float radius) {
- mCurrentRadius = radius;
- }
+ public int getStyle() {
+ return mCurrentStyle;
+ }
- @Override
- public void setColor(int color) {
- mCurrentColor = color;
- }
+ public static interface DrawStyle {
+ public void setType(byte type);
+ public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
+ int quality);
+ }
- @Override
- public void startStroke(float x, float y) {
- mCurrentPath = new Path();
- mCurrentPath.moveTo(x, y);
- }
+ class SimpleDraw implements DrawStyle {
+ byte mType;
@Override
- public void stroke(float x, float y) {
- if (mCurrentPath != null) {
- mCurrentPath.lineTo(x, y);
- }
+ public void setType(byte type) {
+ mType = type;
}
@Override
- public void endStroke(float x, float y) {
- if (mCurrentPath != null) {
- mCurrentPath.lineTo(x, y);
- Path[] np = new Path[mStrokeCnt + 1];
- for (int i = 0; i < mStrokeCnt; i++) {
- np[i] = mPaths[i];
- }
- np[mStrokeCnt] = mCurrentPath;
- mColors = Arrays.copyOf(mColors, mColors.length + 1);
- mRadius = Arrays.copyOf(mRadius, mRadius.length + 1);
- mRadius[mStrokeCnt] = mCurrentRadius;
- mColors[mStrokeCnt] = mCurrentColor;
- mPaths = np;
- mStrokeCnt++;
+ public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
+ int quality) {
+ if (sd == null) {
+ return;
}
- }
-
- @Override
- public void clearCurren(){
- mCurrentPath = null;
- }
-
- @Override
- public void paintCurrentStroke(Canvas canvas, Matrix toScrMatrix, boolean highQuality) {
- Path path = mCurrentPath;
- if (path == null) {
+ if (sd.mPath == null) {
return;
}
Paint paint = new Paint();
paint.setStyle(Style.STROKE);
- paint.setColor(mCurrentColor);
- paint.setStrokeWidth(toScrMatrix.mapRadius(mCurrentRadius));
+ paint.setColor(sd.mColor);
+ paint.setStrokeWidth(toScrMatrix.mapRadius(sd.mRadius));
- // don this way because a bug in path.transform(matrix)
+ // done this way because of a bug in path.transform(matrix)
Path mCacheTransPath = new Path();
- mCacheTransPath.addPath(path, toScrMatrix);
+ mCacheTransPath.addPath(sd.mPath, toScrMatrix);
canvas.drawPath(mCacheTransPath, paint);
}
-
- @Override
- public int paintLast(int from, Canvas canvas, Matrix toScrMatrix, boolean highQuality) {
- Paint paint = new Paint();
- Matrix m = new Matrix();
- canvas.save();
- canvas.concat(toScrMatrix);
- paint.setStyle(Style.STROKE);
- for (int i = from; i < mStrokeCnt; i++) {
- paint.setColor(mColors[i]);
- paint.setStrokeWidth(mRadius[i]);
- canvas.drawPath(mPaths[i], paint);
- }
- canvas.restore();
- return mStrokeCnt;
- }
-
- @Override
- public boolean same(DrawStyle o) {
- if (!(o instanceof SimpleDraw)) {
- return false;
- }
- SimpleDraw sd = (SimpleDraw) o;
- boolean same;
- same = Arrays.equals(mRadius, sd.mRadius);
- if (!same) {
- return false;
- }
- same = Arrays.equals(mColors, sd.mColors);
- if (!same) {
- return false;
- }
- for (int i = 0; i < mPaths.length; i++) {
- if (!mPaths[i].equals(sd.mPaths)) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public int getNumberOfStrokes() {
- return mStrokeCnt;
- }
}
class Brush implements DrawStyle {
- private Path[] mPaths = new Path[0];
- private int[] mColors = new int[0];
- private float[] mRadius = new float[0];
- private int mStrokeCnt = 0;
-
- private Path mCurrentPath;
- private float mCurrentRadius;
- private int mCurrentColor;
-
- @Override
- public DrawStyle clone() {
- Brush ret = new Brush();
- ret.mPaths = new Path[mPaths.length];
- for (int i = 0; i < ret.mPaths.length; i++) {
- ret.mPaths[i] = new Path(mPaths[i]);
- }
- ret.mColors = Arrays.copyOf(mColors, mColors.length);
- ret.mRadius = Arrays.copyOf(mRadius, mRadius.length);
- ret.mStrokeCnt = mStrokeCnt;
- return ret;
- }
-
- @Override
- public boolean empty() {
- return mStrokeCnt == -1;
- }
-
- @Override
- public void setSize(float radius) {
- mCurrentRadius = radius;
- }
-
- @Override
- public void setColor(int color) {
- mCurrentColor = color;
- }
-
- @Override
- public void startStroke(float x, float y) {
- mCurrentPath = new Path();
- mCurrentPath.moveTo(x, y);
- }
-
- @Override
- public void stroke(float x, float y) {
- if (mCurrentPath != null) {
- mCurrentPath.lineTo(x, y);
+ int mBrushID;
+ Bitmap mBrush;
+ byte mType;
+
+ public Brush(int brushID) {
+ mBrushID = brushID;
+ }
+ public Bitmap getBrush() {
+ if (mBrush == null) {
+ BitmapFactory.Options opt = new BitmapFactory.Options();
+ opt.inPreferredConfig = Bitmap.Config.ALPHA_8;
+ mBrush = MasterImage.getImage().getImageLoader().decodeImage(mBrushID, opt);
+ mBrush = mBrush.extractAlpha();
}
+ return mBrush;
}
@Override
- public void endStroke(float x, float y) {
- if (mCurrentPath != null) {
- mCurrentPath.lineTo(x, y);
- Path[] np = new Path[mStrokeCnt + 1];
- for (int i = 0; i < mStrokeCnt; i++) {
- np[i] = mPaths[i];
- }
- np[mStrokeCnt] = mCurrentPath;
- mColors = Arrays.copyOf(mColors, mColors.length + 1);
- mRadius = Arrays.copyOf(mRadius, mRadius.length + 1);
- mRadius[mStrokeCnt] = mCurrentRadius;
- mColors[mStrokeCnt] = mCurrentColor;
- mPaths = np;
- mStrokeCnt++;
- clearCurren();
- }
- }
-
- @Override
- public void clearCurren() {
- mCurrentPath = null;
- }
-
- @Override
- public void paintCurrentStroke(Canvas canvas, Matrix toScrMatrix, boolean highQuality) {
- Path path = mCurrentPath;
- if (path == null) {
+ public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
+ int quality) {
+ if (sd == null || sd.mPath == null) {
return;
}
Paint paint = new Paint();
paint.setStyle(Style.STROKE);
-
- float scale = toScrMatrix.mapRadius(1);
+ paint.setAntiAlias(true);
Path mCacheTransPath = new Path();
- mCacheTransPath.addPath(path, toScrMatrix);
- draw(canvas, paint, mCurrentColor, toScrMatrix.mapRadius(mCurrentRadius),
+ mCacheTransPath.addPath(sd.mPath, toScrMatrix);
+ draw(canvas, paint, sd.mColor, toScrMatrix.mapRadius(sd.mRadius) * 2,
mCacheTransPath);
}
- @Override
- public int paintLast(int from, Canvas canvas, Matrix toScrMatrix, boolean highQuality) {
- Paint paint = new Paint();
-
+ public Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
+ {
Matrix m = new Matrix();
- canvas.save();
- canvas.concat(toScrMatrix);
- paint.setStyle(Style.STROKE);
- for (int i = from; i < mStrokeCnt; i++) {
+ m.setScale(dstWidth / (float) src.getWidth(), dstHeight / (float) src.getHeight());
+ Bitmap result = Bitmap.createBitmap(dstWidth, dstHeight, src.getConfig());
+ Canvas canvas = new Canvas(result);
- draw(canvas, paint, mColors[i], mRadius[i], mPaths[i]);
- }
- canvas.restore();
- return mStrokeCnt;
- }
+ Paint paint = new Paint();
+ paint.setFilterBitmap(filter);
+ canvas.drawBitmap(src, m, paint);
- PathMeasure mPathMeasure = new PathMeasure();
+ return result;
+ }
void draw(Canvas canvas, Paint paint, int color, float size, Path path) {
+ PathMeasure mPathMeasure = new PathMeasure();
+ float[] mPosition = new float[2];
+ float[] mTan = new float[2];
mPathMeasure.setPath(path, false);
- float[] pos = new float[2];
- float[] tan = new float[2];
- paint.setColor(color);
- float len = mPathMeasure.getLength();
- for (float i = 0; i < len; i += (size) / 2) {
- mPathMeasure.getPosTan(i, pos, tan);
- canvas.drawCircle(pos[0], pos[1], size, paint);
- }
- }
+ paint.setAntiAlias(true);
+ paint.setColor(color);
- @Override
- public boolean same(DrawStyle o) {
- if (!(o instanceof Brush)) {
- return false;
- }
- Brush sd = (Brush) o;
- boolean same;
- same = Arrays.equals(mRadius, sd.mRadius);
- if (!same) {
- return false;
- }
- same = Arrays.equals(mColors, sd.mColors);
- if (!same) {
- return false;
- }
- for (int i = 0; i < mPaths.length; i++) {
- if (!mPaths[i].equals(sd.mPaths)) {
- return false;
- }
+ paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
+ Bitmap brush;
+ // done this way because of a bug in
+ // Bitmap.createScaledBitmap(getBrush(),(int) size,(int) size,true);
+ brush = createScaledBitmap(getBrush(), (int) size, (int) size, true);
+ float len = mPathMeasure.getLength();
+ float s2 = size / 2;
+ float step = s2 / 8;
+ for (float i = 0; i < len; i += step) {
+ mPathMeasure.getPosTan(i, mPosition, mTan);
+ // canvas.drawCircle(pos[0], pos[1], size, paint);
+ canvas.drawBitmap(brush, mPosition[0] - s2, mPosition[1] - s2, paint);
}
- return true;
}
@Override
- public int getNumberOfStrokes() {
- return mStrokeCnt;
+ public void setType(byte type) {
+ mType = type;
}
}
- public void startSection(int color, float size, float x, float y) {
- mDrawings[mCurrentStyle].setColor(color);
- mDrawings[mCurrentStyle].setSize(size);
- mDrawings[mCurrentStyle].startStroke(x, y);
+ void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix,
+ int quality) {
+ mDrawingsTypes[sd.mType].paint(sd, canvas, toScrMatrix, quality);
}
- public void addPoint(float x, float y) {
- mDrawings[mCurrentStyle].stroke(x, y);
- }
-
- public void endSection(float x, float y) {
- mDrawings[mCurrentStyle].endStroke(x, y);
- }
-
- public ImageFilterDraw() {
- mName = "Image Draw";
- }
-
- public void drawData(Canvas canvas, Matrix originalRotateToScreen, boolean highQuality) {
+ public void drawData(Canvas canvas, Matrix originalRotateToScreen, int quality) {
Paint paint = new Paint();
- if (highQuality) {
+ if (quality == ImagePreset.QUALITY_FINAL) {
paint.setAntiAlias(true);
}
paint.setStyle(Style.STROKE);
paint.setColor(Color.RED);
paint.setStrokeWidth(40);
- boolean empty = true;
- for (int i = 0; i < mDrawings.length; i++) {
- empty &= mDrawings[i].empty();
- }
- if (empty) {
+
+ if (mParameters.getDrawing().isEmpty() && mParameters.getCurrentDrawing() == null) {
return;
}
- if (highQuality) {
- for (int i = 0; i < mDrawings.length; i++) {
- mDrawings[i].paintLast(0, canvas, originalRotateToScreen, highQuality);
+ if (quality == ImagePreset.QUALITY_FINAL) {
+ for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) {
+ paint(strokeData, canvas, originalRotateToScreen, quality);
}
-
return;
}
+
if (mOverlayBitmap == null ||
mOverlayBitmap.getWidth() != canvas.getWidth() ||
- mOverlayBitmap.getHeight() != canvas.getHeight()) {
+ mOverlayBitmap.getHeight() != canvas.getHeight() ||
+ mParameters.getDrawing().size() < mCachedStrokes) {
mOverlayBitmap = Bitmap.createBitmap(
canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
mCachedStrokes = 0;
}
- if (mCachedStrokes < mDrawings[mCurrentStyle].getNumberOfStrokes()) {
+
+ if (mCachedStrokes < mParameters.getDrawing().size()) {
fillBuffer(originalRotateToScreen);
}
canvas.drawBitmap(mOverlayBitmap, 0, 0, paint);
- }
- public void fillBuffer(Matrix originalRotateToScreen) {
- Canvas drawCache = new Canvas(mOverlayBitmap);
- for (int i = 0; i < mDrawings.length; i++) {
-
- mCachedStrokes = mDrawings[i].paintLast(
- mCachedStrokes, drawCache, originalRotateToScreen, false);
+ StrokeData stroke = mParameters.getCurrentDrawing();
+ if (stroke != null) {
+ paint(stroke, canvas, originalRotateToScreen, quality);
}
}
- @Override
- public int getButtonId() {
- return R.id.drawOnImageButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.imageDraw;
- }
-
- @Override
- public int getEditingViewId() {
- return EditorDraw.ID;
- }
-
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilterDraw filter = (ImageFilterDraw) super.clone();
-
- filter.mDrawings = mDrawings.clone();
- return filter;
- }
-
- @Override
- public boolean isNil() {
- for (int i = 0; i < mDrawings.length; i++) {
- if (mDrawings[i].getNumberOfStrokes() != 0) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public boolean same(ImageFilter filter) {
- boolean isSuperSame = super.same(filter);
- if (!isSuperSame || !(filter instanceof ImageFilterDraw)) {
- return false;
- }
+ public void fillBuffer(Matrix originalRotateToScreen) {
+ Canvas drawCache = new Canvas(mOverlayBitmap);
+ Vector<FilterDrawRepresentation.StrokeData> v = mParameters.getDrawing();
+ int n = v.size();
- ImageFilterDraw dfilter = (ImageFilterDraw) filter;
- boolean same = true;
- for (int i = 0; i < mDrawings.length; i++) {
- same &= mDrawings[i].same(dfilter.mDrawings[i]);
+ for (int i = mCachedStrokes; i < n; i++) {
+ paint(v.get(i), drawCache, originalRotateToScreen, ImagePreset.QUALITY_PREVIEW);
}
- return same;
- }
-
- public void clear() {
- mDrawings[mCurrentStyle].clearCurren();
+ mCachedStrokes = n;
}
public void draw(Canvas canvas, Matrix originalRotateToScreen) {
- for (int i = 0; i < mDrawings.length; i++) {
- mDrawings[i].paintCurrentStroke(canvas, originalRotateToScreen, false);
+ for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) {
+ paint(strokeData, canvas, originalRotateToScreen, ImagePreset.QUALITY_PREVIEW);
}
+ mDrawingsTypes[mCurrentStyle].paint(
+ null, canvas, originalRotateToScreen, ImagePreset.QUALITY_PREVIEW);
}
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- short[] rect = new short[4];
-
- Matrix m = new Matrix();
- m.setScale(scaleFactor, scaleFactor);
-
- drawData(new Canvas(bitmap), m, highQuality);
+ Matrix m = getOriginalToScreenMatrix(w, h);
+ drawData(new Canvas(bitmap), m, quality);
return bitmap;
}
+
}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
index 9eda64874..55c709573 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
@@ -20,35 +20,31 @@ import android.graphics.Bitmap;
import com.android.gallery3d.R;
-public class ImageFilterEdge extends ImageFilter {
+public class ImageFilterEdge extends SimpleImageFilter {
public ImageFilterEdge() {
mName = "Edge";
- mPreviewParameter = 0;
}
- native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float p);
-
- @Override
- public int getButtonId() {
- return R.id.edgeButton;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterRepresentation representation = super.getDefaultRepresentation();
+ representation.setName("Edge");
+ representation.setFilterClass(ImageFilterEdge.class);
+ representation.setTextId(R.string.edge);
+ representation.setButtonId(R.id.edgeButton);
+ return representation;
}
- @Override
- public int getTextId() {
- return R.string.edge;
- }
-
- @Override
- public boolean isNil() {
- return false;
- }
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float p);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- float p = mParameter + 101;
+ float p = getParameters().getValue() + 101;
p = (float) p / 100;
nativeApplyFilter(bitmap, w, h, p);
return bitmap;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
index 63f860171..7a8df71af 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
@@ -20,30 +20,35 @@ import com.android.gallery3d.R;
import android.graphics.Bitmap;
-public class ImageFilterExposure extends ImageFilter {
+public class ImageFilterExposure extends SimpleImageFilter {
public ImageFilterExposure() {
mName = "Exposure";
}
- @Override
- public int getButtonId() {
- return R.id.exposureButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.exposure;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Exposure");
+ representation.setFilterClass(ImageFilterExposure.class);
+ representation.setTextId(R.string.exposure);
+ representation.setButtonId(R.id.exposureButton);
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ return representation;
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float bright);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- int p = mParameter;
- float value = p;
+ float value = getParameters().getValue();
nativeApplyFilter(bitmap, w, h, value);
return bitmap;
}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java
index 345202fe6..820ec3e51 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java
@@ -18,67 +18,40 @@ package com.android.gallery3d.filtershow.filters;
import android.graphics.Bitmap;
+import com.android.gallery3d.filtershow.editors.BasicEditor;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+
public class ImageFilterFx extends ImageFilter {
private static final String TAG = "ImageFilterFx";
- Bitmap fxBitmap;
- int mNameResource = 0;
+ private FilterFxRepresentation mParameters = null;
- public ImageFilterFx(Bitmap fxBitmap, String name, int nameResource) {
- setFilterType(TYPE_FX);
- mName = name;
- this.fxBitmap = fxBitmap;
- mNameResource = nameResource;
+ public ImageFilterFx() {
}
- @Override
- public int getTextId() {
- return mNameResource;
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterFxRepresentation parameters = (FilterFxRepresentation) representation;
+ mParameters = parameters;
}
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilterFx filter = (ImageFilterFx) super.clone();
- filter.fxBitmap = this.fxBitmap;
- return filter;
- }
-
- @Override
- public boolean isNil() {
- if (fxBitmap != null) {
- return false;
- }
- return true;
- }
-
- @Override
- public boolean showParameterValue() {
- return false;
- }
-
- @Override
- public boolean showEditingControls() {
- return false;
- }
-
- @Override
- public boolean showUtilityPanel() {
- return false;
+ public FilterFxRepresentation getParameters() {
+ return mParameters;
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h,Bitmap fxBitmap, int fxw, int fxh);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
- if (fxBitmap==null)
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null || getParameters().getFxBitmap() ==null) {
return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- int fxw = fxBitmap.getWidth();
- int fxh = fxBitmap.getHeight();
+ int fxw = getParameters().getFxBitmap().getWidth();
+ int fxh = getParameters().getFxBitmap().getHeight();
- nativeApplyFilter(bitmap, w, h, fxBitmap, fxw, fxh);
+ nativeApplyFilter(bitmap, w, h, getParameters().getFxBitmap(), fxw, fxh);
return bitmap;
}
}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java
index 33ecc8ab9..329ca81b9 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java
@@ -45,6 +45,7 @@ public class ImageFilterGeometry extends ImageFilter {
@Override
public ImageFilter clone() throws CloneNotSupportedException {
+ // FIXME: clone() should not be needed. Remove when we fix geometry.
ImageFilterGeometry filter = (ImageFilterGeometry) super.clone();
return filter;
}
@@ -66,7 +67,12 @@ public class ImageFilterGeometry extends ImageFilter {
Bitmap dst, int dstWidth, int dstHeight, float straightenAngle);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public void useRepresentation(FilterRepresentation representation) {
+
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
// TODO: implement bilinear or bicubic here... for now, just use
// canvas to do a simple implementation...
// TODO: and be more memory efficient! (do it in native?)
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterGradient.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterGradient.java
deleted file mode 100644
index be4ba871d..000000000
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterGradient.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2012 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.filtershow.filters;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.LinearGradient;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.Shader.TileMode;
-
-public class ImageFilterGradient extends ImageFilter {
-
- private Bitmap mGradientBitmap = null;
- private int[] mColors = null;
- private float[] mPositions = null;
-
- public ImageFilterGradient() {
- mName = "Gradient";
- }
-
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilterGradient filter = (ImageFilterGradient) super.clone();
- System.arraycopy(mColors, 0, filter.mColors, 0, mColors.length);
- System.arraycopy(mPositions, 0, filter.mPositions, 0, mPositions.length);
- return filter;
- }
-
- public void addColor(int color, float position) {
- int length = 0;
- if (mColors != null) {
- length = mColors.length;
- }
- int[] colors = new int[length + 1];
- float[] positions = new float[length + 1];
-
- for (int i = 0; i < length; i++) {
- colors[i] = mColors[i];
- positions[i] = mPositions[i];
- }
-
- colors[length] = color;
- positions[length] = position;
-
- mColors = colors;
- mPositions = positions;
- }
-
- @Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
- createGradient();
- int[] gradient = new int[256];
- int[] redGradient = new int[256];
- int[] greenGradient = new int[256];
- int[] blueGradient = new int[256];
- mGradientBitmap.getPixels(gradient, 0, 256, 0, 0, 256, 1);
-
- for (int i = 0; i < 256; i++) {
- redGradient[i] = Color.red(gradient[i]);
- greenGradient[i] = Color.green(gradient[i]);
- blueGradient[i] = Color.blue(gradient[i]);
- }
- nativeApplyGradientFilter(bitmap, bitmap.getWidth(), bitmap.getHeight(),
- redGradient, greenGradient, blueGradient);
- return bitmap;
- }
-
- public void createGradient() {
- if (mGradientBitmap != null) {
- return;
- }
-
- /* Create a 200 x 200 bitmap and fill it with black. */
- Bitmap b = Bitmap.createBitmap(256, 1, Config.ARGB_8888);
- Canvas c = new Canvas(b);
- c.drawColor(Color.BLACK);
-
- /* Create your gradient. */
-
- /*
- * int[] colors = new int[2]; colors[0] = Color.argb(255, 20, 20, 10);
- * colors[0] = Color.BLACK; colors[1] = Color.argb(255, 228, 231, 193);
- * float[] positions = new float[2]; positions[0] = 0; positions[1] = 1;
- */
-
- LinearGradient grad = new LinearGradient(0, 0, 255, 1, mColors,
- mPositions, TileMode.CLAMP);
-
- /* Draw your gradient to the top of your bitmap. */
- Paint p = new Paint();
- p.setStyle(Style.FILL);
- p.setShader(grad);
- c.drawRect(0, 0, 256, 1, p);
- mGradientBitmap = b;
- }
-
-}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
index 6b9869be3..8c484c72e 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
@@ -21,46 +21,37 @@ import com.android.gallery3d.filtershow.editors.BasicEditor;
import android.graphics.Bitmap;
-public class ImageFilterHue extends ImageFilter {
+public class ImageFilterHue extends SimpleImageFilter {
private ColorSpaceMatrix cmatrix = null;
public ImageFilterHue() {
mName = "Hue";
cmatrix = new ColorSpaceMatrix();
- mMaxParameter = 180;
- mMinParameter = -180;
}
- @Override
- public int getButtonId() {
- return R.id.hueButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.hue;
- }
-
- @Override
- public int getEditingViewId() {
- return BasicEditor.ID;
- }
-
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilterHue filter = (ImageFilterHue) super.clone();
- filter.cmatrix = new ColorSpaceMatrix(cmatrix);
- return filter;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Hue");
+ representation.setFilterClass(ImageFilterHue.class);
+ representation.setMinimum(-180);
+ representation.setMaximum(180);
+ representation.setTextId(R.string.hue);
+ representation.setButtonId(R.id.hueButton);
+ representation.setEditorId(BasicEditor.ID);
+ return representation;
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float []matrix);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- float p = mParameter;
- float value = p;
+ float value = getParameters().getValue();
cmatrix.identity();
cmatrix.setHue(value);
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
index f03baca39..f48bd047a 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
@@ -20,17 +20,13 @@ import android.graphics.Bitmap;
import android.text.format.Time;
import com.android.gallery3d.R;
+import com.android.gallery3d.ingest.ui.MtpThumbnailTileView;
-public class ImageFilterKMeans extends ImageFilter {
+public class ImageFilterKMeans extends SimpleImageFilter {
private int mSeed = 0;
public ImageFilterKMeans() {
mName = "KMeans";
- mMaxParameter = 20;
- mMinParameter = 2;
- mPreviewParameter = 4;
- mDefaultParameter = 4;
- mParameter = 4;
// set random seed for session
Time t = new Time();
@@ -38,27 +34,29 @@ public class ImageFilterKMeans extends ImageFilter {
mSeed = (int) t.toMillis(false);
}
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("KMeans");
+ representation.setFilterClass(ImageFilterKMeans.class);
+ representation.setMaximum(20);
+ representation.setMinimum(2);
+ representation.setValue(4);
+ representation.setDefaultValue(4);
+ representation.setPreviewValue(4);
+ representation.setTextId(R.string.kmeans);
+ representation.setButtonId(R.id.kmeansButton);
+ return representation;
+ }
+
native protected void nativeApplyFilter(Bitmap bitmap, int width, int height,
Bitmap large_ds_bm, int lwidth, int lheight, Bitmap small_ds_bm,
int swidth, int sheight, int p, int seed);
@Override
- public int getButtonId() {
- return R.id.kmeansButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.kmeans;
- }
-
- @Override
- public boolean isNil() {
- return false;
- }
-
- @Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
@@ -87,8 +85,10 @@ public class ImageFilterKMeans extends ImageFilter {
small_bm_ds = Bitmap.createScaledBitmap(large_bm_ds, sw, sh, true);
}
- int p = Math.max(mParameter, mMinParameter) % (mMaxParameter + 1);
- nativeApplyFilter(bitmap, w, h, large_bm_ds, lw, lh, small_bm_ds, sw, sh, p, mSeed);
+ if (getParameters() != null) {
+ int p = Math.max(getParameters().getValue(), getParameters().getMinimum()) % (getParameters().getMaximum() + 1);
+ nativeApplyFilter(bitmap, w, h, large_bm_ds, lw, lh, small_bm_ds, sw, sh, p, mSeed);
+ }
return bitmap;
}
}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
index 04fd1e42e..841c5c913 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
@@ -3,6 +3,7 @@ package com.android.gallery3d.filtershow.filters;
import android.graphics.Bitmap;
import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
public class ImageFilterNegative extends ImageFilter {
@@ -10,35 +11,26 @@ public class ImageFilterNegative extends ImageFilter {
mName = "Negative";
}
- @Override
- public int getButtonId() {
- return R.id.negativeButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.negative;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterRepresentation representation = new FilterDirectRepresentation("Negative");
+ representation.setFilterClass(ImageFilterNegative.class);
+ representation.setTextId(R.string.negative);
+ representation.setButtonId(R.id.negativeButton);
+ representation.setShowEditingControls(false);
+ representation.setShowParameterValue(false);
+ representation.setEditorId(ImageOnlyEditor.ID);
+ return representation;
}
- @Override
- public boolean isNil() {
- return false;
- }
+ native protected void nativeApplyFilter(Bitmap bitmap, int w, int h);
@Override
- public boolean showEditingControls() {
- return false;
- }
+ public void useRepresentation(FilterRepresentation representation) {
- @Override
- public boolean showParameterValue() {
- return false;
}
- native protected void nativeApplyFilter(Bitmap bitmap, int w, int h);
-
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
nativeApplyFilter(bitmap, w, h);
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java
index 681eb1221..316a286e8 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java
@@ -26,85 +26,29 @@ import android.graphics.RectF;
import com.android.gallery3d.R;
public class ImageFilterParametricBorder extends ImageFilter {
- private int mBorderColor = Color.WHITE;
- private int mBorderSize = 10;
- private int mBorderCornerRadius = 10;
+ private FilterColorBorderRepresentation mParameters = null;
public ImageFilterParametricBorder() {
- setFilterType(TYPE_BORDER);
mName = "Border";
}
- @Override
- public int getTextId() {
- return R.string.borders;
- }
-
- @Override
- public boolean showParameterValue() {
- return false;
- }
-
- @Override
- public boolean showEditingControls() {
- return false;
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterColorBorderRepresentation parameters = (FilterColorBorderRepresentation) representation;
+ mParameters = parameters;
}
- @Override
- public boolean showUtilityPanel() {
- return false;
- }
-
- public ImageFilterParametricBorder(int color, int size, int radius) {
- setBorder(color, size, radius);
- setFilterType(TYPE_BORDER);
- }
-
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilterParametricBorder filter = (ImageFilterParametricBorder) super.clone();
- filter.setBorder(mBorderColor, mBorderSize, mBorderCornerRadius);
- return filter;
- }
-
- @Override
- public boolean isNil() {
- return false;
- }
-
- @Override
- public boolean same(ImageFilter filter) {
- boolean isBorderFilter = super.same(filter);
- if (!isBorderFilter) {
- return false;
- }
- if (!(filter instanceof ImageFilterParametricBorder)) {
- return false;
- }
- ImageFilterParametricBorder borderFilter = (ImageFilterParametricBorder) filter;
- if (borderFilter.mBorderColor != mBorderColor) {
- return false;
- }
- if (borderFilter.mBorderSize != mBorderSize) {
- return false;
- }
- if (borderFilter.mBorderCornerRadius != mBorderCornerRadius) {
- return false;
- }
- return true;
- }
-
- public void setBorder(int color, int size, int radius) {
- mBorderColor = color;
- mBorderSize = size;
- mBorderCornerRadius = radius;
+ public FilterColorBorderRepresentation getParameters() {
+ return mParameters;
}
private void applyHelper(Canvas canvas, int w, int h) {
+ if (getParameters() == null) {
+ return;
+ }
Path border = new Path();
border.moveTo(0, 0);
- float bs = mBorderSize / 100.0f * w;
- float r = mBorderCornerRadius / 100.0f * w;
+ float bs = getParameters().getBorderSize() / 100.0f * w;
+ float r = getParameters().getBorderRadius() / 100.0f * w;
border.lineTo(0, h);
border.lineTo(w, h);
border.lineTo(w, 0);
@@ -114,19 +58,19 @@ public class ImageFilterParametricBorder extends ImageFilter {
Paint paint = new Paint();
paint.setAntiAlias(true);
- paint.setColor(mBorderColor);
+ paint.setColor(getParameters().getColor());
canvas.drawPath(border, paint);
}
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
Canvas canvas = new Canvas(bitmap);
applyHelper(canvas, bitmap.getWidth(), bitmap.getHeight());
return bitmap;
}
@Override
- public Bitmap iconApply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap iconApply(Bitmap bitmap, float scaleFactor, int quality) {
Canvas canvas = new Canvas(bitmap);
applyHelper(canvas, bitmap.getWidth() * 4, bitmap.getHeight() * 4);
return bitmap;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
index 368e29a78..d5297904d 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
@@ -21,7 +21,7 @@ import android.graphics.Bitmap;
import android.support.v8.renderscript.*;
import android.util.Log;
-public class ImageFilterRS extends ImageFilter {
+public abstract class ImageFilterRS extends ImageFilter {
private final String LOGTAG = "ImageFilterRS";
private static RenderScript mRS = null;
@@ -31,10 +31,13 @@ public class ImageFilterRS extends ImageFilter {
private static Bitmap sOldBitmap = null;
private Bitmap mOldBitmap = null;
- private static Bitmap mReturnBitmap = null;
private final Bitmap.Config mBitmapConfig = Bitmap.Config.ARGB_8888;
- public void prepare(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public void resetBitmap() {
+ mOldBitmap = null;
+ }
+
+ public void prepare(Bitmap bitmap, float scaleFactor, int quality) {
if (sOldBitmap == null
|| (bitmap.getWidth() != sOldBitmap.getWidth())
|| (bitmap.getHeight() != sOldBitmap.getHeight())) {
@@ -53,13 +56,13 @@ public class ImageFilterRS extends ImageFilter {
}
mInPixelsAllocation.copyFrom(bitmap);
if (mOldBitmap != sOldBitmap) {
- createFilter(mResources, scaleFactor, highQuality);
+ createFilter(mResources, scaleFactor, quality);
mOldBitmap = sOldBitmap;
}
}
public void createFilter(android.content.res.Resources res,
- float scaleFactor, boolean highQuality) {
+ float scaleFactor, int quality) {
// Stub
}
@@ -72,12 +75,12 @@ public class ImageFilterRS extends ImageFilter {
}
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
if (bitmap == null) {
return bitmap;
}
try {
- prepare(bitmap, scaleFactor, highQuality);
+ prepare(bitmap, scaleFactor, quality);
runFilter();
update(bitmap);
} catch (android.renderscript.RSIllegalArgumentException e) {
@@ -93,8 +96,19 @@ public class ImageFilterRS extends ImageFilter {
}
public static void setRenderScriptContext(Activity context) {
- mRS = RenderScript.create(context);
+ if (mRS == null) {
+ mRS = RenderScript.create(context);
+ }
mResources = context.getResources();
+ if (mInPixelsAllocation != null) {
+ mInPixelsAllocation.destroy();
+ mInPixelsAllocation = null;
+ }
+ if (mOutPixelsAllocation != null) {
+ mOutPixelsAllocation.destroy();
+ mOutPixelsAllocation = null;
+ }
+ sOldBitmap = null;
}
}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java
index 9ae6f511e..511f9e90f 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -20,157 +20,53 @@ import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
-
import java.util.Vector;
public class ImageFilterRedEye extends ImageFilter {
private static final String LOGTAG = "ImageFilterRedEye";
- private Vector<RedEyeCandidate> mCandidates = null;
+ FilterRedEyeRepresentation mParameters = new FilterRedEyeRepresentation();
public ImageFilterRedEye() {
mName = "Red Eye";
}
@Override
- public int getButtonId() {
- return R.id.redEyeButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.redeye;
- }
-
- @Override
- public int getEditingViewId() {
- return R.id.imageRedEyes;
- }
-
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilterRedEye filter = (ImageFilterRedEye) super.clone();
- if (mCandidates != null) {
- int size = mCandidates.size();
- filter.mCandidates = new Vector<RedEyeCandidate>();
- for (int i = 0; i < size; i++) {
- filter.mCandidates.add(new RedEyeCandidate(mCandidates.elementAt(i)));
- }
- }
- return filter;
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterRedEyeRepresentation();
}
- @Override
public boolean isNil() {
- if (mCandidates != null && mCandidates.size() > 0) {
- return false;
- }
- return true;
- }
-
- @Override
- public boolean same(ImageFilter filter) {
- boolean isRedEyeFilter = super.same(filter);
- if (!isRedEyeFilter) {
- return false;
- }
- ImageFilterRedEye redEyeFilter = (ImageFilterRedEye) filter;
- if (redEyeFilter.mCandidates == null && mCandidates == null) {
- return true;
- }
- if (redEyeFilter.mCandidates == null || mCandidates == null) {
- return false;
- }
- if (redEyeFilter.mCandidates.size() != mCandidates.size()) {
- return false;
- }
- int size = mCandidates.size();
- for (int i = 0; i < size; i++) {
- RedEyeCandidate c1 = mCandidates.elementAt(i);
- RedEyeCandidate c2 = redEyeFilter.mCandidates.elementAt(i);
- if (!c1.equals(c2)) {
- return false;
- }
- }
- return true;
- }
-
- public Vector<RedEyeCandidate> getCandidates() {
- if (mCandidates == null) {
- mCandidates = new Vector<RedEyeCandidate>();
- }
- return mCandidates;
+ return mParameters.isNil();
}
- public void addRect(RectF rect, RectF bounds) {
- if (mCandidates == null) {
- mCandidates = new Vector<RedEyeCandidate>();
- }
- Vector<RedEyeCandidate> intersects = new Vector<RedEyeCandidate>();
- for (int i = 0; i < mCandidates.size(); i++) {
- RedEyeCandidate r = mCandidates.elementAt(i);
- if (r.intersect(rect)) {
- intersects.add(r);
- }
- }
- for (int i = 0; i < intersects.size(); i++) {
- RedEyeCandidate r = intersects.elementAt(i);
- rect.union(r.mRect);
- bounds.union(r.mBounds);
- mCandidates.remove(r);
- }
- mCandidates.add(new RedEyeCandidate(rect, bounds));
+ public Vector<FilterPoint> getCandidates() {
+ return mParameters.getCandidates();
}
public void clear() {
- if (mCandidates == null) {
- mCandidates = new Vector<RedEyeCandidate>();
- }
- mCandidates.clear();
+ mParameters.clearCandidates();
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, short[] matrix);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterRedEyeRepresentation parameters = (FilterRedEyeRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
short[] rect = new short[4];
- if (mCandidates != null && mCandidates.size() > 0) {
- for (int i = 0; i < mCandidates.size(); i++) {
- RectF r = new RectF(mCandidates.elementAt(i).mRect);
- GeometryMetadata geo = getImagePreset().mGeoData;
- Matrix originalToScreen = geo.getOriginalToScreen(true,
- getImagePreset().getImageLoader().getOriginalBounds().width(),
- getImagePreset().getImageLoader().getOriginalBounds().height(),
- w, h);
- originalToScreen.mapRect(r);
- if (r.left < 0) {
- r.left = 0;
- }
- if (r.left > w) {
- r.left = w;
- }
- if (r.top < 0) {
- r.top = 0;
- }
- if (r.top > h) {
- r.top = h;
- }
- if (r.right < 0) {
- r.right = 0;
- }
- if (r.right > w) {
- r.right = w;
- }
- if (r.bottom < 0) {
- r.bottom = 0;
- }
- if (r.bottom > h) {
- r.bottom = h;
- }
+ int size = mParameters.getNumberOfCandidates();
+ Matrix originalToScreen = getOriginalToScreenMatrix(w, h);
+ for (int i = 0; i < size; i++) {
+ RectF r = new RectF(((RedEyeCandidate) (mParameters.getCandidate(i))).mRect);
+ originalToScreen.mapRect(r);
+ if (r.intersect(0, 0, w, h)) {
rect[0] = (short) r.left;
rect[1] = (short) r.top;
rect[2] = (short) r.width();
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
index 129165b3e..6cd833206 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
@@ -20,29 +20,36 @@ import com.android.gallery3d.R;
import android.graphics.Bitmap;
-public class ImageFilterSaturated extends ImageFilter {
+public class ImageFilterSaturated extends SimpleImageFilter {
public ImageFilterSaturated() {
mName = "Saturated";
}
@Override
- public int getButtonId() {
- return R.id.saturationButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.saturation;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Saturated");
+ representation.setFilterClass(ImageFilterSaturated.class);
+ representation.setTextId(R.string.saturation);
+ representation.setButtonId(R.id.saturationButton);
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ return representation;
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float saturation);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- int p = mParameter;
+ int p = getParameters().getValue();
float value = 1 + p / 100.0f;
nativeApplyFilter(bitmap, w, h, value);
return bitmap;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
index de8fcd5ea..e17823955 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
@@ -20,36 +20,36 @@ import com.android.gallery3d.R;
import android.graphics.Bitmap;
-public class ImageFilterShadows extends ImageFilter {
+public class ImageFilterShadows extends SimpleImageFilter {
public ImageFilterShadows() {
mName = "Shadows";
}
- @Override
- public int getButtonId() {
- return R.id.shadowRecoveryButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.shadow_recovery;
- }
-
- @Override
- public ImageFilter clone() throws CloneNotSupportedException {
- ImageFilterShadows filter = (ImageFilterShadows) super.clone();
- return filter;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Shadows");
+ representation.setFilterClass(ImageFilterShadows.class);
+ representation.setTextId(R.string.shadow_recovery);
+ representation.setButtonId(R.id.shadowRecoveryButton);
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ return representation;
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float factor);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- float p = mParameter;
+ float p = getParameters().getValue();
nativeApplyFilter(bitmap, w, h, p);
return bitmap;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
index 1f9bf22c0..9c99d57d0 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
@@ -24,33 +24,31 @@ public class ImageFilterSharpen extends ImageFilterRS {
private ScriptC_convolve3x3 mScript;
float mScaleFactor;
+ private FilterBasicRepresentation mParameters;
+
public ImageFilterSharpen() {
mName = "Sharpen";
}
- @Override
- public int getButtonId() {
- return R.id.sharpenButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.sharpness;
- }
-
- @Override
- public int getOverlayBitmaps() {
- return R.drawable.filtershow_button_colors_sharpen;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterRepresentation representation = new FilterBasicRepresentation("Sharpen", 0, 0, 100);
+ representation.setShowParameterValue(true);
+ representation.setFilterClass(ImageFilterSharpen.class);
+ representation.setTextId(R.string.sharpness);
+ representation.setButtonId(R.id.sharpenButton);
+ representation.setOverlayId(R.drawable.filtershow_button_colors_sharpen);
+ representation.setEditorId(R.id.imageZoom);
+ return representation;
}
- @Override
- public int getEditingViewId() {
- return R.id.imageZoom;
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterBasicRepresentation parameters = (FilterBasicRepresentation) representation;
+ mParameters = parameters;
}
@Override
public void createFilter(android.content.res.Resources res, float scaleFactor,
- boolean highQuality) {
+ int quality) {
int w = mInPixelsAllocation.getType().getX();
int h = mInPixelsAllocation.getType().getY();
mScaleFactor = scaleFactor;
@@ -63,7 +61,7 @@ public class ImageFilterSharpen extends ImageFilterRS {
}
private void computeKernel(){
- float p1 = mParameter * mScaleFactor;
+ float p1 = mParameters.getValue() * mScaleFactor;
float value = p1 / 100.0f;
float f[] = new float[9];
float p = value;
@@ -81,6 +79,9 @@ public class ImageFilterSharpen extends ImageFilterRS {
@Override
public void runFilter() {
+ if (mParameters == null) {
+ return;
+ }
computeKernel();
mScript.set_gIn(mInPixelsAllocation);
mScript.bind_gPixels(mInPixelsAllocation);
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterStraighten.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterStraighten.java
index 85fcf273f..a3bb6f980 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterStraighten.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterStraighten.java
@@ -32,6 +32,7 @@ public class ImageFilterStraighten extends ImageFilter {
@Override
public ImageFilter clone() throws CloneNotSupportedException {
+ // FIXME: clone() should not be needed. Remove when we fix geometry.
ImageFilterStraighten filter = (ImageFilterStraighten) super.clone();
filter.mRotation = mRotation;
filter.mZoomFactor = mZoomFactor;
@@ -52,7 +53,12 @@ public class ImageFilterStraighten extends ImageFilter {
}
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public void useRepresentation(FilterRepresentation representation) {
+
+ }
+
+ @Override
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
// TODO: implement bilinear or bicubic here... for now, just use
// canvas to do a simple implementation...
// TODO: and be more memory efficient! (do it in native?)
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java
index 36bd62630..702cc664c 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java
@@ -18,22 +18,26 @@ package com.android.gallery3d.filtershow.filters;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
import android.graphics.RectF;
import com.adobe.xmp.XMPException;
import com.adobe.xmp.XMPMeta;
import com.android.gallery3d.R;
import com.android.gallery3d.app.Log;
+import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
import com.android.gallery3d.filtershow.presets.ImagePreset;
/**
* An image filter which creates a tiny planet projection.
*/
-public class ImageFilterTinyPlanet extends ImageFilter {
- private float mAngle = 0;
+public class ImageFilterTinyPlanet extends SimpleImageFilter {
- private static final String TAG = ImageFilterTinyPlanet.class.getSimpleName();
+
+ private static final String LOGTAG = ImageFilterTinyPlanet.class.getSimpleName();
public static final String GOOGLE_PANO_NAMESPACE = "http://ns.google.com/photos/1.0/panorama/";
+ FilterTinyPlanetRepresentation mParameters = new FilterTinyPlanetRepresentation();
public static final String CROPPED_AREA_IMAGE_WIDTH_PIXELS =
"CroppedAreaImageWidthPixels";
@@ -49,38 +53,18 @@ public class ImageFilterTinyPlanet extends ImageFilter {
"CroppedAreaTopPixels";
public ImageFilterTinyPlanet() {
- setFilterType(TYPE_TINYPLANET);
mName = "TinyPlanet";
-
- mMinParameter = 10;
- mMaxParameter = 60;
- mDefaultParameter = 20;
- mPreviewParameter = 20;
- mParameter = 20;
- mAngle = 0;
}
@Override
- public int getButtonId() {
- return R.id.tinyplanetButton;
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterTinyPlanetRepresentation parameters = (FilterTinyPlanetRepresentation) representation;
+ mParameters = parameters;
}
@Override
- public int getTextId() {
- return R.string.tinyplanet;
- }
-
- public void setAngle(float angle) {
- mAngle = angle;
- }
-
- public float getAngle() {
- return mAngle;
- }
-
- public boolean isNil() {
- // TinyPlanet always has an effect
- return false;
+ public FilterRepresentation getDefaultRepresentation() {
+ return new FilterTinyPlanetRepresentation();
}
native protected void nativeApplyFilter(
@@ -88,7 +72,7 @@ public class ImageFilterTinyPlanet extends ImageFilter {
float angle);
@Override
- public Bitmap apply(Bitmap bitmapIn, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmapIn, float scaleFactor, int quality) {
int w = bitmapIn.getWidth();
int h = bitmapIn.getHeight();
int outputSize = (int) (w / 2f);
@@ -110,11 +94,38 @@ public class ImageFilterTinyPlanet extends ImageFilter {
} catch (java.lang.OutOfMemoryError e) {
System.gc();
outputSize /= 2;
- Log.v(TAG, "No memory to create Full Tiny Planet create half");
+ Log.v(LOGTAG, "No memory to create Full Tiny Planet create half");
}
}
nativeApplyFilter(bitmapIn, bitmapIn.getWidth(), bitmapIn.getHeight(), mBitmapOut,
- outputSize, mParameter / 100f, mAngle);
+ outputSize, mParameters.getZoom() / 100f, mParameters.getAngle());
+
+ if (true) {
+ // TODO(hoford): FIXME and remove this section
+ String text = "Tiny Planet Not Working";
+ int w2 = bitmapIn.getWidth() / 2;
+ int h2 = bitmapIn.getHeight() / 2;
+ Canvas c = new Canvas(bitmapIn);
+ Paint p = new Paint();
+ Rect src = new Rect(0, 0, mBitmapOut.getWidth(), mBitmapOut.getHeight());
+ Rect dst = new Rect(0, 0, bitmapIn.getWidth(), bitmapIn.getHeight());
+ c.drawBitmap(mBitmapOut, 0, 0, p);
+ float size = Math.min(w2, h2) / 4f;
+ p.setTextSize(size);
+ p.setColor(0xFF000000);
+ p.setStyle(Paint.Style.STROKE);
+ p.setStrokeWidth(20);
+ Rect bounds = new Rect();
+ p.getTextBounds(text, 0, text.length(), bounds);
+ int tw = bounds.width() / 2;
+ c.drawText(text, w2 - tw, h2, p);
+
+ p.setColor(0xFFFF0000);
+ p.setStyle(Paint.Style.FILL);
+ p.setStrokeWidth(0);
+
+ c.drawText(text, w2 - tw, h2, p);
+ }
return mBitmapOut;
}
@@ -143,7 +154,6 @@ public class ImageFilterTinyPlanet extends ImageFilter {
} catch (java.lang.OutOfMemoryError e) {
System.gc();
scale /= 2;
- Log.v(TAG, "No memory to create Full Tiny Planet create half");
}
}
Canvas paddedCanvas = new Canvas(paddedBitmap);
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
index 7720d0490..a57af71df 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
@@ -20,30 +20,35 @@ import com.android.gallery3d.R;
import android.graphics.Bitmap;
-public class ImageFilterVibrance extends ImageFilter {
+public class ImageFilterVibrance extends SimpleImageFilter {
public ImageFilterVibrance() {
mName = "Vibrance";
}
- @Override
- public int getButtonId() {
- return R.id.vibranceButton;
- }
-
- @Override
- public int getTextId() {
- return R.string.vibrance;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Vibrance");
+ representation.setFilterClass(ImageFilterVibrance.class);
+ representation.setTextId(R.string.vibrance);
+ representation.setButtonId(R.id.vibranceButton);
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+ return representation;
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float bright);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- int p = mParameter;
- float value = p;
+ float value = getParameters().getValue();
nativeApplyFilter(bitmap, w, h, value);
return bitmap;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
index 3c904fa6c..465d90bfd 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
@@ -19,32 +19,42 @@ package com.android.gallery3d.filtershow.filters;
import com.android.gallery3d.R;
import android.graphics.Bitmap;
+import com.android.gallery3d.app.Log;
-public class ImageFilterVignette extends ImageFilter {
+public class ImageFilterVignette extends SimpleImageFilter {
+
+ private static final String LOGTAG = "ImageFilterVignette";
public ImageFilterVignette() {
- setFilterType(TYPE_VIGNETTE);
mName = "Vignette";
}
- @Override
- public int getButtonId() {
- return R.id.vignetteButton;
- }
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterBasicRepresentation representation =
+ (FilterBasicRepresentation) super.getDefaultRepresentation();
+ representation.setName("Vignette");
+ representation.setFilterClass(ImageFilterVignette.class);
+ representation.setPriority(FilterRepresentation.TYPE_VIGNETTE);
+ representation.setTextId(R.string.vignette);
+ representation.setButtonId(R.id.vignetteButton);
- @Override
- public int getTextId() {
- return R.string.vignette;
+ representation.setMinimum(-100);
+ representation.setMaximum(100);
+ representation.setDefaultValue(0);
+
+ return representation;
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float strength);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+ if (getParameters() == null) {
+ return bitmap;
+ }
int w = bitmap.getWidth();
int h = bitmap.getHeight();
- float p = mParameter;
- float value = p / 100.0f;
+ float value = getParameters().getValue() / 100.0f;
nativeApplyFilter(bitmap, w, h, value);
return bitmap;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
index 8665dc54c..2f4852306 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
@@ -17,6 +17,7 @@
package com.android.gallery3d.filtershow.filters;
import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
import android.graphics.Bitmap;
@@ -24,36 +25,34 @@ public class ImageFilterWBalance extends ImageFilter {
private static final String TAG = "ImageFilterWBalance";
public ImageFilterWBalance() {
- setFilterType(TYPE_WBALANCE);
mName = "WBalance";
}
- @Override
- public int getButtonId() {
- return R.id.wbalanceButton;
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterRepresentation representation = new FilterDirectRepresentation("WBalance");
+ representation.setFilterClass(ImageFilterWBalance.class);
+ representation.setPriority(FilterRepresentation.TYPE_WBALANCE);
+ representation.setTextId(R.string.wbalance);
+ representation.setButtonId(R.id.wbalanceButton);
+ representation.setShowEditingControls(false);
+ representation.setShowParameterValue(false);
+ representation.setEditorId(ImageOnlyEditor.ID);
+ return representation;
}
@Override
- public int getTextId() {
- return R.string.wbalance;
- }
+ public void useRepresentation(FilterRepresentation representation) {
- public boolean showEditingControls() {
- return false;
}
native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, int locX, int locY);
@Override
- public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
nativeApplyFilter(bitmap, w, h, -1, -1);
return bitmap;
}
- @Override
- public boolean isNil() {
- return false;
- }
}
diff --git a/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java b/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java
index 58d3afa3b..a40d4fa3b 100644
--- a/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java
+++ b/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -18,7 +18,7 @@ package com.android.gallery3d.filtershow.filters;
import android.graphics.RectF;
-public class RedEyeCandidate {
+public class RedEyeCandidate implements FilterPoint {
RectF mRect = new RectF();
RectF mBounds = new RectF();
diff --git a/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java b/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java
new file mode 100644
index 000000000..922a16a0f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 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.filtershow.filters;
+
+import android.graphics.Bitmap;
+
+public class SimpleImageFilter extends ImageFilter {
+
+ private FilterBasicRepresentation mParameters;
+
+ public FilterRepresentation getDefaultRepresentation() {
+ FilterRepresentation representation = new FilterBasicRepresentation("Default", 0, 50, 100);
+ representation.setShowParameterValue(true);
+ return representation;
+ }
+
+ public void useRepresentation(FilterRepresentation representation) {
+ FilterBasicRepresentation parameters = (FilterBasicRepresentation) representation;
+ mParameters = parameters;
+ }
+
+ public FilterBasicRepresentation getParameters() {
+ return mParameters;
+ }
+
+ @Override
+ public Bitmap iconApply(Bitmap bitmap, float scaleFactor, int quality) {
+ FilterRepresentation representation = getDefaultRepresentation();
+ this.useRepresentation(representation);
+ return apply(bitmap, scaleFactor, quality);
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryListener.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryListener.java
new file mode 100644
index 000000000..549c2e7a5
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2013 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.filtershow.imageshow;
+
+public interface GeometryListener {
+ public void geometryChanged();
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java
index b53284061..a3645d6f5 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java
@@ -86,12 +86,12 @@ public class GeometryMetadata {
return false;
}
- public Bitmap apply(Bitmap original, float scaleFactor, boolean highQuality) {
+ public Bitmap apply(Bitmap original, float scaleFactor, int quality) {
if (!hasModifications()) {
return original;
}
mImageFilter.setGeometryMetadata(this);
- Bitmap m = mImageFilter.apply(original, scaleFactor, highQuality);
+ Bitmap m = mImageFilter.apply(original, scaleFactor, quality);
return m;
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
index 16076fde9..0cd229968 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
@@ -5,15 +5,14 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
+import com.android.gallery3d.filtershow.editors.EditorDraw;
+import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation;
import com.android.gallery3d.filtershow.filters.ImageFilterDraw;
-import com.android.gallery3d.filtershow.filters.RedEyeCandidate;
public class ImageDraw extends ImageShow {
@@ -21,20 +20,36 @@ public class ImageDraw extends ImageShow {
private int mCurrentColor = Color.RED;
final static float INITAL_STROKE_RADIUS = 40;
private float mCurrentSize = INITAL_STROKE_RADIUS;
+ private byte mType = 0;
+ private FilterDrawRepresentation mFRep;
+ private EditorDraw mEditorDraw;
public ImageDraw(Context context, AttributeSet attrs) {
super(context, attrs);
+ resetParameter();
}
public ImageDraw(Context context) {
super(context);
+ resetParameter();
+ }
+
+ public void setEditor(EditorDraw editorDraw) {
+ mEditorDraw = editorDraw;
+ }
+ public void setFilterDrawRepresentation(FilterDrawRepresentation fr) {
+ mFRep = fr;
+ }
+
+ public Drawable getIcon(Context context) {
+
+ return null;
}
@Override
public void resetParameter() {
- ImageFilterDraw filter = (ImageFilterDraw) getCurrentFilter();
- if (filter != null) {
- filter.clear();
+ if (mFRep != null) {
+ mFRep.clear();
}
}
@@ -46,9 +61,12 @@ public class ImageDraw extends ImageShow {
mCurrentSize = size;
}
- public void setStyle(char style) {
- ImageFilterDraw filter = (ImageFilterDraw) getCurrentFilter();
- filter.setStyle(style);
+ public void setStyle(byte style) {
+ mType = (byte) (style % ImageFilterDraw.NUMBER_OF_STYLES);
+ }
+
+ public int getStyle() {
+ return mType;
}
public int getSize() {
@@ -71,11 +89,10 @@ public class ImageDraw extends ImageShow {
ImageFilterDraw filter = (ImageFilterDraw) getCurrentFilter();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
-
mTmpPoint[0] = event.getX();
mTmpPoint[1] = event.getY();
mToOrig.mapPoints(mTmpPoint);
- filter.startSection(mCurrentColor, mCurrentSize, mTmpPoint[0], mTmpPoint[1]);
+ mFRep.startNewSection(mType, mCurrentColor, mCurrentSize, mTmpPoint[0], mTmpPoint[1]);
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
@@ -87,7 +104,7 @@ public class ImageDraw extends ImageShow {
mTmpPoint[0] = event.getHistoricalX(p, h);
mTmpPoint[1] = event.getHistoricalY(p, h);
mToOrig.mapPoints(mTmpPoint);
- filter.addPoint(mTmpPoint[0], mTmpPoint[1]);
+ mFRep.addPoint(mTmpPoint[0], mTmpPoint[1]);
}
}
}
@@ -95,10 +112,9 @@ public class ImageDraw extends ImageShow {
mTmpPoint[0] = event.getX();
mTmpPoint[1] = event.getY();
mToOrig.mapPoints(mTmpPoint);
- filter.endSection(mTmpPoint[0], mTmpPoint[1]);
- this.resetImageCaches(this);
-
+ mFRep.endSection(mTmpPoint[0], mTmpPoint[1]);
}
+ mEditorDraw.commitLocalRepresentation();
invalidate();
return true;
}
@@ -122,11 +138,8 @@ public class ImageDraw extends ImageShow {
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
- ImageFilterDraw filter = (ImageFilterDraw) getCurrentFilter();
- if (filter != null) {
- calcScreenMapping();
- filter.draw(canvas, mRotateToScreen);
- }
+ calcScreenMapping();
+
}
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java b/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java
index 3d73ef686..e18f0d034 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java
@@ -29,6 +29,7 @@ import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
+import com.android.gallery3d.app.Log;
import com.android.gallery3d.filtershow.imageshow.GeometryMetadata.FLIP;
import com.android.gallery3d.filtershow.presets.ImagePreset;
@@ -241,6 +242,7 @@ public abstract class ImageGeometry extends ImageShow {
super.onVisibilityChanged(changedView, visibility);
if (visibility == View.VISIBLE) {
mVisibilityGained = true;
+ MasterImage.getImage().invalidateFiltersOnly();
syncLocalToMasterGeometry();
updateScale();
gainedVisibility();
@@ -326,7 +328,7 @@ public abstract class ImageGeometry extends ImageShow {
}
public void saveAndSetPreset() {
- ImagePreset lastHistoryItem = mMasterImage.getHistory().getLast();
+ ImagePreset lastHistoryItem = MasterImage.getImage().getHistory().getLast();
if (lastHistoryItem != null && lastHistoryItem.historyName().equalsIgnoreCase(getName())) {
getImagePreset().setGeometry(mLocalGeometry);
resetImageCaches(this);
@@ -336,7 +338,7 @@ public abstract class ImageGeometry extends ImageShow {
copy.setGeometry(mLocalGeometry);
copy.setHistoryName(getName());
copy.setIsFx(false);
- mMasterImage.setPreset(copy, true);
+ MasterImage.getImage().setPreset(copy, true);
}
}
invalidate();
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java b/src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java
new file mode 100644
index 000000000..06b055d3c
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 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.filtershow.imageshow;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.gallery3d.filtershow.editors.EditorRedEye;
+import com.android.gallery3d.filtershow.filters.FilterPoint;
+import com.android.gallery3d.filtershow.filters.FilterRedEyeRepresentation;
+import com.android.gallery3d.filtershow.filters.ImageFilterRedEye;
+import com.android.gallery3d.filtershow.filters.RedEyeCandidate;
+
+public abstract class ImagePoint extends ImageShow {
+
+ private static final String LOGTAG = "ImageRedEyes";
+ protected EditorRedEye mEditorRedEye;
+ protected FilterRedEyeRepresentation mRedEyeRep;
+ protected static float mTouchPadding = 80;
+
+ public static void setTouchPadding(float padding) {
+ mTouchPadding = padding;
+ }
+
+ public ImagePoint(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ImagePoint(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void resetParameter() {
+ ImageFilterRedEye filter = (ImageFilterRedEye) getCurrentFilter();
+ if (filter != null) {
+ filter.clear();
+ }
+ invalidate();
+ }
+
+ @Override
+ public void updateImage() {
+ super.updateImage();
+ invalidate();
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ Paint paint = new Paint();
+ paint.setStyle(Style.STROKE);
+ paint.setColor(Color.RED);
+ paint.setStrokeWidth(2);
+
+ GeometryMetadata geo = getImagePreset().mGeoData;
+ Matrix originalToScreen = geo.getOriginalToScreen(false,
+ mImageLoader.getOriginalBounds().width(),
+ mImageLoader.getOriginalBounds().height(), getWidth(), getHeight());
+ Matrix originalRotateToScreen = geo.getOriginalToScreen(true,
+ mImageLoader.getOriginalBounds().width(),
+ mImageLoader.getOriginalBounds().height(), getWidth(), getHeight());
+ if (mRedEyeRep != null) {
+ for (FilterPoint candidate : mRedEyeRep.getCandidates()) {
+ drawPoint(candidate, canvas, originalToScreen, originalRotateToScreen, paint);
+ }
+ }
+ }
+
+ protected abstract void drawPoint(
+ FilterPoint candidate, Canvas canvas, Matrix originalToScreen,
+ Matrix originalRotateToScreen, Paint paint);
+
+ public void setEditor(EditorRedEye editorRedEye) {
+ mEditorRedEye = editorRedEye;
+ }
+
+ public void setRepresentation(FilterRedEyeRepresentation redEyeRep) {
+ mRedEyeRep = redEyeRep;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageRedEyes.java b/src/com/android/gallery3d/filtershow/imageshow/ImageRedEye.java
index c012ff1cc..c3ff5e151 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageRedEyes.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageRedEye.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2013 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.filtershow.imageshow;
@@ -8,54 +23,32 @@ import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
-import android.util.AttributeSet;
import android.view.MotionEvent;
-import com.android.gallery3d.filtershow.filters.ImageFilterRedEye;
+import com.android.gallery3d.filtershow.filters.FilterPoint;
import com.android.gallery3d.filtershow.filters.RedEyeCandidate;
-public class ImageRedEyes extends ImageShow {
-
+public class ImageRedEye extends ImagePoint {
private static final String LOGTAG = "ImageRedEyes";
private RectF mCurrentRect = null;
- private static float mTouchPadding = 80;
-
- public static void setTouchPadding(float padding) {
- mTouchPadding = padding;
- }
-
- public ImageRedEyes(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public ImageRedEyes(Context context) {
+ public ImageRedEye(Context context) {
super(context);
}
@Override
public void resetParameter() {
- ImageFilterRedEye filter = (ImageFilterRedEye) getCurrentFilter();
- if (filter != null) {
- filter.clear();
- }
- mCurrentRect = null;
+ super.resetParameter();
invalidate();
}
@Override
- public void updateImage() {
- super.updateImage();
- invalidate();
- }
- @Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
float ex = event.getX();
float ey = event.getY();
- ImageFilterRedEye filter = (ImageFilterRedEye) getCurrentFilter();
-
// let's transform (ex, ey) to displayed image coordinates
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mCurrentRect = new RectF();
@@ -87,11 +80,12 @@ public class ImageRedEyes extends ImageShow {
invert.reset();
originalNoRotateToScreen.invert(invert);
invert.mapRect(r2);
- filter.addRect(r, r2);
+ mRedEyeRep.addRect(r, r2);
this.resetImageCaches(this);
}
mCurrentRect = null;
}
+ mEditorRedEye.commitLocalRepresentation();
invalidate();
return true;
}
@@ -108,41 +102,35 @@ public class ImageRedEyes extends ImageShow {
RectF drawRect = new RectF(mCurrentRect);
canvas.drawRect(drawRect, paint);
}
+ }
- GeometryMetadata geo = getImagePreset().mGeoData;
- Matrix originalToScreen = geo.getOriginalToScreen(false,
- mImageLoader.getOriginalBounds().width(),
- mImageLoader.getOriginalBounds().height(), getWidth(), getHeight());
- Matrix originalRotateToScreen = geo.getOriginalToScreen(true,
- mImageLoader.getOriginalBounds().width(),
- mImageLoader.getOriginalBounds().height(), getWidth(), getHeight());
-
- ImageFilterRedEye filter = (ImageFilterRedEye) getCurrentFilter();
- for (RedEyeCandidate candidate : filter.getCandidates()) {
- RectF rect = candidate.getRect();
- RectF drawRect = new RectF();
- originalToScreen.mapRect(drawRect, rect);
- RectF fullRect = new RectF();
- originalRotateToScreen.mapRect(fullRect, rect);
- paint.setColor(Color.BLUE);
- canvas.drawRect(fullRect, paint);
- canvas.drawLine(fullRect.centerX(), fullRect.top,
- fullRect.centerX(), fullRect.bottom, paint);
- canvas.drawLine(fullRect.left, fullRect.centerY(),
- fullRect.right, fullRect.centerY(), paint);
- paint.setColor(Color.GREEN);
- float dw = drawRect.width();
- float dh = drawRect.height();
- float dx = fullRect.centerX() - dw/2;
- float dy = fullRect.centerY() - dh/2;
- drawRect.set(dx, dy, dx + dw, dy + dh);
- canvas.drawRect(drawRect, paint);
- canvas.drawLine(drawRect.centerX(), drawRect.top,
- drawRect.centerX(), drawRect.bottom, paint);
- canvas.drawLine(drawRect.left, drawRect.centerY(),
- drawRect.right, drawRect.centerY(), paint);
- canvas.drawCircle(drawRect.centerX(), drawRect.centerY(),
- mTouchPadding, paint);
- }
+ @Override
+ protected void drawPoint(FilterPoint point, Canvas canvas, Matrix originalToScreen,
+ Matrix originalRotateToScreen, Paint paint) {
+ RedEyeCandidate candidate = (RedEyeCandidate) point;
+ RectF rect = candidate.getRect();
+ RectF drawRect = new RectF();
+ originalToScreen.mapRect(drawRect, rect);
+ RectF fullRect = new RectF();
+ originalRotateToScreen.mapRect(fullRect, rect);
+ paint.setColor(Color.BLUE);
+ canvas.drawRect(fullRect, paint);
+ canvas.drawLine(fullRect.centerX(), fullRect.top,
+ fullRect.centerX(), fullRect.bottom, paint);
+ canvas.drawLine(fullRect.left, fullRect.centerY(),
+ fullRect.right, fullRect.centerY(), paint);
+ paint.setColor(Color.GREEN);
+ float dw = drawRect.width();
+ float dh = drawRect.height();
+ float dx = fullRect.centerX() - dw / 2;
+ float dy = fullRect.centerY() - dh / 2;
+ drawRect.set(dx, dy, dx + dw, dy + dh);
+ canvas.drawRect(drawRect, paint);
+ canvas.drawLine(drawRect.centerX(), drawRect.top,
+ drawRect.centerX(), drawRect.bottom, paint);
+ canvas.drawLine(drawRect.left, drawRect.centerY(),
+ drawRect.right, drawRect.centerY(), paint);
+ canvas.drawCircle(drawRect.centerX(), drawRect.centerY(),
+ mTouchPadding, paint);
}
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
index 93c4622fa..463756839 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
@@ -50,7 +50,6 @@ public class ImageShow extends View implements OnGestureListener,
SliderListener,
OnSeekBarChangeListener {
- protected MasterImage mMasterImage = MasterImage.getImage();
private static final String LOGTAG = "ImageShow";
protected Paint mPaint = new Paint();
@@ -141,12 +140,6 @@ public class ImageShow extends View implements OnGestureListener,
if (mSeekBar != null) {
mSeekBar.setOnSeekBarChangeListener(this);
}
- if (getCurrentFilter() != null) {
- int parameter = getCurrentFilter().getParameter();
- int maxp = getCurrentFilter().getMaxParameter();
- int minp = getCurrentFilter().getMinParameter();
- updateSeekBar(parameter, minp, maxp);
- }
}
private int parameterToUI(int parameter, int minp, int maxp, int uimax) {
@@ -178,11 +171,7 @@ public class ImageShow extends View implements OnGestureListener,
}
public void resetParameter() {
- ImageFilter currentFilter = getCurrentFilter();
- if (currentFilter != null) {
- updateSeekBar(currentFilter.getDefaultParameter(),
- getCurrentFilter().getMinParameter(), getCurrentFilter().getMaxParameter());
- }
+ // TODO: implement reset
}
public void setPanelController(PanelController controller) {
@@ -195,18 +184,8 @@ public class ImageShow extends View implements OnGestureListener,
@Override
public void onNewValue(int parameter) {
- int maxp = ImageFilter.DEFAULT_MAX_PARAMETER;
- int minp = ImageFilter.DEFAULT_MIN_PARAMETER;
- if (getCurrentFilter() != null) {
- if (getCurrentFilter().getParameter() == parameter) {
- return;
- }
- getCurrentFilter().setParameter(parameter);
- maxp = getCurrentFilter().getMaxParameter();
- minp = getCurrentFilter().getMinParameter();
- }
if (getImagePreset() != null) {
- getImagePreset().fillImageStateAdapter(mMasterImage.getState());
+ getImagePreset().fillImageStateAdapter(MasterImage.getImage().getState());
}
if (getPanelController() != null) {
getPanelController().onNewValue(parameter);
@@ -231,7 +210,7 @@ public class ImageShow extends View implements OnGestureListener,
setupGestureDetector(context);
mActivity = (FilterShowActivity) context;
- mMasterImage.addObserver(this);
+ MasterImage.getImage().addObserver(this);
}
public ImageShow(Context context) {
@@ -239,7 +218,7 @@ public class ImageShow extends View implements OnGestureListener,
setupGestureDetector(context);
mActivity = (FilterShowActivity) context;
- mMasterImage.addObserver(this);
+ MasterImage.getImage().addObserver(this);
}
public void setupGestureDetector(Context context) {
@@ -258,7 +237,7 @@ public class ImageShow extends View implements OnGestureListener,
}
public ImageFilter getCurrentFilter() {
- return mMasterImage.getCurrentFilter();
+ return MasterImage.getImage().getCurrentFilter();
}
public void showToast(String text) {
@@ -295,7 +274,7 @@ public class ImageShow extends View implements OnGestureListener,
}
public ImagePreset getImagePreset() {
- return mMasterImage.getPreset();
+ return MasterImage.getImage().getPreset();
}
public void drawToast(Canvas canvas) {
@@ -350,19 +329,19 @@ public class ImageShow extends View implements OnGestureListener,
if (mImageLoader == null) {
return;
}
- mMasterImage.updatePresets(true);
+ MasterImage.getImage().updatePresets(true);
}
public Bitmap getFiltersOnlyImage() {
- return mMasterImage.getFiltersOnlyImage();
+ return MasterImage.getImage().getFiltersOnlyImage();
}
public Bitmap getGeometryOnlyImage() {
- return mMasterImage.getGeometryOnlyImage();
+ return MasterImage.getImage().getGeometryOnlyImage();
}
public Bitmap getFilteredImage() {
- return mMasterImage.getFilteredImage();
+ return MasterImage.getImage().getFilteredImage();
}
public void drawImage(Canvas canvas, Bitmap image) {
@@ -427,8 +406,12 @@ public class ImageShow extends View implements OnGestureListener,
paint.setTextSize(mOriginalTextSize);
paint.getTextBounds(mOriginalText, 0, mOriginalText.length(), bounds);
paint.setColor(Color.BLACK);
- canvas.drawText(mOriginalText, mImageBounds.left + mOriginalTextMargin + 1,
- mImageBounds.top + bounds.height() + mOriginalTextMargin + 1, paint);
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeWidth(3);
+ canvas.drawText(mOriginalText, mImageBounds.left + mOriginalTextMargin,
+ mImageBounds.top + bounds.height() + mOriginalTextMargin, paint);
+ paint.setStyle(Paint.Style.FILL);
+ paint.setStrokeWidth(1);
paint.setColor(Color.WHITE);
canvas.drawText(mOriginalText, mImageBounds.left + mOriginalTextMargin,
mImageBounds.top + bounds.height() + mOriginalTextMargin, paint);
@@ -484,7 +467,7 @@ public class ImageShow extends View implements OnGestureListener,
mImageLoader = loader;
if (mImageLoader != null) {
mImageLoader.addListener(this);
- mMasterImage.setImageLoader(mImageLoader);
+ MasterImage.getImage().setImageLoader(mImageLoader);
}
}
@@ -616,12 +599,6 @@ public class ImageShow extends View implements OnGestureListener,
@Override
public void onProgressChanged(SeekBar arg0, int progress, boolean arg2) {
int parameter = progress;
- if (getCurrentFilter() != null) {
- int maxp = getCurrentFilter().getMaxParameter();
- int minp = getCurrentFilter().getMinParameter();
- parameter = uiToParameter(progress, minp, maxp, arg0.getMax());
- }
-
onNewValue(parameter);
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java b/src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java
index 82d87214f..3e95d4e15 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java
@@ -17,9 +17,14 @@
package com.android.gallery3d.filtershow.imageshow;
import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
+import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
+import com.android.gallery3d.filtershow.filters.FilterCurvesRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation;
import com.android.gallery3d.filtershow.filters.ImageFilterTinyPlanet;
public class ImageTinyPlanet extends ImageShow {
@@ -31,6 +36,8 @@ public class ImageTinyPlanet extends ImageShow {
private float mCenterX = 0;
private float mCenterY = 0;
private float mStartAngle = 0;
+ private FilterTinyPlanetRepresentation mTinyPlanetRep;
+ private EditorTinyPlanet mEditorTinyPlanet;
public ImageTinyPlanet(Context context) {
super(context);
@@ -60,7 +67,6 @@ public class ImageTinyPlanet extends ImageShow {
@Override
public boolean onTouchEvent(MotionEvent event) {
- ImageFilterTinyPlanet filter = (ImageFilterTinyPlanet) getCurrentFilter();
float x = event.getX();
float y = event.getY();
mCurrentX = x;
@@ -71,15 +77,30 @@ public class ImageTinyPlanet extends ImageShow {
case (MotionEvent.ACTION_DOWN):
mTouchCenterX = x;
mTouchCenterY = y;
- mStartAngle = filter.getAngle();
+ mStartAngle = mTinyPlanetRep.getAngle();
break;
case (MotionEvent.ACTION_UP):
case (MotionEvent.ACTION_MOVE):
- filter.setAngle(mStartAngle + getCurrentTouchAngle());
+ mTinyPlanetRep.setAngle(mStartAngle + getCurrentTouchAngle());
break;
}
resetImageCaches(this);
invalidate();
+ mEditorTinyPlanet.commitLocalRepresentation();
return true;
}
+
+ public void setRepresentation(FilterTinyPlanetRepresentation tinyPlanetRep) {
+ mTinyPlanetRep = tinyPlanetRep;
+ }
+
+ public void setEditor(EditorTinyPlanet editorTinyPlanet) {
+ mEditorTinyPlanet = editorTinyPlanet;
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ }
+
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
index 5e9ec7a7a..3172c79dc 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
@@ -19,23 +19,21 @@ package com.android.gallery3d.filtershow.imageshow;
import android.graphics.Bitmap;
import android.graphics.RectF;
-import com.android.gallery3d.app.Log;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.HistoryAdapter;
import com.android.gallery3d.filtershow.ImageStateAdapter;
-import com.android.gallery3d.filtershow.cache.TripleBufferBitmap;
-import com.android.gallery3d.filtershow.cache.FilteringPipeline;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.cache.*;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.filters.ImageFilter;
import com.android.gallery3d.filtershow.presets.ImagePreset;
import java.util.Vector;
-public class MasterImage {
+public class MasterImage implements RenderingRequestCaller {
private static final String LOGTAG = "MasterImage";
- private static MasterImage sMasterImage = new MasterImage();
+ private static MasterImage sMasterImage = null;
private ImageFilter mCurrentFilter = null;
private ImagePreset mPreset = null;
@@ -43,8 +41,9 @@ public class MasterImage {
private ImagePreset mFiltersOnlyPreset = null;
private TripleBufferBitmap mFilteredPreview = new TripleBufferBitmap();
- private TripleBufferBitmap mGeometryOnlyPreview = new TripleBufferBitmap();
- private TripleBufferBitmap mFiltersOnlyPreview = new TripleBufferBitmap();
+
+ private Bitmap mGeometryOnlyBitmap = null;
+ private Bitmap mFiltersOnlyBitmap = null;
private ImageLoader mLoader = null;
private HistoryAdapter mHistory = null;
@@ -53,14 +52,25 @@ public class MasterImage {
private FilterShowActivity mActivity = null;
private Vector<ImageShow> mObservers = new Vector<ImageShow>();
+ private FilterRepresentation mCurrentFilterRepresentation;
+ private Vector<GeometryListener> mGeometryListeners = new Vector<GeometryListener>();
+
+ private GeometryMetadata mPreviousGeometry = null;
- private MasterImage() { }
+ private MasterImage() {
+ }
public static MasterImage getImage() {
+ if (sMasterImage == null) {
+ sMasterImage = new MasterImage();
+ }
return sMasterImage;
}
public void addObserver(ImageShow observer) {
+ if (mObservers.contains(observer)) {
+ return;
+ }
mObservers.add(observer);
}
@@ -68,6 +78,10 @@ public class MasterImage {
mActivity = activity;
}
+ public ImageLoader getLoader() {
+ return mLoader;
+ }
+
public synchronized ImagePreset getPreset() {
return mPreset;
}
@@ -89,6 +103,11 @@ public class MasterImage {
mHistory.addHistoryItem(mPreset);
}
updatePresets(true);
+ GeometryMetadata geo = mPreset.mGeoData;
+ if (!geo.equals(mPreviousGeometry)) {
+ notifyGeometryChange();
+ }
+ mPreviousGeometry = new GeometryMetadata(geo);
}
private void setGeometry() {
@@ -113,6 +132,7 @@ public class MasterImage {
// We need a copy from the history
mHistory.setCurrentPreset(position);
}
+
public HistoryAdapter getHistory() {
return mHistory;
}
@@ -133,6 +153,10 @@ public class MasterImage {
mLoader = loader;
}
+ public ImageLoader getImageLoader() {
+ return mLoader;
+ }
+
public void setCurrentFilter(ImageFilter filter) {
mCurrentFilter = filter;
}
@@ -152,24 +176,16 @@ public class MasterImage {
return mFilteredPreview;
}
- public TripleBufferBitmap getGeometryOnlyBuffer() {
- return mGeometryOnlyPreview;
- }
-
- public TripleBufferBitmap getFiltersOnlyBuffer() {
- return mFiltersOnlyPreview;
- }
-
public Bitmap getFilteredImage() {
return mFilteredPreview.getConsumer();
}
public Bitmap getFiltersOnlyImage() {
- return mFiltersOnlyPreview.getConsumer();
+ return mFiltersOnlyBitmap;
}
public Bitmap getGeometryOnlyImage() {
- return mGeometryOnlyPreview.getConsumer();
+ return mGeometryOnlyBitmap;
}
public void notifyObservers() {
@@ -185,6 +201,8 @@ public class MasterImage {
if (mGeometryOnlyPreset == null
|| !newPreset.same(mGeometryOnlyPreset)) {
mGeometryOnlyPreset = newPreset;
+ RenderingRequest.post(mLoader.getOriginalBitmapLarge(),
+ mGeometryOnlyPreset, RenderingRequest.GEOMETRY_RENDERING, this);
}
}
if (force || mFiltersOnlyPreset == null) {
@@ -193,16 +211,56 @@ public class MasterImage {
if (mFiltersOnlyPreset == null
|| !newPreset.same(mFiltersOnlyPreset)) {
mFiltersOnlyPreset = newPreset;
+ RenderingRequest.post(mLoader.getOriginalBitmapLarge(),
+ mFiltersOnlyPreset, RenderingRequest.FILTERS_RENDERING, this);
}
}
+ invalidatePreview();
mActivity.enableSave(hasModifications());
- updateBuffers();
}
- public void updateBuffers() {
+ public FilterRepresentation getCurrentFilterRepresentation() {
+ return mCurrentFilterRepresentation;
+ }
+
+ public void setCurrentFilterRepresentation(FilterRepresentation currentFilterRepresentation) {
+ mCurrentFilterRepresentation = currentFilterRepresentation;
+ }
+
+ public void invalidateFiltersOnly() {
+ mFiltersOnlyPreset = null;
+ updatePresets(false);
+ }
+
+ public void invalidatePreview() {
+ mFilteredPreview.invalidate();
FilteringPipeline.getPipeline().updatePreviewBuffer();
- FilteringPipeline.getPipeline().updateGeometryOnlyPreviewBuffer();
- FilteringPipeline.getPipeline().updateFiltersOnlyPreviewBuffer();
}
+ @Override
+ public void available(RenderingRequest request) {
+ if (request.getBitmap() == null) {
+ return;
+ }
+ if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) {
+ mGeometryOnlyBitmap = request.getBitmap();
+ }
+ if (request.getType() == RenderingRequest.FILTERS_RENDERING) {
+ mFiltersOnlyBitmap = request.getBitmap();
+ }
+ }
+
+ public static void reset() {
+ sMasterImage = null;
+ }
+
+ public void addGeometryListener(GeometryListener listener) {
+ mGeometryListeners.add(listener);
+ }
+
+ public void notifyGeometryChange() {
+ for (GeometryListener listener : mGeometryListeners) {
+ listener.geometryChanged();
+ }
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
index d6a69af3e..84266c55d 100644
--- a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
+++ b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
@@ -21,10 +21,12 @@ import android.util.Log;
import com.android.gallery3d.filtershow.ImageStateAdapter;
import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.filters.ImageFilter;
-import com.android.gallery3d.filtershow.filters.ImageFilterRS;
import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
-import com.android.gallery3d.filtershow.imageshow.ImageShow;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
import java.util.Vector;
@@ -32,13 +34,16 @@ public class ImagePreset {
private static final String LOGTAG = "ImagePreset";
- private ImageShow mEndPoint = null;
- private ImageFilter mImageBorder = null;
+ private FilterRepresentation mBorder = null;
private float mScaleFactor = 1.0f;
- private boolean mIsHighQuality = false;
+ public static final int QUALITY_ICON = 0;
+ public static final int QUALITY_PREVIEW = 1;
+ public static final int QUALITY_FINAL = 2;
+ private int mQuality = QUALITY_PREVIEW;
private ImageLoader mImageLoader = null;
- protected Vector<ImageFilter> mFilters = new Vector<ImageFilter>();
+ private Vector<FilterRepresentation> mFilters = new Vector<FilterRepresentation>();
+
protected String mName = "Original";
private String mHistoryName = "Original";
protected boolean mIsFxPreset = false;
@@ -48,10 +53,6 @@ public class ImagePreset {
public final GeometryMetadata mGeoData = new GeometryMetadata();
- enum FullRotate {
- ZERO, NINETY, HUNDRED_EIGHTY, TWO_HUNDRED_SEVENTY
- }
-
public ImagePreset() {
setup();
}
@@ -70,13 +71,12 @@ public class ImagePreset {
public ImagePreset(ImagePreset source) {
try {
- if (source.mImageBorder != null) {
- mImageBorder = source.mImageBorder.clone();
+ if (source.mBorder != null) {
+ mBorder = source.mBorder.clone();
}
for (int i = 0; i < source.mFilters.size(); i++) {
- ImageFilter filter = source.mFilters.elementAt(i).clone();
- filter.setImagePreset(this);
- add(filter);
+ FilterRepresentation representation = source.mFilters.elementAt(i).clone();
+ addFilter(representation);
}
} catch (java.lang.CloneNotSupportedException e) {
Log.v(LOGTAG, "Exception trying to clone: " + e);
@@ -89,6 +89,52 @@ public class ImagePreset {
mGeoData.set(source.mGeoData);
}
+ public FilterRepresentation getFilterRepresentation(int position) {
+ FilterRepresentation representation = null;
+ try {
+ representation = mFilters.elementAt(position).clone();
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ return representation;
+ }
+
+ public int getPositionForRepresentation(FilterRepresentation representation) {
+ for (int i = 0; i < mFilters.size(); i++) {
+ if (mFilters.elementAt(i).getFilterClass() == representation.getFilterClass()) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public FilterRepresentation getFilterRepresentationCopyFrom(FilterRepresentation filterRepresentation) {
+ // TODO: add concept of position in the filters (to allow multiple instances)
+ if (filterRepresentation == null) {
+ return null;
+ }
+ int position = getPositionForRepresentation(filterRepresentation);
+ if (position == -1) {
+ return null;
+ }
+ FilterRepresentation representation = null;
+ try {
+ representation = mFilters.elementAt(position).clone();
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ }
+ return representation;
+ }
+
+ public void updateFilterRepresentation(FilterRepresentation representation) {
+ synchronized (mFilters) {
+ int position = getPositionForRepresentation(representation);
+ FilterRepresentation old = mFilters.elementAt(position);
+ old.updateTempParametersFrom(representation);
+ }
+ MasterImage.getImage().invalidatePreview();
+ }
+
public void setDoApplyGeometry(boolean value) {
mDoApplyGeometry = value;
}
@@ -101,19 +147,19 @@ public class ImagePreset {
return mDoApplyFilters;
}
- public GeometryMetadata getGeometry() {
+ public synchronized GeometryMetadata getGeometry() {
return mGeoData;
}
public boolean hasModifications() {
- if (mImageBorder != null && !mImageBorder.isNil()) {
+ if (mBorder != null && !mBorder.isNil()) {
return true;
}
if (mGeoData.hasModifications()) {
return true;
}
for (int i = 0; i < mFilters.size(); i++) {
- ImageFilter filter = mFilters.elementAt(i);
+ FilterRepresentation filter = mFilters.elementAt(i);
if (!filter.isNil()) {
return true;
}
@@ -122,31 +168,31 @@ public class ImagePreset {
}
public boolean isPanoramaSafe() {
- if (mImageBorder != null && !mImageBorder.isNil()) {
+ if (mBorder != null && !mBorder.isNil()) {
return false;
}
if (mGeoData.hasModifications()) {
return false;
}
- for (ImageFilter filter : mFilters) {
- if (filter.getFilterType() == ImageFilter.TYPE_VIGNETTE
- && !filter.isNil()) {
+ for (FilterRepresentation representation : mFilters) {
+ if (representation.getPriority() == FilterRepresentation.TYPE_VIGNETTE
+ && !representation.isNil()) {
return false;
}
- if (filter.getFilterType() == ImageFilter.TYPE_TINYPLANET
- && !filter.isNil()) {
+ if (representation.getPriority() == FilterRepresentation.TYPE_TINYPLANET
+ && !representation.isNil()) {
return false;
}
}
return true;
}
- public void setGeometry(GeometryMetadata m) {
+ public synchronized void setGeometry(GeometryMetadata m) {
mGeoData.set(m);
}
- private void setBorder(ImageFilter filter) {
- mImageBorder = filter;
+ private void setBorder(FilterRepresentation filter) {
+ mBorder = filter;
}
public boolean isFx() {
@@ -180,8 +226,8 @@ public class ImagePreset {
}
if (mDoApplyFilters && preset.mDoApplyFilters) {
for (int i = 0; i < preset.mFilters.size(); i++) {
- ImageFilter a = preset.mFilters.elementAt(i);
- ImageFilter b = mFilters.elementAt(i);
+ FilterRepresentation a = preset.mFilters.elementAt(i);
+ FilterRepresentation b = mFilters.elementAt(i);
if (!a.equals(b)) {
return false;
}
@@ -190,14 +236,6 @@ public class ImagePreset {
return true;
}
- public void usePreset(ImagePreset preset) {
- for (int i = 0; i < preset.mFilters.size(); i++) {
- ImageFilter a = preset.mFilters.elementAt(i);
- ImageFilter b = mFilters.elementAt(i);
- b.useFilter(a);
- }
- }
-
public boolean same(ImagePreset preset) {
if (preset == null) {
return false;
@@ -219,11 +257,11 @@ public class ImagePreset {
return false;
}
- if (mDoApplyGeometry && mImageBorder != preset.mImageBorder) {
+ if (mDoApplyGeometry && mBorder != preset.mBorder) {
return false;
}
- if (mImageBorder != null && !mImageBorder.same(preset.mImageBorder)) {
+ if (mBorder != null && !mBorder.equals(preset.mBorder)) {
return false;
}
@@ -235,18 +273,15 @@ public class ImagePreset {
if (mDoApplyFilters && preset.mDoApplyFilters) {
for (int i = 0; i < preset.mFilters.size(); i++) {
- ImageFilter a = preset.mFilters.elementAt(i);
- ImageFilter b = mFilters.elementAt(i);
+ FilterRepresentation a = preset.mFilters.elementAt(i);
+ FilterRepresentation b = mFilters.elementAt(i);
if (!a.same(b)) {
return false;
}
}
}
- return true;
- }
- public int nbFilters() {
- return mFilters.size();
+ return true;
}
public int similarUpTo(ImagePreset preset) {
@@ -255,13 +290,13 @@ public class ImagePreset {
}
for (int i = 0; i < preset.mFilters.size(); i++) {
- ImageFilter a = preset.mFilters.elementAt(i);
+ FilterRepresentation a = preset.mFilters.elementAt(i);
if (i < mFilters.size()) {
- ImageFilter b = mFilters.elementAt(i);
+ FilterRepresentation b = mFilters.elementAt(i);
if (!a.same(b)) {
return i;
}
- if (a.getParameter() != b.getParameter()) {
+ if (!a.equals(b)) {
return i;
}
} else {
@@ -279,57 +314,58 @@ public class ImagePreset {
return mHistoryName;
}
- public void add(ImageFilter filter) {
+ public void showFilters() {
+ Log.v(LOGTAG, "\\\\\\ showFilters -- " + mFilters.size() + " filters");
+ int n = 0;
+ for (FilterRepresentation representation : mFilters) {
+ Log.v(LOGTAG, " filter " + n + " : " + representation.toString());
+ n++;
+ }
+ Log.v(LOGTAG, "/// showFilters -- " + mFilters.size() + " filters");
+ }
- if (filter.getFilterType() == ImageFilter.TYPE_BORDER) {
- setHistoryName(filter.getName());
- setBorder(filter);
- } else if (filter.getFilterType() == ImageFilter.TYPE_FX) {
+ public void addFilter(FilterRepresentation representation) {
+ Log.v(LOGTAG, "*** Add Filter *** " + representation);
+ if (representation.getPriority() == FilterRepresentation.TYPE_BORDER) {
+ setHistoryName(representation.getName());
+ setBorder(representation);
+ } else if (representation.getPriority() == FilterRepresentation.TYPE_FX) {
boolean found = false;
for (int i = 0; i < mFilters.size(); i++) {
- byte type = mFilters.get(i).getFilterType();
+ int type = mFilters.elementAt(i).getPriority();
if (found) {
- if (type != ImageFilter.TYPE_VIGNETTE) {
+ if (type != FilterRepresentation.TYPE_VIGNETTE) {
mFilters.remove(i);
continue;
}
}
- if (type == ImageFilter.TYPE_FX) {
+ if (type == FilterRepresentation.TYPE_FX) {
mFilters.remove(i);
- mFilters.add(i, filter);
- setHistoryName(filter.getName());
+ mFilters.add(i, representation);
+ setHistoryName(representation.getName());
found = true;
}
}
if (!found) {
- mFilters.add(filter);
- setHistoryName(filter.getName());
+ mFilters.add(representation);
+ setHistoryName(representation.getName());
}
} else {
- mFilters.add(filter);
- setHistoryName(filter.getName());
+ mFilters.add(representation);
+ setHistoryName(representation.getName());
}
- filter.setImagePreset(this);
}
- public void remove(String filterName) {
- ImageFilter filter = getFilter(filterName);
- if (filter != null) {
- mFilters.remove(filter);
- }
- }
-
- public int getCount() {
- return mFilters.size();
- }
-
- public ImageFilter getFilter(String name) {
+ public FilterRepresentation getRepresentation(FilterRepresentation filterRepresentation) {
for (int i = 0; i < mFilters.size(); i++) {
- ImageFilter filter = mFilters.elementAt(i);
- if (filter.getName().equalsIgnoreCase(name)) {
- return filter;
+ FilterRepresentation representation = mFilters.elementAt(i);
+ if (representation.getFilterClass() == filterRepresentation.getFilterClass()) {
+ return representation;
}
}
+ if (mBorder != null && mBorder.getFilterClass() == filterRepresentation.getFilterClass()) {
+ return mBorder;
+ }
return null;
}
@@ -337,10 +373,6 @@ public class ImagePreset {
// do nothing here
}
- public void setEndpoint(ImageShow image) {
- mEndPoint = image;
- }
-
public Bitmap apply(Bitmap original) {
Bitmap bitmap = original;
bitmap = applyFilters(bitmap, -1, -1);
@@ -350,12 +382,16 @@ public class ImagePreset {
public Bitmap applyGeometry(Bitmap bitmap) {
// Apply any transform -- 90 rotate, flip, straighten, crop
// Returns a new bitmap.
- return mGeoData.apply(bitmap, mScaleFactor, mIsHighQuality);
+ return mGeoData.apply(bitmap, mScaleFactor, mQuality);
}
public Bitmap applyBorder(Bitmap bitmap) {
- if (mImageBorder != null && mDoApplyGeometry) {
- bitmap = mImageBorder.apply(bitmap, mScaleFactor, mIsHighQuality);
+ if (mBorder != null && mDoApplyGeometry) {
+ ImageFilter filter = FiltersManager.getManager().getFilterForRepresentation(mBorder);
+ mBorder.synchronizeRepresentation();
+ filter.useRepresentation(mBorder);
+ filter.setImagePreset(this);
+ bitmap = filter.apply(bitmap, mScaleFactor, mQuality);
}
return bitmap;
}
@@ -370,8 +406,15 @@ public class ImagePreset {
to = mFilters.size();
}
for (int i = from; i < to; i++) {
- ImageFilter filter = mFilters.elementAt(i);
- bitmap = filter.apply(bitmap, mScaleFactor, mIsHighQuality);
+ FilterRepresentation representation = null;
+ synchronized (mFilters) {
+ representation = mFilters.elementAt(i);
+ representation.synchronizeRepresentation();
+ }
+ ImageFilter filter = FiltersManager.getManager().getFilterForRepresentation(representation);
+ filter.useRepresentation(representation);
+ filter.setImagePreset(this);
+ bitmap = filter.apply(bitmap, mScaleFactor, mQuality);
}
}
@@ -383,6 +426,7 @@ public class ImagePreset {
return;
}
imageStateAdapter.clear();
+ // TODO: re-enable the state panel
imageStateAdapter.addAll(mFilters);
imageStateAdapter.notifyDataSetChanged();
}
@@ -391,12 +435,12 @@ public class ImagePreset {
return mScaleFactor;
}
- public boolean isHighQuality() {
- return mIsHighQuality;
+ public int getQuality() {
+ return mQuality;
}
- public void setIsHighQuality(boolean value) {
- mIsHighQuality = value;
+ public void setQuality(int value) {
+ mQuality = value;
}
public void setScaleFactor(float value) {
diff --git a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java
index 38a9a3a2f..e378fe2b7 100644
--- a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java
+++ b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java
@@ -168,7 +168,7 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> {
@Override
protected Uri doInBackground(ImagePreset... params) {
// TODO: Support larger dimensions for photo saving.
- if (params[0] == null) {
+ if (params[0] == null || sourceUri == null) {
return null;
}
ImagePreset preset = params[0];
diff --git a/src/com/android/gallery3d/filtershow/ui/FilterIconButton.java b/src/com/android/gallery3d/filtershow/ui/FilterIconButton.java
index 089b24118..de2e1e5dc 100644
--- a/src/com/android/gallery3d/filtershow/ui/FilterIconButton.java
+++ b/src/com/android/gallery3d/filtershow/ui/FilterIconButton.java
@@ -24,15 +24,26 @@ import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
-import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.filters.ImageFilter;
+import com.android.gallery3d.filtershow.PanelController;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.cache.RenderingRequest;
+import com.android.gallery3d.filtershow.cache.RenderingRequestCaller;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.GeometryListener;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.presets.ImagePreset;
-public class FilterIconButton extends IconButton implements View.OnClickListener {
+public class FilterIconButton extends IconButton implements View.OnClickListener,
+ RenderingRequestCaller, GeometryListener {
+ private static final String LOGTAG = "FilterIconButton";
private Bitmap mOverlayBitmap = null;
- private FilterShowActivity mController = null;
- private ImageFilter mImageFilter = null;
+ private PanelController mController = null;
+ private FilterRepresentation mFilterRepresentation = null;
private LinearLayout mParentContainer = null;
private View.OnClickListener mListener = null;
+ private Bitmap mIconBitmap = null;
+ private ImagePreset mPreset = null;
+ private Rect mDestination = null;
public FilterIconButton(Context context) {
super(context);
@@ -46,30 +57,32 @@ public class FilterIconButton extends IconButton implements View.OnClickListener
super(context, attrs, defStyle);
}
- public void setup(String text, ImageFilter filter, FilterShowActivity controller,
- LinearLayout parent) {
- mImageFilter = filter;
+ public void setup(String text, PanelController controller, LinearLayout parent) {
mController = controller;
setText(text);
-
- if (mImageFilter.getOverlayBitmaps() != 0) {
- mOverlayBitmap = BitmapFactory.decodeResource(getResources(),
- mImageFilter.getOverlayBitmaps());
- }
-
mParentContainer = parent;
super.setOnClickListener(this);
+ MasterImage.getImage().addGeometryListener(this);
invalidate();
}
@Override
protected Bitmap drawImage(Bitmap dst, Bitmap image, Rect destination) {
- dst = super.drawImage(dst, image, destination);
- dst = mImageFilter.iconApply(dst, 1.0f, false);
- if (mOverlayBitmap != null) {
- dst = super.drawImage(dst, mOverlayBitmap, destination);
+ if (mIconBitmap == null && mPreset == null) {
+ ImageLoader loader = MasterImage.getImage().getLoader();
+ if (loader != null) {
+ ImagePreset geoPreset = new ImagePreset(MasterImage.getImage().getGeometryPreset());
+ image = geoPreset.applyGeometry(image);
+ dst = super.drawImage(dst, image, destination);
+ ImagePreset mPreset = new ImagePreset();
+ mPreset.addFilter(mFilterRepresentation);
+ mDestination = destination;
+ RenderingRequest.post(dst.copy(Bitmap.Config.ARGB_8888, true), mPreset, RenderingRequest.ICON_RENDERING, this);
+ }
+ return dst;
+ } else {
+ return mIconBitmap;
}
- return dst;
}
@Override
@@ -79,8 +92,8 @@ public class FilterIconButton extends IconButton implements View.OnClickListener
@Override
public void onClick(View v) {
- if (mController != null && mImageFilter != null) {
- mController.useFilter(mImageFilter);
+ if (mController != null) {
+ mController.useFilterRepresentation(mFilterRepresentation);
mParentContainer.dispatchSetSelected(false);
setSelected(true);
}
@@ -89,7 +102,37 @@ public class FilterIconButton extends IconButton implements View.OnClickListener
}
}
- public ImageFilter getImageFilter() {
- return mImageFilter;
+ public FilterRepresentation getFilterRepresentation() {
+ return mFilterRepresentation;
+ }
+
+ public void setFilterRepresentation(FilterRepresentation filterRepresentation) {
+ mFilterRepresentation = filterRepresentation;
+ if (mFilterRepresentation != null && mFilterRepresentation.getOverlayId() != 0) {
+ mOverlayBitmap = BitmapFactory.decodeResource(getResources(),
+ mFilterRepresentation.getOverlayId());
+ }
+ invalidate();
+ }
+
+ @Override
+ public void available(RenderingRequest request) {
+ if (request.getBitmap() == null) {
+ return;
+ }
+ mIconBitmap = request.getBitmap();
+ if (mOverlayBitmap != null) {
+ mIconBitmap = super.drawImage(mIconBitmap, mOverlayBitmap, mDestination);
+ }
+ invalidate();
+ stale_icon = true;
+ }
+
+ @Override
+ public void geometryChanged() {
+ stale_icon = true;
+ mIconBitmap = null;
+ mPreset = null;
+ invalidate();
}
}
diff --git a/src/com/android/gallery3d/filtershow/ui/IconButton.java b/src/com/android/gallery3d/filtershow/ui/IconButton.java
index 55dfb8043..28d01dfd9 100644
--- a/src/com/android/gallery3d/filtershow/ui/IconButton.java
+++ b/src/com/android/gallery3d/filtershow/ui/IconButton.java
@@ -38,7 +38,7 @@ public class IconButton extends Button {
protected Bitmap mImageMirror = null;
protected Bitmap mIcon = null;
- private boolean stale_icon = true;
+ protected boolean stale_icon = true;
public IconButton(Context context) {
this(context, null);
diff --git a/src/com/android/gallery3d/filtershow/ui/ImageCurves.java b/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
index 80c893562..f581fc733 100644
--- a/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
+++ b/src/com/android/gallery3d/filtershow/ui/ImageCurves.java
@@ -26,7 +26,6 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.AsyncTask;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
@@ -35,6 +34,10 @@ import android.widget.LinearLayout;
import android.widget.PopupMenu;
import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.editors.EditorCurves;
+import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
+import com.android.gallery3d.filtershow.filters.FilterCurvesRepresentation;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
import com.android.gallery3d.filtershow.filters.ImageFilterCurves;
import com.android.gallery3d.filtershow.imageshow.ImageShow;
import com.android.gallery3d.filtershow.presets.ImagePreset;
@@ -57,14 +60,18 @@ public class ImageCurves extends ImageShow {
Path gHistoPath = new Path();
boolean mDoingTouchMove = false;
+ private EditorCurves mEditorCurves;
+ private FilterCurvesRepresentation mFilterCurvesRepresentation;
public ImageCurves(Context context) {
super(context);
+ setLayerType(LAYER_TYPE_SOFTWARE, gPaint);
resetCurve();
}
public ImageCurves(Context context, AttributeSet attrs) {
super(context, attrs);
+ setLayerType(LAYER_TYPE_SOFTWARE, gPaint);
resetCurve();
}
@@ -127,7 +134,7 @@ public class ImageCurves extends ImageShow {
String filterName = getFilterName();
ImagePreset p = getImagePreset();
if (p != null) {
- return (ImageFilterCurves) p.getFilter(filterName);
+ return (ImageFilterCurves) FiltersManager.getManager().getFilter(ImageFilterCurves.class);
}
return null;
}
@@ -284,9 +291,11 @@ public class ImageCurves extends ImageShow {
}
public synchronized void updateCachedImage() {
- // update image
if (getImagePreset() != null) {
resetImageCaches(this);
+ if (mEditorCurves != null) {
+ mEditorCurves.commitLocalRepresentation();
+ }
invalidate();
}
}
@@ -391,6 +400,15 @@ public class ImageCurves extends ImageShow {
break;
}
}
+ mEditorCurves.commitLocalRepresentation();
invalidate();
}
+
+ public void setEditor(EditorCurves editorCurves) {
+ mEditorCurves = editorCurves;
+ }
+
+ public void setFilterDrawRepresentation(FilterCurvesRepresentation drawRep) {
+ mFilterCurvesRepresentation = drawRep;
+ }
}
diff --git a/src/com/android/gallery3d/filtershow/ui/Spline.java b/src/com/android/gallery3d/filtershow/ui/Spline.java
index 83341772b..2cfbd807f 100644
--- a/src/com/android/gallery3d/filtershow/ui/Spline.java
+++ b/src/com/android/gallery3d/filtershow/ui/Spline.java
@@ -110,6 +110,12 @@ public class Spline {
return true;
}
+ public void reset() {
+ mPoints.clear();
+ addPoint(0.0f, 1.0f);
+ addPoint(1.0f, 0.0f);
+ }
+
private void drawHandles(Canvas canvas, Drawable indicator, float centerX, float centerY) {
int left = (int) centerX - mCurveHandleSize / 2;
int top = (int) centerY - mCurveHandleSize / 2;
diff --git a/src/com/android/gallery3d/ingest/IngestActivity.java b/src/com/android/gallery3d/ingest/IngestActivity.java
index 4e603bed3..893f59572 100644
--- a/src/com/android/gallery3d/ingest/IngestActivity.java
+++ b/src/com/android/gallery3d/ingest/IngestActivity.java
@@ -22,11 +22,14 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.res.Configuration;
+import android.database.DataSetObserver;
import android.mtp.MtpObjectInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.support.v4.view.ViewPager;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.Menu;
@@ -36,12 +39,16 @@ import android.view.View;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
-import android.widget.GridView;
import android.widget.TextView;
import com.android.gallery3d.R;
+import com.android.gallery3d.ingest.adapter.CheckBroker;
import com.android.gallery3d.ingest.adapter.MtpAdapter;
+import com.android.gallery3d.ingest.adapter.MtpPagerAdapter;
+import com.android.gallery3d.ingest.data.MtpBitmapFetch;
import com.android.gallery3d.ingest.ui.DateTileView;
+import com.android.gallery3d.ingest.ui.IngestGridView;
+import com.android.gallery3d.ingest.ui.IngestGridView.OnClearChoicesListener;
import java.lang.ref.WeakReference;
import java.util.Collection;
@@ -51,14 +58,22 @@ public class IngestActivity extends Activity implements
private IngestService mHelperService;
private boolean mActive = false;
- private GridView mGridView;
+ private IngestGridView mGridView;
private MtpAdapter mAdapter;
private Handler mHandler;
private ProgressDialog mProgressDialog;
private ActionMode mActiveActionMode;
- private View mWarningOverlay;
- private TextView mWarningOverlayText;
+ private View mWarningView;
+ private TextView mWarningText;
+ private int mLastCheckedPosition = 0;
+
+ private ViewPager mFullscreenPager;
+ private MtpPagerAdapter mPagerAdapter;
+ private boolean mFullscreenPagerVisible = false;
+
+ private MenuItem mMenuSwitcherItem;
+ private MenuItem mActionMenuSwitcherItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -66,18 +81,25 @@ public class IngestActivity extends Activity implements
doBindHelperService();
setContentView(R.layout.ingest_activity_item_list);
- mGridView = (GridView) findViewById(R.id.ingest_gridview);
+ mGridView = (IngestGridView) findViewById(R.id.ingest_gridview);
mAdapter = new MtpAdapter(this);
+ mAdapter.registerDataSetObserver(mMasterObserver);
mGridView.setAdapter(mAdapter);
mGridView.setMultiChoiceModeListener(mMultiChoiceModeListener);
mGridView.setOnItemClickListener(mOnItemClickListener);
+ mGridView.setOnClearChoicesListener(mPositionMappingCheckBroker);
+
+ mFullscreenPager = (ViewPager) findViewById(R.id.ingest_view_pager);
mHandler = new ItemListHandler(this);
+
+ MtpBitmapFetch.configureForContext(this);
}
private OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View itemView, int position, long arg3) {
+ mLastCheckedPosition = position;
mGridView.setItemChecked(position, !mGridView.getCheckedItemPositions().get(position));
}
};
@@ -124,23 +146,18 @@ public class IngestActivity extends Activity implements
mGridView.setItemChecked(i, rangeValue);
}
+ mPositionMappingCheckBroker.onBulkCheckedChange();
mIgnoreItemCheckedStateChanges = false;
+ } else {
+ mPositionMappingCheckBroker.onCheckedChange(position, checked);
}
+ mLastCheckedPosition = position;
updateSelectedTitle(mode);
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- switch (item.getItemId()) {
- case R.id.import_items:
- mHelperService.importSelectedItems(
- mGridView.getCheckedItemPositions(),
- mAdapter);
- mode.finish();
- return true;
- default:
- return false;
- }
+ return onOptionsItemSelected(item);
}
@Override
@@ -149,12 +166,16 @@ public class IngestActivity extends Activity implements
inflater.inflate(R.menu.ingest_menu_item_list_selection, menu);
updateSelectedTitle(mode);
mActiveActionMode = mode;
+ mActionMenuSwitcherItem = menu.findItem(R.id.ingest_switch_view);
+ setSwitcherMenuState(mActionMenuSwitcherItem, mFullscreenPagerVisible);
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mActiveActionMode = null;
+ mActionMenuSwitcherItem = null;
+ mHandler.sendEmptyMessage(ItemListHandler.MSG_BULK_CHECKED_CHANGE);
}
@Override
@@ -164,6 +185,34 @@ public class IngestActivity extends Activity implements
}
};
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.import_items:
+ if (mActiveActionMode != null) {
+ mHelperService.importSelectedItems(
+ mGridView.getCheckedItemPositions(),
+ mAdapter);
+ mActiveActionMode.finish();
+ }
+ return true;
+ case R.id.ingest_switch_view:
+ setFullscreenPagerVisibility(!mFullscreenPagerVisible);
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.ingest_menu_item_list_selection, menu);
+ mMenuSwitcherItem = menu.findItem(R.id.ingest_switch_view);
+ menu.findItem(R.id.import_items).setVisible(false);
+ setSwitcherMenuState(mMenuSwitcherItem, mFullscreenPagerVisible);
+ return true;
+ }
+
@Override
protected void onDestroy() {
super.onDestroy();
@@ -175,7 +224,7 @@ public class IngestActivity extends Activity implements
DateTileView.refreshLocale();
mActive = true;
if (mHelperService != null) mHelperService.setClientActivity(this);
- updateWarningOverlay();
+ updateWarningView();
super.onResume();
}
@@ -187,31 +236,140 @@ public class IngestActivity extends Activity implements
super.onPause();
}
- private void showWarningOverlay(int textResId) {
- if (mWarningOverlay == null) {
- mWarningOverlay = findViewById(R.id.ingest_warning_overlay);
- mWarningOverlayText =
- (TextView)mWarningOverlay.findViewById(R.id.ingest_warning_overlay_text);
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ MtpBitmapFetch.configureForContext(this);
+ }
+
+ private void showWarningView(int textResId) {
+ if (mWarningView == null) {
+ mWarningView = findViewById(R.id.ingest_warning_view);
+ mWarningText =
+ (TextView)mWarningView.findViewById(R.id.ingest_warning_view_text);
}
- mWarningOverlayText.setText(textResId);
- mWarningOverlay.setVisibility(View.VISIBLE);
+ mWarningText.setText(textResId);
+ mWarningView.setVisibility(View.VISIBLE);
+ setFullscreenPagerVisibility(false);
mGridView.setVisibility(View.GONE);
}
- private void hideWarningOverlay() {
- if (mWarningOverlay != null) {
- mWarningOverlay.setVisibility(View.GONE);
- mGridView.setVisibility(View.VISIBLE);
+ private void hideWarningView() {
+ if (mWarningView != null) {
+ mWarningView.setVisibility(View.GONE);
+ setFullscreenPagerVisibility(false);
}
}
- private void updateWarningOverlay() {
+ private PositionMappingCheckBroker mPositionMappingCheckBroker = new PositionMappingCheckBroker();
+
+ private class PositionMappingCheckBroker extends CheckBroker
+ implements OnClearChoicesListener {
+ private int mLastMappingPager = -1;
+ private int mLastMappingGrid = -1;
+
+ private int mapPagerToGridPosition(int position) {
+ if (position != mLastMappingPager) {
+ mLastMappingPager = position;
+ mLastMappingGrid = mAdapter.translatePositionWithoutLabels(position);
+ }
+ return mLastMappingGrid;
+ }
+
+ private int mapGridToPagerPosition(int position) {
+ if (position != mLastMappingGrid) {
+ mLastMappingGrid = position;
+ mLastMappingPager = mPagerAdapter.translatePositionWithLabels(position);
+ }
+ return mLastMappingPager;
+ }
+
+ @Override
+ public void setItemChecked(int position, boolean checked) {
+ mGridView.setItemChecked(mapPagerToGridPosition(position), checked);
+ }
+
+ @Override
+ public void onCheckedChange(int position, boolean checked) {
+ if (mPagerAdapter != null) {
+ super.onCheckedChange(mapGridToPagerPosition(position), checked);
+ }
+ }
+
+ @Override
+ public boolean isItemChecked(int position) {
+ return mGridView.getCheckedItemPositions().get(mapPagerToGridPosition(position));
+ }
+
+ @Override
+ public void onClearChoices() {
+ onBulkCheckedChange();
+ }
+ };
+
+ private DataSetObserver mMasterObserver = new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ if (mPagerAdapter != null) mPagerAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onInvalidated() {
+ if (mPagerAdapter != null) mPagerAdapter.notifyDataSetChanged();
+ }
+ };
+
+ private int pickFullscreenStartingPosition() {
+ int firstVisiblePosition = mGridView.getFirstVisiblePosition();
+ if (mLastCheckedPosition <= firstVisiblePosition
+ || mLastCheckedPosition > mGridView.getLastVisiblePosition()) {
+ return firstVisiblePosition;
+ } else {
+ return mLastCheckedPosition;
+ }
+ }
+
+ private void setSwitcherMenuState(MenuItem menuItem, boolean inFullscreenMode) {
+ if (menuItem == null) return;
+ if (!inFullscreenMode) {
+ menuItem.setIcon(android.R.drawable.ic_menu_zoom);
+ menuItem.setTitle(R.string.switch_photo_fullscreen);
+ } else {
+ menuItem.setIcon(android.R.drawable.ic_dialog_dialer);
+ menuItem.setTitle(R.string.switch_photo_grid);
+ }
+ }
+
+ private void setFullscreenPagerVisibility(boolean visible) {
+ mFullscreenPagerVisible = visible;
+ if (visible) {
+ if (mPagerAdapter == null) {
+ mPagerAdapter = new MtpPagerAdapter(this, mPositionMappingCheckBroker);
+ mPagerAdapter.setMtpDeviceIndex(mAdapter.getMtpDeviceIndex());
+ }
+ mFullscreenPager.setAdapter(mPagerAdapter);
+ mFullscreenPager.setCurrentItem(mPagerAdapter.translatePositionWithLabels(
+ pickFullscreenStartingPosition()), false);
+ } else if (mPagerAdapter != null) {
+ mGridView.setSelection(mAdapter.translatePositionWithoutLabels(
+ mFullscreenPager.getCurrentItem()));
+ mFullscreenPager.setAdapter(null);
+ }
+ mGridView.setVisibility(visible ? View.INVISIBLE : View.VISIBLE);
+ mFullscreenPager.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ if (mActionMenuSwitcherItem != null) {
+ setSwitcherMenuState(mActionMenuSwitcherItem, visible);
+ }
+ setSwitcherMenuState(mMenuSwitcherItem, visible);
+ }
+
+ private void updateWarningView() {
if (!mAdapter.deviceConnected()) {
- showWarningOverlay(R.string.ingest_no_device);
+ showWarningView(R.string.ingest_no_device);
} else if (mAdapter.indexReady() && mAdapter.getCount() == 0) {
- showWarningOverlay(R.string.ingest_empty_device);
+ showWarningView(R.string.ingest_empty_device);
} else {
- hideWarningOverlay();
+ hideWarningView();
}
}
@@ -221,7 +379,7 @@ public class IngestActivity extends Activity implements
mActiveActionMode.finish();
mActiveActionMode = null;
}
- updateWarningOverlay();
+ updateWarningView();
}
protected void notifyIndexChanged() {
@@ -330,6 +488,7 @@ public class IngestActivity extends Activity implements
public static final int MSG_PROGRESS_UPDATE = 0;
public static final int MSG_PROGRESS_HIDE = 1;
public static final int MSG_NOTIFY_CHANGED = 2;
+ public static final int MSG_BULK_CHECKED_CHANGE = 3;
WeakReference<IngestActivity> mParentReference;
@@ -352,6 +511,9 @@ public class IngestActivity extends Activity implements
case MSG_NOTIFY_CHANGED:
parent.UiThreadNotifyIndexChanged();
break;
+ case MSG_BULK_CHECKED_CHANGE:
+ parent.mPositionMappingCheckBroker.onBulkCheckedChange();
+ break;
default:
break;
}
@@ -362,7 +524,9 @@ public class IngestActivity extends Activity implements
public void onServiceConnected(ComponentName className, IBinder service) {
mHelperService = ((IngestService.LocalBinder) service).getService();
mHelperService.setClientActivity(IngestActivity.this);
- mAdapter.setMtpDeviceIndex(mHelperService.getIndex());
+ MtpDeviceIndex index = mHelperService.getIndex();
+ mAdapter.setMtpDeviceIndex(index);
+ if (mPagerAdapter != null) mPagerAdapter.setMtpDeviceIndex(index);
}
public void onServiceDisconnected(ComponentName className) {
diff --git a/src/com/android/gallery3d/ingest/IngestService.java b/src/com/android/gallery3d/ingest/IngestService.java
index 12b056b60..5e0ca0b68 100644
--- a/src/com/android/gallery3d/ingest/IngestService.java
+++ b/src/com/android/gallery3d/ingest/IngestService.java
@@ -37,7 +37,7 @@ import android.widget.Adapter;
import com.android.gallery3d.R;
import com.android.gallery3d.app.NotificationIds;
import com.android.gallery3d.data.MtpClient;
-import com.android.gallery3d.ingest.ui.MtpBitmapCache;
+import com.android.gallery3d.ingest.data.MtpBitmapFetch;
import com.android.gallery3d.util.BucketNames;
import java.util.ArrayList;
@@ -66,6 +66,7 @@ public class IngestService extends Service implements ImportTask.Listener,
private boolean mRedeliverImportFinish = false;
private Collection<MtpObjectInfo> mRedeliverObjectsNotImported;
private boolean mRedeliverNotifyIndexChanged = false;
+ private boolean mRedeliverIndexFinish = false;
private NotificationManager mNotificationManager;
private NotificationCompat.Builder mNotificationBuilder;
private long mLastProgressIndexTime = 0;
@@ -108,13 +109,19 @@ public class IngestService extends Service implements ImportTask.Listener,
mRedeliverImportFinish = false;
mRedeliverObjectsNotImported = null;
mRedeliverNotifyIndexChanged = false;
+ mRedeliverIndexFinish = false;
mDevice = device;
mIndex.setDevice(mDevice);
if (mDevice != null) {
MtpDeviceInfo deviceInfo = mDevice.getDeviceInfo();
- mDevicePrettyName = deviceInfo.getModel();
- mNotificationBuilder.setContentTitle(mDevicePrettyName);
- new Thread(mIndex.getIndexRunnable()).start();
+ if (deviceInfo == null) {
+ setDevice(null);
+ return;
+ } else {
+ mDevicePrettyName = deviceInfo.getModel();
+ mNotificationBuilder.setContentTitle(mDevicePrettyName);
+ new Thread(mIndex.getIndexRunnable()).start();
+ }
} else {
mDevicePrettyName = null;
}
@@ -144,6 +151,10 @@ public class IngestService extends Service implements ImportTask.Listener,
mClientActivity.notifyIndexChanged();
mRedeliverNotifyIndexChanged = false;
}
+ if (mRedeliverIndexFinish) {
+ mClientActivity.onIndexFinish();
+ mRedeliverIndexFinish = false;
+ }
}
protected void importSelectedItems(SparseBooleanArray selected, Adapter adapter) {
@@ -176,8 +187,8 @@ public class IngestService extends Service implements ImportTask.Listener,
public void deviceRemoved(MtpDevice device) {
if (device == mDevice) {
setDevice(null);
+ MtpBitmapFetch.onDeviceDisconnected(device);
}
- MtpBitmapCache.onDeviceDisconnected(device);
}
@Override
@@ -197,6 +208,7 @@ public class IngestService extends Service implements ImportTask.Listener,
@Override
public void onImportFinish(Collection<MtpObjectInfo> objectsNotImported) {
+ stopForeground(true);
if (mClientActivity != null) {
mClientActivity.onImportFinish(objectsNotImported);
} else {
@@ -207,7 +219,6 @@ public class IngestService extends Service implements ImportTask.Listener,
mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_IMPORTING,
mNotificationBuilder.build());
}
- stopForeground(mClientActivity != null);
}
@Override
@@ -241,6 +252,7 @@ public class IngestService extends Service implements ImportTask.Listener,
.setContentText(getResources().getText(R.string.ingest_scanning_done));
mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING,
mNotificationBuilder.build());
+ mRedeliverIndexFinish = true;
}
}
diff --git a/src/com/android/gallery3d/ingest/MtpDeviceIndex.java b/src/com/android/gallery3d/ingest/MtpDeviceIndex.java
index 28e115ab0..e873dd1ca 100644
--- a/src/com/android/gallery3d/ingest/MtpDeviceIndex.java
+++ b/src/com/android/gallery3d/ingest/MtpDeviceIndex.java
@@ -180,55 +180,90 @@ public class MtpDeviceIndex {
* order
*/
public Object get(int position, SortOrder order) {
+ if (mProgress != Progress.Finished) return null;
if(order == SortOrder.Ascending) {
- return getAscending(position);
+ DateBucket bucket = mBuckets[mUnifiedLookupIndex[position]];
+ if (bucket.unifiedStartIndex == position) {
+ return bucket.bucket;
+ } else {
+ return mMtpObjects[bucket.itemsStartIndex + position - 1
+ - bucket.unifiedStartIndex];
+ }
} else {
- return getDescending(position);
+ int zeroIndex = mUnifiedLookupIndex.length - 1 - position;
+ DateBucket bucket = mBuckets[mUnifiedLookupIndex[zeroIndex]];
+ if (bucket.unifiedEndIndex == zeroIndex) {
+ return bucket.bucket;
+ } else {
+ return mMtpObjects[bucket.itemsStartIndex + zeroIndex
+ - bucket.unifiedStartIndex];
+ }
}
}
/**
- * @param position Index of item to fetch, where 0 is the first item in
- * ascending order
- * @return position-th item in ascending order
+ * @param position Index of item to fetch from a view of the data that doesn't
+ * include labels and is in the specified order
+ * @return position-th item in specified order, when not including labels
*/
- public Object getAscending(int position) {
+ public MtpObjectInfo getWithoutLabels(int position, SortOrder order) {
if (mProgress != Progress.Finished) return null;
- DateBucket bucket = mBuckets[mUnifiedLookupIndex[position]];
- if (bucket.unifiedStartIndex == position) {
- return bucket.bucket;
+ if (order == SortOrder.Ascending) {
+ return mMtpObjects[position];
} else {
- return bucket.get(position - 1 - bucket.unifiedStartIndex);
+ return mMtpObjects[mMtpObjects.length - 1 - position];
}
}
/**
- * @param position Index of item to fetch, where 0 is the last item in
- * ascending order
- * @return position-th item in descending order
+ * Although this is O(log(number of buckets)), and thus should not be used
+ * in hotspots, even if the attached device has items for every day for
+ * a five-year timeframe, it would still only take 11 iterations at most,
+ * so shouldn't be a huge issue.
+ * @param position Index of item to map from a view of the data that doesn't
+ * include labels and is in the specified order
+ * @param order
+ * @return position in a view of the data that does include labels
*/
- public Object getDescending(int position) {
- if (mProgress != Progress.Finished) return null;
- int zeroIndex = mUnifiedLookupIndex.length - 1 - position;
- DateBucket bucket = mBuckets[mUnifiedLookupIndex[zeroIndex]];
- if (bucket.unifiedEndIndex == zeroIndex) {
- return bucket.bucket;
- } else {
- return bucket.get(zeroIndex - bucket.unifiedStartIndex);
+ public int getPositionFromPositionWithoutLabels(int position, SortOrder order) {
+ if (mProgress != Progress.Finished) return -1;
+ if (order == SortOrder.Descending) {
+ position = mMtpObjects.length - 1 - position;
+ }
+ int bucketNumber = 0;
+ int iMin = 0;
+ int iMax = mBuckets.length - 1;
+ while (iMax >= iMin) {
+ int iMid = (iMax + iMin) / 2;
+ if (mBuckets[iMid].itemsStartIndex + mBuckets[iMid].numItems <= position) {
+ iMin = iMid + 1;
+ } else if (mBuckets[iMid].itemsStartIndex > position) {
+ iMax = iMid - 1;
+ } else {
+ bucketNumber = iMid;
+ break;
+ }
}
+ int mappedPos = mBuckets[bucketNumber].unifiedStartIndex
+ + position - mBuckets[bucketNumber].itemsStartIndex;
+ if (order == SortOrder.Descending) {
+ mappedPos = mUnifiedLookupIndex.length - 1 - mappedPos;
+ }
+ return mappedPos;
}
- /**
- * @param position Index of item to fetch from a view of the data that doesn't
- * include labels and is in ascending order
- * @return position-th item in ascending order, when not including labels
- */
- public MtpObjectInfo getWithoutLabels(int position, SortOrder order) {
- if (mProgress != Progress.Finished) return null;
- if (order == SortOrder.Ascending) {
- return mMtpObjects[position];
+ public int getPositionWithoutLabelsFromPosition(int position, SortOrder order) {
+ if (mProgress != Progress.Finished) return -1;
+ if(order == SortOrder.Ascending) {
+ DateBucket bucket = mBuckets[mUnifiedLookupIndex[position]];
+ if (bucket.unifiedStartIndex == position) position++;
+ return bucket.itemsStartIndex + position - 1 - bucket.unifiedStartIndex;
} else {
- return mMtpObjects[mMtpObjects.length - 1 - position];
+ int zeroIndex = mUnifiedLookupIndex.length - 1 - position;
+ DateBucket bucket = mBuckets[mUnifiedLookupIndex[zeroIndex]];
+ if (bucket.unifiedEndIndex == zeroIndex) zeroIndex--;
+ return mMtpObjects.length - 1 - bucket.itemsStartIndex
+ - zeroIndex + bucket.unifiedStartIndex;
}
}
@@ -288,6 +323,7 @@ public class MtpDeviceIndex {
int unifiedStartIndex;
int unifiedEndIndex;
int itemsStartIndex;
+ int numItems;
public DateBucket(SimpleDate bucket) {
this.bucket = bucket;
@@ -302,10 +338,6 @@ public class MtpDeviceIndex {
Collections.sort(tempElementsList, comparator);
}
- public MtpObjectInfo get(int position) {
- return mMtpObjects[itemsStartIndex + position];
- }
-
@Override
public String toString() {
return bucket.toString();
@@ -413,7 +445,8 @@ public class MtpDeviceIndex {
currentUnifiedIndexEntry = nextUnifiedEntry;
bucket.itemsStartIndex = currentItemsEntry;
- for (int j = 0; j < bucket.tempElementsList.size(); j++) {
+ bucket.numItems = bucket.tempElementsList.size();
+ for (int j = 0; j < bucket.numItems; j++) {
mMtpObjects[currentItemsEntry] = bucket.tempElementsList.get(j);
currentItemsEntry++;
}
diff --git a/src/com/android/gallery3d/ingest/adapter/CheckBroker.java b/src/com/android/gallery3d/ingest/adapter/CheckBroker.java
new file mode 100644
index 000000000..6783f23c5
--- /dev/null
+++ b/src/com/android/gallery3d/ingest/adapter/CheckBroker.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2013 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.ingest.adapter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public abstract class CheckBroker {
+ private Collection<OnCheckedChangedListener> mListeners =
+ new ArrayList<OnCheckedChangedListener>();
+
+ public interface OnCheckedChangedListener {
+ public void onCheckedChanged(int position, boolean isChecked);
+ public void onBulkCheckedChanged();
+ }
+
+ public abstract void setItemChecked(int position, boolean checked);
+
+ public void onCheckedChange(int position, boolean checked) {
+ if (isItemChecked(position) != checked) {
+ for (OnCheckedChangedListener l : mListeners) {
+ l.onCheckedChanged(position, checked);
+ }
+ }
+ }
+
+ public void onBulkCheckedChange() {
+ for (OnCheckedChangedListener l : mListeners) {
+ l.onBulkCheckedChanged();
+ }
+ }
+
+ public abstract boolean isItemChecked(int position);
+
+ public void registerOnCheckedChangeListener(OnCheckedChangedListener l) {
+ mListeners.add(l);
+ }
+
+ public void unregisterOnCheckedChangeListener(OnCheckedChangedListener l) {
+ mListeners.remove(l);
+ }
+}
diff --git a/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java b/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java
index 611d880db..e8dd69f8c 100644
--- a/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java
+++ b/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java
@@ -45,8 +45,7 @@ public class MtpAdapter extends BaseAdapter implements SectionIndexer {
public MtpAdapter(Activity context) {
super();
mContext = context;
- mInflater = (LayoutInflater)context.getSystemService
- (Context.LAYOUT_INFLATER_SERVICE);
+ mInflater = LayoutInflater.from(context);
}
public void setMtpDeviceIndex(MtpDeviceIndex index) {
@@ -54,6 +53,10 @@ public class MtpAdapter extends BaseAdapter implements SectionIndexer {
notifyDataSetChanged();
}
+ public MtpDeviceIndex getMtpDeviceIndex() {
+ return mModel;
+ }
+
@Override
public void notifyDataSetChanged() {
mGeneration++;
@@ -177,4 +180,13 @@ public class MtpAdapter extends BaseAdapter implements SectionIndexer {
public Object[] getSections() {
return getCount() > 0 ? mModel.getBuckets(mSortOrder) : null;
}
+
+ public SortOrder getSortOrder() {
+ return mSortOrder;
+ }
+
+ public int translatePositionWithoutLabels(int position) {
+ if (mModel == null) return -1;
+ return mModel.getPositionFromPositionWithoutLabels(position, mSortOrder);
+ }
}
diff --git a/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java b/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java
new file mode 100644
index 000000000..9e7abc01d
--- /dev/null
+++ b/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013 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.ingest.adapter;
+
+import android.content.Context;
+import android.mtp.MtpObjectInfo;
+import android.support.v4.view.PagerAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.ingest.MtpDeviceIndex;
+import com.android.gallery3d.ingest.MtpDeviceIndex.SortOrder;
+import com.android.gallery3d.ingest.ui.MtpFullscreenView;
+
+public class MtpPagerAdapter extends PagerAdapter {
+
+ private LayoutInflater mInflater;
+ private int mGeneration = 0;
+ private CheckBroker mBroker;
+ private MtpDeviceIndex mModel;
+ private SortOrder mSortOrder = SortOrder.Descending;
+
+ private MtpFullscreenView mReusableView = null;
+
+ public MtpPagerAdapter(Context context, CheckBroker broker) {
+ super();
+ mInflater = LayoutInflater.from(context);
+ mBroker = broker;
+ }
+
+ public void setMtpDeviceIndex(MtpDeviceIndex index) {
+ mModel = index;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getCount() {
+ return mModel != null ? mModel.sizeWithoutLabels() : 0;
+ }
+
+ @Override
+ public void notifyDataSetChanged() {
+ mGeneration++;
+ super.notifyDataSetChanged();
+ }
+
+ public int translatePositionWithLabels(int position) {
+ if (mModel == null) return -1;
+ return mModel.getPositionWithoutLabelsFromPosition(position, mSortOrder);
+ }
+
+ @Override
+ public void finishUpdate(ViewGroup container) {
+ mReusableView = null;
+ super.finishUpdate(container);
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view == object;
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ MtpFullscreenView v = (MtpFullscreenView)object;
+ container.removeView(v);
+ mBroker.unregisterOnCheckedChangeListener(v);
+ mReusableView = v;
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ MtpFullscreenView v;
+ if (mReusableView != null) {
+ v = mReusableView;
+ mReusableView = null;
+ } else {
+ v = (MtpFullscreenView) mInflater.inflate(R.layout.ingest_fullsize, container, false);
+ }
+ MtpObjectInfo i = mModel.getWithoutLabels(position, mSortOrder);
+ v.getImageView().setMtpDeviceAndObjectInfo(mModel.getDevice(), i, mGeneration);
+ v.setPositionAndBroker(position, mBroker);
+ container.addView(v);
+ return v;
+ }
+}
diff --git a/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java b/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java
new file mode 100644
index 000000000..bbc90f670
--- /dev/null
+++ b/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 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.ingest.data;
+
+import android.graphics.Bitmap;
+
+public class BitmapWithMetadata {
+ public Bitmap bitmap;
+ public int rotationDegrees;
+
+ public BitmapWithMetadata(Bitmap bitmap, int rotationDegrees) {
+ this.bitmap = bitmap;
+ this.rotationDegrees = rotationDegrees;
+ }
+}
diff --git a/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java b/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java
new file mode 100644
index 000000000..46a2051be
--- /dev/null
+++ b/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013 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.ingest.data;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.mtp.MtpDevice;
+import android.mtp.MtpObjectInfo;
+import android.util.DisplayMetrics;
+import android.view.WindowManager;
+
+import com.android.camera.Exif;
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.BitmapPool;
+
+import java.util.ArrayList;
+
+public class MtpBitmapFetch {
+ private static final int BITMAP_POOL_SIZE = 32;
+ private static BitmapPool sThumbnailPool = new BitmapPool(BITMAP_POOL_SIZE);
+ private static int sMaxSize = 0;
+
+ public static void recycleThumbnail(Bitmap b) {
+ if (b != null) {
+ sThumbnailPool.recycle(b);
+ }
+ }
+
+ public static Bitmap getThumbnail(MtpDevice device, MtpObjectInfo info) {
+ byte[] imageBytes = device.getThumbnail(info.getObjectHandle());
+ if (imageBytes == null) return null;
+ BitmapFactory.Options o = new BitmapFactory.Options();
+ o.inJustDecodeBounds = true;
+ BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
+ if (o.outWidth == 0 || o.outHeight == 0) return null;
+ o.inBitmap = sThumbnailPool.getBitmap(o.outWidth, o.outHeight);
+ o.inMutable = true;
+ o.inJustDecodeBounds = false;
+ o.inSampleSize = 1;
+ return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
+ }
+
+ public static BitmapWithMetadata getFullsize(MtpDevice device, MtpObjectInfo info) {
+ return getFullsize(device, info, sMaxSize);
+ }
+
+ public static BitmapWithMetadata getFullsize(MtpDevice device, MtpObjectInfo info, int maxSide) {
+ byte[] imageBytes = device.getObject(info.getObjectHandle(), info.getCompressedSize());
+ if (imageBytes == null) return null;
+ Bitmap created;
+ if (maxSide > 0) {
+ BitmapFactory.Options o = new BitmapFactory.Options();
+ o.inJustDecodeBounds = true;
+ BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
+ int w = o.outWidth;
+ int h = o.outHeight;
+ int comp = Math.max(h, w);
+ int sampleSize = 1;
+ while ((comp >> 1) >= maxSide) {
+ comp = comp >> 1;
+ sampleSize++;
+ }
+ o.inSampleSize = sampleSize;
+ o.inJustDecodeBounds = false;
+ created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o);
+ } else {
+ created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
+ }
+ if (created == null) return null;
+
+ return new BitmapWithMetadata(created, Exif.getOrientation(imageBytes));
+ }
+
+ public static void onDeviceDisconnected(MtpDevice device) {
+ sThumbnailPool.clear();
+ }
+
+ public static void configureForContext(Context context) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+ wm.getDefaultDisplay().getMetrics(metrics);
+ sMaxSize = Math.max(metrics.heightPixels, metrics.widthPixels);
+ }
+}
diff --git a/src/com/android/gallery3d/ingest/ui/IngestGridView.java b/src/com/android/gallery3d/ingest/ui/IngestGridView.java
new file mode 100644
index 000000000..c821259fe
--- /dev/null
+++ b/src/com/android/gallery3d/ingest/ui/IngestGridView.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 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.ingest.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.GridView;
+
+/**
+ * This just extends GridView with the ability to listen for calls
+ * to clearChoices()
+ */
+public class IngestGridView extends GridView {
+
+ public interface OnClearChoicesListener {
+ public void onClearChoices();
+ }
+
+ private OnClearChoicesListener mOnClearChoicesListener = null;
+
+ public IngestGridView(Context context) {
+ super(context);
+ }
+
+ public IngestGridView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public IngestGridView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public void setOnClearChoicesListener(OnClearChoicesListener l) {
+ mOnClearChoicesListener = l;
+ }
+
+ @Override
+ public void clearChoices() {
+ super.clearChoices();
+ if (mOnClearChoicesListener != null) {
+ mOnClearChoicesListener.onClearChoices();
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/ingest/ui/MtpBitmapCache.java b/src/com/android/gallery3d/ingest/ui/MtpBitmapCache.java
deleted file mode 100644
index 307531d5b..000000000
--- a/src/com/android/gallery3d/ingest/ui/MtpBitmapCache.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2013 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.ingest.ui;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.mtp.MtpDevice;
-import android.util.LruCache;
-
-public class MtpBitmapCache extends LruCache<Integer, Bitmap> {
- private static final int PER_DEVICE_CACHE_MAX_BYTES = 4194304;
- private static MtpBitmapCache sInstance;
-
- public synchronized static MtpBitmapCache getInstanceForDevice(MtpDevice device) {
- if (sInstance == null || sInstance.mDevice != device) {
- sInstance = new MtpBitmapCache(PER_DEVICE_CACHE_MAX_BYTES, device);
- }
- return sInstance;
- }
-
- public synchronized static void onDeviceDisconnected(MtpDevice device) {
- if (sInstance != null && sInstance.mDevice == device) {
- synchronized (sInstance) {
- sInstance.mDevice = null;
- }
- sInstance = null;
- }
- }
-
- private MtpDevice mDevice;
-
- private MtpBitmapCache(int maxSize, MtpDevice device) {
- super(maxSize);
- mDevice = device;
- }
-
- @Override
- protected int sizeOf(Integer key, Bitmap value) {
- return value.getByteCount();
- }
-
- public Bitmap getOrCreate(Integer key) {
- Bitmap b = get(key);
- return b == null ? createAndInsert(key) : b;
- }
-
- private Bitmap createAndInsert(Integer key) {
- MtpDevice device;
- synchronized (this) {
- device = mDevice;
- }
- if (device == null) return null;
- byte[] imageBytes = device.getThumbnail(key);
- if (imageBytes == null) return null;
- Bitmap created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
- put(key, created);
- return created;
- }
-}
diff --git a/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java b/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java
new file mode 100644
index 000000000..8d3884dc6
--- /dev/null
+++ b/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2013 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.ingest.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.CheckBox;
+import android.widget.Checkable;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.RelativeLayout;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.ingest.adapter.CheckBroker;
+
+public class MtpFullscreenView extends RelativeLayout implements Checkable,
+ CompoundButton.OnCheckedChangeListener, CheckBroker.OnCheckedChangedListener {
+
+ private MtpImageView mImageView;
+ private CheckBox mCheckbox;
+ private int mPosition = -1;
+ private CheckBroker mBroker;
+
+ public MtpFullscreenView(Context context) {
+ super(context);
+ }
+
+ public MtpFullscreenView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public MtpFullscreenView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mImageView = (MtpImageView) findViewById(R.id.ingest_fullsize_image);
+ mCheckbox = (CheckBox) findViewById(R.id.ingest_fullsize_image_checkbox);
+ mCheckbox.setOnCheckedChangeListener(this);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mCheckbox.isChecked();
+ }
+
+ @Override
+ public void setChecked(boolean checked) {
+ mCheckbox.setChecked(checked);
+ }
+
+ @Override
+ public void toggle() {
+ mCheckbox.toggle();
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ setPositionAndBroker(-1, null);
+ super.onDetachedFromWindow();
+ }
+
+ public MtpImageView getImageView() {
+ return mImageView;
+ }
+
+ public int getPosition() {
+ return mPosition;
+ }
+
+ public void setPositionAndBroker(int position, CheckBroker b) {
+ if (mBroker != null) {
+ mBroker.unregisterOnCheckedChangeListener(this);
+ }
+ mPosition = position;
+ mBroker = b;
+ if (mBroker != null) {
+ setChecked(mBroker.isItemChecked(position));
+ mBroker.registerOnCheckedChangeListener(this);
+ }
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton arg0, boolean isChecked) {
+ if (mBroker != null) mBroker.setItemChecked(mPosition, isChecked);
+ }
+
+ @Override
+ public void onCheckedChanged(int position, boolean isChecked) {
+ if (position == mPosition) {
+ setChecked(isChecked);
+ }
+ }
+
+ @Override
+ public void onBulkCheckedChanged() {
+ if(mBroker != null) setChecked(mBroker.isItemChecked(mPosition));
+ }
+}
diff --git a/src/com/android/gallery3d/ingest/ui/MtpImageView.java b/src/com/android/gallery3d/ingest/ui/MtpImageView.java
new file mode 100644
index 000000000..5664d8a34
--- /dev/null
+++ b/src/com/android/gallery3d/ingest/ui/MtpImageView.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2013 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.ingest.ui;
+
+import android.content.Context;
+import android.mtp.MtpDevice;
+import android.mtp.MtpObjectInfo;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import com.android.gallery3d.ingest.data.BitmapWithMetadata;
+import com.android.gallery3d.ingest.data.MtpBitmapFetch;
+
+import java.lang.ref.WeakReference;
+
+public class MtpImageView extends ImageView {
+ private int mObjectHandle;
+ private int mGeneration;
+
+ private WeakReference<MtpImageView> mWeakReference = new WeakReference<MtpImageView>(this);
+ private Object mFetchLock = new Object();
+ private boolean mFetchPending = false;
+ private MtpObjectInfo mFetchObjectInfo;
+ private MtpDevice mFetchDevice;
+ private Object mFetchResult;
+
+ private static final FetchImageHandler sFetchHandler = FetchImageHandler.createOnNewThread();
+ private static final ShowImageHandler sFetchCompleteHandler = new ShowImageHandler();
+
+ private void init() {
+ showPlaceholder();
+ }
+
+ public MtpImageView(Context context) {
+ super(context);
+ init();
+ }
+
+ public MtpImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public MtpImageView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void showPlaceholder() {
+ setImageResource(android.R.color.transparent);
+ }
+
+ public void setMtpDeviceAndObjectInfo(MtpDevice device, MtpObjectInfo object, int gen) {
+ int handle = object.getObjectHandle();
+ if (handle == mObjectHandle && gen == mGeneration) {
+ return;
+ }
+ cancelLoadingAndClear();
+ showPlaceholder();
+ mGeneration = gen;
+ mObjectHandle = handle;
+ synchronized (mFetchLock) {
+ mFetchObjectInfo = object;
+ mFetchDevice = device;
+ if (mFetchPending) return;
+ mFetchPending = true;
+ sFetchHandler.sendMessage(
+ sFetchHandler.obtainMessage(0, mWeakReference));
+ }
+ }
+
+ protected Object fetchMtpImageDataFromDevice(MtpDevice device, MtpObjectInfo info) {
+ return MtpBitmapFetch.getFullsize(device, info);
+ }
+
+ protected void onMtpImageDataFetchedFromDevice(Object result) {
+ BitmapWithMetadata bitmapWithMetadata = (BitmapWithMetadata)result;
+ setImageBitmap(bitmapWithMetadata.bitmap);
+ setRotation(bitmapWithMetadata.rotationDegrees);
+ }
+
+ protected void cancelLoadingAndClear() {
+ synchronized (mFetchLock) {
+ mFetchDevice = null;
+ mFetchObjectInfo = null;
+ mFetchResult = null;
+ }
+ setImageResource(android.R.color.transparent);
+ setRotation(0);
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ cancelLoadingAndClear();
+ super.onDetachedFromWindow();
+ }
+
+ private static class FetchImageHandler extends Handler {
+ public FetchImageHandler(Looper l) {
+ super(l);
+ }
+
+ public static FetchImageHandler createOnNewThread() {
+ HandlerThread t = new HandlerThread("MtpImageView Fetch");
+ t.start();
+ return new FetchImageHandler(t.getLooper());
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ @SuppressWarnings("unchecked")
+ MtpImageView parent = ((WeakReference<MtpImageView>) msg.obj).get();
+ if (parent == null) return;
+ MtpObjectInfo objectInfo;
+ MtpDevice device;
+ synchronized (parent.mFetchLock) {
+ parent.mFetchPending = false;
+ device = parent.mFetchDevice;
+ objectInfo = parent.mFetchObjectInfo;
+ }
+ if (device == null) return;
+ Object result = parent.fetchMtpImageDataFromDevice(device, objectInfo);
+ if (result == null) return;
+ synchronized (parent.mFetchLock) {
+ if (parent.mFetchObjectInfo != objectInfo) return;
+ parent.mFetchResult = result;
+ parent.mFetchDevice = null;
+ parent.mFetchObjectInfo = null;
+ sFetchCompleteHandler.sendMessage(
+ sFetchCompleteHandler.obtainMessage(0, parent.mWeakReference));
+ }
+ }
+ }
+
+ private static class ShowImageHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ @SuppressWarnings("unchecked")
+ MtpImageView parent = ((WeakReference<MtpImageView>) msg.obj).get();
+ if (parent == null) return;
+ Object result;
+ synchronized (parent.mFetchLock) {
+ result = parent.mFetchResult;
+ }
+ if (result == null) return;
+ parent.onMtpImageDataFetchedFromDevice(result);
+ }
+ }
+}
diff --git a/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java b/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java
index 2aeda73db..3307e78aa 100644
--- a/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java
+++ b/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java
@@ -22,26 +22,22 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.mtp.MtpDevice;
import android.mtp.MtpObjectInfo;
-import android.os.AsyncTask;
import android.util.AttributeSet;
-import android.view.View;
import android.widget.Checkable;
-import android.widget.ImageView;
import com.android.gallery3d.R;
+import com.android.gallery3d.ingest.data.MtpBitmapFetch;
-public class MtpThumbnailTileView extends ImageView implements Checkable {
- private static final int FADE_IN_TIME_MS = 80;
+
+public class MtpThumbnailTileView extends MtpImageView implements Checkable {
private Paint mForegroundPaint;
private boolean mIsChecked;
- private int mObjectHandle;
- private int mGeneration;
+ private Bitmap mBitmap;
private void init() {
mForegroundPaint = new Paint();
mForegroundPaint.setColor(getResources().getColor(R.color.ingest_highlight_semitransparent));
- showPlaceholder();
}
public MtpThumbnailTileView(Context context) {
@@ -66,9 +62,20 @@ public class MtpThumbnailTileView extends ImageView implements Checkable {
}
@Override
+ protected Object fetchMtpImageDataFromDevice(MtpDevice device, MtpObjectInfo info) {
+ return MtpBitmapFetch.getThumbnail(device, info);
+ }
+
+ @Override
+ protected void onMtpImageDataFetchedFromDevice(Object result) {
+ mBitmap = (Bitmap)result;
+ setImageBitmap(mBitmap);
+ }
+
+ @Override
public void draw(Canvas canvas) {
super.draw(canvas);
- if (mIsChecked) {
+ if (isChecked()) {
canvas.drawRect(canvas.getClipBounds(), mForegroundPaint);
}
}
@@ -88,65 +95,12 @@ public class MtpThumbnailTileView extends ImageView implements Checkable {
setChecked(!mIsChecked);
}
- private void showPlaceholder() {
- setAlpha(0f);
- }
-
- private LoadThumbnailTask mTask;
-
- public void setMtpDeviceAndObjectInfo(MtpDevice device, MtpObjectInfo object, int gen) {
- int handle = object.getObjectHandle();
- if (handle == mObjectHandle && gen == mGeneration) {
- return;
- }
- animate().cancel();
- if (mTask != null) {
- mTask.cancel(true);
- }
- mGeneration = gen;
- mObjectHandle = handle;
- Bitmap thumbnail = MtpBitmapCache.getInstanceForDevice(device)
- .get(handle);
- if (thumbnail != null) {
- setAlpha(1f);
- setImageBitmap(thumbnail);
- } else {
- showPlaceholder();
- mTask = new LoadThumbnailTask(device);
- mTask.execute(object);
- }
- }
-
- private class LoadThumbnailTask extends AsyncTask<MtpObjectInfo, Void, Bitmap> {
- private MtpDevice mDevice;
-
- public LoadThumbnailTask(MtpDevice device) {
- mDevice = device;
- }
-
- @Override
- protected Bitmap doInBackground(MtpObjectInfo... args) {
- Bitmap result = null;
- if (!isCancelled()) {
- result = MtpBitmapCache.getInstanceForDevice(mDevice).getOrCreate(
- args[0].getObjectHandle());
- }
- mDevice = null;
- return result;
- }
-
- @Override
- protected void onPostExecute(Bitmap result) {
- if (isCancelled() || result == null) {
- return;
- }
- setAlpha(0f);
- setImageBitmap(result);
- animate().alpha(1f).setDuration(FADE_IN_TIME_MS);
- }
-
- @Override
- protected void onCancelled() {
+ @Override
+ protected void cancelLoadingAndClear() {
+ super.cancelLoadingAndClear();
+ if (mBitmap != null) {
+ MtpBitmapFetch.recycleThumbnail(mBitmap);
+ mBitmap = null;
}
}
}
diff --git a/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java b/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
index 5c1d004b6..67ccf9c80 100644
--- a/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
+++ b/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
@@ -26,6 +26,7 @@ public class EditorManager {
public static void addEditors(EditorPlaceHolder editorPlaceHolder) {
editorPlaceHolder.addEditor(new EditorZoom());
editorPlaceHolder.addEditor(new EditorCurves());
+ editorPlaceHolder.addEditor(new EditorTinyPlanet());
editorPlaceHolder.addEditor(new EditorDraw());
}
diff --git a/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java b/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
index 915041bb9..988cf2d81 100644
--- a/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
+++ b/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
@@ -16,33 +16,13 @@
package com.android.gallery3d.filtershow.filters;
-import android.util.Log;
+public class FiltersManager extends BaseFiltersManager {
+ private static FiltersManager gInstance = null;
-import com.android.gallery3d.filtershow.cache.ImageLoader;
-
-import java.util.Vector;
-
-public class FiltersManager {
-
- private static final String LOGTAG = "FiltersManager";
-
- public static void addFilters(Vector<ImageFilter> filters, ImageLoader imageLoader) {
- filters.add(new ImageFilterTinyPlanet());
- filters.add(new ImageFilterWBalance());
- filters.add(new ImageFilterExposure());
- filters.add(new ImageFilterVignette());
- filters.add(new ImageFilterContrast());
- filters.add(new ImageFilterShadows());
- filters.add(new ImageFilterVibrance());
- filters.add(new ImageFilterSharpen());
- filters.add(new ImageFilterCurves());
- filters.add(new ImageFilterDraw());
- filters.add(new ImageFilterHue());
- filters.add(new ImageFilterSaturated());
- filters.add(new ImageFilterBwFilter());
- filters.add(new ImageFilterNegative());
- filters.add(new ImageFilterEdge());
- filters.add(new ImageFilterKMeans());
- filters.add(new ImageFilterDownsample(imageLoader));
+ public static FiltersManager getManager() {
+ if (gInstance == null) {
+ gInstance = new FiltersManager();
+ }
+ return gInstance;
}
}
diff --git a/tests/src/com/android/gallery3d/CameraTestRunner.java b/tests/src/com/android/gallery3d/CameraTestRunner.java
new file mode 100755
index 000000000..503233675
--- /dev/null
+++ b/tests/src/com/android/gallery3d/CameraTestRunner.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 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;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+
+import com.android.gallery3d.functional.CameraTest;
+import com.android.gallery3d.functional.ImageCaptureIntentTest;
+import com.android.gallery3d.functional.VideoCaptureIntentTest;
+import com.android.gallery3d.unittest.CameraUnitTest;
+
+import junit.framework.TestSuite;
+
+
+public class CameraTestRunner extends InstrumentationTestRunner {
+
+ @Override
+ public TestSuite getAllTests() {
+ TestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(CameraTest.class);
+ suite.addTestSuite(ImageCaptureIntentTest.class);
+ suite.addTestSuite(VideoCaptureIntentTest.class);
+ suite.addTestSuite(CameraUnitTest.class);
+ return suite;
+ }
+
+ @Override
+ public ClassLoader getLoader() {
+ return CameraTestRunner.class.getClassLoader();
+ }
+}
diff --git a/tests/src/com/android/gallery3d/StressTests.java b/tests/src/com/android/gallery3d/StressTests.java
new file mode 100755
index 000000000..32eefdcec
--- /dev/null
+++ b/tests/src/com/android/gallery3d/StressTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 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;
+
+import com.android.gallery3d.stress.CameraLatency;
+import com.android.gallery3d.stress.CameraStartUp;
+import com.android.gallery3d.stress.ImageCapture;
+import com.android.gallery3d.stress.SwitchPreview;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * Instrumentation Test Runner for all Camera tests.
+ *
+ * Running all tests:
+ *
+ * adb shell am instrument \
+ * -e class com.android.gallery3d.StressTests \
+ * -w com.google.android.gallery3d.tests/com.android.gallery3d.stress.CameraStressTestRunner
+ */
+
+public class StressTests extends TestSuite {
+ public static Test suite() {
+ TestSuite result = new TestSuite();
+ result.addTestSuite(CameraLatency.class);
+ result.addTestSuite(CameraStartUp.class);
+ result.addTestSuite(ImageCapture.class);
+ result.addTestSuite(SwitchPreview.class);
+ return result;
+ }
+}
diff --git a/tests/src/com/android/gallery3d/functional/CameraTest.java b/tests/src/com/android/gallery3d/functional/CameraTest.java
new file mode 100644
index 000000000..c293c0d4a
--- /dev/null
+++ b/tests/src/com/android/gallery3d/functional/CameraTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.functional;
+
+import com.android.camera.CameraActivity;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.Process;
+import android.provider.MediaStore;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import java.io.File;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+
+public class CameraTest extends InstrumentationTestCase {
+ @LargeTest
+ public void testVideoCaptureIntentFdLeak() throws Exception {
+ Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+ intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.parse("file://"
+ + Environment.getExternalStorageDirectory().toString()
+ + "test_fd_leak.3gp"));
+ getInstrumentation().startActivitySync(intent).finish();
+ // Test if the fd is closed.
+ for (File f: new File("/proc/" + Process.myPid() + "/fd").listFiles()) {
+ assertEquals(-1, f.getCanonicalPath().indexOf("test_fd_leak.3gp"));
+ }
+ }
+
+ @LargeTest
+ public void testActivityLeak() throws Exception {
+ checkActivityLeak(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+ checkActivityLeak(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
+ }
+
+ private void checkActivityLeak(String action) throws Exception {
+ final int TEST_COUNT = 5;
+ Intent intent = new Intent(action);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setClass(getInstrumentation().getTargetContext(),
+ CameraActivity.class);
+ ArrayList<WeakReference<Activity>> refs =
+ new ArrayList<WeakReference<Activity>>();
+ for (int i = 0; i < TEST_COUNT; i++) {
+ Activity activity = getInstrumentation().startActivitySync(intent);
+ refs.add(new WeakReference<Activity>(activity));
+ activity.finish();
+ getInstrumentation().waitForIdleSync();
+ activity = null;
+ }
+ Runtime.getRuntime().gc();
+ Runtime.getRuntime().runFinalization();
+ Runtime.getRuntime().gc();
+ int refCount = 0;
+ for (WeakReference<Activity> c: refs) {
+ if (c.get() != null) refCount++;
+ }
+ // If applications are leaking activity, every reference is reachable.
+ assertTrue(refCount != TEST_COUNT);
+ }
+}
diff --git a/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java b/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java
new file mode 100644
index 000000000..c2eeabcce
--- /dev/null
+++ b/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2011 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.functional;
+
+import com.android.camera.CameraActivity;
+import com.android.camera.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.KeyEvent;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+
+public class ImageCaptureIntentTest extends ActivityInstrumentationTestCase2 <CameraActivity> {
+ private Intent mIntent;
+
+ public ImageCaptureIntentTest() {
+ super(CameraActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ }
+
+ @LargeTest
+ public void testNoExtraOutput() throws Exception {
+ setActivityIntent(mIntent);
+ getActivity();
+
+ takePicture();
+ pressDone();
+
+ assertTrue(getActivity().isFinishing());
+ assertEquals(Activity.RESULT_OK, getActivity().getResultCode());
+ Intent resultData = getActivity().getResultData();
+ Bitmap bitmap = (Bitmap) resultData.getParcelableExtra("data");
+ assertNotNull(bitmap);
+ assertTrue(bitmap.getWidth() > 0);
+ assertTrue(bitmap.getHeight() > 0);
+ }
+
+ @LargeTest
+ public void testExtraOutput() throws Exception {
+ File file = new File(Environment.getExternalStorageDirectory(),
+ "test.jpg");
+ BufferedInputStream stream = null;
+ byte[] jpegData;
+
+ try {
+ mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
+ setActivityIntent(mIntent);
+ getActivity();
+
+ takePicture();
+ pressDone();
+
+ assertTrue(getActivity().isFinishing());
+ assertEquals(Activity.RESULT_OK, getActivity().getResultCode());
+
+ // Verify the jpeg file
+ int fileLength = (int) file.length();
+ assertTrue(fileLength > 0);
+ jpegData = new byte[fileLength];
+ stream = new BufferedInputStream(new FileInputStream(file));
+ stream.read(jpegData);
+ } finally {
+ if (stream != null) stream.close();
+ file.delete();
+ }
+
+ Bitmap b = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length);
+ assertTrue(b.getWidth() > 0);
+ assertTrue(b.getHeight() > 0);
+ }
+
+ @LargeTest
+ public void testCancel() throws Exception {
+ setActivityIntent(mIntent);
+ getActivity();
+
+ pressCancel();
+
+ assertTrue(getActivity().isFinishing());
+ assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode());
+ }
+
+ @LargeTest
+ public void testSnapshotCancel() throws Exception {
+ setActivityIntent(mIntent);
+ getActivity();
+
+ takePicture();
+ pressCancel();
+
+ assertTrue(getActivity().isFinishing());
+ assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode());
+ }
+
+ private void takePicture() throws Exception {
+ getInstrumentation().sendKeySync(
+ new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS));
+ getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
+ Thread.sleep(4000);
+ }
+
+ private void pressDone() {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().findViewById(R.id.btn_done).performClick();
+ }
+ });
+ }
+
+ private void pressCancel() {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().findViewById(R.id.btn_cancel).performClick();
+ }
+ });
+ }
+}
diff --git a/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java b/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java
new file mode 100644
index 000000000..3802060e2
--- /dev/null
+++ b/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2011 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.functional;
+
+import com.android.camera.CameraActivity;
+import com.android.camera.R;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.database.Cursor;
+import android.media.MediaMetadataRetriever;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.provider.MediaStore.Video.VideoColumns;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import java.io.File;
+
+public class VideoCaptureIntentTest extends ActivityInstrumentationTestCase2 <CameraActivity> {
+ private static final String TAG = "VideoCaptureIntentTest";
+ private Intent mIntent;
+ private Uri mVideoUri;
+ private File mFile, mFile2;
+
+ public VideoCaptureIntentTest() {
+ super(CameraActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (mVideoUri != null) {
+ ContentResolver resolver = getActivity().getContentResolver();
+ Uri query = mVideoUri.buildUpon().build();
+ String[] projection = new String[] {VideoColumns.DATA};
+
+ Cursor cursor = null;
+ try {
+ cursor = resolver.query(query, projection, null, null, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ new File(cursor.getString(0)).delete();
+ }
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+
+ resolver.delete(mVideoUri, null, null);
+ }
+ if (mFile != null) mFile.delete();
+ if (mFile2 != null) mFile2.delete();
+ super.tearDown();
+ }
+
+ @LargeTest
+ public void testNoExtraOutput() throws Exception {
+ setActivityIntent(mIntent);
+ getActivity();
+
+ recordVideo();
+ pressDone();
+
+ Intent resultData = getActivity().getResultData();
+ mVideoUri = resultData.getData();
+ assertNotNull(mVideoUri);
+ verify(getActivity(), mVideoUri);
+ }
+
+ @LargeTest
+ public void testExtraOutput() throws Exception {
+ mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
+
+ Uri uri = Uri.fromFile(mFile);
+ mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
+ setActivityIntent(mIntent);
+ getActivity();
+
+ recordVideo();
+ pressDone();
+
+ verify(getActivity(), uri);
+ }
+
+ @LargeTest
+ public void testCancel() throws Exception {
+ setActivityIntent(mIntent);
+ getActivity();
+
+ pressCancel();
+
+ assertTrue(getActivity().isFinishing());
+ assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode());
+ }
+
+ @LargeTest
+ public void testRecordCancel() throws Exception {
+ setActivityIntent(mIntent);
+ getActivity();
+
+ recordVideo();
+ pressCancel();
+
+ assertTrue(getActivity().isFinishing());
+ assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode());
+ }
+
+ @LargeTest
+ public void testExtraSizeLimit() throws Exception {
+ mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
+ final long sizeLimit = 500000; // bytes
+
+ Uri uri = Uri.fromFile(mFile);
+ mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
+ mIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, sizeLimit);
+ mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); // use low quality to speed up
+ setActivityIntent(mIntent);
+ getActivity();
+
+ recordVideo(5000);
+ pressDone();
+
+ verify(getActivity(), uri);
+ long length = mFile.length();
+ Log.v(TAG, "Video size is " + length + " bytes.");
+ assertTrue(length > 0);
+ assertTrue("Actual size=" + length, length <= sizeLimit);
+ }
+
+ @LargeTest
+ public void testExtraDurationLimit() throws Exception {
+ mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
+ final int durationLimit = 2; // seconds
+
+ Uri uri = Uri.fromFile(mFile);
+ mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
+ mIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationLimit);
+ setActivityIntent(mIntent);
+ getActivity();
+
+ recordVideo(5000);
+ pressDone();
+
+ int duration = verify(getActivity(), uri);
+ // The duraion should be close to to the limit. The last video duration
+ // also has duration, so the total duration may exceeds the limit a
+ // little bit.
+ Log.v(TAG, "Video length is " + duration + " ms.");
+ assertTrue(duration < (durationLimit + 1) * 1000);
+ }
+
+ @LargeTest
+ public void testExtraVideoQuality() throws Exception {
+ mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp");
+ mFile2 = new File(Environment.getExternalStorageDirectory(), "video2.tmp");
+
+ Uri uri = Uri.fromFile(mFile);
+ mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
+ mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); // low quality
+ setActivityIntent(mIntent);
+ getActivity();
+
+ recordVideo();
+ pressDone();
+
+ verify(getActivity(), uri);
+ setActivity(null);
+
+ uri = Uri.fromFile(mFile2);
+ mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
+ mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // high quality
+ setActivityIntent(mIntent);
+ getActivity();
+
+ recordVideo();
+ pressDone();
+
+ verify(getActivity(), uri);
+ assertTrue(mFile.length() <= mFile2.length());
+ }
+
+ // Verify result code, result data, and the duration.
+ private int verify(CameraActivity activity, Uri uri) throws Exception {
+ assertTrue(activity.isFinishing());
+ assertEquals(Activity.RESULT_OK, activity.getResultCode());
+
+ // Verify the video file
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ retriever.setDataSource(activity, uri);
+ String duration = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_DURATION);
+ assertNotNull(duration);
+ int durationValue = Integer.parseInt(duration);
+ Log.v(TAG, "Video duration is " + durationValue);
+ assertTrue(durationValue > 0);
+ return durationValue;
+ }
+
+ private void recordVideo(int ms) throws Exception {
+ getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
+ Thread.sleep(ms);
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ // If recording is in progress, stop it. Run these atomically in
+ // UI thread.
+ CameraActivity activity = getActivity();
+ if (activity.isRecording()) {
+ activity.findViewById(R.id.shutter_button).performClick();
+ }
+ }
+ });
+ }
+
+ private void recordVideo() throws Exception {
+ recordVideo(2000);
+ }
+
+ private void pressDone() {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().findViewById(R.id.btn_done).performClick();
+ }
+ });
+ }
+
+ private void pressCancel() {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().findViewById(R.id.btn_cancel).performClick();
+ }
+ });
+ }
+}
diff --git a/tests/src/com/android/gallery3d/power/ImageAndVideoCapture.java b/tests/src/com/android/gallery3d/power/ImageAndVideoCapture.java
new file mode 100755
index 000000000..cd5079355
--- /dev/null
+++ b/tests/src/com/android/gallery3d/power/ImageAndVideoCapture.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2009 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.power;
+
+import com.android.camera.CameraActivity;
+
+import android.app.Instrumentation;
+import android.provider.MediaStore;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.content.Intent;
+/**
+ * Junit / Instrumentation test case for camera power measurement
+ *
+ * Running the test suite:
+ *
+ * adb shell am instrument \
+ * -e com.android.camera.power.ImageAndVideoCapture \
+ * -w com.android.camera.tests/android.test.InstrumentationTestRunner
+ *
+ */
+
+public class ImageAndVideoCapture extends ActivityInstrumentationTestCase2 <CameraActivity> {
+ private String TAG = "ImageAndVideoCapture";
+ private static final int TOTAL_NUMBER_OF_IMAGECAPTURE = 5;
+ private static final int TOTAL_NUMBER_OF_VIDEOCAPTURE = 5;
+ private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 1500; //1.5 sedconds
+ private static final long WAIT_FOR_VIDEO_CAPTURE_TO_BE_TAKEN = 10000; //10 seconds
+ private static final long WAIT_FOR_PREVIEW = 1500; //1.5 seconds
+ private static final long WAIT_FOR_STABLE_STATE = 2000; //2 seconds
+
+ public ImageAndVideoCapture() {
+ super(CameraActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ getActivity();
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @LargeTest
+ public void testLaunchCamera() {
+ // This test case capture the baseline for the image preview.
+ try {
+ Thread.sleep(WAIT_FOR_STABLE_STATE);
+ } catch (Exception e) {
+ Log.v(TAG, "Got exception", e);
+ assertTrue("testImageCaptureDoNothing", false);
+ }
+ }
+
+ @LargeTest
+ public void testCapture5Image() {
+ // This test case will use the default camera setting
+ Instrumentation inst = getInstrumentation();
+ try {
+ for (int i = 0; i < TOTAL_NUMBER_OF_IMAGECAPTURE; i++) {
+ Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
+ inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP);
+ inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
+ Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
+ }
+ Thread.sleep(WAIT_FOR_STABLE_STATE);
+ } catch (Exception e) {
+ Log.v(TAG, "Got exception", e);
+ assertTrue("testImageCapture", false);
+ }
+ }
+
+ @LargeTest
+ public void testCapture5Videos() {
+ // This test case will use the default camera setting
+ Instrumentation inst = getInstrumentation();
+ try {
+ // Switch to the video mode
+ Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
+ intent.setClass(getInstrumentation().getTargetContext(),
+ CameraActivity.class);
+ getActivity().startActivity(intent);
+ for (int i = 0; i < TOTAL_NUMBER_OF_VIDEOCAPTURE; i++) {
+ Thread.sleep(WAIT_FOR_PREVIEW);
+ // record a video
+ inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
+ Thread.sleep(WAIT_FOR_VIDEO_CAPTURE_TO_BE_TAKEN);
+ inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
+ Thread.sleep(WAIT_FOR_PREVIEW);
+ }
+ Thread.sleep(WAIT_FOR_STABLE_STATE);
+ } catch (Exception e) {
+ Log.v(TAG, "Got exception", e);
+ assertTrue("testVideoCapture", false);
+ }
+ }
+}
diff --git a/tests/src/com/android/gallery3d/stress/CameraLatency.java b/tests/src/com/android/gallery3d/stress/CameraLatency.java
new file mode 100755
index 000000000..7177abe6c
--- /dev/null
+++ b/tests/src/com/android/gallery3d/stress/CameraLatency.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2009 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.stress;
+
+import com.android.camera.CameraActivity;
+
+import android.app.Instrumentation;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+
+/**
+ * Junit / Instrumentation test case for camera test
+ *
+ */
+
+public class CameraLatency extends ActivityInstrumentationTestCase2 <CameraActivity> {
+ private String TAG = "CameraLatency";
+ private static final int TOTAL_NUMBER_OF_IMAGECAPTURE = 20;
+ private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 4000;
+ private static final String CAMERA_TEST_OUTPUT_FILE =
+ Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
+
+ private long mTotalAutoFocusTime;
+ private long mTotalShutterLag;
+ private long mTotalShutterToPictureDisplayedTime;
+ private long mTotalPictureDisplayedToJpegCallbackTime;
+ private long mTotalJpegCallbackFinishTime;
+ private long mAvgAutoFocusTime;
+ private long mAvgShutterLag = mTotalShutterLag;
+ private long mAvgShutterToPictureDisplayedTime;
+ private long mAvgPictureDisplayedToJpegCallbackTime;
+ private long mAvgJpegCallbackFinishTime;
+
+ public CameraLatency() {
+ super(CameraActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ getActivity();
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @LargeTest
+ public void testImageCapture() {
+ Log.v(TAG, "start testImageCapture test");
+ Instrumentation inst = getInstrumentation();
+ inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
+ try {
+ for (int i = 0; i < TOTAL_NUMBER_OF_IMAGECAPTURE; i++) {
+ Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
+ inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
+ Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
+ //skip the first measurement
+ if (i != 0) {
+ CameraActivity c = getActivity();
+
+ // if any of the latency var accessor methods return -1 then the
+ // camera is set to a different module other than PhotoModule so
+ // skip the shot and try again
+ if (c.getAutoFocusTime() != -1) {
+ mTotalAutoFocusTime += c.getAutoFocusTime();
+ mTotalShutterLag += c.getShutterLag();
+ mTotalShutterToPictureDisplayedTime +=
+ c.getShutterToPictureDisplayedTime();
+ mTotalPictureDisplayedToJpegCallbackTime +=
+ c.getPictureDisplayedToJpegCallbackTime();
+ mTotalJpegCallbackFinishTime += c.getJpegCallbackFinishTime();
+ }
+ else {
+ i--;
+ continue;
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.v(TAG, "Got exception", e);
+ }
+ //ToDO: yslau
+ //1) Need to get the baseline from the cupcake so that we can add the
+ //failure condition of the camera latency.
+ //2) Only count those number with succesful capture. Set the timer to invalid
+ //before capture and ignore them if the value is invalid
+ int numberofRun = TOTAL_NUMBER_OF_IMAGECAPTURE - 1;
+ mAvgAutoFocusTime = mTotalAutoFocusTime / numberofRun;
+ mAvgShutterLag = mTotalShutterLag / numberofRun;
+ mAvgShutterToPictureDisplayedTime =
+ mTotalShutterToPictureDisplayedTime / numberofRun;
+ mAvgPictureDisplayedToJpegCallbackTime =
+ mTotalPictureDisplayedToJpegCallbackTime / numberofRun;
+ mAvgJpegCallbackFinishTime =
+ mTotalJpegCallbackFinishTime / numberofRun;
+
+ try {
+ FileWriter fstream = null;
+ fstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true);
+ BufferedWriter out = new BufferedWriter(fstream);
+ out.write("Camera Latency : \n");
+ out.write("Number of loop: " + TOTAL_NUMBER_OF_IMAGECAPTURE + "\n");
+ out.write("Avg AutoFocus = " + mAvgAutoFocusTime + "\n");
+ out.write("Avg mShutterLag = " + mAvgShutterLag + "\n");
+ out.write("Avg mShutterToPictureDisplayedTime = "
+ + mAvgShutterToPictureDisplayedTime + "\n");
+ out.write("Avg mPictureDisplayedToJpegCallbackTime = "
+ + mAvgPictureDisplayedToJpegCallbackTime + "\n");
+ out.write("Avg mJpegCallbackFinishTime = " +
+ mAvgJpegCallbackFinishTime + "\n");
+ out.close();
+ fstream.close();
+ } catch (Exception e) {
+ fail("Camera Latency write output to file");
+ }
+ Log.v(TAG, "The Image capture wait time = " +
+ WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
+ Log.v(TAG, "Avg AutoFocus = " + mAvgAutoFocusTime);
+ Log.v(TAG, "Avg mShutterLag = " + mAvgShutterLag);
+ Log.v(TAG, "Avg mShutterToPictureDisplayedTime = "
+ + mAvgShutterToPictureDisplayedTime);
+ Log.v(TAG, "Avg mPictureDisplayedToJpegCallbackTime = "
+ + mAvgPictureDisplayedToJpegCallbackTime);
+ Log.v(TAG, "Avg mJpegCallbackFinishTime = " + mAvgJpegCallbackFinishTime);
+ }
+}
+
diff --git a/tests/src/com/android/gallery3d/stress/CameraStartUp.java b/tests/src/com/android/gallery3d/stress/CameraStartUp.java
new file mode 100644
index 000000000..8524465ac
--- /dev/null
+++ b/tests/src/com/android/gallery3d/stress/CameraStartUp.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2009 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.stress;
+
+import com.android.camera.CameraActivity;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import java.io.FileWriter;
+import java.io.BufferedWriter;
+
+/**
+ * Test cases to measure the camera and video recorder startup time.
+ */
+public class CameraStartUp extends InstrumentationTestCase {
+
+ private static final int TOTAL_NUMBER_OF_STARTUP = 20;
+
+ private String TAG = "CameraStartUp";
+ private static final String CAMERA_TEST_OUTPUT_FILE =
+ Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
+ private static int WAIT_TIME_FOR_PREVIEW = 1500; //1.5 second
+
+ private long launchCamera() {
+ long startupTime = 0;
+ try {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ long beforeStart = System.currentTimeMillis();
+ Instrumentation inst = getInstrumentation();
+ Activity cameraActivity = inst.startActivitySync(intent);
+ long cameraStarted = System.currentTimeMillis();
+ Thread.sleep(WAIT_TIME_FOR_PREVIEW);
+ cameraActivity.finish();
+ startupTime = cameraStarted - beforeStart;
+ Thread.sleep(1000);
+ Log.v(TAG, "camera startup time: " + startupTime);
+ } catch (Exception e) {
+ Log.v(TAG, "Got exception", e);
+ fail("Fails to get the output file");
+ }
+ return startupTime;
+ }
+
+ private long launchVideo() {
+ long startupTime = 0;
+
+ try {
+ Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
+ intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ long beforeStart = System.currentTimeMillis();
+ Instrumentation inst = getInstrumentation();
+ Activity recorderActivity = inst.startActivitySync(intent);
+ long cameraStarted = System.currentTimeMillis();
+ recorderActivity.finish();
+ startupTime = cameraStarted - beforeStart;
+ Log.v(TAG, "Video Startup Time = " + startupTime);
+ // wait for 1s to make sure it reach a clean stage
+ Thread.sleep(WAIT_TIME_FOR_PREVIEW);
+ Log.v(TAG, "video startup time: " + startupTime);
+ } catch (Exception e) {
+ Log.v(TAG, "Got exception", e);
+ fail("Fails to launch video output file");
+ }
+ return startupTime;
+ }
+
+ private void writeToOutputFile(long totalStartupTime,
+ String individualStartupTime, boolean firstStartUp, String Type) throws Exception {
+ // TODO (yslau) : Need to integrate the output data with central
+ // dashboard
+ try {
+ FileWriter fstream = null;
+ fstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true);
+ BufferedWriter out = new BufferedWriter(fstream);
+ if (firstStartUp) {
+ out.write("First " + Type + " Startup: " + totalStartupTime + "\n");
+ } else {
+ long averageStartupTime = totalStartupTime / (TOTAL_NUMBER_OF_STARTUP -1);
+ out.write(Type + "startup time: " + "\n");
+ out.write("Number of loop: " + (TOTAL_NUMBER_OF_STARTUP -1) + "\n");
+ out.write(individualStartupTime + "\n\n");
+ out.write(Type + " average startup time: " + averageStartupTime + " ms\n\n");
+ }
+ out.close();
+ fstream.close();
+ } catch (Exception e) {
+ fail("Camera write output to file");
+ }
+ }
+
+ @LargeTest
+ public void testLaunchVideo() throws Exception {
+ String individualStartupTime;
+ individualStartupTime = "Individual Video Startup Time = ";
+ long totalStartupTime = 0;
+ long startupTime = 0;
+ for (int i = 0; i < TOTAL_NUMBER_OF_STARTUP; i++) {
+ if (i == 0) {
+ // Capture the first startup time individually
+ long firstStartUpTime = launchVideo();
+ writeToOutputFile(firstStartUpTime, "na", true, "Video");
+ } else {
+ startupTime = launchVideo();
+ totalStartupTime += startupTime;
+ individualStartupTime += startupTime + " ,";
+ }
+ }
+ Log.v(TAG, "totalStartupTime =" + totalStartupTime);
+ writeToOutputFile(totalStartupTime, individualStartupTime, false, "Video");
+ }
+
+ @LargeTest
+ public void testLaunchCamera() throws Exception {
+ String individualStartupTime;
+ individualStartupTime = "Individual Camera Startup Time = ";
+ long totalStartupTime = 0;
+ long startupTime = 0;
+ for (int i = 0; i < TOTAL_NUMBER_OF_STARTUP; i++) {
+ if (i == 0) {
+ // Capture the first startup time individually
+ long firstStartUpTime = launchCamera();
+ writeToOutputFile(firstStartUpTime, "na", true, "Camera");
+ } else {
+ startupTime = launchCamera();
+ totalStartupTime += startupTime;
+ individualStartupTime += startupTime + " ,";
+ }
+ }
+ Log.v(TAG, "totalStartupTime =" + totalStartupTime);
+ writeToOutputFile(totalStartupTime,
+ individualStartupTime, false, "Camera");
+ }
+}
diff --git a/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java b/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java
new file mode 100755
index 000000000..57ae69125
--- /dev/null
+++ b/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java
@@ -0,0 +1,61 @@
+/*
+ * 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.stress;
+
+import android.os.Bundle;
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import junit.framework.TestSuite;
+
+public class CameraStressTestRunner extends InstrumentationTestRunner {
+
+ // Default recorder settings
+ public static int mVideoDuration = 20000; // set default to 20 seconds
+ public static int mVideoIterations = 100; // set default to 100 videos
+ public static int mImageIterations = 100; // set default to 100 images
+
+ @Override
+ public TestSuite getAllTests() {
+ TestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(ImageCapture.class);
+ suite.addTestSuite(VideoCapture.class);
+ return suite;
+ }
+
+ @Override
+ public ClassLoader getLoader() {
+ return CameraStressTestRunner.class.getClassLoader();
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ String video_iterations = (String) icicle.get("video_iterations");
+ String image_iterations = (String) icicle.get("image_iterations");
+ String video_duration = (String) icicle.get("video_duration");
+
+ if ( video_iterations != null ) {
+ mVideoIterations = Integer.parseInt(video_iterations);
+ }
+ if ( image_iterations != null) {
+ mImageIterations = Integer.parseInt(image_iterations);
+ }
+ if ( video_duration != null) {
+ mVideoDuration = Integer.parseInt(video_duration);
+ }
+ }
+}
diff --git a/tests/src/com/android/gallery3d/stress/ImageCapture.java b/tests/src/com/android/gallery3d/stress/ImageCapture.java
new file mode 100755
index 000000000..e322eb516
--- /dev/null
+++ b/tests/src/com/android/gallery3d/stress/ImageCapture.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009 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.stress;
+
+import com.android.camera.CameraActivity;
+import com.android.gallery3d.stress.CameraStressTestRunner;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.app.Activity;
+
+/**
+ * Junit / Instrumentation test case for camera test
+ *
+ * Running the test suite:
+ *
+ * adb shell am instrument \
+ * -e class com.android.camera.stress.ImageCapture \
+ * -w com.google.android.camera.tests/android.test.InstrumentationTestRunner
+ *
+ */
+
+public class ImageCapture extends ActivityInstrumentationTestCase2 <CameraActivity> {
+ private String TAG = "ImageCapture";
+ private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 1500; //1.5 sedconds
+ private static final long WAIT_FOR_SWITCH_CAMERA = 3000; //3 seconds
+
+ private TestUtil testUtil = new TestUtil();
+
+ // Private intent extras.
+ private final static String EXTRAS_CAMERA_FACING =
+ "android.intent.extras.CAMERA_FACING";
+
+ public ImageCapture() {
+ super(CameraActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ testUtil.prepareOutputFile();
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ testUtil.closeOutputFile();
+ super.tearDown();
+ }
+
+ public void captureImages(String reportTag, Instrumentation inst) {
+ int total_num_of_images = CameraStressTestRunner.mImageIterations;
+ Log.v(TAG, "no of images = " + total_num_of_images);
+
+ //TODO(yslau): Need to integrate the outoput with the central dashboard,
+ //write to a txt file as a temp solution
+ boolean memoryResult = false;
+ KeyEvent focusEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS);
+
+ try {
+ testUtil.writeReportHeader(reportTag, total_num_of_images);
+ for (int i = 0; i < total_num_of_images; i++) {
+ Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
+ inst.sendKeySync(focusEvent);
+ inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
+ Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN);
+ testUtil.writeResult(i);
+ }
+ } catch (Exception e) {
+ Log.v(TAG, "Got exception: " + e.toString());
+ assertTrue("testImageCapture", false);
+ }
+ }
+
+ @LargeTest
+ public void testBackImageCapture() throws Exception {
+ Instrumentation inst = getInstrumentation();
+ Intent intent = new Intent();
+
+ intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(EXTRAS_CAMERA_FACING,
+ android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK);
+ Activity act = inst.startActivitySync(intent);
+ Thread.sleep(WAIT_FOR_SWITCH_CAMERA);
+ captureImages("Back Camera Image Capture\n", inst);
+ act.finish();
+ }
+
+ @LargeTest
+ public void testFrontImageCapture() throws Exception {
+ Instrumentation inst = getInstrumentation();
+ Intent intent = new Intent();
+
+ intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(EXTRAS_CAMERA_FACING,
+ android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT);
+ Activity act = inst.startActivitySync(intent);
+ Thread.sleep(WAIT_FOR_SWITCH_CAMERA);
+ captureImages("Front Camera Image Capture\n", inst);
+ act.finish();
+ }
+}
diff --git a/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java b/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java
new file mode 100644
index 000000000..a27bd90e6
--- /dev/null
+++ b/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 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.stress;
+
+import android.app.Instrumentation;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.KeyEvent;
+import com.android.camera.CameraActivity;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Junit / Instrumentation test case for measuring camera shot to shot latency
+ */
+public class ShotToShotLatency extends ActivityInstrumentationTestCase2<CameraActivity> {
+ private String TAG = "ShotToShotLatency";
+ private static final int TOTAL_NUMBER_OF_SNAPSHOTS = 250;
+ private static final long SNAPSHOT_WAIT = 1000;
+ private static final String CAMERA_TEST_OUTPUT_FILE =
+ Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
+ private static final String CAMERA_IMAGE_DIRECTORY =
+ Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera/";
+
+ public ShotToShotLatency() {
+ super(CameraActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ getActivity();
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private void cleanupLatencyImages() {
+ try {
+ File sdcard = new File(CAMERA_IMAGE_DIRECTORY);
+ File[] pics = null;
+ FilenameFilter filter = new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".jpg");
+ }
+ };
+ pics = sdcard.listFiles(filter);
+ for (File f : pics) {
+ f.delete();
+ }
+ } catch (SecurityException e) {
+ Log.e(TAG, "Security manager access violation: " + e.toString());
+ }
+ }
+
+ private void sleep(long time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Sleep InterruptedException " + e.toString());
+ }
+ }
+
+ @LargeTest
+ public void testShotToShotLatency() {
+ long sigmaOfDiffFromMeanSquared = 0;
+ double mean = 0;
+ double standardDeviation = 0;
+ ArrayList<Long> captureTimes = new ArrayList<Long>();
+ ArrayList<Long> latencyTimes = new ArrayList<Long>();
+
+ Log.v(TAG, "start testShotToShotLatency test");
+ Instrumentation inst = getInstrumentation();
+
+ // Generate data points
+ for (int i = 0; i < TOTAL_NUMBER_OF_SNAPSHOTS; i++) {
+ inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
+ sleep(SNAPSHOT_WAIT);
+ CameraActivity c = getActivity();
+ if (c.getCaptureStartTime() > 0) {
+ captureTimes.add(c.getCaptureStartTime());
+ }
+ }
+
+ // Calculate latencies
+ for (int j = 1; j < captureTimes.size(); j++) {
+ latencyTimes.add(captureTimes.get(j) - captureTimes.get(j - 1));
+ }
+
+ // Crunch numbers
+ for (long dataPoint : latencyTimes) {
+ mean += (double) dataPoint;
+ }
+ mean /= latencyTimes.size();
+
+ for (long dataPoint : latencyTimes) {
+ sigmaOfDiffFromMeanSquared += (dataPoint - mean) * (dataPoint - mean);
+ }
+ standardDeviation = Math.sqrt(sigmaOfDiffFromMeanSquared / latencyTimes.size());
+
+ // Report statistics
+ File outFile = new File(CAMERA_TEST_OUTPUT_FILE);
+ BufferedWriter output = null;
+ try {
+ output = new BufferedWriter(new FileWriter(outFile, true));
+ output.write("Shot to shot latency - mean: " + mean + "\n");
+ output.write("Shot to shot latency - standard deviation: " + standardDeviation + "\n");
+ cleanupLatencyImages();
+ } catch (IOException e) {
+ Log.e(TAG, "testShotToShotLatency IOException writing to log " + e.toString());
+ } finally {
+ try {
+ if (output != null) {
+ output.close();
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Error closing file: " + e.toString());
+ }
+ }
+ }
+}
diff --git a/tests/src/com/android/gallery3d/stress/SwitchPreview.java b/tests/src/com/android/gallery3d/stress/SwitchPreview.java
new file mode 100755
index 000000000..955d092a6
--- /dev/null
+++ b/tests/src/com/android/gallery3d/stress/SwitchPreview.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2009 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.stress;
+
+import com.android.camera.CameraActivity;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.provider.MediaStore;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+
+/**
+ * Junit / Instrumentation test case for camera test
+ *
+ * Running the test suite:
+ *
+ * adb shell am instrument \
+ * -e class com.android.camera.stress.SwitchPreview \
+ * -w com.android.camera.tests/com.android.camera.stress.CameraStressTestRunner
+ *
+ */
+public class SwitchPreview extends ActivityInstrumentationTestCase2 <CameraActivity>{
+ private String TAG = "SwitchPreview";
+ private static final int TOTAL_NUMBER_OF_SWITCHING = 200;
+ private static final long WAIT_FOR_PREVIEW = 4000;
+
+ private static final String CAMERA_TEST_OUTPUT_FILE =
+ Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
+ private BufferedWriter mOut;
+ private FileWriter mfstream;
+
+ public SwitchPreview() {
+ super(CameraActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ getActivity();
+ prepareOutputFile();
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ getActivity().finish();
+ closeOutputFile();
+ super.tearDown();
+ }
+
+ private void prepareOutputFile(){
+ try{
+ mfstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true);
+ mOut = new BufferedWriter(mfstream);
+ } catch (Exception e){
+ assertTrue("Camera Switch Mode", false);
+ }
+ }
+
+ private void closeOutputFile() {
+ try {
+ mOut.write("\n");
+ mOut.close();
+ mfstream.close();
+ } catch (Exception e) {
+ assertTrue("CameraSwitchMode close output", false);
+ }
+ }
+
+ @LargeTest
+ public void testSwitchMode() {
+ //Switching the video and the video recorder mode
+ Instrumentation inst = getInstrumentation();
+ try{
+ mOut.write("Camera Switch Mode:\n");
+ mOut.write("No of loops :" + TOTAL_NUMBER_OF_SWITCHING + "\n");
+ mOut.write("loop: ");
+ for (int i=0; i< TOTAL_NUMBER_OF_SWITCHING; i++) {
+ Thread.sleep(WAIT_FOR_PREVIEW);
+ Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intent.setClass(getInstrumentation().getTargetContext(),
+ CameraActivity.class);
+ getActivity().startActivity(intent);
+ Thread.sleep(WAIT_FOR_PREVIEW);
+ intent = new Intent();
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intent.setClass(getInstrumentation().getTargetContext(),
+ CameraActivity.class);
+ getActivity().startActivity(intent);
+ mOut.write(" ," + i);
+ mOut.flush();
+ }
+ } catch (Exception e){
+ Log.v(TAG, "Got exception", e);
+ }
+ }
+}
diff --git a/tests/src/com/android/gallery3d/stress/TestUtil.java b/tests/src/com/android/gallery3d/stress/TestUtil.java
new file mode 100644
index 000000000..56ab715f7
--- /dev/null
+++ b/tests/src/com/android/gallery3d/stress/TestUtil.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 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.stress;
+
+import android.os.Environment;
+import java.io.FileWriter;
+import java.io.BufferedWriter;
+
+
+/**
+ * Collection of utility functions used for the test.
+ */
+public class TestUtil {
+ public BufferedWriter mOut;
+ public FileWriter mfstream;
+
+ public TestUtil() {
+ }
+
+ public void prepareOutputFile() throws Exception {
+ String camera_test_output_file =
+ Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt";
+ mfstream = new FileWriter(camera_test_output_file, true);
+ mOut = new BufferedWriter(mfstream);
+ }
+
+ public void closeOutputFile() throws Exception {
+ mOut.write("\n");
+ mOut.close();
+ mfstream.close();
+ }
+
+ public void writeReportHeader(String reportTag, int iteration) throws Exception {
+ mOut.write(reportTag);
+ mOut.write("No of loops :" + iteration + "\n");
+ mOut.write("loop: ");
+ }
+
+ public void writeResult(int iteration) throws Exception {
+ mOut.write(" ," + iteration);
+ mOut.flush();
+ }
+}
diff --git a/tests/src/com/android/gallery3d/stress/VideoCapture.java b/tests/src/com/android/gallery3d/stress/VideoCapture.java
new file mode 100755
index 000000000..dbbd124d0
--- /dev/null
+++ b/tests/src/com/android/gallery3d/stress/VideoCapture.java
@@ -0,0 +1,115 @@
+/*
+ * 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.stress;
+
+import com.android.camera.CameraActivity;
+import com.android.gallery3d.stress.TestUtil;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.provider.MediaStore;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.KeyEvent;
+
+import com.android.gallery3d.stress.CameraStressTestRunner;
+
+/**
+ * Junit / Instrumentation test case for camera test
+ *
+ * Running the test suite:
+ *
+ * adb shell am instrument \
+ * -e class com.android.camera.stress.VideoCapture \
+ * -w com.google.android.camera.tests/android.test.InstrumentationTestRunner
+ *
+ */
+
+public class VideoCapture extends ActivityInstrumentationTestCase2 <CameraActivity> {
+ private static final long WAIT_FOR_PREVIEW = 1500; //1.5 seconds
+ private static final long WAIT_FOR_SWITCH_CAMERA = 3000; //2 seconds
+
+ // Private intent extras which control the camera facing.
+ private final static String EXTRAS_CAMERA_FACING =
+ "android.intent.extras.CAMERA_FACING";
+
+ private TestUtil testUtil = new TestUtil();
+
+ public VideoCapture() {
+ super(CameraActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ testUtil.prepareOutputFile();
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ testUtil.closeOutputFile();
+ super.tearDown();
+ }
+
+ @LargeTest
+ public void captureVideos(String reportTag, Instrumentation inst) throws Exception{
+ boolean memoryResult = false;
+ int total_num_of_videos = CameraStressTestRunner.mVideoIterations;
+ int video_duration = CameraStressTestRunner.mVideoDuration;
+ testUtil.writeReportHeader(reportTag, total_num_of_videos);
+
+ for (int i = 0; i < total_num_of_videos; i++) {
+ Thread.sleep(WAIT_FOR_PREVIEW);
+ // record a video
+ inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
+ Thread.sleep(video_duration);
+ inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA);
+ testUtil.writeResult(i);
+ }
+ }
+
+ @LargeTest
+ public void testBackVideoCapture() throws Exception {
+ Instrumentation inst = getInstrumentation();
+ Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
+
+ intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(EXTRAS_CAMERA_FACING,
+ android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK);
+ Activity act = inst.startActivitySync(intent);
+ Thread.sleep(WAIT_FOR_SWITCH_CAMERA);
+ captureVideos("Back Camera Video Capture\n", inst);
+ act.finish();
+ }
+
+ @LargeTest
+ public void testFrontVideoCapture() throws Exception {
+ Instrumentation inst = getInstrumentation();
+ Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
+
+ intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(EXTRAS_CAMERA_FACING,
+ android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT);
+ Activity act = inst.startActivitySync(intent);
+ Thread.sleep(WAIT_FOR_SWITCH_CAMERA);
+ captureVideos("Front Camera Video Capture\n", inst);
+ act.finish();
+ }
+}
diff --git a/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java b/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java
new file mode 100644
index 000000000..b8fb05fc2
--- /dev/null
+++ b/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.unittest;
+
+import com.android.camera.Util;
+
+import android.graphics.Matrix;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+@SmallTest
+public class CameraUnitTest extends TestCase {
+ public void testRoundOrientation() {
+ int h = Util.ORIENTATION_HYSTERESIS;
+ assertEquals(0, Util.roundOrientation(0, 0));
+ assertEquals(0, Util.roundOrientation(359, 0));
+ assertEquals(0, Util.roundOrientation(0 + 44 + h, 0));
+ assertEquals(90, Util.roundOrientation(0 + 45 + h, 0));
+ assertEquals(0, Util.roundOrientation(360 - 44 - h, 0));
+ assertEquals(270, Util.roundOrientation(360 - 45 - h, 0));
+
+ assertEquals(90, Util.roundOrientation(90, 90));
+ assertEquals(90, Util.roundOrientation(90 + 44 + h, 90));
+ assertEquals(180, Util.roundOrientation(90 + 45 + h, 90));
+ assertEquals(90, Util.roundOrientation(90 - 44 - h, 90));
+ assertEquals(0, Util.roundOrientation(90 - 45 - h, 90));
+
+ assertEquals(180, Util.roundOrientation(180, 180));
+ assertEquals(180, Util.roundOrientation(180 + 44 + h, 180));
+ assertEquals(270, Util.roundOrientation(180 + 45 + h, 180));
+ assertEquals(180, Util.roundOrientation(180 - 44 - h, 180));
+ assertEquals(90, Util.roundOrientation(180 - 45 - h, 180));
+
+ assertEquals(270, Util.roundOrientation(270, 270));
+ assertEquals(270, Util.roundOrientation(270 + 44 + h, 270));
+ assertEquals(0, Util.roundOrientation(270 + 45 + h, 270));
+ assertEquals(270, Util.roundOrientation(270 - 44 - h, 270));
+ assertEquals(180, Util.roundOrientation(270 - 45 - h, 270));
+
+ assertEquals(90, Util.roundOrientation(90, 0));
+ assertEquals(180, Util.roundOrientation(180, 0));
+ assertEquals(270, Util.roundOrientation(270, 0));
+
+ assertEquals(0, Util.roundOrientation(0, 90));
+ assertEquals(180, Util.roundOrientation(180, 90));
+ assertEquals(270, Util.roundOrientation(270, 90));
+
+ assertEquals(0, Util.roundOrientation(0, 180));
+ assertEquals(90, Util.roundOrientation(90, 180));
+ assertEquals(270, Util.roundOrientation(270, 180));
+
+ assertEquals(0, Util.roundOrientation(0, 270));
+ assertEquals(90, Util.roundOrientation(90, 270));
+ assertEquals(180, Util.roundOrientation(180, 270));
+ }
+
+ public void testPrepareMatrix() {
+ Matrix matrix = new Matrix();
+ float[] points;
+ int[] expected;
+
+ Util.prepareMatrix(matrix, false, 0, 800, 480);
+ points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250};
+ expected = new int[] {0, 0, 400, 240, 800, 480, 400, 480, 100, 300};
+ matrix.mapPoints(points);
+ assertEquals(expected, points);
+
+ Util.prepareMatrix(matrix, false, 90, 800, 480);
+ points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250};
+ expected = new int[] {800, 0, 400, 240, 0, 480, 0, 240, 300, 60};
+ matrix.mapPoints(points);
+ assertEquals(expected, points);
+
+ Util.prepareMatrix(matrix, false, 180, 800, 480);
+ points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250};
+ expected = new int[] {800, 480, 400, 240, 0, 0, 400, 0, 700, 180};
+ matrix.mapPoints(points);
+ assertEquals(expected, points);
+
+ Util.prepareMatrix(matrix, true, 180, 800, 480);
+ points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250};
+ expected = new int[] {0, 480, 400, 240, 800, 0, 400, 0, 100, 180};
+ matrix.mapPoints(points);
+ assertEquals(expected, points);
+ }
+
+ private void assertEquals(int expected[], float[] actual) {
+ for (int i = 0; i < expected.length; i++) {
+ assertEquals("Array index " + i + " mismatch", expected[i], Math.round(actual[i]));
+ }
+ }
+}