Android Camera+SurfaceView實現自定義拍照

jopen 10年前發布 | 128K 次閱讀 Android開發 移動開發 SurfaceView

          對Activity強制橫屏,保證預覽方向正確。使用OrientationEventListener監聽設備方向,判斷豎拍時,旋轉照片后再保存,保證豎拍時預覽圖片和保存后的圖片方向一致。

      運行效果:

 Android Camera+SurfaceView實現自定義拍照


代碼:

TestCameraActivity.java
    package com.example.testcamera;

import java.io.ByteArrayOutputStream;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.util.List;  
import java.util.UUID;  

import android.annotation.SuppressLint;  
import android.app.Activity;  
import android.content.Context;  
import android.content.Intent;  
import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.graphics.Matrix;  
import android.hardware.Camera;  
import android.hardware.Camera.Parameters;  
import android.hardware.Camera.Size;  
import android.os.Build;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.OrientationEventListener;  
import android.view.SurfaceHolder;  
import android.view.SurfaceView;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  

public class TestCameraActivity extends Activity implements OnClickListener,  
        SurfaceHolder.Callback {  
    private static final String TAG = "TestCameraActivity";  
    public static final String KEY_FILENAME = "filename";  
    private Button mTakePhoto;  
    private SurfaceView mSurfaceView;  
    private Camera mCamera;  
    private String mFileName;  
    private OrientationEventListener mOrEventListener; // 設備方向監聽器  
    private Boolean mCurrentOrientation; // 當前設備方向 橫屏false,豎屏true  

    /* 圖像數據處理還未完成時的回調函數 */  
    private Camera.ShutterCallback mShutter = new Camera.ShutterCallback() {  
        @Override  
        public void onShutter() {  
            // 一般顯示進度條  
        }  
    };  

    /* 圖像數據處理完成后的回調函數 */  
    private Camera.PictureCallback mJpeg = new Camera.PictureCallback() {  

        @Override  
        public void onPictureTaken(byte[] data, Camera camera) {  
            // 保存圖片  
            mFileName = UUID.randomUUID().toString() + ".jpg";  
            Log.i(TAG, mFileName);  
            FileOutputStream out = null;  
            try {  
                out = openFileOutput(mFileName, Context.MODE_PRIVATE);  
                byte[] newData = null;  
                if (mCurrentOrientation) {  
                    // 豎屏時,旋轉圖片再保存  
                    Bitmap oldBitmap = BitmapFactory.decodeByteArray(data, 0,  
                            data.length);  
                    Matrix matrix = new Matrix();  
                    matrix.setRotate(90);  
                    Bitmap newBitmap = Bitmap.createBitmap(oldBitmap, 0, 0,  
                            oldBitmap.getWidth(), oldBitmap.getHeight(),  
                            matrix, true);  
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();  
                    newBitmap.compress(Bitmap.CompressFormat.JPEG, 85, baos);  
                    newData = baos.toByteArray();  
                    out.write(newData);  
                } else {  
                    out.write(data);  
                }  

            } catch (IOException e) {  
                e.printStackTrace();  
            } finally {  
                try {  
                    if (out != null)  
                        out.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
            Intent i = new Intent(TestCameraActivity.this, ShowPicture.class);  
            i.putExtra(KEY_FILENAME, mFileName);  
            startActivity(i);  
            finish();  
        }  
    };  

    @SuppressWarnings("deprecation")  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_test_camera);  
        mTakePhoto = (Button) findViewById(R.id.take_photo);  
        mTakePhoto.setOnClickListener(this); // 拍照按鈕監聽器  

        startOrientationChangeListener(); // 啟動設備方向監聽器  
        mSurfaceView = (SurfaceView) findViewById(R.id.my_surfaceView);  
        SurfaceHolder holder = mSurfaceView.getHolder();  
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
        holder.addCallback(this); // 回調接口  

    }  

    private final void startOrientationChangeListener() {  
        mOrEventListener = new OrientationEventListener(this) {  
            @Override  
            public void onOrientationChanged(int rotation) {  
                if (((rotation >= 0) && (rotation <= 45)) || (rotation >= 315)  
                        || ((rotation >= 135) && (rotation <= 225))) {// portrait  
                    mCurrentOrientation = true;  
                    Log.i(TAG, "豎屏");  
                } else if (((rotation > 45) && (rotation < 135))  
                        || ((rotation > 225) && (rotation < 315))) {// landscape  
                    mCurrentOrientation = false;  
                    Log.i(TAG, "橫屏");  
                }  
            }  
        };  
        mOrEventListener.enable();  
    }  

    @Override  
    public void onClick(View v) {  
        // 點擊拍照  
        switch (v.getId()) {  
        case R.id.take_photo:  
            mCamera.takePicture(mShutter, null, mJpeg);  
            break;  
        default:  
            break;  
        }  

    }  

    @Override  
    public void surfaceChanged(SurfaceHolder holder, int format, int width,  
            int height) {  
        // SurfaceView尺寸發生改變時(首次在屏幕上顯示同樣會調用此方法),初始化mCamera參數,啟動Camera預覽  

        Parameters parameters = mCamera.getParameters();// 獲取mCamera的參數對象  
        Size largestSize = getBestSupportedSize(parameters  
                .getSupportedPreviewSizes());  
        parameters.setPreviewSize(largestSize.width, largestSize.height);// 設置預覽圖片尺寸  
        largestSize = getBestSupportedSize(parameters  
                .getSupportedPictureSizes());// 設置捕捉圖片尺寸  
        parameters.setPictureSize(largestSize.width, largestSize.height);  
        mCamera.setParameters(parameters);  

        try {  
            mCamera.startPreview();  
        } catch (Exception e) {  
            if (mCamera != null) {  
                mCamera.release();  
                mCamera = null;  
            }  
        }  

    }  

    @Override  
    public void surfaceCreated(SurfaceHolder holder) {  
        // SurfaceView創建時,建立Camera和SurfaceView的聯系  
        if (mCamera != null) {  
            try {  
                mCamera.setPreviewDisplay(holder);  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  

    }  

    @Override  
    public void surfaceDestroyed(SurfaceHolder holder) {  
        // SurfaceView銷毀時,取消Camera預覽  
        if (mCamera != null) {  
            mCamera.stopPreview();  
        }  
    }  

    @SuppressLint("NewApi")  
    @Override  
    public void onResume() {  
        super.onResume();  
        // 開啟相機  
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {  
            mCamera = Camera.open(0);  
            // i=0 表示后置相機  
        } else  
            mCamera = Camera.open();  
    }  

    @Override  
    public void onPause() {  
        super.onPause();  
        // 釋放相機  
        if (mCamera != null) {  
            mCamera.release();  
            mCamera = null;  
        }  

    }  

    private Size getBestSupportedSize(List<Size> sizes) {  
        // 取能適用的最大的SIZE  
        Size largestSize = sizes.get(0);  
        int largestArea = sizes.get(0).height * sizes.get(0).width;  
        for (Size s : sizes) {  
            int area = s.width * s.height;  
            if (area > largestArea) {  
                largestArea = area;  
                largestSize = s;  
            }  
        }  
        return largestSize;  
    }  
}  </pre></span>ShowPicture.java<pre class="brush:java; toolbar: true; auto-links: false;">    package com.example.testcamera;  

import android.app.Activity;  
import android.graphics.Bitmap;  
import android.graphics.BitmapFactory;  
import android.graphics.drawable.BitmapDrawable;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.Display;  
import android.widget.ImageView;  

public class ShowPicture extends Activity {  

    private static final String TAG = "ShowPicture";  
    private ImageView mPicture;  

    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_show_picture);  

        mPicture = (ImageView) findViewById(R.id.picture);  
        String fileName = getIntent().getStringExtra(  
                TestCameraActivity.KEY_FILENAME);  
        // 圖片路徑  
        Log.i(TAG, fileName);  
        String path = getFileStreamPath(fileName).getAbsolutePath();  

        Display display = getWindowManager().getDefaultDisplay(); // 顯示屏尺寸  
        float destWidth = display.getWidth();  
        float destHeight = display.getHeight();  

        // 讀取本地圖片尺寸  
        BitmapFactory.Options options = new BitmapFactory.Options();  
        options.inJustDecodeBounds = true;  
        BitmapFactory.decodeFile(path, options);// 設置為true,options依然對應此圖片,但解碼器不會為此圖片分配內存  

        float srcWidth = options.outWidth;  
        float srcHeight = options.outHeight;  

        int inSampleSize = 1;  
        if (srcHeight > destHeight || srcWidth > destWidth) { // 當圖片長寬大于屏幕長寬時  
            if (srcWidth > srcHeight) {  
                inSampleSize = Math.round(srcHeight / destHeight);  
            } else {  
                inSampleSize = Math.round(srcWidth / destWidth);  
            }  
        }  
        options = new BitmapFactory.Options();  
        options.inSampleSize = inSampleSize;  

        Bitmap bitmap = BitmapFactory.decodeFile(path, options);  
        BitmapDrawable bDrawable = new BitmapDrawable(getResources(), bitmap);  
        mPicture.setImageDrawable(bDrawable);  
    }  

    @Override  
    public void onDestroy() {  
        if (!(mPicture.getDrawable() instanceof BitmapDrawable))  
            return;  
        // 釋放bitmap占用的空間  
        BitmapDrawable b = (BitmapDrawable) mPicture.getDrawable();  
        b.getBitmap().recycle();  
        mPicture.setImageDrawable(null);  
    }  

}  </pre>來自:http://blog.csdn.net/u012964281/article/details/41143169
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!