Snippet Preview
Snippet HTML Code
1
/*
2
* Copyright (C) 2007 The Android Open Source Project
3
*
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
7
8
* http://www.apache.org/licenses/LICENSE-2.0
9
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
15
*/
16
17
package com.android.camera;
18
19
import com.android.gallery.R;
20
21
import com.android.camera.gallery.IImage;
22
import com.android.camera.gallery.IImageList;
23
24
import android.app.WallpaperManager;
25
import android.content.ContentResolver;
26
import android.content.Context;
27
import android.content.Intent;
28
import android.graphics.Bitmap;
29
import android.graphics.Canvas;
30
import android.graphics.Matrix;
31
import android.graphics.Path;
32
import android.graphics.PointF;
33
import android.graphics.PorterDuff;
34
import android.graphics.Rect;
35
import android.graphics.RectF;
36
import android.graphics.Region;
37
import android.media.FaceDetector;
38
import android.net.Uri;
39
import android.os.Bundle;
40
import android.os.Handler;
41
import android.provider.MediaStore;
42
import android.util.AttributeSet;
43
import android.util.Log;
44
import android.view.MotionEvent;
45
import android.view.View;
46
import android.view.Window;
47
import android.view.WindowManager;
48
import android.widget.Toast;
49
50
import java.io.File;
51
import java.io.IOException;
52
import java.io.OutputStream;
53
import java.util.ArrayList;
54
import java.util.concurrent.CountDownLatch;
58
59
public class CropImage extends MonitoredActivity {
60
private static final String TAG = "CropImage";
61
62
// These are various options can be specified in the intent.
63
private Bitmap.CompressFormat mOutputFormat =
64
Bitmap.CompressFormat.JPEG; // only used with mSaveUri
65
private Uri mSaveUri = null;
66
private boolean mSetWallpaper = false;
67
private int mAspectX, mAspectY;
68
private boolean mDoFaceDetection = true;
69
private boolean mCircleCrop = false;
70
private final Handler mHandler = new Handler();
71
72
// These options specifiy the output image size and whether we should
73
// scale the output to fit it (or just crop it).
74
private int mOutputX, mOutputY;
75
private boolean mScale;
76
private boolean mScaleUp = true;
77
78
boolean mWaitingToPick; // Whether we are wait the user to pick a face.
79
boolean mSaving; // Whether the "save" button is already clicked.
80
81
private CropImageView mImageView;
82
private ContentResolver mContentResolver;
83
84
private Bitmap mBitmap;
85
HighlightView mCrop;
86
87
private IImageList mAllImages;
88
private IImage mImage;
89
90
@Override
91
public void onCreate(Bundle icicle) {
92
super.onCreate(icicle);
93
mContentResolver = getContentResolver();
94
95
requestWindowFeature(Window.FEATURE_NO_TITLE);
96
setContentView(R.layout.cropimage);
97
98
mImageView = (CropImageView) findViewById(R.id.image);
99
100
MenuHelper.showStorageToast(this);
101
102
Intent intent = getIntent();
103
Bundle extras = intent.getExtras();
104
105
if (extras != null) {
106
if (extras.getString("circleCrop") != null) {
107
mCircleCrop = true;
108
mAspectX = 1;
109
mAspectY = 1;
110
}
111
mSaveUri = (Uri) extras.getParcelable(MediaStore.EXTRA_OUTPUT);
112
if (mSaveUri != null) {
113
String outputFormatString = extras.getString("outputFormat");
114
if (outputFormatString != null) {
115
mOutputFormat = Bitmap.CompressFormat.valueOf(
116
outputFormatString);
117
118
} else {
119
mSetWallpaper = extras.getBoolean("setWallpaper");
120
121
mBitmap = (Bitmap) extras.getParcelable("data");
122
mAspectX = extras.getInt("aspectX");
123
mAspectY = extras.getInt("aspectY");
124
mOutputX = extras.getInt("outputX");
125
mOutputY = extras.getInt("outputY");
126
mScale = extras.getBoolean("scale", true);
127
mScaleUp = extras.getBoolean("scaleUpIfNeeded", true);
128
mDoFaceDetection = extras.containsKey("noFaceDetection")
129
? !extras.getBoolean("noFaceDetection")
130
: true;
131
132
133
if (mBitmap == null) {
134
Uri target = intent.getData();
135
mAllImages = ImageManager.makeImageList(mContentResolver, target,
136
ImageManager.SORT_ASCENDING);
137
mImage = mAllImages.getImageForUri(target);
138
if (mImage != null) {
139
// Don't read in really large bitmaps. Use the (big) thumbnail
140
// instead.
141
// TODO when saving the resulting bitmap use the
142
// decode/crop/encode api so we don't lose any resolution.
143
mBitmap = mImage.thumbBitmap(IImage.ROTATE_AS_NEEDED);
144
145
146
147
148
finish();
149
return;
150
151
152
// Make UI fullscreen.
153
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
154
155
findViewById(R.id.discard).setOnClickListener(
156
new View.OnClickListener() {
157
public void onClick(View v) {
158
setResult(RESULT_CANCELED);
159
160
161
});
162
163
findViewById(R.id.save).setOnClickListener(
164
165
166
onSaveClicked();
167
168
169
170
startFaceDetection();
171
172
173
private void startFaceDetection() {
174
if (isFinishing()) {
175
176
177
178
mImageView.setImageBitmapResetBase(mBitmap, true);
179
180
Util.startBackgroundJob(this, null,
181
getResources().getString(R.string.runningFaceDetection),
182
new Runnable() {
183
public void run() {
184
final CountDownLatch latch = new CountDownLatch(1);
185
final Bitmap b = (mImage != null)
186
? mImage.fullSizeBitmap(IImage.UNCONSTRAINED,
187
1024 * 1024)
188
: mBitmap;
189
mHandler.post(new Runnable() {
190
191
if (b != mBitmap && b != null) {
192
mImageView.setImageBitmapResetBase(b, true);
193
mBitmap.recycle();
194
mBitmap = b;
195
196
if (mImageView.getScale() == 1F) {
197
mImageView.center(true, true);
198
199
latch.countDown();
200
201
202
try {
203
latch.await();
204
} catch (InterruptedException e) {
205
throw new RuntimeException(e);
206
207
mRunFaceDetection.run();
208
209
}, mHandler);
210
211
212
private void onSaveClicked() {
213
// TODO this code needs to change to use the decode/crop/encode single
214
// step api so that we don't require that the whole (possibly large)
215
// bitmap doesn't have to be read into memory
216
if (mCrop == null) {
217
218
219
220
if (mSaving) return;
221
mSaving = true;
222
223
Bitmap croppedImage;
224
225
// If the output is required to a specific size, create an new image
226
// with the cropped image in the center and the extra space filled.
227
if (mOutputX != 0 && mOutputY != 0 && !mScale) {
228
// Don't scale the image but instead fill it so it's the
229
// required dimension
230
croppedImage = Bitmap.createBitmap(mOutputX,