From 795776f67fe5bca902b09c01edec630879263341 Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Wed, 5 Dec 2012 22:07:12 -0800 Subject: Removed old crop. Bug: 7441237 Change-Id: I29801f798a1d1ad3af81a82950edbb8a72ccae82 --- AndroidManifest.xml | 19 +- src/com/android/gallery3d/app/AlbumPage.java | 7 +- src/com/android/gallery3d/app/CropImage.java | 1040 -------------------- src/com/android/gallery3d/app/Wallpaper.java | 20 +- src/com/android/gallery3d/data/CropExtras.java | 121 --- .../android/gallery3d/filtershow/CropExtras.java | 121 +++ .../gallery3d/filtershow/FilterShowActivity.java | 3 +- .../gallery3d/filtershow/cache/ImageLoader.java | 2 +- .../filtershow/filters/ImageFilterGeometry.java | 2 +- .../filtershow/imageshow/GeometryMetadata.java | 2 +- .../gallery3d/filtershow/imageshow/ImageCrop.java | 2 +- .../android/gallery3d/gadget/WidgetConfigure.java | 16 +- src/com/android/gallery3d/ui/CropView.java | 794 --------------- src/com/android/gallery3d/ui/MenuExecutor.java | 1 - 14 files changed, 150 insertions(+), 2000 deletions(-) delete mode 100644 src/com/android/gallery3d/app/CropImage.java delete mode 100644 src/com/android/gallery3d/data/CropExtras.java create mode 100644 src/com/android/gallery3d/filtershow/CropExtras.java delete mode 100644 src/com/android/gallery3d/ui/CropView.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 644a409a1..f2dac1256 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -199,23 +199,6 @@ - - - - - - - - - - - - - - @@ -248,7 +231,7 @@ - + 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 mLoadTask; - private Future mLoadBitmapTask; - private Future 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 { - 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() { - @Override - public void onFutureDone(Future 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() { - @Override - public void onFutureDone(Future 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() { - @Override - public void onFutureDone(Future 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 loadTask = mLoadTask; - if (loadTask != null && !loadTask.isDone()) { - // load in progress, try to cancel it - loadTask.cancel(); - loadTask.waitDone(); - } - - Future loadBitmapTask = mLoadBitmapTask; - if (loadBitmapTask != null && !loadBitmapTask.isDone()) { - // load in progress, try to cancel it - loadBitmapTask.cancel(); - loadBitmapTask.waitDone(); - } - - Future 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 { - 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 { - 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/data/CropExtras.java deleted file mode 100644 index 8cec32a34..000000000 --- a/src/com/android/gallery3d/data/CropExtras.java +++ /dev/null @@ -1,121 +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.data; - -import android.net.Uri; - -public class CropExtras { - - public static final String KEY_CROPPED_RECT = "cropped-rect"; - 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_SCALE_UP_IF_NEEDED = "scaleUpIfNeeded"; - public static final String KEY_ASPECT_X = "aspectX"; - public static final String KEY_ASPECT_Y = "aspectY"; - public static final String KEY_SET_AS_WALLPAPER = "set-as-wallpaper"; - public static final String KEY_RETURN_DATA = "return-data"; - public static final String KEY_DATA = "data"; - public static final String KEY_SPOTLIGHT_X = "spotlightX"; - public static final String KEY_SPOTLIGHT_Y = "spotlightY"; - public static final String KEY_SHOW_WHEN_LOCKED = "showWhenLocked"; - public static final String KEY_OUTPUT_FORMAT = "outputFormat"; - - private int mOutputX = 0; - private int mOutputY = 0; - private boolean mScaleUp = true; - private int mAspectX = 0; - private int mAspectY = 0; - private boolean mSetAsWallpaper = false; - private boolean mReturnData = false; - private Uri mExtraOutput = null; - private String mOutputFormat = null; - private boolean mShowWhenLocked = false; - private float mSpotlightX = 0; - private float mSpotlightY = 0; - - public CropExtras(int outputX, int outputY, boolean scaleUp, int aspectX, int aspectY, - boolean setAsWallpaper, boolean returnData, Uri extraOutput, String outputFormat, - boolean showWhenLocked, float spotlightX, float spotlightY) { - mOutputX = outputX; - mOutputY = outputY; - mScaleUp = scaleUp; - mAspectX = aspectX; - mAspectY = aspectY; - mSetAsWallpaper = setAsWallpaper; - mReturnData = returnData; - mExtraOutput = extraOutput; - mOutputFormat = outputFormat; - mShowWhenLocked = showWhenLocked; - mSpotlightX = spotlightX; - mSpotlightY = spotlightY; - } - - public CropExtras(CropExtras c) { - this(c.mOutputX, c.mOutputY, c.mScaleUp, c.mAspectX, c.mAspectY, c.mSetAsWallpaper, - c.mReturnData, c.mExtraOutput, c.mOutputFormat, c.mShowWhenLocked, - c.mSpotlightX, c.mSpotlightY); - } - - public int getOutputX() { - return mOutputX; - } - - public int getOutputY() { - return mOutputY; - } - - public boolean getScaleUp() { - return mScaleUp; - } - - public int getAspectX() { - return mAspectX; - } - - public int getAspectY() { - return mAspectY; - } - - public boolean getSetAsWallpaper() { - return mSetAsWallpaper; - } - - public boolean getReturnData() { - return mReturnData; - } - - public Uri getExtraOutput() { - return mExtraOutput; - } - - public String getOutputFormat() { - return mOutputFormat; - } - - public boolean getShowWhenLocked() { - return mShowWhenLocked; - } - - public float getSpotlightX() { - return mSpotlightX; - } - - public float getSpotlightY() { - return mSpotlightY; - } -} diff --git a/src/com/android/gallery3d/filtershow/CropExtras.java b/src/com/android/gallery3d/filtershow/CropExtras.java new file mode 100644 index 000000000..7ed8f1eb5 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/CropExtras.java @@ -0,0 +1,121 @@ +/* + * 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; + +import android.net.Uri; + +public class CropExtras { + + public static final String KEY_CROPPED_RECT = "cropped-rect"; + 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_SCALE_UP_IF_NEEDED = "scaleUpIfNeeded"; + public static final String KEY_ASPECT_X = "aspectX"; + public static final String KEY_ASPECT_Y = "aspectY"; + public static final String KEY_SET_AS_WALLPAPER = "set-as-wallpaper"; + public static final String KEY_RETURN_DATA = "return-data"; + public static final String KEY_DATA = "data"; + public static final String KEY_SPOTLIGHT_X = "spotlightX"; + public static final String KEY_SPOTLIGHT_Y = "spotlightY"; + public static final String KEY_SHOW_WHEN_LOCKED = "showWhenLocked"; + public static final String KEY_OUTPUT_FORMAT = "outputFormat"; + + private int mOutputX = 0; + private int mOutputY = 0; + private boolean mScaleUp = true; + private int mAspectX = 0; + private int mAspectY = 0; + private boolean mSetAsWallpaper = false; + private boolean mReturnData = false; + private Uri mExtraOutput = null; + private String mOutputFormat = null; + private boolean mShowWhenLocked = false; + private float mSpotlightX = 0; + private float mSpotlightY = 0; + + public CropExtras(int outputX, int outputY, boolean scaleUp, int aspectX, int aspectY, + boolean setAsWallpaper, boolean returnData, Uri extraOutput, String outputFormat, + boolean showWhenLocked, float spotlightX, float spotlightY) { + mOutputX = outputX; + mOutputY = outputY; + mScaleUp = scaleUp; + mAspectX = aspectX; + mAspectY = aspectY; + mSetAsWallpaper = setAsWallpaper; + mReturnData = returnData; + mExtraOutput = extraOutput; + mOutputFormat = outputFormat; + mShowWhenLocked = showWhenLocked; + mSpotlightX = spotlightX; + mSpotlightY = spotlightY; + } + + public CropExtras(CropExtras c) { + this(c.mOutputX, c.mOutputY, c.mScaleUp, c.mAspectX, c.mAspectY, c.mSetAsWallpaper, + c.mReturnData, c.mExtraOutput, c.mOutputFormat, c.mShowWhenLocked, + c.mSpotlightX, c.mSpotlightY); + } + + public int getOutputX() { + return mOutputX; + } + + public int getOutputY() { + return mOutputY; + } + + public boolean getScaleUp() { + return mScaleUp; + } + + public int getAspectX() { + return mAspectX; + } + + public int getAspectY() { + return mAspectY; + } + + public boolean getSetAsWallpaper() { + return mSetAsWallpaper; + } + + public boolean getReturnData() { + return mReturnData; + } + + public Uri getExtraOutput() { + return mExtraOutput; + } + + public String getOutputFormat() { + return mOutputFormat; + } + + public boolean getShowWhenLocked() { + return mShowWhenLocked; + } + + public float getSpotlightX() { + return mSpotlightX; + } + + public float getSpotlightY() { + return mSpotlightY; + } +} 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 mFaces = new ArrayList(); - 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 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 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; -- cgit v1.2.3