自动对焦拍照,以及可移动方框定位

最近工作中遇到一个这样的功能,自动对焦拍照后将照片显示在当前页面,并出现两个长方形框体对照片的选中区域进行定位,获取其坐标。

这里就主要涉及到以下四个功能:拍照、照片显示、可移动的长方形框体、定位。

开始没有什么思路,于是从界面下手,

1.首先做出可移动框体,自定义一个view重写ondraw方法;

2.然后在这界面添加控制方向的按钮;

3.为了拍照,需要有一个SurfaceView,为了显示拍照的结果,需要一个ImageView来装载照片,这个view为了画图所以应当包含在之前的自定义view中;

4.为了让照片完全遮挡surfaceView所以使用帧布局,两个view设置成完全一致的宽高。

当上面的布局出来之后发现思路已经完全打开了。

一方面响应按钮事件,每点击一次按钮就重画一次,另一方面拍照就可以了。

一些关键代码如下:

自定义View DrawImageView.java@SuppressLint("DrawAllocation")@Overrideprotected void onDraw(Canvas canvas) {Log.e("====>>>>","开始绘图");super.onDraw(canvas);Paint cpaint = new Paint();cpaint.setAntiAlias(true);cpaint.setColor(Color.RED);cpaint.setStyle(Style.STROKE);cpaint.setStrokeWidth(2.5f);// 设置线宽cpaint.setAlpha(100);canvas.drawRect(cx, cy, cx+width, cy+height, cpaint);// 绘制c矩形Paint tpaint = new Paint();tpaint.setAntiAlias(true);tpaint.setColor(Color.GREEN);tpaint.setStyle(Style.STROKE);tpaint.setStrokeWidth(2.5f);// 设置线宽tpaint.setAlpha(100);canvas.drawRect(tx, ty, tx+width, ty+height, tpaint);// 绘制t矩形Log.e("====>>>>","结束绘图");}

MainActivity.java:

package com.example.camera;import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;public class MainActivity extends Activity implements SurfaceHolder.Callback,AutoFocusCallback, PictureCallback {private static final String TAG = "camera";private Button c_move_to_left;private Button c_move_to_right;private Button t_move_to_left;private Button t_move_to_right;private Button move_to_top;private Button move_to_bottom;private Button retake_picture;private Button commit;private SurfaceView surfaceView;private DrawImageView drawView;private ResultImageView resultView;private ImageView iv;private Camera camera;private SurfaceHolder surfaceHolder;private AutoFocusCallback autoFocusCallback;private int cx = 184;private int cy = 123;private int tx = 246;private int ty = 123;private int trueWidth;private int trueHeight;private double a = 0.625;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();initData();initListener();}private void initView() {surfaceView = (SurfaceView) findViewById(R.id.sv_preview);resultView = (ResultImageView) findViewById(R.id.resultView);drawView = (DrawImageView) resultView.findViewById(R.id.drawView);c_move_to_left = (Button) findViewById(R.id.c_move_to_left);c_move_to_right = (Button) findViewById(R.id.c_move_to_right);t_move_to_left = (Button) findViewById(R.id.t_move_to_left);t_move_to_right = (Button) findViewById(R.id.t_move_to_right);move_to_top = (Button) findViewById(R.id.move_to_top);move_to_bottom = (Button) findViewById(R.id.move_to_bottom);retake_picture = (Button) findViewById(R.id.retake_picture);commit = (Button) findViewById(R.id.commit);}@SuppressWarnings("deprecation")private void initData() {surfaceHolder = surfaceView.getHolder();// 设置SurfaceHolder类型surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// translucent半透明surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);// 屏幕常亮surfaceHolder.setKeepScreenOn(true);// 为SurfaceView的句柄添加一个回调函数surfaceHolder.addCallback(this);surfaceView.postDelayed(new Runnable() {@Overridepublic void run() {if (camera != null) {camera.autoFocus(MainActivity.this);}}}, 2000);}private void initListener() {c_move_to_left.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {cx = drawView.getCx() - 5;drawView.setCx(cx);drawView.invalidate();}});c_move_to_right.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {cx = drawView.getCx() + 5;drawView.setCx(cx);drawView.invalidate();}});t_move_to_left.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {tx = drawView.getTx() - 5;drawView.setTx(tx);drawView.invalidate();}});t_move_to_right.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {tx = drawView.getTx() + 5;drawView.setTx(tx);drawView.invalidate();}});move_to_top.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {cy = drawView.getCy() - 5;ty = drawView.getTy() - 5;drawView.setCy(cy);drawView.setTy(ty);drawView.invalidate();}});move_to_bottom.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {cy = drawView.getCy() + 5;ty = drawView.getTy() + 5;drawView.setCy(cy);drawView.setTy(ty);drawView.invalidate();}});retake_picture.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(MainActivity.this,MainActivity.class);startActivity(intent);finish();}});commit.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Log.e("=====>>>>", "" + drawView.getCx());Log.e("=====>>>>", "" + drawView.getCy());Log.e("=====>>>>", "" + drawView.getTx());Log.e("=====>>>>", "" + drawView.getTy());Log.e("=====>>>>", "" + drawView.getHeight());Log.e("=====>>>>", "" + drawView.getWidth());Log.e("=====>>>>", "" + ((double) drawView.getCx() / a));Log.e("=====>>>>", "" + ((double) drawView.getCy() / a));}});}/*** 拍照状态发生改变*/@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}/*** 开始拍照时调用该方法**/@Overridepublic void surfaceCreated(SurfaceHolder holder) {// TODO Auto-generated method stubtry {Log.e("====>>>>", "surfaceCreated开始");// 打开摄像头camera = Camera.open();// 设置用于显示拍照影像的SurfaceHolder对象camera.setPreviewDisplay(holder);updateCameraParameters();// 开始预览camera.startPreview();Log.e("====>>>>", "surfaceCreated结束");} catch (Exception e) {e.printStackTrace();}}private void updateCameraParameters() {if (camera != null) {Camera.Parameters p = camera.getParameters();long time = new Date().getTime();p.setGpsTimestamp(time);Camera.Size previewSize = findBestPreviewSize(p);p.setPreviewSize(previewSize.width, previewSize.height);p.setPictureSize(previewSize.width, previewSize.height);if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {camera.setDisplayOrientation(90);p.setRotation(90);}camera.setParameters(p);}}/*** 找到最合适的显示分辨率 (防止预览图像变形)* * @param parameters* @return*/private Camera.Size findBestPreviewSize(Camera.Parameters parameters) {// 系统支持的所有预览分辨率String previewSizeValueString = null;previewSizeValueString = parameters.get("preview-size-values");if (previewSizeValueString == null) {previewSizeValueString = parameters.get("preview-size-value");}if (previewSizeValueString == null) { // 有些手机例如m9获取不到支持的预览大小 就直接返回屏幕大小DisplayMetrics metrics = getResources().getDisplayMetrics();return camera.new Size(metrics.widthPixels, metrics.heightPixels);}float bestX = 0;float bestY = 0;float tmpRadio = 0;float viewRadio = 0;if (surfaceView.getWidth() != 0 && surfaceView.getHeight() != 0) {viewRadio = Math.min((float) surfaceView.getWidth(),(float) surfaceView.getHeight())/ Math.max((float) surfaceView.getWidth(),(float) surfaceView.getHeight());}String[] COMMA_PATTERN = previewSizeValueString.split(",");for (String prewsizeString : COMMA_PATTERN) {prewsizeString = prewsizeString.trim();int dimPosition = prewsizeString.indexOf('x');if (dimPosition == -1) {continue;}float newX = 0;float newY = 0;try {newX = Float.parseFloat(prewsizeString.substring(0, dimPosition));newY = Float.parseFloat(prewsizeString.substring(dimPosition + 1));} catch (NumberFormatException e) {continue;}float radio = Math.min(newX, newY) / Math.max(newX, newY);if (tmpRadio == 0) {tmpRadio = radio;bestX = newX;bestY = newY;} else if (tmpRadio != 0&& (Math.abs(radio - viewRadio)) < (Math.abs(tmpRadio- viewRadio))) {tmpRadio = radio;bestX = newX;bestY = newY;}}if (bestX > 0 && bestY > 0) {// System.out.println("CustomCameraView previewSizeValueString bestX = "// +// bestX + ", bestY = " + bestY);return camera.new Size((int) bestX, (int) bestY);}return null;}/*** 停止拍照时调用该方法**/@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {Log.e("====>>>>", "surfaceDestroyed开始");// TODO Auto-generated method stubif (camera != null) {// 释放照相机camera.setPreviewCallback(null);camera.release();camera = null;}Log.e("====>>>>", "surfaceDestroyed结束");}/*** 自动对焦**/@Overridepublic void onAutoFocus(boolean success, Camera camera) {Log.e("====>>>>", "onAutoFocus开始");// TODO Auto-generated method stubcamera.takePicture(null, null, MainActivity.this);Log.e("====>>>>", "onAutoFocus结束");}/*** 拍照完成时调用**/@SuppressLint("WrongCall")@Overridepublic void onPictureTaken(byte[] data, Camera camera) {Log.e("====>>>>", "onPictureTaken开始");// TODO Auto-generated method stub// drawView.setCx(cx);// drawView.setCy(cy);// drawView.onDraw(new Canvas());try {Bundle bundle = new Bundle();bundle.putByteArray("bytes", data); // 将图片字节数据保存在bundle当中,实现数据交换saveToSDCard(data); // 保存图片到sd卡中Toast.makeText(getApplicationContext(), "成功", Toast.LENGTH_SHORT).show();// camera.startPreview(); // 拍完照后,重新开始预览Log.e("====>>>>", "onPictureTaken结束");} catch (Exception e) {e.printStackTrace();}}/*** 将拍下来的照片存放在SD卡中* * @param data* @throws IOException*/public void saveToSDCard(byte[] data) throws IOException {Date date = new Date();SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); // 格式化时间String filename = format.format(date) + ".png";Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);File jpgFile = Utils.createFile(Environment.getExternalStorageDirectory() + "/readingmeter/",filename);Utils.savaBimapToFile(bitmap, jpgFile);// Intent intent = new Intent();// intent.putExtra(RESULT_PIC_PATH,jpgFile.getAbsolutePath());// setResult(RESULT_OK, intent);String picPath = jpgFile.getAbsolutePath();Bitmap bitmapr = Utils.convertToBitmap(picPath, 640, 480);Bitmap cmpcut = ImageCut.cut(bitmapr, 155, 90, 480, 300);String filename1 = format.format(date) + "_640*480" + ".png";File jpgFile1 = Utils.createFile(Environment.getExternalStorageDirectory() + "/readingmeter/",filename1);String filename2 = format.format(date) + "_400*300" + ".png";File jpgFile2 = Utils.createFile(Environment.getExternalStorageDirectory() + "/readingmeter/",filename2);Utils.savaBimapToFile(bitmapr, jpgFile1);Utils.savaBimapToFile(cmpcut, jpgFile2);if (camera != null) {// 释放照相机camera.setPreviewCallback(null);camera.release();camera = null;Log.e("====>>>>", "camera != null");}// 显示切割后的图片resultView.setVisibility(View.VISIBLE);drawView.setImageBitmap(cmpcut);resultView.setBackgroundColor(Color.BLACK);Log.e("====>>>>", "显示切割后的图片");}
}

布局:


在确定按钮的OnClick事件,会打印出选择框左上角的位置。

这里面还有一个变化,就是ImageView是fill_parent还是wrap_content对坐标是有影响的,不同的方式坐标原点是不同的。另外稍加修改可以得到相对于屏幕左上角的位置。


完整DEMO下载:






本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部