Android開發(fā)之Camera+surefaceView簡單使用

最近公司新項(xiàng)目需要增加一個(gè)臉證功能,說白了就是需要在SurefaceView上顯示Camera預(yù)覽當(dāng)按鈕點(diǎn)擊后并把照片傳給服務(wù)器進(jìn)行匹配。

具體代碼如下:

DisplayMetrics metric = new DisplayMetrics();

getActivity().getWindowManager().getDefaultDisplay().getMetrics(metric);

int width = metric.widthPixels;? ? // 屏幕寬度(像素)

int height = metric.heightPixels;? // 屏幕高度(像素)


LayoutParams lp = surfaceView.getLayoutParams();

lp.height= height/2;

lp.width = width/2;

//在這里根據(jù)屏幕的寬高去設(shè)置surefaceView的寬高 不能自定義寬高 不然Camera拍出的照片會(huì)變形。

surfaceView.setLayoutParams(lp);

surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

surfaceView.getHolder().setFixedSize(200, 200);

surfaceView.getHolder().addCallback(new SurfaceViewCallback());





private final class SurfaceViewCallback implements SurfaceHolder.Callback {

/** * surfaceView 被創(chuàng)建成功后調(diào)用此方法 */

@SuppressWarnings("deprecation")

@Override

public void surfaceCreated(SurfaceHolder holder) {

Log.d(TAG, "surfaceCreated");

/* * 在SurfaceView創(chuàng)建好之后 打開攝像頭 注意是 android.hardware.Camera */

// 此處判斷是否有前置攝像頭

try {

boolean isFrontFacingCamera = CheckCamera.hasFrontFacingCamera();

if (isFrontFacingCamera) {camera = Camera.open(1);

}else {

ToastUtil.showToast(mContext, "您的手機(jī)沒有前置攝像頭...");}}

?catch (Exception e) {? ? ? ? ?

?? e.printStackTrace();? ? ? ? ?

?? ToastUtil.showToast(mContext,"沒有拍照權(quán)限");? ? ?

?? }/* * This method must be called before startPreview(). otherwise * surfaceview沒有圖像 */

try {

Camera.Parameters parameters = camera.getParameters();

??Listrange = parameters.getSupportedPreviewFpsRange(); Log.i("msg", "range:"+range.size()); for(int j=0;j1){

parameters.setPreviewFpsRange(range.get(range.size()-1)[0], range.get(range.size()-1)[1]);

}

// ? ? ? ? ? ? parameters.setPreviewFrameRate(10);

注意這句話在Android 華為Mate8 華為P9手機(jī)上并不適用,因?yàn)槊棵氩东@多少幀是有硬件決定 所以這句話可以刪掉(當(dāng)初就是沒刪除這句話 折騰了好久)

parameters.setPictureFormat(PixelFormat.JPEG); //? 設(shè)置照片的輸出格式:jpg

parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP); // picture,默認(rèn)為NV21

// //橫豎屏 切換 90°旋轉(zhuǎn)

if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {

parameters.set(ORIENTATION, PORTRAIT);

camera.setDisplayOrientation(90);// useful above 2.2

parameters.setRotation(90);

} else {

parameters.set(ORIENTATION, LANDSCAPE);

camera.setDisplayOrientation(0);// useful above 2.2

parameters.setRotation(0);

}

camera.setParameters(parameters);

camera.setPreviewDisplay(holder);

} catch (Exception e) {

e.printStackTrace();

Log.i("msg", "設(shè)置錯(cuò)誤 ............");

}

camera.startPreview();

preview = true;

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width,

int height) {

}

/**

* SurfaceView 被銷毀時(shí)釋放掉 攝像頭

*/

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

if (camera != null) {

/* 若攝像頭正在工作,先停止它 */

if (preview) {

camera.stopPreview();

preview = false;

}

// 如果注冊了此回調(diào),在release之前調(diào)用,否則release之后還回調(diào),crash

camera.setPreviewCallback(null);

camera.release();

}

}

}




/**

* 處理照片被拍攝之后的事件

*/

private final Camera.PictureCallback jpeg = new Camera.PictureCallback() {

@Override

public void onPictureTaken(byte[] data, Camera camera) {

Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

String manuf=android.os.Build.MANUFACTURER; // 手機(jī)型號

String model = android.os.Build.MODEL;

LogUtils.e("廠商", manuf);

LogUtils.e("型號", model);

Bitmap bm = null;

if (manuf.equals("samsung")||manuf.equals("LGE")) {

//目前根據(jù)手機(jī)前置攝像頭打開后的效果 暫時(shí)只發(fā)現(xiàn) 三星和LGE手機(jī)拍完照傳給服務(wù)器的是旋轉(zhuǎn)了90度的照片

bm = rotateBitmap(bitmap, 270);

}else {

bm = rotateBitmap(bitmap, 180);

}

ByteArrayOutputStream output = new ByteArrayOutputStream();// 初始化一個(gè)流對象

//這里對照片進(jìn)行壓縮,由于照片像素很高 所以必須壓縮

Bitmap bm_result = BitmapUtil.ratio(bm,200,200);

bm_result.compress(Bitmap.CompressFormat.JPEG, 100, output);

// bm.recycle();// 自由選擇是否進(jìn)行回收

byte[] result = output.toByteArray();// 轉(zhuǎn)換成功了

camera.stopPreview();

final String imgString = Base64.encodeToString(result, Base64.DEFAULT);

post(imgString);

}

};

//旋轉(zhuǎn)代碼

private Bitmap rotateBitmap(Bitmap src, int degrees) {

Matrix matrix = new Matrix();

matrix.reset();

matrix.setRotate(degrees);

Bitmap dstBitmap = Bitmap.createBitmap(src, 0, 0, src.getWidth(),

src.getHeight(), matrix, true);

src.recycle();

return dstBitmap;

}



拍照的話 在點(diǎn)擊事件里面調(diào)用 ? camera.takePicture(null, null, jpeg);這句話就行。

在執(zhí)行完一次拍照后需要繼續(xù)預(yù)覽(打開)前置攝像頭需要

try {

camera.reconnect();

camera.startPreview();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

然后再重新調(diào)用camera.takePicture(null, null, jpeg) 就可以再次打開攝像頭

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容