android---图片获得与裁剪

 图片从手机的图库中获取或者直接通过相机拍摄获得,获得图片后利用工具类对图片进行裁剪,为了防止内存溢出。

图片裁剪的工具类:CropImageActivity.java

 package com.example.cropimage


import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.Toast;


/**
 * 裁剪界面
 *
 */
public class CropImageActivity extends Activity implements OnClickListener{
private CropImageView mImageView;
private Bitmap mBitmap;
private CropImage mCrop;
private Button mSave;
private Button mCancel,rotateLeft,rotateRight;
private String mPath = "CropImageActivity";
private String TAG = "";
public int screenWidth = 0;
public int screenHeight = 0;
private ProgressBar mProgressBar;
public static final int SHOW_PROGRESS = 2000;

public static final int REMOVE_PROGRESS = 2001;
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {

switch (msg.what) {
case SHOW_PROGRESS:
mProgressBar.setVisibility(View.VISIBLE);
break;
case REMOVE_PROGRESS:
mHandler.removeMessages(SHOW_PROGRESS);
mProgressBar.setVisibility(View.INVISIBLE);
break;
}

}
};
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.gl_modify_avatar);
        
        init();
    }
    @Override
    protected void onStop(){
    super.onStop();
    if(mBitmap!=null){
    mBitmap=null;
    }
    }
    
    private void init()
    {
    getWindowWH();
    mPath = getIntent().getStringExtra("path");
    Log.i(TAG, "得到的图片的路径是 = " + mPath);
        mImageView = (CropImageView) findViewById(R.id.gl_modify_avatar_image);
        mSave = (Button) this.findViewById(R.id.gl_modify_avatar_save);
        mCancel = (Button) this.findViewById(R.id.gl_modify_avatar_cancel);
        rotateLeft = (Button) this.findViewById(R.id.gl_modify_avatar_rotate_left);
        rotateRight = (Button) this.findViewById(R.id.gl_modify_avatar_rotate_right);
        mSave.setOnClickListener(this);
        mCancel.setOnClickListener(this);
        rotateLeft.setOnClickListener(this);
        rotateRight.setOnClickListener(this);
        try{
            mBitmap = createBitmap(mPath,screenWidth,screenHeight);
            if(mBitmap==null){
            Toast.makeText(CropImageActivity.this, CropImageActivity.this.getResources().getString(R.string.app_can_not_find_pic), 0).show();
    finish();
            }else{
            resetImageView(mBitmap);
            }
        }catch (Exception e) {
        Toast.makeText(CropImageActivity.this, CropImageActivity.this.getResources().getString(R.string.app_can_not_find_pic), 0).show();
finish();
}
        addProgressbar();       
    }
    /**
     * 获取屏幕的高和宽
     */
    private void getWindowWH(){
DisplayMetrics dm=new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
screenWidth=dm.widthPixels;
screenHeight=dm.heightPixels;
}
    private void resetImageView(Bitmap b){
     mImageView.clear();
     mImageView.setImageBitmap(b);
         mImageView.setImageBitmapResetBase(b, true);
         mCrop = new CropImage(this, mImageView,mHandler);
         mCrop.crop(b);
    }
    
    @Override
public void onClick(View v)
    {
    switch (v.getId())
    {
    case R.id.gl_modify_avatar_cancel:
//    mCrop.cropCancel();
    finish();
    break;
    case R.id.gl_modify_avatar_save:
    String path = mCrop.saveToLocal(mCrop.cropAndSave());
    Log.i(TAG, "截取后图片的路径是 = " + path);
    Intent intent = new Intent();
    intent.putExtra("path", path);
    setResult(RESULT_OK, intent);
    finish();
    break;
    case R.id.gl_modify_avatar_rotate_left:
    mCrop.startRotate(270.f);
    break;
    case R.id.gl_modify_avatar_rotate_right:
    mCrop.startRotate(90.f);
    break;
   
    }
    }
    protected void addProgressbar() {
mProgressBar = new ProgressBar(this);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
addContentView(mProgressBar, params);
mProgressBar.setVisibility(View.INVISIBLE);
}
    
    public Bitmap createBitmap(String path,int w,int h){
    try{
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
// 这里是整个方法的关键,inJustDecodeBounds设为true时将不为图片分配内存。
BitmapFactory.decodeFile(path, opts);
int srcWidth = opts.outWidth;// 获取图片的原始宽度
int srcHeight = opts.outHeight;// 获取图片原始高度
int destWidth = 0;
int destHeight = 0;
// 缩放的比例
double ratio = 0.0;
if (srcWidth < w || srcHeight < h) {
ratio = 0.0;
destWidth = srcWidth;
destHeight = srcHeight;
} else if (srcWidth > srcHeight) {// 按比例计算缩放后的图片大小,maxLength是长或宽允许的最大长度
ratio = (double) srcWidth / w;
destWidth = w;
destHeight = (int) (srcHeight / ratio);
} else {
ratio = (double) srcHeight / h;
destHeight = h;
destWidth = (int) (srcWidth / ratio);
}
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 缩放的比例,缩放是很难按准备的比例进行缩放的,目前我只发现只能通过inSampleSize来进行缩放,其值表明缩放的倍数,SDK中建议其值是2的指数值
newOpts.inSampleSize = (int) ratio + 1;
// inJustDecodeBounds设为false表示把图片读进内存中
newOpts.inJustDecodeBounds = false;
// 设置大小,这个一般是不准确的,是以inSampleSize的为准,但是如果不设置却不能缩放
newOpts.outHeight = destHeight;
newOpts.outWidth = destWidth;
// 获取缩放后图片
return BitmapFactory.decodeFile(path, newOpts);
} catch (Exception e) {
// TODO: handle exception
return null;
}
    }
   
}

