调用系统照相机

来源:互联网 发布:能在淘宝上买貂皮吗 编辑:程序博客网 时间:2024/05/01 05:06

很多时候我们都需要调用系统的照相机功能,来满足诸如设置图片、上传图片等操作,那么我们来看看如何调用相机吧。

代码很简单,如下:

/** * 调用系统照相功能,返回所照相片到PicUtils.PIC_PATH下 */private void startCamera() {Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);startActivityForResult(camera, CAMERA);}
其中CAMERA可以是任意的整数,它是照完相之后返回到当前界面时,得到的请求码,然后我们在Activity中的方法onActivityResult(int requestCode, int resultCode, Intent data)中得到照相的结果:

/** * 当调用完系统应用之后,返回界面时的操作 requestCode = CAMERA、系统照相 requestCode = CAMERA + * 1、系统裁剪 */protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);File file = new File(PicUtils.PIC_PATH + getUid() + "tmp.png"); // 临时图像if (requestCode == CAMERA && resultCode == Activity.RESULT_OK) {Bundle bundle = data.getExtras();Bitmap bitmap = (Bitmap) bundle.get("data"); // 得到照完相之后的图片数据        }

其中的requestCode则为调用startActivityForRuesult的请求码,而Activity.RESULT_OK也是整数,为结果码,上面的代码表示当照相完成点击确定之后,则将数据转换成Bitmap对象。

值得注意的是这样写只能得到图片较小的结果,当图片太大时,这样写是得不到照相机的图片的,那个时候,我们就需要使用Uri来传递照相图片:

/** * 调用系统照相功能,照相文件指向imageUri路径 */private void startCamera() {Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);camera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);startActivityForResult(camera, CAMERA);}
这样得到的照相图片则存放在imageUri所指向的文件中,而imageUri可以这样定义:imageUri=Uri.parse(PIC_PATH);然后我们就可以操作得到的Bitmap对象了。

照完相之后,可能有些应用也需要调用系统的裁剪功能,代码如下:

