FileDocCategorySizeDatePackage
CropImage.javaAPI DocAndroid 1.5 API33185Wed May 06 22:42:42 BST 2009com.android.camera

CropImage

public 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 voidcloseProgressDialog()

        if (mFaceDetectionDialog != null) {
            mFaceDetectionDialog.dismiss();
            mFaceDetectionDialog = null;
        }
        if (mSavingProgressDialog != null) {
            mSavingProgressDialog.dismiss();
            mSavingProgressDialog = null;
        }
    
private voidfillCanvas(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 voidonCreate(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 booleanonCreateOptionsMenu(android.view.Menu menu)

        return super.onCreateOptionsMenu(menu);
    
public voidonResume()

        super.onResume();
    
public voidonStop()


    
       
        closeProgressDialog();
        super.onStop();
        if (mAllImages != null)
            mAllImages.deactivate();