summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRuben Brunk <rubenbrunk@google.com>2012-12-05 22:07:12 -0800
committerRuben Brunk <rubenbrunk@google.com>2012-12-06 12:25:39 -0800
commit2ef34aafcf6957ed8bd764a5fe0921c376c0b416 (patch)
tree06108ed0324edb1fd3a94238348da63cf7b3908f /src
parent6425413690fccb004b52f64b23bc7e3c9cd33e7e (diff)
downloadandroid_packages_apps_Snap-2ef34aafcf6957ed8bd764a5fe0921c376c0b416.tar.gz
android_packages_apps_Snap-2ef34aafcf6957ed8bd764a5fe0921c376c0b416.tar.bz2
android_packages_apps_Snap-2ef34aafcf6957ed8bd764a5fe0921c376c0b416.zip
Removed old crop.
Bug: 7441237 Change-Id: I29801f798a1d1ad3af81a82950edbb8a72ccae82
Diffstat (limited to 'src')
-rw-r--r--src/com/android/gallery3d/app/AlbumPage.java7
-rw-r--r--src/com/android/gallery3d/app/CropImage.java1040
-rw-r--r--src/com/android/gallery3d/app/Wallpaper.java20
-rw-r--r--src/com/android/gallery3d/filtershow/CropExtras.java (renamed from src/com/android/gallery3d/data/CropExtras.java)2
-rw-r--r--src/com/android/gallery3d/filtershow/FilterShowActivity.java3
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ImageLoader.java2
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java2
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java2
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java2
-rw-r--r--src/com/android/gallery3d/gadget/WidgetConfigure.java16
-rw-r--r--src/com/android/gallery3d/ui/CropView.java794
-rw-r--r--src/com/android/gallery3d/ui/MenuExecutor.java1
12 files changed, 29 insertions, 1862 deletions
diff --git a/src/com/android/gallery3d/app/AlbumPage.java b/src/com/android/gallery3d/app/AlbumPage.java
index 50f5e024c..60000903d 100644
--- a/src/com/android/gallery3d/app/AlbumPage.java
+++ b/src/com/android/gallery3d/app/AlbumPage.java
@@ -57,6 +57,9 @@ import com.android.gallery3d.ui.SynchronizedHandler;
import com.android.gallery3d.util.Future;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.MediaSetUtils;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.CropExtras;
+
public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner,
SelectionManager.SelectionListener, MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener {
@@ -317,11 +320,11 @@ public class AlbumPage extends ActivityState implements GalleryActionBar.Cluster
if (mData.getString(Gallery.EXTRA_CROP) != null) {
// TODO: Handle MtpImagew
Uri uri = dm.getContentUri(item.getPath());
- Intent intent = new Intent(CropImage.ACTION_CROP, uri)
+ Intent intent = new Intent(FilterShowActivity.CROP_ACTION, uri)
.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
.putExtras(getData());
if (mData.getParcelable(MediaStore.EXTRA_OUTPUT) == null) {
- intent.putExtra(CropImage.KEY_RETURN_DATA, true);
+ intent.putExtra(CropExtras.KEY_RETURN_DATA, true);
}
activity.startActivity(intent);
activity.finish();
diff --git a/src/com/android/gallery3d/app/CropImage.java b/src/com/android/gallery3d/app/CropImage.java
deleted file mode 100644
index e7e95fdaa..000000000
--- a/src/com/android/gallery3d/app/CropImage.java
+++ /dev/null
@@ -1,1040 +0,0 @@
-/*
- * 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.app;
-
-import android.annotation.TargetApi;
-import android.app.ProgressDialog;
-import android.app.WallpaperManager;
-import android.content.ContentValues;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.Message;
-import android.provider.MediaStore;
-import android.provider.MediaStore.Images;
-import android.util.FloatMath;
-import android.view.WindowManager;
-import android.widget.Toast;
-
-import com.actionbarsherlock.app.ActionBar;
-import com.actionbarsherlock.view.Menu;
-import com.actionbarsherlock.view.MenuItem;
-import com.actionbarsherlock.view.Window;
-import com.android.camera.Util;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.DataManager;
-import com.android.gallery3d.data.LocalImage;
-import com.android.gallery3d.data.MediaItem;
-import com.android.gallery3d.data.MediaObject;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.exif.ExifData;
-import com.android.gallery3d.exif.ExifOutputStream;
-import com.android.gallery3d.exif.ExifReader;
-import com.android.gallery3d.exif.ExifTag;
-import com.android.gallery3d.picasasource.PicasaSource;
-import com.android.gallery3d.ui.BitmapScreenNail;
-import com.android.gallery3d.ui.BitmapTileProvider;
-import com.android.gallery3d.ui.CropView;
-import com.android.gallery3d.ui.GLRoot;
-import com.android.gallery3d.ui.SynchronizedHandler;
-import com.android.gallery3d.ui.TileImageViewAdapter;
-import com.android.gallery3d.util.BucketNames;
-import com.android.gallery3d.util.Future;
-import com.android.gallery3d.util.FutureListener;
-import com.android.gallery3d.util.GalleryUtils;
-import com.android.gallery3d.util.InterruptableOutputStream;
-import com.android.gallery3d.util.ThreadPool.CancelListener;
-import com.android.gallery3d.util.ThreadPool.Job;
-import com.android.gallery3d.util.ThreadPool.JobContext;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.ByteOrder;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-/**
- * The activity can crop specific region of interest from an image.
- */
-public class CropImage extends AbstractGalleryActivity {
- private static final String TAG = "CropImage";
- public static final String ACTION_CROP = "com.android.camera.action.CROP";
-
- private static final int MAX_PIXEL_COUNT = 5 * 1000000; // 5M pixels
- private static final int MAX_FILE_INDEX = 1000;
- private static final int TILE_SIZE = 512;
- private static final int BACKUP_PIXEL_COUNT = 480000; // around 800x600
-
- private static final int MSG_LARGE_BITMAP = 1;
- private static final int MSG_BITMAP = 2;
- private static final int MSG_SAVE_COMPLETE = 3;
- private static final int MSG_SHOW_SAVE_ERROR = 4;
- private static final int MSG_CANCEL_DIALOG = 5;
-
- private static final int MAX_BACKUP_IMAGE_SIZE = 320;
- private static final int DEFAULT_COMPRESS_QUALITY = 90;
- private static final String TIME_STAMP_NAME = "'IMG'_yyyyMMdd_HHmmss";
-
- public static final String KEY_RETURN_DATA = "return-data";
- public static final String KEY_CROPPED_RECT = "cropped-rect";
- public static final String KEY_ASPECT_X = "aspectX";
- public static final String KEY_ASPECT_Y = "aspectY";
- public static final String KEY_SPOTLIGHT_X = "spotlightX";
- public static final String KEY_SPOTLIGHT_Y = "spotlightY";
- public static final String KEY_OUTPUT_X = "outputX";
- public static final String KEY_OUTPUT_Y = "outputY";
- public static final String KEY_SCALE = "scale";
- public static final String KEY_DATA = "data";
- public static final String KEY_SCALE_UP_IF_NEEDED = "scaleUpIfNeeded";
- public static final String KEY_OUTPUT_FORMAT = "outputFormat";
- public static final String KEY_SET_AS_WALLPAPER = "set-as-wallpaper";
- public static final String KEY_NO_FACE_DETECTION = "noFaceDetection";
- public static final String KEY_SHOW_WHEN_LOCKED = "showWhenLocked";
-
- private static final String KEY_STATE = "state";
-
- private static final int STATE_INIT = 0;
- private static final int STATE_LOADED = 1;
- private static final int STATE_SAVING = 2;
-
- public static final File DOWNLOAD_BUCKET = new File(
- Environment.getExternalStorageDirectory(), BucketNames.DOWNLOAD);
-
- public static final String CROP_ACTION = "com.android.camera.action.CROP";
-
- private int mState = STATE_INIT;
-
- private CropView mCropView;
-
- private boolean mDoFaceDetection = true;
-
- private Handler mMainHandler;
-
- // We keep the following members so that we can free them
-
- // mBitmap is the unrotated bitmap we pass in to mCropView for detect faces.
- // mCropView is responsible for rotating it to the way that it is viewed by users.
- private Bitmap mBitmap;
- private BitmapTileProvider mBitmapTileProvider;
- private BitmapRegionDecoder mRegionDecoder;
- private Bitmap mBitmapInIntent;
- private boolean mUseRegionDecoder = false;
- private BitmapScreenNail mBitmapScreenNail;
-
- private ProgressDialog mProgressDialog;
- private Future<BitmapRegionDecoder> mLoadTask;
- private Future<Bitmap> mLoadBitmapTask;
- private Future<Intent> mSaveTask;
-
- private MediaItem mMediaItem;
-
- @Override
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- requestWindowFeature(Window.FEATURE_ACTION_BAR);
- requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
-
- // Initialize UI
- setContentView(R.layout.cropimage);
- mCropView = new CropView(this);
- getGLRoot().setContentPane(mCropView);
-
- ActionBar actionBar = getSupportActionBar();
- int displayOptions = ActionBar.DISPLAY_HOME_AS_UP
- | ActionBar.DISPLAY_SHOW_TITLE;
- actionBar.setDisplayOptions(displayOptions, displayOptions);
-
- Bundle extra = getIntent().getExtras();
- if (extra != null) {
- if (extra.getBoolean(KEY_SET_AS_WALLPAPER, false)) {
- actionBar.setTitle(getString(R.string.set_wallpaper));
- }
- if (extra.getBoolean(KEY_SHOW_WHEN_LOCKED, false)) {
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
- }
- }
-
- mMainHandler = new SynchronizedHandler(getGLRoot()) {
- @Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case MSG_LARGE_BITMAP: {
- dismissProgressDialogIfShown();
- onBitmapRegionDecoderAvailable((BitmapRegionDecoder) message.obj);
- break;
- }
- case MSG_BITMAP: {
- dismissProgressDialogIfShown();
- onBitmapAvailable((Bitmap) message.obj);
- break;
- }
- case MSG_SHOW_SAVE_ERROR: {
- dismissProgressDialogIfShown();
- setResult(RESULT_CANCELED);
- Toast.makeText(CropImage.this,
- CropImage.this.getString(R.string.save_error),
- Toast.LENGTH_LONG).show();
- finish();
- }
- case MSG_SAVE_COMPLETE: {
- dismissProgressDialogIfShown();
- setResult(RESULT_OK, (Intent) message.obj);
- finish();
- break;
- }
- case MSG_CANCEL_DIALOG: {
- setResult(RESULT_CANCELED);
- finish();
- break;
- }
- }
- }
- };
-
- setCropParameters();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle saveState) {
- saveState.putInt(KEY_STATE, mState);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- getSupportMenuInflater().inflate(R.menu.crop, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home: {
- finish();
- break;
- }
- case R.id.cancel: {
- setResult(RESULT_CANCELED);
- finish();
- break;
- }
- case R.id.save: {
- onSaveClicked();
- break;
- }
- }
- return true;
- }
-
- @Override
- public void onBackPressed() {
- finish();
- }
-
- private class SaveOutput implements Job<Intent> {
- private final RectF mCropRect;
-
- public SaveOutput(RectF cropRect) {
- mCropRect = cropRect;
- }
-
- @Override
- public Intent run(JobContext jc) {
- RectF cropRect = mCropRect;
- Bundle extra = getIntent().getExtras();
-
- Rect rect = new Rect(
- Math.round(cropRect.left), Math.round(cropRect.top),
- Math.round(cropRect.right), Math.round(cropRect.bottom));
-
- Intent result = new Intent();
- result.putExtra(KEY_CROPPED_RECT, rect);
- Bitmap cropped = null;
- boolean outputted = false;
- if (extra != null) {
- Uri uri = (Uri) extra.getParcelable(MediaStore.EXTRA_OUTPUT);
- if (uri != null) {
- if (jc.isCancelled()) return null;
- outputted = true;
- cropped = getCroppedImage(rect);
- if (!saveBitmapToUri(jc, cropped, uri)) return null;
- }
- if (extra.getBoolean(KEY_RETURN_DATA, false)) {
- if (jc.isCancelled()) return null;
- outputted = true;
- if (cropped == null) cropped = getCroppedImage(rect);
- result.putExtra(KEY_DATA, cropped);
- }
- if (extra.getBoolean(KEY_SET_AS_WALLPAPER, false)) {
- if (jc.isCancelled()) return null;
- outputted = true;
- if (cropped == null) cropped = getCroppedImage(rect);
- if (!setAsWallpaper(jc, cropped)) return null;
- }
- }
- if (!outputted) {
- if (jc.isCancelled()) return null;
- if (cropped == null) cropped = getCroppedImage(rect);
- Uri data = saveToMediaProvider(jc, cropped);
- if (data != null) result.setData(data);
- }
- return result;
- }
- }
-
- public static String determineCompressFormat(MediaObject obj) {
- String compressFormat = "JPEG";
- if (obj instanceof MediaItem) {
- String mime = ((MediaItem) obj).getMimeType();
- if (mime.contains("png") || mime.contains("gif")) {
- // Set the compress format to PNG for png and gif images
- // because they may contain alpha values.
- compressFormat = "PNG";
- }
- }
- return compressFormat;
- }
-
- private boolean setAsWallpaper(JobContext jc, Bitmap wallpaper) {
- try {
- WallpaperManager.getInstance(this).setBitmap(wallpaper);
- } catch (IOException e) {
- Log.w(TAG, "fail to set wall paper", e);
- }
- return true;
- }
-
- private File saveMedia(
- JobContext jc, Bitmap cropped, File directory, String filename, ExifData exifData) {
- // Try file-1.jpg, file-2.jpg, ... until we find a filename
- // which does not exist yet.
- File candidate = null;
- String fileExtension = getFileExtension();
- for (int i = 1; i < MAX_FILE_INDEX; ++i) {
- candidate = new File(directory, filename + "-" + i + "."
- + fileExtension);
- try {
- if (candidate.createNewFile()) break;
- } catch (IOException e) {
- Log.e(TAG, "fail to create new file: "
- + candidate.getAbsolutePath(), e);
- return null;
- }
- }
- if (!candidate.exists() || !candidate.isFile()) {
- throw new RuntimeException("cannot create file: " + filename);
- }
-
- candidate.setReadable(true, false);
- candidate.setWritable(true, false);
-
- try {
- FileOutputStream fos = new FileOutputStream(candidate);
- try {
- if (exifData != null) {
- ExifOutputStream eos = new ExifOutputStream(fos);
- eos.setExifData(exifData);
- saveBitmapToOutputStream(jc, cropped,
- convertExtensionToCompressFormat(fileExtension), eos);
- } else {
- saveBitmapToOutputStream(jc, cropped,
- convertExtensionToCompressFormat(fileExtension), fos);
- }
- } finally {
- fos.close();
- }
- } catch (IOException e) {
- Log.e(TAG, "fail to save image: "
- + candidate.getAbsolutePath(), e);
- candidate.delete();
- return null;
- }
-
- if (jc.isCancelled()) {
- candidate.delete();
- return null;
- }
-
- return candidate;
- }
-
- private ExifData getExifData(String path) {
- FileInputStream is = null;
- try {
- is = new FileInputStream(path);
- ExifReader reader = new ExifReader();
- ExifData data = reader.read(is);
- return data;
- } catch (Throwable t) {
- Log.w(TAG, "Cannot read EXIF data", t);
- return null;
- } finally {
- Util.closeSilently(is);
- }
- }
-
- private static final String EXIF_SOFTWARE_VALUE = "Android Gallery";
-
- private void changeExifData(ExifData data, int width, int height) {
- data.addTag(ExifTag.TAG_IMAGE_WIDTH).setValue(width);
- data.addTag(ExifTag.TAG_IMAGE_LENGTH).setValue(height);
- data.addTag(ExifTag.TAG_SOFTWARE).setValue(EXIF_SOFTWARE_VALUE);
- data.addTag(ExifTag.TAG_DATE_TIME).setTimeValue(System.currentTimeMillis());
- // Remove the original thumbnail
- // TODO: generate a new thumbnail for the cropped image.
- data.removeThumbnailData();
- }
-
- private Uri saveToMediaProvider(JobContext jc, Bitmap cropped) {
- if (PicasaSource.isPicasaImage(mMediaItem)) {
- return savePicasaImage(jc, cropped);
- } else if (mMediaItem instanceof LocalImage) {
- return saveLocalImage(jc, cropped);
- } else {
- return saveGenericImage(jc, cropped);
- }
- }
-
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- private static void setImageSize(ContentValues values, int width, int height) {
- // The two fields are available since ICS but got published in JB
- if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) {
- values.put(Images.Media.WIDTH, width);
- values.put(Images.Media.HEIGHT, height);
- }
- }
-
- private Uri savePicasaImage(JobContext jc, Bitmap cropped) {
- if (!DOWNLOAD_BUCKET.isDirectory() && !DOWNLOAD_BUCKET.mkdirs()) {
- throw new RuntimeException("cannot create download folder");
- }
- String filename = PicasaSource.getImageTitle(mMediaItem);
- int pos = filename.lastIndexOf('.');
- if (pos >= 0) filename = filename.substring(0, pos);
- ExifData exifData = new ExifData(ByteOrder.BIG_ENDIAN);
- PicasaSource.extractExifValues(mMediaItem, exifData);
- changeExifData(exifData, cropped.getWidth(), cropped.getHeight());
- File output = saveMedia(jc, cropped, DOWNLOAD_BUCKET, filename, exifData);
- if (output == null) return null;
-
- long now = System.currentTimeMillis() / 1000;
- ContentValues values = new ContentValues();
- values.put(Images.Media.TITLE, PicasaSource.getImageTitle(mMediaItem));
- values.put(Images.Media.DISPLAY_NAME, output.getName());
- values.put(Images.Media.DATE_TAKEN, PicasaSource.getDateTaken(mMediaItem));
- values.put(Images.Media.DATE_MODIFIED, now);
- values.put(Images.Media.DATE_ADDED, now);
- values.put(Images.Media.MIME_TYPE, getOutputMimeType());
- values.put(Images.Media.ORIENTATION, 0);
- values.put(Images.Media.DATA, output.getAbsolutePath());
- values.put(Images.Media.SIZE, output.length());
- setImageSize(values, cropped.getWidth(), cropped.getHeight());
-
- double latitude = PicasaSource.getLatitude(mMediaItem);
- double longitude = PicasaSource.getLongitude(mMediaItem);
- if (GalleryUtils.isValidLocation(latitude, longitude)) {
- values.put(Images.Media.LATITUDE, latitude);
- values.put(Images.Media.LONGITUDE, longitude);
- }
- return getContentResolver().insert(
- Images.Media.EXTERNAL_CONTENT_URI, values);
- }
-
- private Uri saveLocalImage(JobContext jc, Bitmap cropped) {
- LocalImage localImage = (LocalImage) mMediaItem;
-
- File oldPath = new File(localImage.filePath);
- File directory = new File(oldPath.getParent());
-
- String filename = oldPath.getName();
- int pos = filename.lastIndexOf('.');
- if (pos >= 0) filename = filename.substring(0, pos);
- File output = null;
-
- ExifData exifData = null;
- if (convertExtensionToCompressFormat(getFileExtension()) == CompressFormat.JPEG) {
- exifData = getExifData(oldPath.getAbsolutePath());
- if (exifData != null) {
- changeExifData(exifData, cropped.getWidth(), cropped.getHeight());
- }
- }
- output = saveMedia(jc, cropped, directory, filename, exifData);
- if (output == null) return null;
-
- long now = System.currentTimeMillis() / 1000;
- ContentValues values = new ContentValues();
- values.put(Images.Media.TITLE, localImage.caption);
- values.put(Images.Media.DISPLAY_NAME, output.getName());
- values.put(Images.Media.DATE_TAKEN, localImage.dateTakenInMs);
- values.put(Images.Media.DATE_MODIFIED, now);
- values.put(Images.Media.DATE_ADDED, now);
- values.put(Images.Media.MIME_TYPE, getOutputMimeType());
- values.put(Images.Media.ORIENTATION, 0);
- values.put(Images.Media.DATA, output.getAbsolutePath());
- values.put(Images.Media.SIZE, output.length());
-
- setImageSize(values, cropped.getWidth(), cropped.getHeight());
-
- if (GalleryUtils.isValidLocation(localImage.latitude, localImage.longitude)) {
- values.put(Images.Media.LATITUDE, localImage.latitude);
- values.put(Images.Media.LONGITUDE, localImage.longitude);
- }
- return getContentResolver().insert(
- Images.Media.EXTERNAL_CONTENT_URI, values);
- }
-
- private Uri saveGenericImage(JobContext jc, Bitmap cropped) {
- if (!DOWNLOAD_BUCKET.isDirectory() && !DOWNLOAD_BUCKET.mkdirs()) {
- throw new RuntimeException("cannot create download folder");
- }
-
- long now = System.currentTimeMillis();
- String filename = new SimpleDateFormat(TIME_STAMP_NAME).
- format(new Date(now));
-
- File output = saveMedia(jc, cropped, DOWNLOAD_BUCKET, filename, null);
- if (output == null) return null;
-
- ContentValues values = new ContentValues();
- values.put(Images.Media.TITLE, filename);
- values.put(Images.Media.DISPLAY_NAME, output.getName());
- values.put(Images.Media.DATE_TAKEN, now);
- values.put(Images.Media.DATE_MODIFIED, now / 1000);
- values.put(Images.Media.DATE_ADDED, now / 1000);
- values.put(Images.Media.MIME_TYPE, getOutputMimeType());
- values.put(Images.Media.ORIENTATION, 0);
- values.put(Images.Media.DATA, output.getAbsolutePath());
- values.put(Images.Media.SIZE, output.length());
-
- setImageSize(values, cropped.getWidth(), cropped.getHeight());
-
- return getContentResolver().insert(
- Images.Media.EXTERNAL_CONTENT_URI, values);
- }
-
- private boolean saveBitmapToOutputStream(
- JobContext jc, Bitmap bitmap, CompressFormat format, OutputStream os) {
- // We wrap the OutputStream so that it can be interrupted.
- final InterruptableOutputStream ios = new InterruptableOutputStream(os);
- jc.setCancelListener(new CancelListener() {
- @Override
- public void onCancel() {
- ios.interrupt();
- }
- });
- try {
- bitmap.compress(format, DEFAULT_COMPRESS_QUALITY, ios);
- return !jc.isCancelled();
- } finally {
- jc.setCancelListener(null);
- Utils.closeSilently(ios);
- }
- }
-
- private boolean saveBitmapToUri(JobContext jc, Bitmap bitmap, Uri uri) {
- try {
- OutputStream out = getContentResolver().openOutputStream(uri);
- try {
- return saveBitmapToOutputStream(jc, bitmap,
- convertExtensionToCompressFormat(getFileExtension()), out);
- } finally {
- Utils.closeSilently(out);
- }
- } catch (FileNotFoundException e) {
- Log.w(TAG, "cannot write output", e);
- }
- return true;
- }
-
- private CompressFormat convertExtensionToCompressFormat(String extension) {
- return extension.equals("png")
- ? CompressFormat.PNG
- : CompressFormat.JPEG;
- }
-
- private String getOutputMimeType() {
- return getFileExtension().equals("png") ? "image/png" : "image/jpeg";
- }
-
- private String getFileExtension() {
- String requestFormat = getIntent().getStringExtra(KEY_OUTPUT_FORMAT);
- String outputFormat = (requestFormat == null)
- ? determineCompressFormat(mMediaItem)
- : requestFormat;
-
- outputFormat = outputFormat.toLowerCase();
- return (outputFormat.equals("png") || outputFormat.equals("gif"))
- ? "png" // We don't support gif compression.
- : "jpg";
- }
-
- private void onSaveClicked() {
- Bundle extra = getIntent().getExtras();
- RectF cropRect = mCropView.getCropRectangle();
- if (cropRect == null) return;
- mState = STATE_SAVING;
- int messageId = extra != null && extra.getBoolean(KEY_SET_AS_WALLPAPER)
- ? R.string.wallpaper
- : R.string.saving_image;
- mProgressDialog = ProgressDialog.show(
- this, null, getString(messageId), true, false);
- mSaveTask = getThreadPool().submit(new SaveOutput(cropRect),
- new FutureListener<Intent>() {
- @Override
- public void onFutureDone(Future<Intent> future) {
- mSaveTask = null;
- if (future.isCancelled()) return;
- Intent intent = future.get();
- if (intent != null) {
- mMainHandler.sendMessage(mMainHandler.obtainMessage(
- MSG_SAVE_COMPLETE, intent));
- } else {
- mMainHandler.sendEmptyMessage(MSG_SHOW_SAVE_ERROR);
- }
- }
- });
- }
-
- private Bitmap getCroppedImage(Rect rect) {
- Utils.assertTrue(rect.width() > 0 && rect.height() > 0);
-
- Bundle extras = getIntent().getExtras();
- // (outputX, outputY) = the width and height of the returning bitmap.
- int outputX = rect.width();
- int outputY = rect.height();
- if (extras != null) {
- outputX = extras.getInt(KEY_OUTPUT_X, outputX);
- outputY = extras.getInt(KEY_OUTPUT_Y, outputY);
- }
-
- if (outputX * outputY > MAX_PIXEL_COUNT) {
- float scale = FloatMath.sqrt((float) MAX_PIXEL_COUNT / outputX / outputY);
- Log.w(TAG, "scale down the cropped image: " + scale);
- outputX = Math.round(scale * outputX);
- outputY = Math.round(scale * outputY);
- }
-
- // (rect.width() * scaleX, rect.height() * scaleY) =
- // the size of drawing area in output bitmap
- float scaleX = 1;
- float scaleY = 1;
- Rect dest = new Rect(0, 0, outputX, outputY);
- if (extras == null || extras.getBoolean(KEY_SCALE, true)) {
- scaleX = (float) outputX / rect.width();
- scaleY = (float) outputY / rect.height();
- if (extras == null || !extras.getBoolean(
- KEY_SCALE_UP_IF_NEEDED, false)) {
- if (scaleX > 1f) scaleX = 1;
- if (scaleY > 1f) scaleY = 1;
- }
- }
-
- // Keep the content in the center (or crop the content)
- int rectWidth = Math.round(rect.width() * scaleX);
- int rectHeight = Math.round(rect.height() * scaleY);
- dest.set(Math.round((outputX - rectWidth) / 2f),
- Math.round((outputY - rectHeight) / 2f),
- Math.round((outputX + rectWidth) / 2f),
- Math.round((outputY + rectHeight) / 2f));
-
- if (mBitmapInIntent != null) {
- Bitmap source = mBitmapInIntent;
- Bitmap result = Bitmap.createBitmap(
- outputX, outputY, Config.ARGB_8888);
- Canvas canvas = new Canvas(result);
- canvas.drawBitmap(source, rect, dest, null);
- return result;
- }
-
- if (mUseRegionDecoder) {
- int rotation = mMediaItem.getFullImageRotation();
- rotateRectangle(rect, mCropView.getImageWidth(),
- mCropView.getImageHeight(), 360 - rotation);
- rotateRectangle(dest, outputX, outputY, 360 - rotation);
-
- BitmapFactory.Options options = new BitmapFactory.Options();
- int sample = BitmapUtils.computeSampleSizeLarger(
- Math.max(scaleX, scaleY));
- options.inSampleSize = sample;
-
- // The decoding result is what we want if
- // 1. The size of the decoded bitmap match the destination's size
- // 2. The destination covers the whole output bitmap
- // 3. No rotation
- if ((rect.width() / sample) == dest.width()
- && (rect.height() / sample) == dest.height()
- && (outputX == dest.width()) && (outputY == dest.height())
- && rotation == 0) {
- // To prevent concurrent access in GLThread
- synchronized (mRegionDecoder) {
- return mRegionDecoder.decodeRegion(rect, options);
- }
- }
- Bitmap result = Bitmap.createBitmap(
- outputX, outputY, Config.ARGB_8888);
- Canvas canvas = new Canvas(result);
- rotateCanvas(canvas, outputX, outputY, rotation);
- drawInTiles(canvas, mRegionDecoder, rect, dest, sample);
- return result;
- } else {
- int rotation = mMediaItem.getRotation();
- rotateRectangle(rect, mCropView.getImageWidth(),
- mCropView.getImageHeight(), 360 - rotation);
- rotateRectangle(dest, outputX, outputY, 360 - rotation);
- Bitmap result = Bitmap.createBitmap(outputX, outputY, Config.ARGB_8888);
- Canvas canvas = new Canvas(result);
- rotateCanvas(canvas, outputX, outputY, rotation);
- canvas.drawBitmap(mBitmap,
- rect, dest, new Paint(Paint.FILTER_BITMAP_FLAG));
- return result;
- }
- }
-
- private static void rotateCanvas(
- Canvas canvas, int width, int height, int rotation) {
- canvas.translate(width / 2, height / 2);
- canvas.rotate(rotation);
- if (((rotation / 90) & 0x01) == 0) {
- canvas.translate(-width / 2, -height / 2);
- } else {
- canvas.translate(-height / 2, -width / 2);
- }
- }
-
- private static void rotateRectangle(
- Rect rect, int width, int height, int rotation) {
- if (rotation == 0 || rotation == 360) return;
-
- int w = rect.width();
- int h = rect.height();
- switch (rotation) {
- case 90: {
- rect.top = rect.left;
- rect.left = height - rect.bottom;
- rect.right = rect.left + h;
- rect.bottom = rect.top + w;
- return;
- }
- case 180: {
- rect.left = width - rect.right;
- rect.top = height - rect.bottom;
- rect.right = rect.left + w;
- rect.bottom = rect.top + h;
- return;
- }
- case 270: {
- rect.left = rect.top;
- rect.top = width - rect.right;
- rect.right = rect.left + h;
- rect.bottom = rect.top + w;
- return;
- }
- default: throw new AssertionError();
- }
- }
-
- private void drawInTiles(Canvas canvas,
- BitmapRegionDecoder decoder, Rect rect, Rect dest, int sample) {
- int tileSize = TILE_SIZE * sample;
- Rect tileRect = new Rect();
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inPreferredConfig = Config.ARGB_8888;
- options.inSampleSize = sample;
- canvas.translate(dest.left, dest.top);
- canvas.scale((float) sample * dest.width() / rect.width(),
- (float) sample * dest.height() / rect.height());
- Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
- for (int tx = rect.left, x = 0;
- tx < rect.right; tx += tileSize, x += TILE_SIZE) {
- for (int ty = rect.top, y = 0;
- ty < rect.bottom; ty += tileSize, y += TILE_SIZE) {
- tileRect.set(tx, ty, tx + tileSize, ty + tileSize);
- if (tileRect.intersect(rect)) {
- Bitmap bitmap;
-
- // To prevent concurrent access in GLThread
- synchronized (decoder) {
- bitmap = decoder.decodeRegion(tileRect, options);
- }
- canvas.drawBitmap(bitmap, x, y, paint);
- bitmap.recycle();
- }
- }
- }
- }
-
- private void onBitmapRegionDecoderAvailable(
- BitmapRegionDecoder regionDecoder) {
-
- if (regionDecoder == null) {
- Toast.makeText(this, R.string.fail_to_load_image, Toast.LENGTH_SHORT).show();
- finish();
- return;
- }
- mRegionDecoder = regionDecoder;
- mUseRegionDecoder = true;
- mState = STATE_LOADED;
-
- BitmapFactory.Options options = new BitmapFactory.Options();
- int width = regionDecoder.getWidth();
- int height = regionDecoder.getHeight();
- options.inSampleSize = BitmapUtils.computeSampleSize(width, height,
- BitmapUtils.UNCONSTRAINED, BACKUP_PIXEL_COUNT);
- mBitmap = regionDecoder.decodeRegion(
- new Rect(0, 0, width, height), options);
-
- mBitmapScreenNail = new BitmapScreenNail(mBitmap);
-
- TileImageViewAdapter adapter = new TileImageViewAdapter();
- adapter.setScreenNail(mBitmapScreenNail, width, height);
- adapter.setRegionDecoder(regionDecoder);
-
- mCropView.setDataModel(adapter, mMediaItem.getFullImageRotation());
- if (mDoFaceDetection) {
- mCropView.detectFaces(mBitmap);
- } else {
- mCropView.initializeHighlightRectangle();
- }
- }
-
- private void onBitmapAvailable(Bitmap bitmap) {
- if (bitmap == null) {
- Toast.makeText(this, R.string.fail_to_load_image, Toast.LENGTH_SHORT).show();
- finish();
- return;
- }
- mUseRegionDecoder = false;
- mState = STATE_LOADED;
-
- mBitmap = bitmap;
- BitmapFactory.Options options = new BitmapFactory.Options();
- mCropView.setDataModel(new BitmapTileProvider(bitmap, 512),
- mMediaItem.getRotation());
- if (mDoFaceDetection) {
- mCropView.detectFaces(bitmap);
- } else {
- mCropView.initializeHighlightRectangle();
- }
- }
-
- private void setCropParameters() {
- Bundle extras = getIntent().getExtras();
- if (extras == null)
- return;
- int aspectX = extras.getInt(KEY_ASPECT_X, 0);
- int aspectY = extras.getInt(KEY_ASPECT_Y, 0);
- if (aspectX != 0 && aspectY != 0) {
- mCropView.setAspectRatio((float) aspectX / aspectY);
- }
-
- float spotlightX = extras.getFloat(KEY_SPOTLIGHT_X, 0);
- float spotlightY = extras.getFloat(KEY_SPOTLIGHT_Y, 0);
- if (spotlightX != 0 && spotlightY != 0) {
- mCropView.setSpotlightRatio(spotlightX, spotlightY);
- }
- }
-
- private void initializeData() {
- Bundle extras = getIntent().getExtras();
-
- if (extras != null) {
- if (extras.containsKey(KEY_NO_FACE_DETECTION)) {
- mDoFaceDetection = !extras.getBoolean(KEY_NO_FACE_DETECTION);
- }
-
- mBitmapInIntent = extras.getParcelable(KEY_DATA);
-
- if (mBitmapInIntent != null) {
- mBitmapTileProvider =
- new BitmapTileProvider(mBitmapInIntent, MAX_BACKUP_IMAGE_SIZE);
- mCropView.setDataModel(mBitmapTileProvider, 0);
- if (mDoFaceDetection) {
- mCropView.detectFaces(mBitmapInIntent);
- } else {
- mCropView.initializeHighlightRectangle();
- }
- mState = STATE_LOADED;
- return;
- }
- }
-
- mProgressDialog = ProgressDialog.show(
- this, null, getString(R.string.loading_image), true, true);
- mProgressDialog.setCanceledOnTouchOutside(false);
- mProgressDialog.setCancelMessage(mMainHandler.obtainMessage(MSG_CANCEL_DIALOG));
-
- mMediaItem = getMediaItemFromIntentData();
- if (mMediaItem == null) return;
-
- boolean supportedByBitmapRegionDecoder =
- (mMediaItem.getSupportedOperations() & MediaItem.SUPPORT_FULL_IMAGE) != 0;
- if (supportedByBitmapRegionDecoder) {
- mLoadTask = getThreadPool().submit(new LoadDataTask(mMediaItem),
- new FutureListener<BitmapRegionDecoder>() {
- @Override
- public void onFutureDone(Future<BitmapRegionDecoder> future) {
- mLoadTask = null;
- BitmapRegionDecoder decoder = future.get();
- if (future.isCancelled()) {
- if (decoder != null) decoder.recycle();
- return;
- }
- mMainHandler.sendMessage(mMainHandler.obtainMessage(
- MSG_LARGE_BITMAP, decoder));
- }
- });
- } else {
- mLoadBitmapTask = getThreadPool().submit(new LoadBitmapDataTask(mMediaItem),
- new FutureListener<Bitmap>() {
- @Override
- public void onFutureDone(Future<Bitmap> future) {
- mLoadBitmapTask = null;
- Bitmap bitmap = future.get();
- if (future.isCancelled()) {
- if (bitmap != null) bitmap.recycle();
- return;
- }
- mMainHandler.sendMessage(mMainHandler.obtainMessage(
- MSG_BITMAP, bitmap));
- }
- });
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- if (mState == STATE_INIT) initializeData();
- if (mState == STATE_SAVING) onSaveClicked();
-
- // TODO: consider to do it in GLView system
- GLRoot root = getGLRoot();
- root.lockRenderThread();
- try {
- mCropView.resume();
- } finally {
- root.unlockRenderThread();
- }
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- dismissProgressDialogIfShown();
-
- Future<BitmapRegionDecoder> loadTask = mLoadTask;
- if (loadTask != null && !loadTask.isDone()) {
- // load in progress, try to cancel it
- loadTask.cancel();
- loadTask.waitDone();
- }
-
- Future<Bitmap> loadBitmapTask = mLoadBitmapTask;
- if (loadBitmapTask != null && !loadBitmapTask.isDone()) {
- // load in progress, try to cancel it
- loadBitmapTask.cancel();
- loadBitmapTask.waitDone();
- }
-
- Future<Intent> saveTask = mSaveTask;
- if (saveTask != null && !saveTask.isDone()) {
- // save in progress, try to cancel it
- saveTask.cancel();
- saveTask.waitDone();
- }
- GLRoot root = getGLRoot();
- root.lockRenderThread();
- try {
- mCropView.pause();
- } finally {
- root.unlockRenderThread();
- }
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (mBitmapScreenNail != null) {
- mBitmapScreenNail.recycle();
- mBitmapScreenNail = null;
- }
- }
-
- private void dismissProgressDialogIfShown() {
- if (mProgressDialog != null) {
- mProgressDialog.dismiss();
- mProgressDialog = null;
- }
- }
-
- private MediaItem getMediaItemFromIntentData() {
- Uri uri = getIntent().getData();
- DataManager manager = getDataManager();
- Path path = manager.findPathByUri(uri, getIntent().getType());
- if (path == null) {
- Log.w(TAG, "cannot get path for: " + uri + ", or no data given");
- return null;
- }
- return (MediaItem) manager.getMediaObject(path);
- }
-
- private class LoadDataTask implements Job<BitmapRegionDecoder> {
- MediaItem mItem;
-
- public LoadDataTask(MediaItem item) {
- mItem = item;
- }
-
- @Override
- public BitmapRegionDecoder run(JobContext jc) {
- return mItem == null ? null : mItem.requestLargeImage().run(jc);
- }
- }
-
- private class LoadBitmapDataTask implements Job<Bitmap> {
- MediaItem mItem;
-
- public LoadBitmapDataTask(MediaItem item) {
- mItem = item;
- }
- @Override
- public Bitmap run(JobContext jc) {
- return mItem == null
- ? null
- : mItem.requestImage(MediaItem.TYPE_THUMBNAIL).run(jc);
- }
- }
-}
diff --git a/src/com/android/gallery3d/app/Wallpaper.java b/src/com/android/gallery3d/app/Wallpaper.java
index fce4bacca..1bbe8d2c6 100644
--- a/src/com/android/gallery3d/app/Wallpaper.java
+++ b/src/com/android/gallery3d/app/Wallpaper.java
@@ -27,6 +27,7 @@ import android.view.Display;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.CropExtras;
/**
* Wallpaper picker for the gallery application. This just redirects to the
@@ -102,16 +103,15 @@ public class Wallpaper extends Activity {
Intent request = new Intent(FilterShowActivity.CROP_ACTION)
.setDataAndType(mPickedItem, IMAGE_TYPE)
.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
- .putExtra(CropImage.KEY_OUTPUT_X, width)
- .putExtra(CropImage.KEY_OUTPUT_Y, height)
- .putExtra(CropImage.KEY_ASPECT_X, width)
- .putExtra(CropImage.KEY_ASPECT_Y, height)
- .putExtra(CropImage.KEY_SPOTLIGHT_X, spotlightX)
- .putExtra(CropImage.KEY_SPOTLIGHT_Y, spotlightY)
- .putExtra(CropImage.KEY_SCALE, true)
- .putExtra(CropImage.KEY_SCALE_UP_IF_NEEDED, true)
- .putExtra(CropImage.KEY_NO_FACE_DETECTION, true)
- .putExtra(CropImage.KEY_SET_AS_WALLPAPER, true);
+ .putExtra(CropExtras.KEY_OUTPUT_X, width)
+ .putExtra(CropExtras.KEY_OUTPUT_Y, height)
+ .putExtra(CropExtras.KEY_ASPECT_X, width)
+ .putExtra(CropExtras.KEY_ASPECT_Y, height)
+ .putExtra(CropExtras.KEY_SPOTLIGHT_X, spotlightX)
+ .putExtra(CropExtras.KEY_SPOTLIGHT_Y, spotlightY)
+ .putExtra(CropExtras.KEY_SCALE, true)
+ .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true)
+ .putExtra(CropExtras.KEY_SET_AS_WALLPAPER, true);
startActivity(request);
finish();
}
diff --git a/src/com/android/gallery3d/data/CropExtras.java b/src/com/android/gallery3d/filtershow/CropExtras.java
index 8cec32a34..7ed8f1eb5 100644
--- a/src/com/android/gallery3d/data/CropExtras.java
+++ b/src/com/android/gallery3d/filtershow/CropExtras.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.gallery3d.data;
+package com.android.gallery3d.filtershow;
import android.net.Uri;
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index 9cc3b6ef4..cf10a3e55 100644
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -54,7 +54,6 @@ import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
import android.widget.Toast;
import com.android.gallery3d.R;
-import com.android.gallery3d.data.CropExtras;
import com.android.gallery3d.data.LocalAlbum;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.filters.ImageFilter;
@@ -103,7 +102,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
OnShareTargetSelectedListener {
// fields for supporting crop action
- public static final String CROP_ACTION = "com.android.camera.action.EDITOR_CROP";
+ public static final String CROP_ACTION = "com.android.camera.action.CROP";
private CropExtras mCropExtras = null;
public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET";
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
index 0af152cb9..a1a1ba186 100644
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
@@ -38,10 +38,10 @@ import com.adobe.xmp.XMPMeta;
import com.android.gallery3d.R;
import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.data.CropExtras;
import com.android.gallery3d.exif.ExifInvalidFormatException;
import com.android.gallery3d.exif.ExifParser;
import com.android.gallery3d.exif.ExifTag;
+import com.android.gallery3d.filtershow.CropExtras;
import com.android.gallery3d.filtershow.FilterShowActivity;
import com.android.gallery3d.filtershow.HistoryAdapter;
import com.android.gallery3d.filtershow.imageshow.ImageCrop;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java
index 2917717f9..33ecc8ab9 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java
@@ -23,7 +23,7 @@ import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
-import com.android.gallery3d.data.CropExtras;
+import com.android.gallery3d.filtershow.CropExtras;
import com.android.gallery3d.filtershow.imageshow.GeometryMath;
import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java
index 5f32515e7..b53284061 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java
@@ -21,7 +21,7 @@ import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
-import com.android.gallery3d.data.CropExtras;
+import com.android.gallery3d.filtershow.CropExtras;
import com.android.gallery3d.filtershow.cache.ImageLoader;
import com.android.gallery3d.filtershow.filters.ImageFilterGeometry;
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
index 84ddaa32d..594e008a2 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
@@ -29,7 +29,7 @@ import android.util.AttributeSet;
import android.util.Log;
import com.android.gallery3d.R;
-import com.android.gallery3d.data.CropExtras;
+import com.android.gallery3d.filtershow.CropExtras;
public class ImageCrop extends ImageGeometry {
private static final boolean LOGV = false;
diff --git a/src/com/android/gallery3d/gadget/WidgetConfigure.java b/src/com/android/gallery3d/gadget/WidgetConfigure.java
index b58de7242..3a1b52bdc 100644
--- a/src/com/android/gallery3d/gadget/WidgetConfigure.java
+++ b/src/com/android/gallery3d/gadget/WidgetConfigure.java
@@ -27,10 +27,10 @@ import android.widget.RemoteViews;
import com.android.gallery3d.R;
import com.android.gallery3d.app.AlbumPicker;
-import com.android.gallery3d.app.CropImage;
import com.android.gallery3d.app.DialogPicker;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.CropExtras;
public class WidgetConfigure extends Activity {
@SuppressWarnings("unused")
@@ -144,13 +144,13 @@ public class WidgetConfigure extends Activity {
mPickedItem = data.getData();
Intent request = new Intent(FilterShowActivity.CROP_ACTION, mPickedItem)
- .putExtra(CropImage.KEY_OUTPUT_X, widgetWidth)
- .putExtra(CropImage.KEY_OUTPUT_Y, widgetHeight)
- .putExtra(CropImage.KEY_ASPECT_X, widgetWidth)
- .putExtra(CropImage.KEY_ASPECT_Y, widgetHeight)
- .putExtra(CropImage.KEY_SCALE_UP_IF_NEEDED, true)
- .putExtra(CropImage.KEY_SCALE, true)
- .putExtra(CropImage.KEY_RETURN_DATA, true);
+ .putExtra(CropExtras.KEY_OUTPUT_X, widgetWidth)
+ .putExtra(CropExtras.KEY_OUTPUT_Y, widgetHeight)
+ .putExtra(CropExtras.KEY_ASPECT_X, widgetWidth)
+ .putExtra(CropExtras.KEY_ASPECT_Y, widgetHeight)
+ .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true)
+ .putExtra(CropExtras.KEY_SCALE, true)
+ .putExtra(CropExtras.KEY_RETURN_DATA, true);
startActivityForResult(request, REQUEST_CROP_IMAGE);
}
diff --git a/src/com/android/gallery3d/ui/CropView.java b/src/com/android/gallery3d/ui/CropView.java
deleted file mode 100644
index a575557bb..000000000
--- a/src/com/android/gallery3d/ui/CropView.java
+++ /dev/null
@@ -1,794 +0,0 @@
-/*
- * 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.ui;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PointF;
-import android.graphics.RectF;
-import android.media.FaceDetector;
-import android.os.Handler;
-import android.os.Message;
-import android.util.FloatMath;
-import android.view.MotionEvent;
-import android.view.animation.DecelerateInterpolator;
-import android.widget.Toast;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.anim.Animation;
-import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.common.Utils;
-
-import java.util.ArrayList;
-
-/**
- * The activity can crop specific region of interest from an image.
- */
-public class CropView extends GLView {
- @SuppressWarnings("unused")
- private static final String TAG = "CropView";
-
- private static final int FACE_PIXEL_COUNT = 120000; // around 400x300
-
- private static final int COLOR_OUTLINE = 0xFF008AFF;
- private static final int COLOR_FACE_OUTLINE = 0xFF000000;
-
- private static final float OUTLINE_WIDTH = 3f;
-
- private static final int SIZE_UNKNOWN = -1;
- private static final int TOUCH_TOLERANCE = 30;
-
- private static final float MIN_SELECTION_LENGTH = 16f;
- public static final float UNSPECIFIED = -1f;
-
- private static final int MAX_FACE_COUNT = 3;
- private static final float FACE_EYE_RATIO = 2f;
-
- private static final int ANIMATION_DURATION = 1250;
-
- private static final int MOVE_LEFT = 1;
- private static final int MOVE_TOP = 2;
- private static final int MOVE_RIGHT = 4;
- private static final int MOVE_BOTTOM = 8;
- private static final int MOVE_BLOCK = 16;
-
- private static final float MAX_SELECTION_RATIO = 0.8f;
- private static final float MIN_SELECTION_RATIO = 0.4f;
- private static final float SELECTION_RATIO = 0.60f;
- private static final int ANIMATION_TRIGGER = 64;
-
- private static final int MSG_UPDATE_FACES = 1;
-
- private float mAspectRatio = UNSPECIFIED;
- private float mSpotlightRatioX = 0;
- private float mSpotlightRatioY = 0;
-
- private Handler mMainHandler;
-
- private FaceHighlightView mFaceDetectionView;
- private HighlightRectangle mHighlightRectangle;
- private TileImageView mImageView;
- private AnimationController mAnimation = new AnimationController();
-
- private int mImageWidth = SIZE_UNKNOWN;
- private int mImageHeight = SIZE_UNKNOWN;
-
- private AbstractGalleryActivity mActivity;
-
- private GLPaint mPaint = new GLPaint();
- private GLPaint mFacePaint = new GLPaint();
-
- private int mImageRotation;
-
- public CropView(AbstractGalleryActivity activity) {
- mActivity = activity;
- mImageView = new TileImageView(activity);
- mFaceDetectionView = new FaceHighlightView();
- mHighlightRectangle = new HighlightRectangle();
-
- addComponent(mImageView);
- addComponent(mFaceDetectionView);
- addComponent(mHighlightRectangle);
-
- mHighlightRectangle.setVisibility(GLView.INVISIBLE);
-
- mPaint.setColor(COLOR_OUTLINE);
- mPaint.setLineWidth(OUTLINE_WIDTH);
-
- mFacePaint.setColor(COLOR_FACE_OUTLINE);
- mFacePaint.setLineWidth(OUTLINE_WIDTH);
-
- mMainHandler = new SynchronizedHandler(activity.getGLRoot()) {
- @Override
- public void handleMessage(Message message) {
- Utils.assertTrue(message.what == MSG_UPDATE_FACES);
- ((DetectFaceTask) message.obj).updateFaces();
- }
- };
- }
-
- public void setAspectRatio(float ratio) {
- mAspectRatio = ratio;
- }
-
- public void setSpotlightRatio(float ratioX, float ratioY) {
- mSpotlightRatioX = ratioX;
- mSpotlightRatioY = ratioY;
- }
-
- @Override
- public void onLayout(boolean changed, int l, int t, int r, int b) {
- int width = r - l;
- int height = b - t;
-
- mFaceDetectionView.layout(0, 0, width, height);
- mHighlightRectangle.layout(0, 0, width, height);
- mImageView.layout(0, 0, width, height);
- if (mImageHeight != SIZE_UNKNOWN) {
- mAnimation.initialize();
- if (mHighlightRectangle.getVisibility() == GLView.VISIBLE) {
- mAnimation.parkNow(
- mHighlightRectangle.mHighlightRect);
- }
- }
- }
-
- private boolean setImageViewPosition(int centerX, int centerY, float scale) {
- int inverseX = mImageWidth - centerX;
- int inverseY = mImageHeight - centerY;
- TileImageView t = mImageView;
- int rotation = mImageRotation;
- switch (rotation) {
- case 0: return t.setPosition(centerX, centerY, scale, 0);
- case 90: return t.setPosition(centerY, inverseX, scale, 90);
- case 180: return t.setPosition(inverseX, inverseY, scale, 180);
- case 270: return t.setPosition(inverseY, centerX, scale, 270);
- default: throw new IllegalArgumentException(String.valueOf(rotation));
- }
- }
-
- @Override
- public void render(GLCanvas canvas) {
- AnimationController a = mAnimation;
- if (a.calculate(AnimationTime.get())) invalidate();
- setImageViewPosition(a.getCenterX(), a.getCenterY(), a.getScale());
- super.render(canvas);
- }
-
- @Override
- public void renderBackground(GLCanvas canvas) {
- canvas.clearBuffer();
- }
-
- public RectF getCropRectangle() {
- if (mHighlightRectangle.getVisibility() == GLView.INVISIBLE) return null;
- RectF rect = mHighlightRectangle.mHighlightRect;
- RectF result = new RectF(rect.left * mImageWidth, rect.top * mImageHeight,
- rect.right * mImageWidth, rect.bottom * mImageHeight);
- return result;
- }
-
- public int getImageWidth() {
- return mImageWidth;
- }
-
- public int getImageHeight() {
- return mImageHeight;
- }
-
- private class FaceHighlightView extends GLView {
- private static final int INDEX_NONE = -1;
- private ArrayList<RectF> mFaces = new ArrayList<RectF>();
- private RectF mRect = new RectF();
- private int mPressedFaceIndex = INDEX_NONE;
-
- public void addFace(RectF faceRect) {
- mFaces.add(faceRect);
- invalidate();
- }
-
- private void renderFace(GLCanvas canvas, RectF face, boolean pressed) {
- if (pressed) {
- canvas.enableStencil();
- canvas.clearStencilBuffer();
- canvas.updateStencil(true);
- canvas.drawOnlyOutsideStencil(false);
- }
-
- RectF r = mAnimation.mapRect(face, mRect);
- canvas.fillRect(r.left, r.top, r.width(), r.height(), Color.TRANSPARENT);
- canvas.drawRect(r.left, r.top, r.width(), r.height(), mFacePaint);
-
- if (pressed) {
- canvas.updateStencil(false);
- canvas.disableStencil();
- }
- }
-
- @Override
- protected void renderBackground(GLCanvas canvas) {
- ArrayList<RectF> faces = mFaces;
- for (int i = 0, n = faces.size(); i < n; ++i) {
- renderFace(canvas, faces.get(i), i == mPressedFaceIndex);
- }
-
- if (mPressedFaceIndex != INDEX_NONE) {
- canvas.enableStencil();
- canvas.drawOnlyOutsideStencil(true);
- canvas.fillRect(0, 0, getWidth(), getHeight(), 0x66000000);
- canvas.disableStencil();
- }
- }
-
- private void setPressedFace(int index) {
- if (mPressedFaceIndex == index) return;
- mPressedFaceIndex = index;
- invalidate();
- }
-
- private int getFaceIndexByPosition(float x, float y) {
- ArrayList<RectF> faces = mFaces;
- for (int i = 0, n = faces.size(); i < n; ++i) {
- RectF r = mAnimation.mapRect(faces.get(i), mRect);
- if (r.contains(x, y)) return i;
- }
- return INDEX_NONE;
- }
-
- @Override
- protected boolean onTouch(MotionEvent event) {
- float x = event.getX();
- float y = event.getY();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_MOVE: {
- setPressedFace(getFaceIndexByPosition(x, y));
- break;
- }
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP: {
- int index = mPressedFaceIndex;
- setPressedFace(INDEX_NONE);
- if (index != INDEX_NONE) {
- mHighlightRectangle.setRectangle(mFaces.get(index));
- mHighlightRectangle.setVisibility(GLView.VISIBLE);
- setVisibility(GLView.INVISIBLE);
- }
- }
- }
- return true;
- }
- }
-
- private class AnimationController extends Animation {
- private int mCurrentX;
- private int mCurrentY;
- private float mCurrentScale;
- private int mStartX;
- private int mStartY;
- private float mStartScale;
- private int mTargetX;
- private int mTargetY;
- private float mTargetScale;
-
- public AnimationController() {
- setDuration(ANIMATION_DURATION);
- setInterpolator(new DecelerateInterpolator(4));
- }
-
- public void initialize() {
- mCurrentX = mImageWidth / 2;
- mCurrentY = mImageHeight / 2;
- mCurrentScale = Math.min(2, Math.min(
- (float) getWidth() / mImageWidth,
- (float) getHeight() / mImageHeight));
- }
-
- public void startParkingAnimation(RectF highlight) {
- RectF r = mAnimation.mapRect(highlight, new RectF());
- int width = getWidth();
- int height = getHeight();
-
- float wr = r.width() / width;
- float hr = r.height() / height;
- final int d = ANIMATION_TRIGGER;
- if (wr >= MIN_SELECTION_RATIO && wr < MAX_SELECTION_RATIO
- && hr >= MIN_SELECTION_RATIO && hr < MAX_SELECTION_RATIO
- && r.left >= d && r.right < width - d
- && r.top >= d && r.bottom < height - d) return;
-
- mStartX = mCurrentX;
- mStartY = mCurrentY;
- mStartScale = mCurrentScale;
- calculateTarget(highlight);
- start();
- }
-
- public void parkNow(RectF highlight) {
- calculateTarget(highlight);
- forceStop();
- mStartX = mCurrentX = mTargetX;
- mStartY = mCurrentY = mTargetY;
- mStartScale = mCurrentScale = mTargetScale;
- }
-
- public void inverseMapPoint(PointF point) {
- float s = mCurrentScale;
- point.x = Utils.clamp(((point.x - getWidth() * 0.5f) / s
- + mCurrentX) / mImageWidth, 0, 1);
- point.y = Utils.clamp(((point.y - getHeight() * 0.5f) / s
- + mCurrentY) / mImageHeight, 0, 1);
- }
-
- public RectF mapRect(RectF input, RectF output) {
- float offsetX = getWidth() * 0.5f;
- float offsetY = getHeight() * 0.5f;
- int x = mCurrentX;
- int y = mCurrentY;
- float s = mCurrentScale;
- output.set(
- offsetX + (input.left * mImageWidth - x) * s,
- offsetY + (input.top * mImageHeight - y) * s,
- offsetX + (input.right * mImageWidth - x) * s,
- offsetY + (input.bottom * mImageHeight - y) * s);
- return output;
- }
-
- @Override
- protected void onCalculate(float progress) {
- mCurrentX = Math.round(mStartX + (mTargetX - mStartX) * progress);
- mCurrentY = Math.round(mStartY + (mTargetY - mStartY) * progress);
- mCurrentScale = mStartScale + (mTargetScale - mStartScale) * progress;
-
- if (mCurrentX == mTargetX && mCurrentY == mTargetY
- && mCurrentScale == mTargetScale) forceStop();
- }
-
- public int getCenterX() {
- return mCurrentX;
- }
-
- public int getCenterY() {
- return mCurrentY;
- }
-
- public float getScale() {
- return mCurrentScale;
- }
-
- private void calculateTarget(RectF highlight) {
- float width = getWidth();
- float height = getHeight();
-
- if (mImageWidth != SIZE_UNKNOWN) {
- float minScale = Math.min(width / mImageWidth, height / mImageHeight);
- float scale = Utils.clamp(SELECTION_RATIO * Math.min(
- width / (highlight.width() * mImageWidth),
- height / (highlight.height() * mImageHeight)), minScale, 2f);
- int centerX = Math.round(
- mImageWidth * (highlight.left + highlight.right) * 0.5f);
- int centerY = Math.round(
- mImageHeight * (highlight.top + highlight.bottom) * 0.5f);
-
- if (Math.round(mImageWidth * scale) > width) {
- int limitX = Math.round(width * 0.5f / scale);
- centerX = Math.round(
- (highlight.left + highlight.right) * mImageWidth / 2);
- centerX = Utils.clamp(centerX, limitX, mImageWidth - limitX);
- } else {
- centerX = mImageWidth / 2;
- }
- if (Math.round(mImageHeight * scale) > height) {
- int limitY = Math.round(height * 0.5f / scale);
- centerY = Math.round(
- (highlight.top + highlight.bottom) * mImageHeight / 2);
- centerY = Utils.clamp(centerY, limitY, mImageHeight - limitY);
- } else {
- centerY = mImageHeight / 2;
- }
- mTargetX = centerX;
- mTargetY = centerY;
- mTargetScale = scale;
- }
- }
-
- }
-
- private class HighlightRectangle extends GLView {
- private RectF mHighlightRect = new RectF(0.25f, 0.25f, 0.75f, 0.75f);
- private RectF mTempRect = new RectF();
- private PointF mTempPoint = new PointF();
-
- private ResourceTexture mArrow;
-
- private int mMovingEdges = 0;
- private float mReferenceX;
- private float mReferenceY;
-
- public HighlightRectangle() {
- mArrow = new ResourceTexture(mActivity.getAndroidContext(),
- R.drawable.camera_crop_holo);
- }
-
- public void setInitRectangle() {
- float targetRatio = mAspectRatio == UNSPECIFIED
- ? 1f
- : mAspectRatio * mImageHeight / mImageWidth;
- float w = SELECTION_RATIO / 2f;
- float h = SELECTION_RATIO / 2f;
- if (targetRatio > 1) {
- h = w / targetRatio;
- } else {
- w = h * targetRatio;
- }
- mHighlightRect.set(0.5f - w, 0.5f - h, 0.5f + w, 0.5f + h);
- }
-
- public void setRectangle(RectF faceRect) {
- mHighlightRect.set(faceRect);
- mAnimation.startParkingAnimation(faceRect);
- invalidate();
- }
-
- private void moveEdges(MotionEvent event) {
- float scale = mAnimation.getScale();
- float dx = (event.getX() - mReferenceX) / scale / mImageWidth;
- float dy = (event.getY() - mReferenceY) / scale / mImageHeight;
- mReferenceX = event.getX();
- mReferenceY = event.getY();
- RectF r = mHighlightRect;
-
- if ((mMovingEdges & MOVE_BLOCK) != 0) {
- dx = Utils.clamp(dx, -r.left, 1 - r.right);
- dy = Utils.clamp(dy, -r.top , 1 - r.bottom);
- r.top += dy;
- r.bottom += dy;
- r.left += dx;
- r.right += dx;
- } else {
- PointF point = mTempPoint;
- point.set(mReferenceX, mReferenceY);
- mAnimation.inverseMapPoint(point);
- float left = r.left + MIN_SELECTION_LENGTH / mImageWidth;
- float right = r.right - MIN_SELECTION_LENGTH / mImageWidth;
- float top = r.top + MIN_SELECTION_LENGTH / mImageHeight;
- float bottom = r.bottom - MIN_SELECTION_LENGTH / mImageHeight;
- if ((mMovingEdges & MOVE_RIGHT) != 0) {
- r.right = Utils.clamp(point.x, left, 1f);
- }
- if ((mMovingEdges & MOVE_LEFT) != 0) {
- r.left = Utils.clamp(point.x, 0, right);
- }
- if ((mMovingEdges & MOVE_TOP) != 0) {
- r.top = Utils.clamp(point.y, 0, bottom);
- }
- if ((mMovingEdges & MOVE_BOTTOM) != 0) {
- r.bottom = Utils.clamp(point.y, top, 1f);
- }
- if (mAspectRatio != UNSPECIFIED) {
- float targetRatio = mAspectRatio * mImageHeight / mImageWidth;
- if (r.width() / r.height() > targetRatio) {
- float height = r.width() / targetRatio;
- if ((mMovingEdges & MOVE_BOTTOM) != 0) {
- r.bottom = Utils.clamp(r.top + height, top, 1f);
- } else {
- r.top = Utils.clamp(r.bottom - height, 0, bottom);
- }
- } else {
- float width = r.height() * targetRatio;
- if ((mMovingEdges & MOVE_LEFT) != 0) {
- r.left = Utils.clamp(r.right - width, 0, right);
- } else {
- r.right = Utils.clamp(r.left + width, left, 1f);
- }
- }
- if (r.width() / r.height() > targetRatio) {
- float width = r.height() * targetRatio;
- if ((mMovingEdges & MOVE_LEFT) != 0) {
- r.left = Utils.clamp(r.right - width, 0, right);
- } else {
- r.right = Utils.clamp(r.left + width, left, 1f);
- }
- } else {
- float height = r.width() / targetRatio;
- if ((mMovingEdges & MOVE_BOTTOM) != 0) {
- r.bottom = Utils.clamp(r.top + height, top, 1f);
- } else {
- r.top = Utils.clamp(r.bottom - height, 0, bottom);
- }
- }
- }
- }
- invalidate();
- }
-
- private void setMovingEdges(MotionEvent event) {
- RectF r = mAnimation.mapRect(mHighlightRect, mTempRect);
- float x = event.getX();
- float y = event.getY();
-
- if (x > r.left + TOUCH_TOLERANCE && x < r.right - TOUCH_TOLERANCE
- && y > r.top + TOUCH_TOLERANCE && y < r.bottom - TOUCH_TOLERANCE) {
- mMovingEdges = MOVE_BLOCK;
- return;
- }
-
- boolean inVerticalRange = (r.top - TOUCH_TOLERANCE) <= y
- && y <= (r.bottom + TOUCH_TOLERANCE);
- boolean inHorizontalRange = (r.left - TOUCH_TOLERANCE) <= x
- && x <= (r.right + TOUCH_TOLERANCE);
-
- if (inVerticalRange) {
- boolean left = Math.abs(x - r.left) <= TOUCH_TOLERANCE;
- boolean right = Math.abs(x - r.right) <= TOUCH_TOLERANCE;
- if (left && right) {
- left = Math.abs(x - r.left) < Math.abs(x - r.right);
- right = !left;
- }
- if (left) mMovingEdges |= MOVE_LEFT;
- if (right) mMovingEdges |= MOVE_RIGHT;
- if (mAspectRatio != UNSPECIFIED && inHorizontalRange) {
- mMovingEdges |= (y >
- (r.top + r.bottom) / 2) ? MOVE_BOTTOM : MOVE_TOP;
- }
- }
- if (inHorizontalRange) {
- boolean top = Math.abs(y - r.top) <= TOUCH_TOLERANCE;
- boolean bottom = Math.abs(y - r.bottom) <= TOUCH_TOLERANCE;
- if (top && bottom) {
- top = Math.abs(y - r.top) < Math.abs(y - r.bottom);
- bottom = !top;
- }
- if (top) mMovingEdges |= MOVE_TOP;
- if (bottom) mMovingEdges |= MOVE_BOTTOM;
- if (mAspectRatio != UNSPECIFIED && inVerticalRange) {
- mMovingEdges |= (x >
- (r.left + r.right) / 2) ? MOVE_RIGHT : MOVE_LEFT;
- }
- }
- }
-
- @Override
- protected boolean onTouch(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN: {
- mReferenceX = event.getX();
- mReferenceY = event.getY();
- setMovingEdges(event);
- invalidate();
- return true;
- }
- case MotionEvent.ACTION_MOVE:
- moveEdges(event);
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP: {
- mMovingEdges = 0;
- mAnimation.startParkingAnimation(mHighlightRect);
- invalidate();
- return true;
- }
- }
- return true;
- }
-
- @Override
- protected void renderBackground(GLCanvas canvas) {
- RectF r = mAnimation.mapRect(mHighlightRect, mTempRect);
- drawHighlightRectangle(canvas, r);
-
- float centerY = (r.top + r.bottom) / 2;
- float centerX = (r.left + r.right) / 2;
- boolean notMoving = mMovingEdges == 0;
- if ((mMovingEdges & MOVE_RIGHT) != 0 || notMoving) {
- mArrow.draw(canvas,
- Math.round(r.right - mArrow.getWidth() / 2),
- Math.round(centerY - mArrow.getHeight() / 2));
- }
- if ((mMovingEdges & MOVE_LEFT) != 0 || notMoving) {
- mArrow.draw(canvas,
- Math.round(r.left - mArrow.getWidth() / 2),
- Math.round(centerY - mArrow.getHeight() / 2));
- }
- if ((mMovingEdges & MOVE_TOP) != 0 || notMoving) {
- mArrow.draw(canvas,
- Math.round(centerX - mArrow.getWidth() / 2),
- Math.round(r.top - mArrow.getHeight() / 2));
- }
- if ((mMovingEdges & MOVE_BOTTOM) != 0 || notMoving) {
- mArrow.draw(canvas,
- Math.round(centerX - mArrow.getWidth() / 2),
- Math.round(r.bottom - mArrow.getHeight() / 2));
- }
- }
-
- private void drawHighlightRectangle(GLCanvas canvas, RectF r) {
-
- canvas.enableStencil();
- canvas.clearStencilBuffer();
- canvas.updateStencil(true);
- canvas.drawOnlyOutsideStencil(false);
-
- if (mSpotlightRatioX == 0 || mSpotlightRatioY == 0) {
- canvas.fillRect(r.left, r.top, r.width(), r.height(), Color.TRANSPARENT);
- canvas.drawRect(r.left, r.top, r.width(), r.height(), mPaint);
- canvas.drawOnlyOutsideStencil(true);
- } else {
- float sx = r.width() * mSpotlightRatioX;
- float sy = r.height() * mSpotlightRatioY;
- float cx = r.centerX();
- float cy = r.centerY();
-
- canvas.fillRect(cx - sx / 2, cy - sy / 2, sx, sy, Color.TRANSPARENT);
- canvas.drawRect(cx - sx / 2, cy - sy / 2, sx, sy, mPaint);
- canvas.drawRect(r.left, r.top, r.width(), r.height(), mPaint);
-
- canvas.drawOnlyOutsideStencil(true);
-
- canvas.drawRect(cx - sy / 2, cy - sx / 2, sy, sx, mPaint);
- canvas.fillRect(cx - sy / 2, cy - sx / 2, sy, sx, Color.TRANSPARENT);
- canvas.fillRect(r.left, r.top, r.width(), r.height(), 0x80000000);
- }
-
- canvas.updateStencil(false);
- canvas.fillRect(0, 0, getWidth(), getHeight(), 0xA0000000);
-
- canvas.disableStencil();
- }
- }
-
- private class DetectFaceTask extends Thread {
- private final FaceDetector.Face[] mFaces = new FaceDetector.Face[MAX_FACE_COUNT];
- private final Bitmap mFaceBitmap;
- private int mFaceCount;
-
- public DetectFaceTask(Bitmap bitmap) {
- mFaceBitmap = bitmap;
- setName("face-detect");
- }
-
- @Override
- public void run() {
- Bitmap bitmap = mFaceBitmap;
- FaceDetector detector = new FaceDetector(
- bitmap.getWidth(), bitmap.getHeight(), MAX_FACE_COUNT);
- mFaceCount = detector.findFaces(bitmap, mFaces);
- mMainHandler.sendMessage(
- mMainHandler.obtainMessage(MSG_UPDATE_FACES, this));
- }
-
- private RectF getFaceRect(FaceDetector.Face face) {
- PointF point = new PointF();
- face.getMidPoint(point);
-
- int width = mFaceBitmap.getWidth();
- int height = mFaceBitmap.getHeight();
- float rx = face.eyesDistance() * FACE_EYE_RATIO;
- float ry = rx;
- float aspect = mAspectRatio;
- if (aspect != UNSPECIFIED) {
- if (aspect > 1) {
- rx = ry * aspect;
- } else {
- ry = rx / aspect;
- }
- }
-
- RectF r = new RectF(
- point.x - rx, point.y - ry, point.x + rx, point.y + ry);
- r.intersect(0, 0, width, height);
-
- if (aspect != UNSPECIFIED) {
- if (r.width() / r.height() > aspect) {
- float w = r.height() * aspect;
- r.left = (r.left + r.right - w) * 0.5f;
- r.right = r.left + w;
- } else {
- float h = r.width() / aspect;
- r.top = (r.top + r.bottom - h) * 0.5f;
- r.bottom = r.top + h;
- }
- }
-
- r.left /= width;
- r.right /= width;
- r.top /= height;
- r.bottom /= height;
- return r;
- }
-
- public void updateFaces() {
- if (mFaceCount > 1) {
- for (int i = 0, n = mFaceCount; i < n; ++i) {
- mFaceDetectionView.addFace(getFaceRect(mFaces[i]));
- }
- mFaceDetectionView.setVisibility(GLView.VISIBLE);
- Toast.makeText(mActivity.getAndroidContext(),
- R.string.multiface_crop_help, Toast.LENGTH_SHORT).show();
- } else if (mFaceCount == 1) {
- mFaceDetectionView.setVisibility(GLView.INVISIBLE);
- mHighlightRectangle.setRectangle(getFaceRect(mFaces[0]));
- mHighlightRectangle.setVisibility(GLView.VISIBLE);
- } else /*mFaceCount == 0*/ {
- mHighlightRectangle.setInitRectangle();
- mHighlightRectangle.setVisibility(GLView.VISIBLE);
- }
- }
- }
-
- public void setDataModel(TileImageView.Model dataModel, int rotation) {
- if (((rotation / 90) & 0x01) != 0) {
- mImageWidth = dataModel.getImageHeight();
- mImageHeight = dataModel.getImageWidth();
- } else {
- mImageWidth = dataModel.getImageWidth();
- mImageHeight = dataModel.getImageHeight();
- }
-
- mImageRotation = rotation;
-
- mImageView.setModel(dataModel);
- mAnimation.initialize();
- }
-
- public void detectFaces(Bitmap bitmap) {
- int rotation = mImageRotation;
- int width = bitmap.getWidth();
- int height = bitmap.getHeight();
- float scale = FloatMath.sqrt((float) FACE_PIXEL_COUNT / (width * height));
-
- // faceBitmap is a correctly rotated bitmap, as viewed by a user.
- Bitmap faceBitmap;
- if (((rotation / 90) & 1) == 0) {
- int w = (Math.round(width * scale) & ~1); // must be even
- int h = Math.round(height * scale);
- faceBitmap = Bitmap.createBitmap(w, h, Config.RGB_565);
- Canvas canvas = new Canvas(faceBitmap);
- canvas.rotate(rotation, w / 2, h / 2);
- canvas.scale((float) w / width, (float) h / height);
- canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));
- } else {
- int w = (Math.round(height * scale) & ~1); // must be even
- int h = Math.round(width * scale);
- faceBitmap = Bitmap.createBitmap(w, h, Config.RGB_565);
- Canvas canvas = new Canvas(faceBitmap);
- canvas.translate(w / 2, h / 2);
- canvas.rotate(rotation);
- canvas.translate(-h / 2, -w / 2);
- canvas.scale((float) w / height, (float) h / width);
- canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));
- }
- new DetectFaceTask(faceBitmap).start();
- }
-
- public void initializeHighlightRectangle() {
- mHighlightRectangle.setInitRectangle();
- mHighlightRectangle.setVisibility(GLView.VISIBLE);
- }
-
- public void resume() {
- mImageView.prepareTextures();
- }
-
- public void pause() {
- mImageView.freeTextures();
- }
-}
-
diff --git a/src/com/android/gallery3d/ui/MenuExecutor.java b/src/com/android/gallery3d/ui/MenuExecutor.java
index 847ec8953..a9eeaf89c 100644
--- a/src/com/android/gallery3d/ui/MenuExecutor.java
+++ b/src/com/android/gallery3d/ui/MenuExecutor.java
@@ -31,7 +31,6 @@ import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.android.gallery3d.R;
import com.android.gallery3d.app.AbstractGalleryActivity;
-import com.android.gallery3d.app.CropImage;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.data.DataManager;