/** * @author ZYJ * @功能 调用系统的裁剪,并开始裁剪指定的图片,返回裁剪的图片到PicUtils.PIC_PATH下 * @param uri *            所需要裁剪的图片的uri */public void startImgResize(Uri uri) {Intent intent = new Intent("com.android.camera.action.CROP"); // 裁剪意图intent.setDataAndType(uri, "image/*"); // 格式intent.putExtra("crop", "true"); // 发送裁剪信号intent.putExtra("aspectX", 4); // X方向上的比例intent.putExtra("aspectY", 3); // Y方向上的比例intent.putExtra("outputX", 1600); // 裁剪区的宽intent.putExtra("outputY", 1200); // 裁剪区的高intent.putExtra("scale", false); // 是否保留比例intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); // 将URI指向相应的file:///intent.putExtra("return-data", false); // 是否将数据保留在Bitmap中返回intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());intent.putExtra("noFaceDetection", true); // no face detectionintent.putExtra("circleCrop", false); // 圆形裁剪区域startActivityForResult(intent, CAMERA + 1);}
这段代码的注释已经写的很清楚了,其中使用Uri来传递图片数据,是因为图片较大,而使用系统裁剪则需要android2.3以上的系统才能支持,startActivityForResult(intent, int);同调用相机的方法。

这个说的是调用系统的裁剪,如果没有系统裁剪呢?比如2.2及以下的系统,那该肿么办?我们可以自己写一个裁剪的例子,代码如下:

public class MyView extends View {private Context context;private Bitmap controlBmp;private RectF mainBmp;private int mainBmpWidth, mainBmpHeight, controlBmpWidth, controlBmpHeight;private Matrix matrix;private float[] srcPs, dstPs;private RectF srcRect, dstRect;private Paint paint, paintRect, paintFrame;private float deltaX = 0, deltaY = 0; // 位移值private float scaleValue = 1; // 缩放值private Point lastPoint;private Point prePivot, lastPivot;private float preDegree, lastDegree;private Point symmetricPoint = new Point(); // 当前操作点对称点/** * 图片操作类型 OPER_DEFAULT 默认 OPER_TRANSLATE 移动 OPER_SCALE 缩放 OPER_ROTATE 旋转 * OPER_SELECTED 选择 */public static final int OPER_DEFAULT = -1;public static final int OPER_TRANSLATE = 0;public static final int OPER_SCALE = 1;public static final int OPER_ROTATE = 2;public static final int OPER_SELECTED = 3;public int lastOper = OPER_DEFAULT;/* * 图片控制点 0---1---2 | | 7 8 3 | | 6---5---4 */public static final int CTR_NONE = -1;public static final int CTR_LEFT_TOP = 0;public static final int CTR_MID_TOP = 1;public static final int CTR_RIGHT_TOP = 2;public static final int CTR_RIGHT_MID = 3;public static final int CTR_RIGHT_BOTTOM = 4;public static final int CTR_MID_BOTTOM = 5;public static final int CTR_LEFT_BOTTOM = 6;public static final int CTR_LEFT_MID = 7;public static final int CTR_MID_MID = 8;public int current_ctr = CTR_NONE;public MyView(Context context) {super(context);this.context = context;initData();}public MyView(Context context, AttributeSet attrs) {super(context, attrs);this.context = context;initData();}/** * @author ZYJ * @功能 初始化数据 */private void initData() {// mainBmp = BitmapFactory.decodeResource(this.context.getResources(),// R.drawable.bg1); // 空白位置mainBmp = new RectF();mainBmp.contains(0, 0, 300, 200);controlBmp = BitmapFactory.decodeResource(this.context.getResources(),R.drawable.dian); // 触控点// mainBmpWidth = mainBmp.getWidth();// mainBmpHeight = mainBmp.getHeight();mainBmpWidth = 200;mainBmpHeight = 200;controlBmpWidth = controlBmp.getWidth();controlBmpHeight = controlBmp.getHeight();// 触控点坐标srcPs = new float[] {0, 0, mainBmpWidth / 2, 0, mainBmpWidth, 0, mainBmpWidth,mainBmpHeight / 2, mainBmpWidth, mainBmpHeight,mainBmpWidth / 2, mainBmpHeight, 0, mainBmpHeight, 0,mainBmpHeight / 2, mainBmpWidth / 2, mainBmpHeight / 2};dstPs = srcPs.clone();srcRect = new RectF(0, 0, mainBmpWidth, mainBmpHeight);dstRect = new RectF();matrix = new Matrix();prePivot = new Point(mainBmpWidth / 2, mainBmpHeight / 2);lastPivot = new Point(mainBmpWidth / 2, mainBmpHeight / 2);lastPoint = new Point(0, 0);paint = new Paint();paintRect = new Paint();paintRect.setColor(Color.RED);paintRect.setAlpha(100);paintRect.setAntiAlias(true);paintFrame = new Paint();paintFrame.setColor(Color.GREEN);paintFrame.setAntiAlias(true);setMatrix(OPER_DEFAULT);}/** * @author ZYJ * @功能 矩阵变换,达到图形变形的目的 */private void setMatrix(int operationType) {switch (operationType) {case OPER_TRANSLATE:matrix.postTranslate(deltaX, deltaY);break;case OPER_SCALE:matrix.postScale(scaleValue, scaleValue, symmetricPoint.x,symmetricPoint.y);break;case OPER_ROTATE:matrix.postRotate(preDegree - lastDegree,dstPs[CTR_MID_MID * 2], dstPs[CTR_MID_MID * 2 + 1]);break;}matrix.mapPoints(dstPs, srcPs); // 在图片变换后,计算坐标,将srcPs坐标转换之后放入dstPs中matrix.mapRect(dstRect, srcRect); // 同上}/** * @author ZYJ * @功能 判断该点是否在变换之后的触控点坐标上 * @param x * @param y * @return true,在坐标上,其他则返回false */private boolean isOnPic(int x, int y) {if (dstRect.contains(x, y)) {return true;} elsereturn false;}/** * @author ZYJ * @功能 根据屏幕的点击或者移动操作,来判断该图片是使用哪种方式进行变换 * @param event * @return 返回代表变换方式的id */private int getOperationType(MotionEvent event) {int evX = (int) event.getX();int evY = (int) event.getY();int curOper = lastOper;switch (event.getAction()) {case MotionEvent.ACTION_DOWN:current_ctr = isOnCP(evX, evY);Log.i("img", "current_ctr is " + current_ctr);if (current_ctr != CTR_NONE || isOnPic(evX, evY)) {curOper = OPER_SELECTED;}break;case MotionEvent.ACTION_MOVE:if (current_ctr > CTR_NONE && current_ctr < CTR_MID_MID) { // 在边缘时进行缩放操作curOper = OPER_SCALE;} else if (current_ctr == CTR_MID_MID) { // 在中心点是进行旋转操作curOper = OPER_ROTATE;} else if (lastOper == OPER_SELECTED) { // 不在触控点上,进行移动curOper = OPER_TRANSLATE;}break;case MotionEvent.ACTION_UP:curOper = OPER_SELECTED;break;default:break;}Log.d("img", "curOper is " + curOper);return curOper;}/** * @author ZYJ * @功能 判断点所在的控制点 * @param evX *            点击屏幕的x坐标 * @param evY *            点击屏幕的y坐标 * @return 返回屏幕点击点所在的触控点id,默认返回第一个 */private int isOnCP(int evx, int evy) {Rect rect = new Rect(evx - controlBmpWidth / 2, evy - controlBmpHeight/ 2, evx + controlBmpWidth / 2, evy + controlBmpHeight / 2);int res = 0;for (int i = 0; i < dstPs.length; i += 2) {if (rect.contains((int) dstPs[i], (int) dstPs[i + 1])) {return res;}++res;}return CTR_NONE;}public boolean onTouchEvent(MotionEvent event) {dispatchTouchEvent(event);return true;}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) { // 分发器int evX = (int) event.getX();int evY = (int) event.getY();int operType = OPER_DEFAULT;// int operType = 0;operType = getOperationType(event);switch (operType) {case OPER_TRANSLATE:translate(evX, evY);break;case OPER_SCALE:scale(event);break;case OPER_ROTATE:rotate(event);break;}lastPoint.x = evX;lastPoint.y = evY;lastOper = operType;invalidate();// 重绘return true;}/** * @author ZYJ * @功能 移动 * @param evx * @param evy */private void translate(int evx, int evy) {// **************************************************************// 计算两点之间的距离,并将它设置到lastPivot中// **************************************************************prePivot.x += evx - lastPoint.x;prePivot.y += evy - lastPoint.y;deltaX = prePivot.x - lastPivot.x;deltaY = prePivot.y - lastPivot.y;lastPivot.x = prePivot.x;lastPivot.y = prePivot.y;setMatrix(OPER_TRANSLATE); // 设置矩阵}/** * 缩放 0---1---2 | | 7 8 3 | | 6---5---4 *  * @param evX * @param evY */private void scale(MotionEvent event) {int pointIndex = current_ctr * 2; // 得到触控点坐标float px = dstPs[pointIndex];float py = dstPs[pointIndex + 1];float evx = event.getX();float evy = event.getY();float oppositeX = 0;float oppositeY = 0;if (current_ctr < 4 && current_ctr >= 0) {oppositeX = dstPs[pointIndex + 8];oppositeY = dstPs[pointIndex + 9];} else if (current_ctr >= 4) {oppositeX = dstPs[pointIndex - 8];oppositeY = dstPs[pointIndex - 7];}float temp1 = getDistanceOfTwoPoints(px, py, oppositeX, oppositeY);float temp2 = getDistanceOfTwoPoints(evx, evy, oppositeX, oppositeY);this.scaleValue = temp2 / temp1; // 缩放倍数symmetricPoint.x = (int) oppositeX;symmetricPoint.y = (int) oppositeY;Log.i("img", "scaleValue is " + scaleValue);setMatrix(OPER_SCALE);}/** * 旋转图片 0---1---2 | | 7 8 3 | | 6---5---4 *  * @param evX * @param evY */private void rotate(MotionEvent event) {if (event.getPointerCount() == 2) { // 两个手指按压屏幕preDegree = computeDegree(new Point((int) event.getX(0),(int) event.getY(0)), new Point((int) event.getX(1),(int) event.getY(1)));} else {preDegree = computeDegree(new Point((int) event.getX(), (int) event.getY()),new Point((int) dstPs[16], (int) dstPs[17]));}setMatrix(OPER_ROTATE);lastDegree = preDegree;}/** * 计算两点与垂直方向夹角 *  * @param p1 * @param p2 * @return */public float computeDegree(Point p1, Point p2) {float tran_x = p1.x - p2.x;float tran_y = p1.y - p2.y;float degree = 0.0f;float angle = (float) (Math.asin(tran_x/ Math.sqrt(tran_x * tran_x + tran_y * tran_y)) * 180 / Math.PI);if (!Float.isNaN(angle)) {if (tran_x >= 0 && tran_y <= 0) {// 第一象限degree = angle;} else if (tran_x <= 0 && tran_y <= 0) {// 第二象限degree = angle;} else if (tran_x <= 0 && tran_y >= 0) {// 第三象限degree = -180 - angle;} else if (tran_x >= 0 && tran_y >= 0) {// 第四象限degree = 180 - angle;}}return degree;}/** * @author ZYJ * @功能 两点之间的距离 * @param x1 * @param y1 * @param x2 * @param y2 * @return */private float getDistanceOfTwoPoints(float x1, float y1, float x2, float y2) {return (float) (Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));}public void onDraw(Canvas canvas) {drawBackground(canvas);// 绘制背景,以便测试矩形的映射// canvas.drawBitmap(mainBmp, matrix, paint);// 绘制主图片drawControlPoints(canvas);// 绘制控制点图片zyj(canvas,BitmapFactory.decodeResource(getResources(), (R.drawable.bg1)));drawFrame(canvas);// 绘制边框,以便测试点的映射}private void zyj(Canvas canvas, Bitmap bitmap) {Matrix m = new Matrix();float beishu = (float) this.getWidth() / bitmap.getWidth();m.postScale(beishu, beishu);Rect r = new Rect();r.left = (int) dstPs[0];r.right = (int) (dstPs[4]);r.top = (int) dstPs[1];r.bottom = (int) (dstPs[13]);canvas.clipRect(r);canvas.drawBitmap(bitmap, m, paint);}private void drawBackground(Canvas canvas) {canvas.drawRect(dstRect, paintRect);}private void drawFrame(Canvas canvas) {canvas.drawLine(dstPs[0], dstPs[1], dstPs[4], dstPs[5], paintFrame);canvas.drawLine(dstPs[4], dstPs[5], dstPs[8], dstPs[9], paintFrame);canvas.drawLine(dstPs[8], dstPs[9], dstPs[12], dstPs[13], paintFrame);canvas.drawLine(dstPs[0], dstPs[1], dstPs[12], dstPs[13], paintFrame);canvas.drawPoint(dstPs[16], dstPs[17], paintFrame);}private void drawControlPoints(Canvas canvas) {for (int i = 0; i < dstPs.length; i += 2) {if (i == 16) {continue;}canvas.drawBitmap(controlBmp, dstPs[i] - controlBmpWidth / 2,dstPs[i + 1] - controlBmpHeight / 2, paint);}}public Bitmap startCrop() {BitmapFactory.Options opts = new BitmapFactory.Options();opts.inDensity = getResources().getDisplayMetrics().densityDpi;opts.inTargetDensity = getResources().getDisplayMetrics().densityDpi;Bitmap tmp = BitmapFactory.decodeResource(getResources(),R.drawable.bg1, opts);float multiple = ((float) (tmp.getWidth()) / this.getWidth());int x = (int) (dstPs[0] * multiple);int y = (int) (dstPs[1] * multiple);if (x < 0) {x = 0;}if (y < 0) {y = 0;}// 打印信息Bitmap result = Bitmap.createBitmap(tmp, x, y, tmp.getWidth() - x,tmp.getHeight() - y);return result;}}

代码可能有点长,它实现了图片的缩放,旋转,位移等操作,其实说穿了,就是通过矩阵来实现这一切的,在startCrop()方法中,来开始裁剪操作好了的图片,从而得到我们所需要的图片。

注:

1、在调用系统相机之前,你可能调用了相机,但你得不到相机的结果,有两种可能,一是你的图片过去,传递数据时出现异常,这个时候你需要用Uri来传递图片数据,二是你的Activity的加载模式配置有问题,因为要得到相机结果,加载模式需要配置成默认的standard,有一次我配置成singleInstance模式,始终得不到结果,所以你可以看看你的Activity模式是否出现了错误,最好是这几种模式都试试

2、在自定义的裁剪中,我所贴出来的代码,也是参照前辈们的,然后自己小改动了一点点,它是基于普通的View组件,所以给它设置背景图片,才能开始裁剪图片

OK,以上就是关于调用系统照相和系统裁剪以及自定义系统裁剪






原创粉丝点击