2015/08/01

Android 相機預覽畫面加入矩形

在相機開啟預覽功能時希望能夠出現矩形
所以就自幹一個吧XD

RectF建構參數:
//left=開始x
   //top=開始y
   //right=結束x
   //bottom=結束y
   //以下方例子來說開始的位置在於(20,20) 結束地方在於(100-20,100-20)
   canvas.drawRect(20, 20, 100, 100, paint);
   //也就是說這個矩形長寬為80



XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <SurfaceView
        android:id="@+id/surfaceViewCamera"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/buttonTakePicture"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true" />

    <com.cyfang.npust.myclass.MyImageView
        android:id="@+id/myImageView"
        android:layout_width="fill_parent"
        android:layout_height="800px" />

    <Button
        android:id="@+id/buttonTakePicture"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:text="拍照" />

</RelativeLayout>

ImageView:
package com.cyfang.npust.myclass;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.ImageView;

public class MyImageView extends ImageView {

 /** 螢幕解析度 */
 private DisplayMetrics metrics = new DisplayMetrics();

 /** 矩形大小 */
 private RectF rectF;


 /** 畫筆 */
 private Paint paint = new Paint();

 {
  paint = new Paint();
  paint.setStyle(Paint.Style.STROKE);
  paint.setColor(Color.BLUE);
 };


 /** 自訂ImageView */
 public MyImageView(Context context, AttributeSet attrs) {
  super(context, attrs);
  // 取得螢幕解析度
  this.metrics = context.getResources().getDisplayMetrics();
  this.rectF = new RectF((int) (metrics.widthPixels / 2 - metrics.widthPixels / 4),
    (int) (metrics.heightPixels / 2 - metrics.heightPixels / 4),
    (int) (metrics.widthPixels / 2 + metrics.widthPixels / 4),
    (int) (metrics.heightPixels / 2 + metrics.heightPixels / 10));
 }

 //onDraw會持續渲染
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  //畫矩形
  canvas.drawRect(rectF, this.paint);
 }

}

Activity:
package com.cyfang.npust;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.List;

import com.cyfang.npust.myclass.MyImageView;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
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;

/** 相機選項 */
public class CameraActivity extends Activity implements SurfaceHolder.Callback {

 /** 相機 */
 private Camera camera;

 /** SurfaceView */
 private SurfaceView surfaceViewCamera;

 /** 處理影像執行序 */
 private SurfaceHolder surfaceHolderCamera;

 /** 拍照按鈕 */
 private Button buttonTakePicture;

 /** 自訂ImageView */
 private MyImageView imageview;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_camera);

  imageview = (MyImageView) findViewById(R.id.myImageView);

  buttonTakePicture = (Button) findViewById(R.id.buttonTakePicture);
  buttonTakePicture.setOnClickListener(clickListener);

  surfaceViewCamera = (SurfaceView) findViewById(R.id.surfaceViewCamera);
  surfaceViewCamera.setZOrderOnTop(false);
  surfaceHolderCamera = surfaceViewCamera.getHolder();
  surfaceHolderCamera.addCallback(this);
  surfaceHolderCamera.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

 }

 /** 拍照按鈕 */
 private Button.OnClickListener clickListener = new OnClickListener() {
  @Override
  public void onClick(View v) {
   if (camera != null)
    camera.takePicture(null, null, pictureCallBack);
  }
 };

 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
  // 停止相機預覽
  camera.stopPreview();

  // 釋放相機資源
  camera.release();
  camera = null;
 }

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
  // 開啟相機功能
  camera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
 }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  try {

   // 取得相機參數
   Parameters parameters = camera.getParameters();

   // 關閉閃光燈
   parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);

   // 預覽尺寸清單
   List<Size> previewList = parameters.getSupportedPreviewSizes();

   // 照片尺寸清單
   List<Size> pictureList = parameters.getSupportedPictureSizes();

   // 設定最佳照片尺寸
   parameters.setPictureSize(pictureList.get(0).width, pictureList.get(0).height);

   // 設定最佳預覽尺寸
   parameters.setPreviewSize(previewList.get(0).width, previewList.get(0).height);

   // 預覽角度
   camera.setDisplayOrientation(90);

   // 設定相機參數
   camera.setParameters(parameters);

   // 設定顯示的Holder
   camera.setPreviewDisplay(surfaceHolderCamera);

   // 開始顯示
   camera.startPreview();

  } catch (IOException e) {

  } catch (RuntimeException e) {
   // 照片尺寸太大會使程式出現Runtime Exception
   Log.e("", e.getMessage());
  }

 }

 private PictureCallback pictureCallBack = new PictureCallback() {
  @Override
  public void onPictureTaken(byte[] data, Camera camera) {
   try {

    // 設定檔案存放位置
    File file = new File(new Date().getTime() + ".jpg");
    FileOutputStream fileOutputStream = new FileOutputStream(file);

    // 進行解碼
    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

    // 圖片壓縮
    bitmap.compress(CompressFormat.JPEG, 85, fileOutputStream);

    // 寫入檔案
    fileOutputStream.flush();
    fileOutputStream.close();

    // 重新開啟預覽
    camera.startPreview();
   } catch (FileNotFoundException e) {
   } catch (IOException e) {
   }

  }
 };

}

執行結果: