目前日期文章:201410 (6)

瀏覽方式: 標題列表 簡短摘要

根據上一章節,這次加入 preview 處理,把 preview 存入 SDcard。

  • preview 處理要先 implements Camera.PreviewCallback
  • 然後再 Camera.setPreviewCallback(this)
  • 這樣每次 camera preview 時都會呼叫 onPreviewFrame()
  • Android 提供 YuvImage class 處理 preview 的 raw data
  • 可以直接使用 YuvImage.compressToJpeg() 存成 JPEG
  • 雖然預覽有轉 90 度,但是 preview raw data 卻沒有,網上找了一個 rotateYUV420Degree90() 幫助轉換角度。
  • preview 轉 90 度後要注意 width height 也要互換喔,長變寬,寬變長,為此我浪費了半天的時間找原因。
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.FrameLayout;

public class CameraTestActivity extends Activity implements SurfaceHolder.Callback, Camera.PreviewCallback {

    private SurfaceView mSurfaceview = null;
    private SurfaceHolder mSurfaceHolder = null;
    private Camera mCamera = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FrameLayout fl = new FrameLayout(this);
        setContentView(fl);

        mSurfaceview = new SurfaceView(this);
        mSurfaceHolder = mSurfaceview.getHolder();
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mSurfaceHolder.addCallback(this);
        fl.addView(mSurfaceview);
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        try {
            mCamera = Camera.open();
            mCamera.setDisplayOrientation(90);
            mCamera.setPreviewDisplay(mSurfaceHolder);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        // set auto focus mode
        Camera.Parameters parameters = mCamera.getParameters();
        List allFocus = parameters.getSupportedFocusModes();
        if(allFocus.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)){
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        }
        else if(allFocus.contains(Camera.Parameters.FLASH_MODE_AUTO)){
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        }
        mCamera.setParameters(parameters);
        mCamera.setPreviewCallback(this);
        mCamera.startPreview();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        mCamera.setPreviewCallback(null);
        mCamera.stopPreview();
        mCamera.release();
    }
@Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        String sFileName = "IMG_"
                + new SimpleDateFormat("yyyyMMdd_HHmmss")
                    .format(new Date())
                    .toString() + ".jpg";
        File root = Environment.getExternalStorageDirectory();
        String dir = "/Camera/";
        File CameraDir = new File(root, dir);
        if (!CameraDir.exists()) CameraDir.mkdirs();
        File jpgFile = new File(root, dir + sFileName);
        if (!jpgFile.exists()) {
            try {
                Camera.Parameters parameters = camera.getParameters();
                Size size = parameters.getPreviewSize();
                YuvImage image = new YuvImage(
                        rotateYUV420Degree90(data, size.width, size.height),
                        parameters.getPreviewFormat(), size.height, size.width, null);
                FileOutputStream filecon = new FileOutputStream(jpgFile);
                image.compressToJpeg(
                        new Rect(0, 0, image.getWidth(), image.getHeight()),
                        90, filecon);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight) {
        byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
        // Rotate the Y luma
        int i = 0;
        for (int x = 0; x < imageWidth; x++) {
            for (int y = imageHeight - 1; y >= 0; y--) {
                yuv[i] = data[y * imageWidth + x];
                i++;
            }
        }
        // Rotate the U and V color components
        i = imageWidth * imageHeight * 3 / 2 - 1;
        for (int x = imageWidth - 1; x > 0; x = x - 2) {
            for (int y = 0; y < imageHeight / 2; y++) {
                yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x];
                i--;
                yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + (x - 1)];
                i--;
            }
        }
        return yuv;
    }
}

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()


台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()


台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

Camera Focus mode 必須透過 setParameters() 設定,自動對焦則有三種模式,FOCUS_MODE_CONTINUOUS_PICTURE,FOCUS_MODE_CONTINUOUS_VIDEO,FOCUS_MODE_AUTO。

  • FOCUS_MODE_CONTINUOUS_PICTURE (API level 14)

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

在手機開啟 Camera 其實很簡單,就類似撥放影片一樣,把 Camera 擷取的影像輸出到 SurfaceView 就可以了。

AndroidManifest.xml

在 AndroidManifest.xml 一定要加入 android.permission.CAMERA,不然程式一開啟就會閃退,因為 APP 沒有 CAMERA 的權限。

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()

camera source code resource

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()