您的位置:首页 > 移动开发 > Android开发

android---图片获得与裁剪

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

图片裁剪的工具类: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 = "";
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: