android 自定义相机拍照的两种方式

第一种方式,通过按拍照键实现PictureCallback接口的方式来拍照。这种方式是非常普遍的,网上也存在很多Demo。当遇到红米手机时,照片的尺寸变成了176x144,很小很模糊,而天语的尺寸则是640x480,三星的图片尺寸是1920x1080。为甚么唯独红米的照片尺寸是最小的尺寸?于是在设置Camrea.Paramter参数时,对预览尺寸和照片尺寸进行设置,最终结果没有什么变化。难道是传递的设置这两个属性的参数值,手机不支持。我把天语,三星和红米手机所支持的尺寸全部打印出来,选取了三者都支持的尺寸,一番测试后,仍然没有效果。网上也有人说,有些手机不支持设置设两个属性。但问题总要解决吧,我不知道红米为什么会出现这样的情况,怎么解决呢?那么只有才去其他方式进行拍照了。也就是第二种方式。‘
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;

import com.lovo.bean.PictureBean;
import com.lovo.police.R;
import com.lovo.ui.widget.CameraGallery;
import com.lovo.ui.widget.PictureImageView;
import com.lovo.util.ImageUtils;

/**
 * 拍照的界面
 *
 */
public class CameraActivity extends Activity implements PictureCallback,Callback,OnClickListener {
	private SurfaceView surfaceView;
	private SurfaceHolder surfaceHolder;
	private Camera camera;
	private int width;
	private int height;
	private boolean isPreview;
	private CameraGallery cameraGallery;
	private ImageView takePictureImageView;
	private Button okBtn;
	private Button cancelBtn;
	private Display display;
	private List pictureBeanList;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.camera_main);
		ImageUtils.loadImages(this);
		surfaceView = (SurfaceView) findViewById(R.id.camera_main_sv);
		takePictureImageView = (ImageView) findViewById(R.id.camera_main_iv_takepic);
		takePictureImageView.setOnClickListener(this);
		
		okBtn = (Button) findViewById(R.id.camera_main_btn_ok);
		cancelBtn = (Button) findViewById(R.id.camera_main_btn_cancel);
		okBtn.setOnClickListener(this);
		cancelBtn.setOnClickListener(this);

		// 获取屏幕可显示大小
		WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
		display = wm.getDefaultDisplay();
		
		surfaceHolder = surfaceView.getHolder();
		surfaceHolder.addCallback(this);
		// 设置该SurfaceView自己不缓冲数据
		surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		
		cameraGallery = (CameraGallery) findViewById(R.id.cameraPictureGallery1);
		pictureBeanList = (List) getIntent().getSerializableExtra("picList");
		for(int i = 0;i < pictureBeanList.size();i++){
			cameraGallery.addImage(pictureBeanList.get(i));
		}
		cameraGallery.showImage();
		cameraGallery.setGalleryOffset();
	}
	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		if (camera != null) {
			camera.stopPreview();
			Parameters parameters = camera.getParameters();
			resetCameraSize(parameters);
			camera.startPreview();
			// 自动对焦
			camera.autoFocus(null);
		}
		cameraGallery.setGalleryOffset();
	}
	public void initCamera(){
 
		if (camera != null && !isPreview) {
			try {
				Camera.Parameters parameters = camera.getParameters();
				//设置闪光灯为自动
				parameters.setFlashMode(Parameters.FLASH_MODE_AUTO);
				camera.setParameters(parameters);
				resetCameraSize(parameters);
				 
				// 设置每秒显示4帧
//				parameters.setPreviewFrameRate(4);
				// 设置图片格式
				parameters.setPictureFormat(PixelFormat.JPEG);
				// 设置JPG照片的质量
				parameters.set("jpeg-quality", 80);
				
				// android2.3后不需要下面代码
				// camera.setParameters(parameters);
				// 通过SurfaceView显示取景画面
				camera.setPreviewDisplay(surfaceHolder);
				
				// 开始预览
				camera.startPreview();
				// 自动对焦
				camera.autoFocus(null);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			isPreview = true;
		}
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		if (camera != null) {
			if (isPreview) {
				camera.stopPreview();
				isPreview = false;
			}
		}
	}
	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		
		if (camera != null) {
			if (!isPreview) {
				camera.startPreview();
				// 自动对焦
				camera.autoFocus(null);
				isPreview = true;
			}
		}
	}
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		initCamera();
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		if (!isPreview) {
			// 打开摄像头
			camera = Camera.open();
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		if (camera != null) {
			if (isPreview) {
				camera.stopPreview();
			}
			camera.release();
			camera = null;
		}
	}

	@Override
	public void onClick(View v) {
		if(v == takePictureImageView){
			//拍照
			camera.takePicture(null, null, this);
		}
		if(v == okBtn){
			//点击确定后将拍好的照片返回给录入界面
			ArrayList picList = (ArrayList) cameraGallery.getPicList();
			ArrayList picBeanList = new ArrayList();
			for (int i = 0; i < picList.size(); i++) {
				picBeanList.add(picList.get(i).getPictureBean());
			}
			Intent intent = new Intent();
			Bundle bundle = new Bundle();
			bundle.putSerializable("picList", picBeanList);
			intent.putExtras(bundle);
			setResult(0, intent);
			finish();
		}
		if(v == cancelBtn){
			setResult(1);
			finish();
		}
	}

	/**
	 * 开始拍照
	 */
	@Override
	public void onPictureTaken(byte[] data, Camera camera) {
		//保存照片
		ImageUtils.isFromCaream=true;
		PictureBean pb = ImageUtils.savePicture(this, data,true);
		//将照片设置给Gallery
		cameraGallery.addImage(pb);
		if (camera != null) {
			camera.stopPreview();
			camera.startPreview();
			// 自动对焦
			camera.autoFocus(null);
			isPreview = true;
		}
	}
	/**
	 * 旋转相机和设置预览大小
	 * @param parameters
	 */
	public void resetCameraSize(Parameters parameters){
		if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
			// 如果是竖屏
			camera.setDisplayOrientation(90);
		} else {
			camera.setDisplayOrientation(0);
		}
		width = display.getWidth();
		height = display.getHeight();

		// 设置预览的大小
		parameters.setPreviewSize(width, height);
		// 设置照片大小
		parameters.setPictureSize(width, height);
	}
//	@Override
//	protected void onDestroy() {
//		super.onDestroy();
//		ImageUtils.clearImageFile(pictureBeanList);
//	}
}

第二种方式,通过实现Camera.PreviewCallback接口,重写public void onPreviewFrame(byte[] data, Camera camera) { }方法。当相机正在预览的时候,按下拍照按钮,取出预览那一张图像,相当于截取预览区域的图像。注意这里面的byte[] data不能直接转换成Bitmap,否则会出现空指针异常,而且图片的大小事0B。只有通过android提供的YuvImage类来压缩成图片。我这里进行了把照片宽高按照4:3的比例来计算。当然,这里获得的Size对象,各个手机的宽高都不一致,但是他们取出来的照片尺寸都很大。符合项目要求。

@Override

    public void onPreviewFrame(byte[] data, Camera camera) {
        mByte = data;
    }

private void saveBitmap(){
        try {
            Camera.Parameters parameters = mCamera.getParameters();
            Size size = parameters.getPreviewSize();
            YuvImage image = new YuvImage(mByte, parameters.getPreviewFormat(),
                    size.width, size.height, null);
            File file = new File(Util.PHOTO_TEMP);
            FileOutputStream filecon = new FileOutputStream(file);
            //按4:3来缩放图片
            int width = image.getWidth();
            int height = image.getHeight();
            int iWidth;
            int iHeigth;
            iHeigth = (width*3)/4;
            if(iHeigth>=height){
                iHeigth = height;
                iWidth = (height*4)/3;
            }else{
                iWidth = width;
            }
            image.compressToJpeg(
                    new Rect(0, 0, iWidth, iHeigth), 100,
                    filecon);
        } catch (Exception e) {

        }
    }


 
  

你可能感兴趣的:(android)