Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android資訊 >> Android Camera+SurfaceView實現自定義拍照

Android Camera+SurfaceView實現自定義拍照

編輯:Android資訊

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

運行效果:

代碼:

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;
	}
}

ShowPicture.java

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);
	}

}

源碼下載

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved