CropImagepublic class CropImage extends android.app.Activity
Fields Summary |
---|
private static final String | TAG | private android.app.ProgressDialog | mFaceDetectionDialog | private android.app.ProgressDialog | mSavingProgressDialog | private ImageManager.IImageList | mAllImages | private Bitmap.CompressFormat | mSaveFormat | private android.net.Uri | mSaveUri | private int | mAspectX | private int | mAspectY | private int | mOutputX | private int | mOutputY | private boolean | mDoFaceDetection | private boolean | mCircleCrop | private boolean | mWaitingToPick | private boolean | mScale | private boolean | mSaving | private boolean | mScaleUp | CropImageView | mImageView | android.content.ContentResolver | mContentResolver | android.graphics.Bitmap | mBitmap | android.graphics.Bitmap | mCroppedImage | HighlightView | mCrop | ImageManager.IImage | mImage | android.os.Handler | mHandler | Runnable | mRunFaceDetection |
Constructors Summary |
---|
public CropImage()
|
Methods Summary |
---|
private synchronized void | closeProgressDialog()
if (mFaceDetectionDialog != null) {
mFaceDetectionDialog.dismiss();
mFaceDetectionDialog = null;
}
if (mSavingProgressDialog != null) {
mSavingProgressDialog.dismiss();
mSavingProgressDialog = null;
}
| private void | fillCanvas(int width, int height, android.graphics.Canvas c)
Paint paint = new Paint();
paint.setColor(0x00000000); // pure alpha
paint.setStyle(android.graphics.Paint.Style.FILL);
paint.setAntiAlias(true);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
c.drawRect(0F, 0F, width, height, paint);
| public void | onCreate(android.os.Bundle icicle)
super.onCreate(icicle);
mContentResolver = getContentResolver();
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.cropimage);
mImageView = (CropImageView) findViewById(R.id.image);
MenuHelper.showStorageToast(this);
try {
android.content.Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (Config.LOGV)
Log.v(TAG, "extras are " + extras);
if (extras != null) {
for (String s: extras.keySet()) {
if (Config.LOGV)
Log.v(TAG, "" + s + " >>> " + extras.get(s));
}
if (extras.getString("circleCrop") != null) {
mCircleCrop = true;
mAspectX = 1;
mAspectY = 1;
}
mSaveUri = (Uri) extras.getParcelable(MediaStore.EXTRA_OUTPUT);
if (mSaveUri != null) {
String compressFormatString = extras.getString("outputFormat");
if (compressFormatString != null)
mSaveFormat = Bitmap.CompressFormat.valueOf(compressFormatString);
}
mBitmap = (Bitmap) extras.getParcelable("data");
mAspectX = extras.getInt("aspectX");
mAspectY = extras.getInt("aspectY");
mOutputX = extras.getInt("outputX");
mOutputY = extras.getInt("outputY");
mScale = extras.getBoolean("scale", true);
mScaleUp = extras.getBoolean("scaleUpIfNeeded", true);
mDoFaceDetection = extras.containsKey("noFaceDetection") ? !extras.getBoolean("noFaceDetection") : true;
}
if (mBitmap == null) {
Uri target = intent.getData();
mAllImages = ImageManager.makeImageList(target, CropImage.this, ImageManager.SORT_ASCENDING);
mImage = mAllImages.getImageForUri(target);
if(mImage != null) {
// don't read in really large bitmaps. max out at 1000.
// TODO when saving the resulting bitmap use the decode/crop/encode
// api so we don't lose any resolution
mBitmap = mImage.thumbBitmap();
if (Config.LOGV)
Log.v(TAG, "thumbBitmap returned " + mBitmap);
}
}
if (mBitmap == null) {
finish();
return;
}
mHandler.postDelayed(new Runnable() {
public void run() {
if (isFinishing()) {
return;
}
mFaceDetectionDialog = ProgressDialog.show(CropImage.this,
null,
getResources().getString(R.string.runningFaceDetection),
true, false);
mImageView.setImageBitmapResetBase(mBitmap, true, true);
if (mImageView.getScale() == 1F)
mImageView.center(true, true, false);
new Thread(new Runnable() {
public void run() {
final Bitmap b = mImage != null ? mImage.fullSizeBitmap(500) : mBitmap;
if (Config.LOGV)
Log.v(TAG, "back from mImage.fullSizeBitmap(500) with bitmap of size " + b.getWidth() + " / " + b.getHeight());
mHandler.post(new Runnable() {
public void run() {
if (b != mBitmap && b != null) {
mBitmap = b;
mImageView.setImageBitmapResetBase(b, true, false);
}
if (mImageView.getScale() == 1F)
mImageView.center(true, true, false);
new Thread(mRunFaceDetection).start();
}
});
}
}).start();
}}, 100);
} catch (Exception e) {
Log.e(TAG, "Failed to load bitmap", e);
finish();
}
findViewById(R.id.discard).setOnClickListener(new android.view.View.OnClickListener() {
public void onClick(View v) {
setResult(RESULT_CANCELED);
finish();
}
});
findViewById(R.id.save).setOnClickListener(new android.view.View.OnClickListener() {
public void onClick(View v) {
// TODO this code needs to change to use the decode/crop/encode single
// step api so that we don't require that the whole (possibly large) bitmap
// doesn't have to be read into memory
mSaving = true;
if (mCroppedImage == null) {
if (mCrop == null) {
if (Config.LOGV)
Log.v(TAG, "no cropped image...");
return;
}
Rect r = mCrop.getCropRect();
int width = r.width();
int height = r.height();
// if we're circle cropping we'll want alpha which is the third param here
mCroppedImage = Bitmap.createBitmap(width, height,
mCircleCrop ?
Bitmap.Config.ARGB_8888 :
Bitmap.Config.RGB_565);
Canvas c1 = new Canvas(mCroppedImage);
c1.drawBitmap(mBitmap, r, new Rect(0, 0, width, height), null);
if (mCircleCrop) {
// OK, so what's all this about?
// Bitmaps are inherently rectangular but we want to return something
// that's basically a circle. So we fill in the area around the circle
// with alpha. Note the all important PortDuff.Mode.CLEAR.
Canvas c = new Canvas (mCroppedImage);
android.graphics.Path p = new android.graphics.Path();
p.addCircle(width/2F, height/2F, width/2F, android.graphics.Path.Direction.CW);
c.clipPath(p, Region.Op.DIFFERENCE);
fillCanvas(width, height, c);
}
}
/* If the output is required to a specific size then scale or fill */
if (mOutputX != 0 && mOutputY != 0) {
if (mScale) {
/* Scale the image to the required dimensions */
mCroppedImage = ImageLoader.transform(new Matrix(),
mCroppedImage, mOutputX, mOutputY, mScaleUp);
} else {
/* Don't scale the image crop it to the size requested.
* Create an new image with the cropped image in the center and
* the extra space filled.
*/
/* Don't scale the image but instead fill it so it's the required dimension */
Bitmap b = Bitmap.createBitmap(mOutputX, mOutputY, Bitmap.Config.RGB_565);
Canvas c1 = new Canvas(b);
/* Draw the cropped bitmap in the center */
Rect r = mCrop.getCropRect();
int left = (mOutputX / 2) - (r.width() / 2);
int top = (mOutputY / 2) - (r.width() / 2);
c1.drawBitmap(mBitmap, r, new Rect(left, top, left
+ r.width(), top + r.height()), null);
/* Set the cropped bitmap as the new bitmap */
mCroppedImage = b;
}
}
Bundle myExtras = getIntent().getExtras();
if (myExtras != null && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) {
Bundle extras = new Bundle();
extras.putParcelable("data", mCroppedImage);
setResult(RESULT_OK,
(new Intent()).setAction("inline-data").putExtras(extras));
finish();
} else {
if (!isFinishing()) {
mSavingProgressDialog = ProgressDialog.show(CropImage.this,
null,
getResources().getString(R.string.savingImage),
true, true);
}
Runnable r = new Runnable() {
public void run() {
if (mSaveUri != null) {
OutputStream outputStream = null;
try {
String scheme = mSaveUri.getScheme();
if (scheme.equals("file")) {
outputStream = new FileOutputStream(mSaveUri.toString().substring(scheme.length()+":/".length()));
} else {
outputStream = mContentResolver.openOutputStream(mSaveUri);
}
if (outputStream != null)
mCroppedImage.compress(mSaveFormat, 75, outputStream);
} catch (IOException ex) {
if (Config.LOGV)
Log.v(TAG, "got IOException " + ex);
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException ex) {
}
}
}
Bundle extras = new Bundle();
setResult(RESULT_OK,
(new Intent())
.setAction(mSaveUri.toString())
.putExtras(extras));
} else {
Bundle extras = new Bundle();
extras.putString("rect", mCrop.getCropRect().toString());
// here we decide whether to create a new image or
// modify the existing image
if (false) {
/*
// this is the "modify" case
ImageManager.IGetBoolean_cancelable cancelable =
mImage.saveImageContents(mCroppedImage, null, null, null, mImage.getDateTaken(), 0, false);
boolean didSave = cancelable.get();
extras.putString("thumb1uri", mImage.thumbUri().toString());
setResult(RESULT_OK,
(new Intent()).setAction(mImage.fullSizeImageUri().toString())
.putExtras(extras));
*/
} else {
// this is the "new image" case
java.io.File oldPath = new java.io.File(mImage.getDataPath());
java.io.File directory = new java.io.File(oldPath.getParent());
int x = 0;
String fileName = oldPath.getName();
fileName = fileName.substring(0, fileName.lastIndexOf("."));
while (true) {
x += 1;
String candidate = directory.toString() + "/" + fileName + "-" + x + ".jpg";
if (Config.LOGV)
Log.v(TAG, "candidate is " + candidate);
boolean exists = (new java.io.File(candidate)).exists();
if (!exists)
break;
}
try {
Uri newUri = ImageManager.instance().addImage(
CropImage.this,
getContentResolver(),
mImage.getTitle(),
mImage.getDescription(),
mImage.getDateTaken(),
null, // TODO this null is going to cause us to lose the location (gps)
0, // TODO this is going to cause the orientation to reset
directory.toString(),
fileName + "-" + x + ".jpg");
ImageManager.IAddImage_cancelable cancelable = ImageManager.instance().storeImage(
newUri,
CropImage.this,
getContentResolver(),
0, // TODO fix this orientation
mCroppedImage,
null);
cancelable.get();
setResult(RESULT_OK,
(new Intent()).setAction(newUri.toString())
.putExtras(extras));
} catch (Exception ex) {
// basically ignore this or put up
// some ui saying we failed
}
}
}
finish();
}
};
Thread t = new Thread(r);
t.start();
}
}
});
| public boolean | onCreateOptionsMenu(android.view.Menu menu)
return super.onCreateOptionsMenu(menu);
| public void | onResume()
super.onResume();
| public void | onStop()
closeProgressDialog();
super.onStop();
if (mAllImages != null)
mAllImages.deactivate();
|
|