Back to project page UniversalImagePick.
The source code is released under:
Apache License
If you think the Android project UniversalImagePick listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.luffyjet.universalimagepick.widget; /*w w w . j a v a2s.c om*/ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.R.integer; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.net.Uri; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.FloatMath; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; /** * * @author Luffyjet * @version 1.0.0 * @since 2014-9-19 {@link https://github.com/luffyjet} */ public class CropImageView extends ImageView { private static final String TAG = "CropImageView"; /** * ?????????? */ private static final long REFRESH_DELAY = 10L; /** * ???? */ private static final int BORDER_WIDTH = 1; /** * ??????????? */ private static final long DOUBLE_CLICK_TIME_SPACE = 300;// ms /** * ??????????????? */ private static final float DISTANCE = 10f; /** * ?????????? */ private long lastClickTime;// ms /** * ?????? */ private static int CROP_WIDTH = 460; private static int CROP_HEIGHT = 460; /** * ???????(CompressFormat default JPEG) */ private static CompressFormat DEFAULT_FORMAT = CompressFormat.JPEG; /** * ???????(Compress quality default 80) */ private static int DEFAULT_QUALITY = 80; /** * ?? */ private Paint mPaint; /** * ???? */ private int maskColor = 0x7A000000;// ?????? /** * ????? */ private Rect mFrame; /** * ????? (the screen width and height) */ private int mScreenWidth; private int mScreenHeight; private int statusBarHeight; private Activity mActivity; private Mode mMode; private Matrix mSupMatrix = new Matrix(); private Matrix mLastMatrix = new Matrix(); private PointF mStartPF = new PointF(); private PointF mCenterPF = new PointF(); private float mLastDist = 1.0f; private final static float DOUBLE_CLICK_SCALE = 1.4f; private float mScale; private float mLastScale; private float offset = 100f; public CropImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } public CropImageView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public CropImageView(Context context) { super(context); init(context); } /** * ?????(touch status) */ static enum Mode { NONE, DRAG, ZOOM; } /** * ???????????? (init Mask CropRect...) * * @param context */ private final void init(Context context) { if (context instanceof Activity) { mActivity = (Activity) context; mPaint = new Paint(); DisplayMetrics dm = new DisplayMetrics(); mActivity.getWindowManager().getDefaultDisplay().getMetrics(dm); mScreenWidth = dm.widthPixels; mScreenHeight = dm.heightPixels; mFrame = getRect(mScreenWidth, mScreenHeight); } else { Log.e(TAG, "context must be a instance of Activity"); } } /** * @param resId */ public void setImageResource(int resId) { setImageResource(resId, null); } /** * * @param resId * @param options */ public void setImageResource(int resId, Options options) { Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId, options); setBitmap(bitmap, mScreenWidth, mScreenHeight); } /** * * @param bitmap */ public void setImageBitmap(Bitmap bitmap) { setBitmap(bitmap, mScreenWidth, mScreenHeight); } /** * * @param bitmap * @param screenWidht * @param screenHeight */ public void setBitmap(Bitmap bitmap, int screenWidht, int screenHeight) { int bmpWidth = bitmap.getWidth(); int bmpHeight = bitmap.getHeight(); // ?????(compute scale) float scaleX = (float) CROP_WIDTH / bmpWidth; float scaleY = (float) CROP_HEIGHT / bmpHeight; // ????????,??????CROP_HEIGHT??????????CROP_WIDTH(if image's width > // height ,so scale to fit CROP_HEIGHT) float scale = scaleX < scaleY ? scaleY : scaleX; Matrix matrix = new Matrix(); // ????????X?(The X coordinate of the left side of the bitmap) float pivotX = (screenWidht - bmpWidth * scale) / 2; // ????????Y?(The Y coordinate of the top of the bitmap) float pivotY = (screenHeight - bmpHeight * scale) / 2; // set bitmap to this Imageview setImageDrawable(new BitmapDrawable(getResources(), bitmap)); // scale and translate ImageView setScaleType(ScaleType.MATRIX); matrix.postScale(scale, scale); matrix.postTranslate(pivotX, pivotY); setImageMatrix(matrix); } /** * ???????????(get crop rect) * * @param screenW * ???? * @param screenH * ???? * @return */ private Rect getRect(int screenW, int screenH) { // ??????????(we need to minus BORDER_WIDTH) int rectLeft = (screenW - CROP_WIDTH - BORDER_WIDTH) / 2; int rectRight = screenW - rectLeft; int rectTop = (screenH - CROP_HEIGHT - BORDER_WIDTH) / 2; int rectBottom = screenH - rectTop; Rect rect = new Rect(rectLeft, rectTop, rectRight, rectBottom); return rect; } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); // ??????????? (get screen w/h) int width = canvas.getWidth(); int height = canvas.getHeight(); mPaint.setColor(maskColor); // ?????????????? (draw mask) canvas.drawRect(0, 0, width, mFrame.top, mPaint);// ??? canvas.drawRect(0, mFrame.top, mFrame.left, mFrame.bottom, mPaint);// ???? canvas.drawRect(mFrame.right, mFrame.top, width, mFrame.bottom, mPaint);// ?????? canvas.drawRect(0, mFrame.bottom, width, height, mPaint);// ??? // ??????????(draw line) mPaint.setColor(Color.WHITE); canvas.drawRect(mFrame.left, mFrame.top, mFrame.right, mFrame.top + BORDER_WIDTH, mPaint);// ???????? canvas.drawRect(mFrame.left, mFrame.top, mFrame.left + BORDER_WIDTH, mFrame.bottom, mPaint);// ?????? canvas.drawRect(mFrame.right - BORDER_WIDTH, mFrame.top, mFrame.right, mFrame.bottom, mPaint);// ???????? canvas.drawRect(mFrame.left, mFrame.bottom - BORDER_WIDTH, mFrame.right, mFrame.bottom, mPaint);// ?? // ???????????????????? (refresh the border) postInvalidateDelayed(REFRESH_DELAY, mFrame.left, mFrame.top, mFrame.right, mFrame.bottom); } /** * ????????(crop) * * @return Bitmap */ public Bitmap cropBitmap() { Bitmap resultBitmap = null; try { // ??????????Content View View view = mActivity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); // ??????????Bitmap Bitmap screenBitmap = view.getDrawingCache(); // get statusBarHeight Rect frame = new Rect(); mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); statusBarHeight = frame.top; // ????Crop???Bitmap resultBitmap = Bitmap.createBitmap(screenBitmap, mFrame.left + BORDER_WIDTH, mFrame.top + statusBarHeight + BORDER_WIDTH, mFrame.right - mFrame.left - 2 * BORDER_WIDTH, mFrame.bottom - mFrame.top - 2 * BORDER_WIDTH); // ?????? view.destroyDrawingCache(); screenBitmap.recycle(); } catch (Exception e) { e.printStackTrace(); } return resultBitmap; } /** * * @param filePath * @return */ public Uri saveCropBitmap(File filePath){ return saveCropBitmap(filePath, DEFAULT_FORMAT, DEFAULT_QUALITY); } /** * ???????????(crop and save img) * @param filePath file save path in SDCard * @param format just like JPEG,PNG * @param quality 1-100 * @return URI of the Image or Null */ public Uri saveCropBitmap(File filePath,CompressFormat format, int quality) { if (filePath == null) { return null; } if (!filePath.getParentFile().exists()) { filePath.getParentFile().mkdirs(); } Uri uri = null; FileOutputStream fos = null; try { fos = new FileOutputStream(filePath); if (null != fos) { cropBitmap().compress(format, quality, fos); fos.flush(); fos.close(); uri = Uri.fromFile(filePath); } } catch (Exception e) { e.printStackTrace(); }finally{ try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } return uri; } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mSupMatrix.set(getImageMatrix()); mLastMatrix.set(mSupMatrix); mStartPF.set(event.getX(), event.getY()); if (1 == event.getPointerCount()) { // ????????????????????????? if (event.getEventTime() - lastClickTime < DOUBLE_CLICK_TIME_SPACE) { onDoubleClick(event); } else { mMode = Mode.DRAG; } } lastClickTime = event.getEventTime(); break; case MotionEvent.ACTION_POINTER_DOWN: mLastDist = computeDistance(event); if (mLastDist > DISTANCE) { mLastMatrix.set(mSupMatrix); computeCenterPoint(mCenterPF, event); mMode = Mode.ZOOM; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mMode = Mode.NONE; break; case MotionEvent.ACTION_MOVE: if (mMode == Mode.DRAG) { // TODO ??????(drag range,there have a bug) if (event.getX() >= offset && event.getX() < mScreenWidth - offset && event.getY() >= offset && event.getY() < mScreenHeight - offset) { mSupMatrix.set(mLastMatrix); mSupMatrix.postTranslate(event.getX() - mStartPF.x, event.getY() - mStartPF.y); } } else if (mMode == Mode.ZOOM) { float newDist = computeDistance(event); if (newDist > DISTANCE) { mSupMatrix.set(mLastMatrix); mScale = newDist / mLastDist; mSupMatrix.postScale(mScale, mScale, mCenterPF.x, mCenterPF.y); } } setImageMatrix(mSupMatrix); break; } return true; } /** * ?????? double click * * @param event */ private void onDoubleClick(MotionEvent event) { if (mLastScale > 1.0f) { mLastScale = 1.0f / mLastScale; } else { mLastScale = DOUBLE_CLICK_SCALE; } mSupMatrix.postScale(mLastScale, mLastScale); setImageMatrix(mSupMatrix); } /** * ??????? * * @param event * @return */ @SuppressLint("FloatMath") private float computeDistance(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return FloatMath.sqrt(x * x + y * y); } /** * ??????? * * @param point * @param event */ private void computeCenterPoint(PointF point, MotionEvent event) { float x = event.getX(0) + event.getX(1); float y = event.getY(0) + event.getY(1); point.set(x / 2, y / 2); } }