Android Open Source - mobilib Mbl Take Image Activity






From Project

Back to project page mobilib.

License

The source code is released under:

MIT License

If you think the Android project mobilib listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.datdo.mobilib.imageinput;
/*from w ww .j  a  v a 2 s  .c o  m*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;

import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.Button;

import com.datdo.mobilib.util.MblUtils;
import com.datdo.mobilib.widget.MblTouchImageView;

/**
 * Activity to take image by camera. Also support cropping.
 */
public class MblTakeImageActivity extends MblDataInputActivity {

    private static final String TAG = MblUtils.getTag(MblTakeImageActivity.class);

    private static final int REQUEST_CODE = 268;

    private static final String EXTRA_INPUT_IMAGE_PATH          = "input_image_path";
    private static final String EXTRA_CROP_SIZE_WIDTH_IN_PX     = "crop_size_width_in_px";
    private static final String EXTRA_CROP_SIZE_HEIGHT_IN_PX    = "crop_size_height_in_px";
    private static final String EXTRA_NATIVE_CAMERA_RETURN_DATA = "return-data";

    private MblTouchImageView mPreviewImageView;
    private Uri     mTakenPhotoUri;
    private String  mInputImagePath;
    private int     mCropSizeWidthInPx;
    private int     mCropSizeHeightInPx;
    private View    mCropFrame;
    private View    mCropFrameMid;
    private boolean mStartTakePhotoOnResume;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.photo_preview_layout);

        // get data from extra
        if (getIntent().getExtras() != null) {
            mInputImagePath     = getIntent().getExtras().getString(EXTRA_INPUT_IMAGE_PATH);
            mCropSizeWidthInPx  = getIntent().getExtras().getInt(EXTRA_CROP_SIZE_WIDTH_IN_PX);
            mCropSizeHeightInPx = getIntent().getExtras().getInt(EXTRA_CROP_SIZE_HEIGHT_IN_PX);
        }

        // init UI
        mPreviewImageView   = (MblTouchImageView) findViewById(R.id.image);
        Button leftButton   = (Button) findViewById(R.id.left_button);
        mCropFrame          = findViewById(R.id.crop_frame);
        mCropFrameMid       = mCropFrame.findViewById(R.id.mid);

        if (mInputImagePath == null) { // take photo

            // left button
            leftButton.setText(R.string.retake_photo);
            leftButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    takePhoto();
                }
            });

            //  show native camera right away
            mStartTakePhotoOnResume = true;

        } else { // load photo from external storage

            // left button
            leftButton.setText(R.string.cancel);
            leftButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    cancelInput();
                }
            });

            // set sizes for transparent area in middle of crop frame
            ViewGroup.LayoutParams lpOfMid = mCropFrameMid.getLayoutParams();
            lpOfMid.width = mCropSizeWidthInPx;
            lpOfMid.height = mCropSizeHeightInPx;
            mCropFrameMid.setLayoutParams(lpOfMid);

            // set sizes frame surrounding middle view of crop frame
            View frameOfMid = mCropFrame.findViewById(R.id.frame);
            ViewGroup.LayoutParams lpOfMidFrame = frameOfMid.getLayoutParams();
            lpOfMidFrame.width = mCropSizeWidthInPx + MblUtils.pxFromDp(2);
            lpOfMidFrame.height = mCropSizeHeightInPx + MblUtils.pxFromDp(2);
            frameOfMid.setLayoutParams(lpOfMidFrame);

            // show crop frame
            mCropFrame.setVisibility(View.VISIBLE);

            // load photo from storage
            loadPhotoFromExternal(mInputImagePath);
        }

        // right button
        final Button rightButton = (Button) findViewById(R.id.right_button);
        rightButton.setText(R.string.use_photo);
        rightButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                rightButton.setEnabled(false);
                if (needCrop()) {
                    cropPhoto();
                } else {
                    usePhoto();
                }
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mStartTakePhotoOnResume) {
            takePhoto();
            mStartTakePhotoOnResume = false;
        }
    }

    private File getTempFile(String name) {
        // get external storage folder to store image
        File externalDir = new File(MblImageInput.sFolderToSaveTakenImages);
        if (!externalDir.exists()) {
            externalDir.mkdirs();
        }

        // create file to store image
        File f = new File(externalDir, name);
        if (f.exists()) {
            f.delete();
        }
        try {
            f.createNewFile();
        } catch (IOException e) {
            Log.e(TAG, "Can not create temp file at: " + f.getAbsolutePath(), e);
            return null;
        }
        return f;
    }

    private void takePhoto() {
        File tempFile = getTempFile(UUID.randomUUID().toString() + ".jpg");
        if (tempFile != null) {
            mTakenPhotoUri = Uri.fromFile(tempFile);
            Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mTakenPhotoUri);
            try {
                cameraIntent.putExtra(EXTRA_NATIVE_CAMERA_RETURN_DATA, true);
                startActivityForResult(cameraIntent, REQUEST_CODE);
            } catch (ActivityNotFoundException e) {
                Log.e(TAG, "Camera is not available", e);
                // TODO: show alert
            }
        } else {
            // TODO: show alert
        }
    }

    private void usePhoto() {
        if (mTakenPhotoUri != null) {
            finishInput(mTakenPhotoUri.getPath());
        }
    }

    private void cropPhoto() {

        try {

            // get image being manipulated
            Bitmap photo = MblUtils.extractBitmap(mPreviewImageView);
            if (photo == null || photo.isRecycled()) {
                cancelInput();
                return;
            }

            // calculate crop area x,y,w,h
            float[] matrixValues    =  mPreviewImageView.getMatrixValues();
            float   transX          = matrixValues[Matrix.MTRANS_X];
            float   transY          = matrixValues[Matrix.MTRANS_Y];
            float   scaleX          = matrixValues[Matrix.MSCALE_X];
            float   scaleY          = matrixValues[Matrix.MSCALE_Y];
            int     cropAreaX       = Math.round((mCropFrameMid.getLeft() - transX) / scaleX);
            int     cropAreaY       = Math.round((mCropFrameMid.getTop() - transY) / scaleY);
            int     cropAreaWidth   = Math.round(mCropFrameMid.getWidth() / scaleX);
            int     cropAreaHeight  = Math.round(mCropFrameMid.getHeight() / scaleY);

            // make crop area be inside photo
            cropAreaWidth   = Math.min(cropAreaWidth, photo.getWidth());
            cropAreaHeight  = Math.min(cropAreaHeight, photo.getHeight());
            cropAreaX       = Math.min(Math.max(0, cropAreaX), photo.getWidth() - cropAreaWidth);
            cropAreaY       = Math.min(Math.max(0, cropAreaY), photo.getHeight() - cropAreaHeight);

            // calculate crop matrix
            Matrix matrix = new Matrix();
            matrix.postScale(1.0f * mCropSizeWidthInPx / cropAreaWidth, 1.0f * mCropSizeHeightInPx / cropAreaHeight);

            // crop bitmap
            Bitmap croppedPhoto = Bitmap.createBitmap(photo, cropAreaX, cropAreaY, cropAreaWidth, cropAreaHeight, matrix, true);

            // save bitmap to cache folder
            String cacheImagePath = MblUtils.getCacheAsbPath(UUID.randomUUID().toString());
            OutputStream os = new FileOutputStream(cacheImagePath);
            croppedPhoto.compress(CompressFormat.JPEG, 100, os);
            os.flush();
            os.close();
            finishInput(cacheImagePath);

        } catch (Exception e) {
            Log.e(TAG, "Can not crop photo", e);
            cancelInput();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        if (requestCode == REQUEST_CODE) {
            resetDefaultMaxAllowedTrasitionBetweenActivity();
            if (resultCode == RESULT_OK) {
                loadPhotoFromExternal(mTakenPhotoUri.getPath());
                if (needCrop()) {
                    mCropFrame.setVisibility(View.VISIBLE);
                }
            } else if (resultCode == RESULT_CANCELED) {
                // delete temp file
                new File(mTakenPhotoUri.getPath()).delete();

                // cancel input
                cancelInput();
            }
        }
    }

    private boolean needCrop() {
        return mCropSizeWidthInPx > 0 && mCropSizeHeightInPx > 0;
    }

    private void loadPhotoFromExternal(final String imagePath) {

        if (mPreviewImageView.getWidth() == 0 || mPreviewImageView.getHeight() == 0) {
            mPreviewImageView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    MblUtils.removeOnGlobalLayoutListener(mPreviewImageView, this);
                    loadPhotoFromExternal(imagePath);
                }
            });
            return;
        }

        MblUtils.executeOnAsyncThread(new Runnable() {
            @Override
            public void run() {
                try {
                    int[] sizes = MblUtils.getBitmapSizes(imagePath);
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inSampleSize =
                            Math.round(1.0f * Math.max(sizes[0], sizes[1]) / Math.max(mPreviewImageView.getWidth(), mPreviewImageView.getHeight()));
                    options.inPreferredConfig = Bitmap.Config.RGB_565;
                    options.inDither = true;
                    Bitmap bm = BitmapFactory.decodeFile(imagePath, options);

                    // rotate bitmap if needed
                    bm = MblUtils.correctBitmapOrientation(imagePath, bm);

                    final Bitmap finalBm = bm;
                    MblUtils.executeOnMainThread(new Runnable() {
                        @Override
                        public void run() {
                            // display bitmap
                            MblUtils.recycleImageView(mPreviewImageView);
                            mPreviewImageView.setImageBitmap(finalBm);

                            // set min and max for zoom
                            float minZoom = MblImageInput.sCropMinZoom;
                            float maxZoom = MblImageInput.sCropMaxZoom;
                            if (needCrop()) {
                                float scaleX = 1;
                                if (finalBm.getWidth() < mCropSizeWidthInPx) {
                                    scaleX = 1.0f * mCropSizeWidthInPx / finalBm.getWidth();
                                }
                                float scaleY = 1;
                                if (finalBm.getHeight() < mCropSizeHeightInPx) {
                                    scaleY = 1.0f * mCropSizeHeightInPx / finalBm.getHeight();
                                }
                                float fullFrameScale = Math.max(scaleX, scaleY);
                                if (minZoom != fullFrameScale) {
                                    float temp = maxZoom / minZoom;
                                    minZoom = fullFrameScale;
                                    maxZoom = minZoom * temp;
                                }
                            }
                            mPreviewImageView.setOptions(
                                    minZoom, maxZoom, minZoom,
                                    mCropFrame.findViewById(R.id.left).getWidth(),
                                    mCropFrame.findViewById(R.id.top).getHeight(),
                                    mCropFrame.findViewById(R.id.right).getWidth(),
                                    mCropFrame.findViewById(R.id.bottom).getHeight());
                        }
                    });
                } catch (IOException e) {
                    cancelInput();
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        MblUtils.recycleImageView(mPreviewImageView);
        super.onDestroy();
    }

    /**
     * <pre>
     * Start activity to take image by camera.
     * Support cropping by passing cropSizeWidthInPx > 0, cropSizeWidthInPx > 0.
     * Also support cropping a specific image (via inputImagePath) without capturing image by camera
     * </pre>
     * @param inputImagePath 
     * @param cropSizeWidthInPx crop image to specific width (in pixel). Pass -1 if you don't want to crop
     * @param cropSizeHeightInPx crop image to specific height (in pixel). Pass -1 if you don't want to crop
     * @param callback callback to receive result
     */
    public static void start(
            String inputImagePath,
            int cropSizeWidthInPx,
            int cropSizeHeightInPx,
            final MblTakeImageCallback callback) {

        Intent intent = createIntent(MblTakeImageActivity.class, new CmDataInputActivityCallback() {
            @Override
            public void onFinish(Object... outputData) {
                if (callback != null) {
                    callback.onFinish((String)outputData[0]);
                }
            }

            @Override
            public void onCancel() {
                if (callback != null) {
                    callback.onCancel();
                }
            }
        }, null);
        intent.putExtra(EXTRA_INPUT_IMAGE_PATH,         inputImagePath);
        intent.putExtra(EXTRA_CROP_SIZE_WIDTH_IN_PX,    cropSizeWidthInPx);
        intent.putExtra(EXTRA_CROP_SIZE_HEIGHT_IN_PX,   cropSizeHeightInPx);
        MblUtils.getCurrentContext().startActivity(intent);
    }

    public static interface MblTakeImageCallback {
        public void onFinish(String path);
        public void onCancel();
    }
}




Java Source Code List

com.datdo.mobilib.api.DBBase.java
com.datdo.mobilib.api.DBHelper.java
com.datdo.mobilib.api.MblApi.java
com.datdo.mobilib.api.MblCache.java
com.datdo.mobilib.api.MblException.java
com.datdo.mobilib.api.MblSSLCertificateUtils.java
com.datdo.mobilib.base.MblActivityPlugin.java
com.datdo.mobilib.base.MblBaseActionBarActivity.java
com.datdo.mobilib.base.MblBaseActivity.java
com.datdo.mobilib.base.MblBaseAdapter.java
com.datdo.mobilib.base.MblBaseApplication.java
com.datdo.mobilib.base.MblBaseFragmentActivity.java
com.datdo.mobilib.base.MblDecorView.java
com.datdo.mobilib.base.MblNetworkStatusChangedReceiver.java
com.datdo.mobilib.event.MblCommonEvents.java
com.datdo.mobilib.event.MblEventCenter.java
com.datdo.mobilib.event.MblEventListener.java
com.datdo.mobilib.event.MblStrongEventListener.java
com.datdo.mobilib.event.MblWeakArrayList.java
com.datdo.mobilib.imageinput.MblAutoResizeSquareImageView.java
com.datdo.mobilib.imageinput.MblDataInputActivity.java
com.datdo.mobilib.imageinput.MblImageFolderScanner.java
com.datdo.mobilib.imageinput.MblImageInput.java
com.datdo.mobilib.imageinput.MblImagePickingScanEngine.java
com.datdo.mobilib.imageinput.MblPickImageActivity.java
com.datdo.mobilib.imageinput.MblPickImageGridViewAdapter.java
com.datdo.mobilib.imageinput.MblTakeImageActivity.java
com.datdo.mobilib.util.MblAsyncTask.java
com.datdo.mobilib.util.MblImageLoader.java
com.datdo.mobilib.util.MblLinkMovementMethod.java
com.datdo.mobilib.util.MblUrlRecognizer.java
com.datdo.mobilib.util.MblUtils.java
com.datdo.mobilib.widget.MblHorizontalViewPager.java
com.datdo.mobilib.widget.MblListViewWithScrollableItems.java
com.datdo.mobilib.widget.MblSequenceImage.java
com.datdo.mobilib.widget.MblSideMenuEnabledLayout.java
com.datdo.mobilib.widget.MblTouchImageView.java