CropImage.java

package com.example.corpimage

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;

import cn.leature.istarbaby.R;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.media.FaceDetector;
import android.os.Environment;
import android.os.Handler;

/**
 * 裁剪处理
 * 
 */
public class CropImage {

public static final File FILE_SDCARD = Environment
.getExternalStorageDirectory();

public static final File FILE_LOCAL = new File(FILE_SDCARD, "weixin");
private static final int CroppedImageWH = 400;

public boolean mWaitingToPick; // Whether we are wait the user to pick a
// face.
public boolean mSaving; // Whether the "save" button is already clicked.
public HighlightView mCrop;

private Context mContext;
private Handler mHandler;
private CropImageView mImageView;
private Bitmap mBitmap;

public CropImage(Context context, CropImageView imageView, Handler handler) {
mContext = context;
mImageView = imageView;
mImageView.setCropImage(this);
mHandler = handler;
}

/**
 * 图片裁剪
 */
public void crop(Bitmap bm) {
mBitmap = bm;
startFaceDetection();
}

public void startRotate(float d) {
if (((Activity) mContext).isFinishing()) {
return;
}
final float degrees = d;
showProgressDialog(mContext.getResources().getString(R.string.gl_wait),
new Runnable() {
@Override
public void run() {
final CountDownLatch latch = new CountDownLatch(1);
mHandler.post(new Runnable() {
@Override
public void run() {
try {
Matrix m = new Matrix();
m.setRotate(degrees);
Bitmap tb = Bitmap.createBitmap(mBitmap, 0,
0, mBitmap.getWidth(),
mBitmap.getHeight(), m, false);
mBitmap = tb;
mImageView.resetView(tb);
if (mImageView.mHighlightViews.size() > 0) {
mCrop = mImageView.mHighlightViews
.get(0);
mCrop.setFocus(true);
}
} catch (Exception e) {
// TODO: handle exception
}
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
// mRunFaceDetection.run();
}
}, mHandler);
}

private void startFaceDetection() {
if (((Activity) mContext).isFinishing()) {
return;
}
showProgressDialog(mContext.getResources().getString(R.string.gl_wait),
new Runnable() {
@Override
public void run() {
final CountDownLatch latch = new CountDownLatch(1);
final Bitmap b = mBitmap;
mHandler.post(new Runnable() {
@Override
public void run() {
if (b != mBitmap && b != null) {
mImageView.setImageBitmapResetBase(b, true);
mBitmap.recycle();
mBitmap = b;
}
if (mImageView.getScale() == 1.0f) {
mImageView.center(true, true);
}
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
mRunFaceDetection.run();
}
}, mHandler);
}

/**
 * 裁剪并保存
 * 
 * @return
 */
public Bitmap cropAndSave() {
final Bitmap bmp = onSaveClicked(mBitmap);
mImageView.mHighlightViews.clear();
return bmp;
}

/**
 * 裁剪并保存
 * 
 * @return
 */
public Bitmap cropAndSave(Bitmap bm) {
final Bitmap bmp = onSaveClicked(bm);
mImageView.mHighlightViews.clear();
return bmp;
}

/**
 * 取消裁剪
 */
public void cropCancel() {
mImageView.mHighlightViews.clear();
mImageView.invalidate();
}

private Bitmap onSaveClicked(Bitmap bm) {
// CR: TODO!
// 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
if (mSaving)
return bm;

if (mCrop == null) {
return bm;
}

mSaving = true;

Rect r = mCrop.getCropRect();
// int width = r.width(); // CR: final == happy panda!
// int height = r.height();

// If we are circle cropping, we want alpha channel, which is the
// third param here.
// Bitmap croppedImage = Bitmap.createBitmap(width, height,
// Bitmap.Config.RGB_565);
// {
// Canvas canvas = new Canvas(croppedImage);
// Rect dstRect = new Rect(0, 0, width, height);
// canvas.drawBitmap(bm, r, dstRect, null);
// }

// Rect dr = mCrop.mDrawRect;
int width = CroppedImageWH; // dr.width(); // modify by yc
int height = CroppedImageWH; // dr.height();
Bitmap croppedImage = Bitmap.createBitmap(width, height,
Bitmap.Config.RGB_565);
{
Canvas canvas = new Canvas(croppedImage);
Rect dstRect = new Rect(0, 0, width, height);
canvas.drawBitmap(bm, r, dstRect, null);
}

return croppedImage;
}

public String saveToLocal(Bitmap bm) {
String path = FILE_LOCAL + "mm.jpg";
try {
FileOutputStream fos = new FileOutputStream(path);
bm.compress(CompressFormat.JPEG, 75, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}

return path;
}

private void showProgressDialog(String msg, Runnable job, Handler handler) {
// final ProgressDialog progress = ProgressDialog.show(mContext, null,
// msg);
// new Thread(new BackgroundJob(progress, job, handler)).start();
new Thread(new BackgroundJob(msg, job, handler)).start();
}

Runnable mRunFaceDetection = new Runnable() {
float mScale = 1F;
Matrix mImageMatrix;
FaceDetector.Face[] mFaces = new FaceDetector.Face[3];
int mNumFaces;

// For each face, we create a HightlightView for it.
private void handleFace(FaceDetector.Face f) {
PointF midPoint = new PointF();

int r = ((int) (f.eyesDistance() * mScale)) * 2;
f.getMidPoint(midPoint);
midPoint.x *= mScale;
midPoint.y *= mScale;

int midX = (int) midPoint.x;
int midY = (int) midPoint.y;

HighlightView hv = new HighlightView(mImageView);

int width = mBitmap.getWidth();
int height = mBitmap.getHeight();

Rect imageRect = new Rect(0, 0, width, height);

RectF faceRect = new RectF(midX, midY, midX, midY);
faceRect.inset(-r, -r);
if (faceRect.left < 0) {
faceRect.inset(-faceRect.left, -faceRect.left);
}

if (faceRect.top < 0) {
faceRect.inset(-faceRect.top, -faceRect.top);
}

if (faceRect.right > imageRect.right) {
faceRect.inset(faceRect.right - imageRect.right, faceRect.right
- imageRect.right);
}

if (faceRect.bottom > imageRect.bottom) {
faceRect.inset(faceRect.bottom - imageRect.bottom,
faceRect.bottom - imageRect.bottom);
}

hv.setup(mImageMatrix, imageRect, faceRect, false, true);

mImageView.add(hv);
}

// Create a default HightlightView if we found no face in the picture.
private void makeDefault() {
HighlightView hv = new HighlightView(mImageView);

int width = mBitmap.getWidth();
int height = mBitmap.getHeight();

Rect imageRect = new Rect(0, 0, width, height);

// CR: sentences!
// make the default size about 4/5 of the width or height
int cropWidth = Math.min(width, height) * 4 / 5;
int cropHeight = cropWidth;

int x = (width - cropWidth) / 2;
int y = (height - cropHeight) / 2;

RectF cropRect = new RectF(x, y, x + cropWidth, y + cropHeight);
hv.setup(mImageMatrix, imageRect, cropRect, false, true);
mImageView.add(hv);
}

// Scale the image down for faster face detection.
private Bitmap prepareBitmap() {
if (mBitmap == null) {
return null;
}

// 256 pixels wide is enough.
if (mBitmap.getWidth() > 256) {
mScale = 256.0F / mBitmap.getWidth(); // CR: F => f (or change
// all f to F).
}
Matrix matrix = new Matrix();
matrix.setScale(mScale, mScale);
Bitmap faceBitmap = Bitmap.createBitmap(mBitmap, 0, 0,
mBitmap.getWidth(), mBitmap.getHeight(), matrix, true);
return faceBitmap;
}

@Override
public void run() {
mImageMatrix = mImageView.getImageMatrix();
Bitmap faceBitmap = prepareBitmap();

mScale = 1.0F / mScale;
if (faceBitmap != null) {
FaceDetector detector = new FaceDetector(faceBitmap.getWidth(),
faceBitmap.getHeight(), mFaces.length);
mNumFaces = detector.findFaces(faceBitmap, mFaces);
}

if (faceBitmap != null && faceBitmap != mBitmap) {
faceBitmap.recycle();
}

mHandler.post(new Runnable() {
@Override
public void run() {
mWaitingToPick = mNumFaces > 1;
// if (mNumFaces > 0) {
// // for (int i = 0; i < mNumFaces; i++) {
// for (int i = 0; i < 1; i++) {
// handleFace(mFaces[i]);
// }
// } else {
makeDefault();
// }
mImageView.invalidate();
if (mImageView.mHighlightViews.size() > 0) {
mCrop = mImageView.mHighlightViews.get(0);
mCrop.setFocus(true);
}

if (mNumFaces > 1) {
// CR: no need for the variable t. just do
// Toast.makeText(...).show().
// Toast t = Toast.makeText(mContext,
// R.string.multiface_crop_help, Toast.LENGTH_SHORT);
// t.show();
}
}
});
}
};

class BackgroundJob implements Runnable {
// private ProgressDialog mProgress;
private String message;
private Runnable mJob;
private Handler mHandler;

// public BackgroundJob(ProgressDialog progress, Runnable job, Handler
// handler)
// {
// mProgress = progress;
// mJob = job;
// mHandler = handler;
// }
public BackgroundJob(String m, Runnable job, Handler handler) {
message = m;
mJob = job;
mHandler = handler;
// mProgress = new ProgressDialog(mContext);
// mProgress.setMessage(message);
// mProgress.show();
}

@Override
public void run() {
final CountDownLatch latch = new CountDownLatch(1);
mHandler.post(new Runnable() {
@Override
public void run() {
try {
mHandler.sendMessage(mHandler
.obtainMessage(CropImageActivity.SHOW_PROGRESS));
// if (mProgress != null && !mProgress.isShowing())
// {
// mProgress.show();
// }
} catch (Exception e) {
// TODO: handle exception
}

latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
mJob.run();
} finally {
mHandler.sendMessage(mHandler
.obtainMessage(CropImageActivity.REMOVE_PROGRESS));
// mHandler.post(new Runnable()
// {
// public void run()
// {
// if (mProgress != null && mProgress.isShowing())
// {
// mProgress.dismiss();
// mProgress = null;
// }
// }
// });
}
}
}
}




CropImageView.java

package cn.leature.istarbaby.info;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;


public class CropImageView extends ImageViewTouchBase {
    public ArrayList<HighlightView> mHighlightViews = new ArrayList<HighlightView>();
    HighlightView mMotionHighlightView = null;
    float mLastX, mLastY;
    int mMotionEdge;
    
    private CropImage mCropImage;

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (mBitmapDisplayed.getBitmap() != null) {
            for (HighlightView hv : mHighlightViews) {
                hv.mMatrix.set(getImageMatrix());
                hv.invalidate();
                if (hv.mIsFocused) {
                    centerBasedOnHighlightView(hv);
                }
            }
        }
    }

    public CropImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void zoomTo(float scale, float centerX, float centerY) {
        super.zoomTo(scale, centerX, centerY);
        for (HighlightView hv : mHighlightViews) {
            hv.mMatrix.set(getImageMatrix());
            hv.invalidate();
        }
    }

    @Override
    protected void zoomIn() {
        super.zoomIn();
        for (HighlightView hv : mHighlightViews) {
            hv.mMatrix.set(getImageMatrix());
            hv.invalidate();
        }
    }

    @Override
    protected void zoomOut() {
        super.zoomOut();
        for (HighlightView hv : mHighlightViews) {
            hv.mMatrix.set(getImageMatrix());
            hv.invalidate();
        }
    }

    @Override
    protected void postTranslate(float deltaX, float deltaY) {
        super.postTranslate(deltaX, deltaY);
        for (int i = 0; i < mHighlightViews.size(); i++) {
            HighlightView hv = mHighlightViews.get(i);
            hv.mMatrix.postTranslate(deltaX, deltaY);
            hv.invalidate();
        }
    }

    // According to the event's position, change the focus to the first
    // hitting cropping rectangle.
    private void recomputeFocus(MotionEvent event) {
        for (int i = 0; i < mHighlightViews.size(); i++) {
            HighlightView hv = mHighlightViews.get(i);
            hv.setFocus(false);
            hv.invalidate();
        }

        for (int i = 0; i < mHighlightViews.size(); i++) {
            HighlightView hv = mHighlightViews.get(i);
            int edge = hv.getHit(event.getX(), event.getY());
            if (edge != HighlightView.GROW_NONE) {
                if (!hv.hasFocus()) {
                    hv.setFocus(true);
                    hv.invalidate();
                }
                break;
            }
        }
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    CropImage cropImage = mCropImage;
        if (cropImage.mSaving) {
            return false;
        }

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: // CR: inline case blocks.
            if (cropImage.mWaitingToPick) {
                recomputeFocus(event);
            } else {
                for (int i = 0; i < mHighlightViews.size(); i++) { // CR:
                                                                   // iterator
                                                                   // for; if
                                                                   // not, then
                                                                   // i++ =>
                                                                   // ++i.
                    HighlightView hv = mHighlightViews.get(i);
                    int edge = hv.getHit(event.getX(), event.getY());
                    if (edge != HighlightView.GROW_NONE) {
                        mMotionEdge = edge;
                        mMotionHighlightView = hv;
                        mLastX = event.getX();
                        mLastY = event.getY();
                        // CR: get rid of the extraneous parens below.
                        mMotionHighlightView.setMode((edge == HighlightView.MOVE) ? HighlightView.ModifyMode.Move
                                : HighlightView.ModifyMode.Grow);
                        break;
                    }
                }
            }
            break;
        // CR: vertical space before case blocks.
        case MotionEvent.ACTION_UP:
            if (cropImage.mWaitingToPick) {
                for (int i = 0; i < mHighlightViews.size(); i++) {
                    HighlightView hv = mHighlightViews.get(i);
                    if (hv.hasFocus()) {
                        cropImage.mCrop = hv;
                        for (int j = 0; j < mHighlightViews.size(); j++) {
                            if (j == i) { // CR: if j != i do your shit; no need
                                          // for continue.
                                continue;
                            }
                            mHighlightViews.get(j).setHidden(true);
                        }
                        centerBasedOnHighlightView(hv);
                        mCropImage.mWaitingToPick = false;
                        return true;
                    }
                }
            } else if (mMotionHighlightView != null) {
                centerBasedOnHighlightView(mMotionHighlightView);
                mMotionHighlightView.setMode(HighlightView.ModifyMode.None);
            }
            mMotionHighlightView = null;
            break;
        case MotionEvent.ACTION_MOVE:
            if (cropImage.mWaitingToPick) {
                recomputeFocus(event);
            } else if (mMotionHighlightView != null) {
                mMotionHighlightView.handleMotion(mMotionEdge, event.getX() - mLastX, event.getY() - mLastY);
                mLastX = event.getX();
                mLastY = event.getY();

                if (true) {
                    // This section of code is optional. It has some user
                    // benefit in that moving the crop rectangle against
                    // the edge of the screen causes scrolling but it means
                    // that the crop rectangle is no longer fixed under
                    // the user's finger.
                    ensureVisible(mMotionHighlightView);
                }
            }
            break;
        }

        switch (event.getAction()) {
        case MotionEvent.ACTION_UP:
            center(true, true);
            break;
        case MotionEvent.ACTION_MOVE:
            // if we're not zoomed then there's no point in even allowing
            // the user to move the image around. This call to center puts
            // it back to the normalized location (with false meaning don't
            // animate).
//            if (getScale() == 1F) {
                center(true, true);
//            }
            break;
        }

        return true;
    }

    // Pan the displayed image to make sure the cropping rectangle is visible.
    private void ensureVisible(HighlightView hv) {
        Rect r = hv.mDrawRect;

        int panDeltaX1 = Math.max(0, getLeft() - r.left);
        int panDeltaX2 = Math.min(0, getRight() - r.right);

        int panDeltaY1 = Math.max(0, getTop() - r.top);
        int panDeltaY2 = Math.min(0, getBottom() - r.bottom);

        int panDeltaX = panDeltaX1 != 0 ? panDeltaX1 : panDeltaX2;
        int panDeltaY = panDeltaY1 != 0 ? panDeltaY1 : panDeltaY2;

        if (panDeltaX != 0 || panDeltaY != 0) {
            panBy(panDeltaX, panDeltaY);
        }
    }

    // If the cropping rectangle's size changed significantly, change the
    // view's center and scale according to the cropping rectangle.
    //hv.mDrawRect.width<0.54*thisWidth||width>0.66*thisWidth,need to zoom
    private void centerBasedOnHighlightView(HighlightView hv) {
        Rect drawRect = hv.mDrawRect;
        
        float width = drawRect.width();
        float height = drawRect.height();

        float thisWidth = getWidth();
        float thisHeight = getHeight();

        float z1 = thisWidth / width * .6F;
        float z2 = thisHeight / height * .6F;

        float zoom = Math.min(z1, z2);
        zoom = zoom * this.getScale();
        zoom = Math.max(1F, zoom);//assure getScale()>1

        if ((Math.abs(zoom - getScale()) / zoom) > 0.1) {
            float[] coordinates = new float[] { hv.mCropRect.centerX(), hv.mCropRect.centerY() };
            getImageMatrix().mapPoints(coordinates);
            zoomTo(zoom, coordinates[0], coordinates[1], 300F); // CR: 300.0f.
        }

        ensureVisible(hv);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < mHighlightViews.size(); i++) {
            mHighlightViews.get(i).draw(canvas);
        }
    }

    public void add(HighlightView hv) {
    mHighlightViews.clear();
        mHighlightViews.add(hv);
        invalidate();
    }
    
    public void setCropImage(CropImage cropImage)
    {
    mCropImage = cropImage;
    }
    public void resetView(Bitmap b){
    setImageBitmap(b);
setImageBitmapResetBase(b, true);
setImageMatrix(getImageViewMatrix());
int width = mBitmapDisplayed.getWidth();
        int height = mBitmapDisplayed.getHeight();
        Rect imageRect = new Rect(0, 0, width, height);
        int cropWidth = Math.min(width, height) * 4 / 5;
        int cropHeight = cropWidth;
        int x = (width - cropWidth) / 2;
        int y = (height - cropHeight) / 2;
        RectF cropRect = new RectF(x, y, x + cropWidth, y + cropHeight);
        HighlightView hv = new HighlightView(this);
        hv.setup(getImageViewMatrix(), imageRect, cropRect, false, true);
        hv.setFocus(true);
add(hv);
centerBasedOnHighlightView(hv);
hv.setMode(HighlightView.ModifyMode.None);
center(true, true);
invalidate();
    }
    
}

ImageViewTouchBase.java

package cn.leature.istarbaby.info;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.ImageView;


public abstract class ImageViewTouchBase extends ImageView {

    @SuppressWarnings("unused")
    private static final String TAG = "ImageViewTouchBase";

    // This is the base transformation which is used to show the image
    // initially. The current computation for this shows the image in
    // it's entirety, letterboxing as needed. One could choose to
    // show the image as cropped instead.
    //
    // This matrix is recomputed when we go from the thumbnail image to
    // the full size image.
    protected Matrix mBaseMatrix = new Matrix();

    // This is the supplementary transformation which reflects what
    // the user has done in terms of zooming and panning.
    //
    // This matrix remains the same when we go from the thumbnail image
    // to the full size image.
    protected Matrix mSuppMatrix = new Matrix();

    // This is the final matrix which is computed as the concatentation
    // of the base matrix and the supplementary matrix.
    private final Matrix mDisplayMatrix = new Matrix();

    // Temporary buffer used for getting the values out of a matrix.
    private final float[] mMatrixValues = new float[9];

    // The current bitmap being displayed.
    final public RotateBitmap mBitmapDisplayed = new RotateBitmap(null);

    int mThisWidth = -1, mThisHeight = -1;

    float mMaxZoom;
    
    /**
     * 高亮状态
     */
    public static final int STATE_HIGHLIGHT = 0x0;
    
    /**
     * 涂鸦状态
     */
    public static final int STATE_DOODLE = STATE_HIGHLIGHT + 1;
    
    /**
     * 没有任何操作
     */
    public static final int STATE_NONE = STATE_HIGHLIGHT + 2;
    protected int mState = STATE_HIGHLIGHT;

    // ImageViewTouchBase will pass a Bitmap to the Recycler if it has finished
    // its use of that Bitmap.
    public interface Recycler {
        public void recycle(Bitmap b);
    }

    public void setRecycler(Recycler r) {
        mRecycler = r;
    }

    private Recycler mRecycler;

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        mThisWidth = right - left;
        mThisHeight = bottom - top;
        Runnable r = mOnLayoutRunnable;
        if (r != null) {
            mOnLayoutRunnable = null;
            r.run();
        }
        if (mBitmapDisplayed.getBitmap() != null) {
            getProperBaseMatrix(mBitmapDisplayed, mBaseMatrix);
            setImageMatrix(getImageViewMatrix());
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && getScale() > 1.0f) {
            // If we're zoomed in, pressing Back jumps out to show the entire
            // image, otherwise Back returns the user to the gallery.
            zoomTo(1.0f);
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    protected Handler mHandler = new Handler();

    protected int mLastXTouchPos;
    protected int mLastYTouchPos;

    @Override
    public void setImageBitmap(Bitmap bitmap) {
        setImageBitmap(bitmap, 0);
    }

    private void setImageBitmap(Bitmap bitmap, int rotation) {
        super.setImageBitmap(bitmap);
        Drawable d = getDrawable();
        if (d != null) {
            d.setDither(true);
        }

        Bitmap old = mBitmapDisplayed.getBitmap();
        mBitmapDisplayed.setBitmap(bitmap);
        mBitmapDisplayed.setRotation(rotation);

        if (old != null && old != bitmap && mRecycler != null) {
            mRecycler.recycle(old);
        }
    }

    public void clear() {
        setImageBitmapResetBase(null, true);
    }

    private Runnable mOnLayoutRunnable = null;

    // This function changes bitmap, reset base matrix according to the size
    // of the bitmap, and optionally reset the supplementary matrix.
    public void setImageBitmapResetBase(final Bitmap bitmap, final boolean resetSupp) {
        setImageRotateBitmapResetBase(new RotateBitmap(bitmap), resetSupp);
    }
    public void setImageRotateBitmapResetBase(final RotateBitmap bitmap, final boolean resetSupp) {
        final int viewWidth = getWidth();

        if (viewWidth <= 0) {
            mOnLayoutRunnable = new Runnable() {
                @Override
public void run() {
                    setImageRotateBitmapResetBase(bitmap, resetSupp);
                }
            };
            return;
        }

        if (bitmap.getBitmap() != null) {
            getProperBaseMatrix(bitmap, mBaseMatrix);
            setImageBitmap(bitmap.getBitmap(), bitmap.getRotation());
        } else {
            mBaseMatrix.reset();
            setImageBitmap(null);
        }

        if (resetSupp) {
            mSuppMatrix.reset();
        }
        setImageMatrix(getImageViewMatrix());
        mMaxZoom = maxZoom();
    }

    // Center as much as possible in one or both axis. Centering is
    // defined as follows: if the image is scaled down below the
    // view's dimensions then center it (literally). If the image
    // is scaled larger than the view and is translated out of view
    // then translate it back into view (i.e. eliminate black bars).
    public void center(boolean horizontal, boolean vertical) {
        if (mBitmapDisplayed.getBitmap() == null) {
            return;
        }

        Matrix m = getImageViewMatrix();

        RectF rect = new RectF(0, 0, mBitmapDisplayed.getBitmap().getWidth(), mBitmapDisplayed.getBitmap().getHeight());

        m.mapRect(rect);

        float height = rect.height();
        float width = rect.width();
        
        float deltaX = 0, deltaY = 0;

        if (vertical) {
            int viewHeight = getHeight();
            if (height < viewHeight) {
                deltaY = (viewHeight - height) / 2 - rect.top;
            } else if (rect.top > 0) {
                deltaY = -rect.top;
            } else if (rect.bottom < viewHeight) {
                deltaY = getHeight() - rect.bottom;
            }
        }

        if (horizontal) {
            int viewWidth = getWidth();
            if (width < viewWidth) {
                deltaX = (viewWidth - width) / 2 - rect.left;
            } else if (rect.left > 0) {
                deltaX = -rect.left;
            } else if (rect.right < viewWidth) {
                deltaX = viewWidth - rect.right;
            }
        }

        postTranslate(deltaX, deltaY);
        setImageMatrix(getImageViewMatrix());
    }

    public ImageViewTouchBase(Context context) {
        super(context);
        init();
    }

    public ImageViewTouchBase(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        setScaleType(ImageView.ScaleType.MATRIX);
    }

    protected float getValue(Matrix matrix, int whichValue) {
        matrix.getValues(mMatrixValues);
        return mMatrixValues[whichValue];
    }

    // Get the scale factor out of the matrix.
    protected float getScale(Matrix matrix) {
        return getValue(matrix, Matrix.MSCALE_X);
    }

    public float getScale() {
        return getScale(mSuppMatrix);
    }

    // Setup the base matrix so that the image is centered and scaled properly.
    private void getProperBaseMatrix(RotateBitmap bitmap, Matrix matrix) {
        float viewWidth = getWidth();
        float viewHeight = getHeight();

        float w = bitmap.getWidth();
        float h = bitmap.getHeight();
        matrix.reset();

        // We limit up-scaling to 2x otherwise the result may look bad if it's
        // a small icon.
        float widthScale = Math.min(viewWidth / w, 2.0f);
        float heightScale = Math.min(viewHeight / h, 2.0f);
        float scale = Math.min(widthScale, heightScale);

        matrix.postConcat(bitmap.getRotateMatrix());
        matrix.postScale(scale, scale);

        matrix.postTranslate((viewWidth - w * scale) / 2F, (viewHeight - h * scale) / 2F);
    }

    // Combine the base matrix and the supp matrix to make the final matrix.
    protected Matrix getImageViewMatrix() {
        // The final matrix is computed as the concatentation of the base matrix
        // and the supplementary matrix.
        mDisplayMatrix.set(mBaseMatrix);
        mDisplayMatrix.postConcat(mSuppMatrix);
        return mDisplayMatrix;
    }

    static final float SCALE_RATE = 1.25F;

    // Sets the maximum zoom, which is a scale relative to the base matrix. It
    // is calculated to show the image at 400% zoom regardless of screen or
    // image orientation. If in the future we decode the full 3 megapixel image,
    // rather than the current 1024x768, this should be changed down to 200%.
    protected float maxZoom() {
        if (mBitmapDisplayed.getBitmap() == null) {
            return 1F;
        }

        float fw = (float) mBitmapDisplayed.getWidth() / (float) mThisWidth;
        float fh = (float) mBitmapDisplayed.getHeight() / (float) mThisHeight;
        float max = Math.max(fw, fh) * 4;
        max = (max<1.0f)?1.0f:max;
        return max;
    }

    protected void zoomTo(float scale, float centerX, float centerY) {
        if (scale > mMaxZoom) {
            scale = mMaxZoom;
        }

        float oldScale = getScale();
        float deltaScale = scale / oldScale;

        mSuppMatrix.postScale(deltaScale, deltaScale, centerX, centerY);
        setImageMatrix(getImageViewMatrix());
        center(true, true);
    }

    protected void zoomTo(final float scale, final float centerX, final float centerY, final float durationMs) {
        final float incrementPerMs = (scale - getScale()) / durationMs;
        final float oldScale = getScale();
        final long startTime = System.currentTimeMillis();

        mHandler.post(new Runnable() {
            @Override
public void run() {
                long now = System.currentTimeMillis();
                float currentMs = Math.min(durationMs, now - startTime);
                float target = oldScale + (incrementPerMs * currentMs);
                zoomTo(target, centerX, centerY);

                if (currentMs < durationMs) {
                    mHandler.post(this);
                }
            }
        });
    }

    protected void zoomTo(float scale) {
        float cx = getWidth() / 2F;
        float cy = getHeight() / 2F;

        zoomTo(scale, cx, cy);
    }

    protected void zoomIn() {
        zoomIn(SCALE_RATE);
    }

    protected void zoomOut() {
        zoomOut(SCALE_RATE);
    }

    protected void zoomIn(float rate) {
        if (getScale() >= mMaxZoom) {
            return; // Don't let the user zoom into the molecular level.
        }
        if (mBitmapDisplayed.getBitmap() == null) {
            return;
        }

        float cx = getWidth() / 2F;
        float cy = getHeight() / 2F;

        mSuppMatrix.postScale(rate, rate, cx, cy);
        setImageMatrix(getImageViewMatrix());
    }

    protected void zoomOut(float rate) {
        if (mBitmapDisplayed.getBitmap() == null) {
            return;
        }

        float cx = getWidth() / 2F;
        float cy = getHeight() / 2F;

        // Zoom out to at most 1x.
        Matrix tmp = new Matrix(mSuppMatrix);
        tmp.postScale(1F / rate, 1F / rate, cx, cy);

        if (getScale(tmp) < 1F) {
            mSuppMatrix.setScale(1F, 1F, cx, cy);
        } else {
            mSuppMatrix.postScale(1F / rate, 1F / rate, cx, cy);
        }
        setImageMatrix(getImageViewMatrix());
        center(true, true);
    }

    protected void postTranslate(float dx, float dy) {
        mSuppMatrix.postTranslate(dx, dy);
    }

    protected void panBy(float dx, float dy) {
        postTranslate(dx, dy);
        setImageMatrix(getImageViewMatrix());
    }
    
}




从相册中获取图片:
intent.setAction(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, FLAG_CHOOSE_IMG);
通过相机获取图片:

 
String status = Environment.getExternalStorageState();
if (status.equals(Environment.MEDIA_MOUNTED)) {
try {
localTempImageFileName = "";
localTempImageFileName = String.valueOf((new Date())
.getTime()) + ".png";
File filePath = FILE_PIC_SCREENSHOT;
if (!filePath.exists()) {
filePath.mkdirs();
}
Intent intent1 = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(filePath, localTempImageFileName);
// localTempImgDir和localTempImageFileName是自己定义的名字
Uri u = Uri.fromFile(f);
intent1.putExtra(ImageColumns.ORIENTATION, 0);
intent1.putExtra(MediaStore.EXTRA_OUTPUT, u);
startActivityForResult(intent1, FLAG_CHOOSE_PHONE);
} catch (ActivityNotFoundException e) {
//
}
}



在Activity回调中:对不同来源的图片进行处理,先交给裁剪工具,裁剪完后再将图片拿来使用

 
if (requestCode == FLAG_CHOOSE_IMG && resultCode == RESULT_OK) {
if (data != null) {
Uri uri = data.getData();
if (!TextUtils.isEmpty(uri.getAuthority())) {
Cursor cursor = getContentResolver().query(uri,
new String[] { MediaColumns.DATA }, null, null,
null);
if (null == cursor) {
return;
}
cursor.moveToFirst();
String path = cursor.getString(cursor
.getColumnIndex(MediaColumns.DATA));
cursor.close();
cursor.close();
Intent intent = new Intent(this, CropImageActivity.class);
intent.putExtra("path", path);
startActivityForResult(intent, FLAG_MODIFY_FINISH);
} else {
Intent intent = new Intent(this, CropImageActivity.class);
intent.putExtra("path", uri.getPath());
startActivityForResult(intent, FLAG_MODIFY_FINISH);
}
}
} else if (requestCode == FLAG_CHOOSE_PHONE && resultCode == RESULT_OK) {
File f = new File(FILE_PIC_SCREENSHOT, localTempImageFileName);
Intent intent = new Intent(this, CropImageActivity.class);
intent.putExtra("path", f.getAbsolutePath());
startActivityForResult(intent, FLAG_MODIFY_FINISH);
} else if (requestCode == FLAG_MODIFY_FINISH && resultCode == RESULT_OK) {
if (data != null) {
final String path = data.getStringExtra("path");
Bitmap bm = BitmapFactory.decodeFile(path);
// 裁剪成正方形图片
mIconBitmap = ResizeImage.resizeBitmapWithRadio(bm, 1, 1);

mChild_Icon.setImageBitmap(mIconBitmap);
uploadIconBitmap();
}
}

 
 备注:private static final int FLAG_CHOOSE_IMG = 5;
private static final int FLAG_CHOOSE_PHONE = 6;
private static final int FLAG_MODIFY_FINISH = 7;
public static final String IMAGE_PATH = "My_weixin";
public static final File FILE_SDCARD = Environment
.getExternalStorageDirectory();
public static final File FILE_LOCAL = new File(FILE_SDCARD, IMAGE_PATH);
public static final File FILE_PIC_SCREENSHOT = new File(FILE_LOCAL,
"images/screenshots");
private static String localTempImageFileName = "";

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值