Android Camera 系列(二)控制Camera
Camera系列文章首發於 ,歡迎關注。
概述
Camera 可能是接下來個人想深入學習的課題,準備新起一個系列,從個人的角度總結闡述自己對於 Android Camera 的研究過程,希望也能夠對其他想學習 Camera 的同學一些幫助。
本小節內容為 Android Camera 官方文件 的精要翻譯,原文請參考:
一、開啟相機物件
獲取Camera
物件的例項是自定義相機的第一步。 作為Android的 自定義相機應用,更推薦是啟動一個單獨的執行緒並在onCreate()
生命週期的回撥開啟Camera
。 開啟攝像機的操作延遲到onResume()
方法中處理是一個不錯的注意,因為Camera
的初始化可能需要一段時間,而在UI執行緒這樣做則有可能讓應用變得卡頓。
如果攝像頭已被其他應用程式使用,則呼叫Camera.open()
會丟擲異常,因此我們將其包裝在try{}
中。
private fun safeCameraOpen(id: Int): Boolean {
return try {
releaseCameraAndPreview()
mCamera = Camera.open(id)
true
} catch (e: Exception) {
Log.e(getString(R.string.app_name), "failed to open Camera")
e.printStackTrace()
false
}
}
private fun releaseCameraAndPreview() {
mPreview?.setCamera(null)
mCamera?.also { camera ->
camera.release()
mCamera = null
}
}
二、建立相機預覽
預覽類
要開始顯示相機的預覽,您需要預覽類。 預覽需要實現android.view.SurfaceHolder.Callback
介面,該介面用於將影像資料從相機硬體傳遞到應用程式。
class Preview(
context: Context,
val mSurfaceView: SurfaceView = SurfaceView(context)
) : ViewGroup(context), SurfaceHolder.Callback {
var mHolder: SurfaceHolder = mSurfaceView.holder.apply {
addCallback(this@Preview)
setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)
}
...
}
必須先將預覽類傳遞給Camera
物件,然後才能啟動實時影像預覽,如下一節所示。
配置並開始預覽
Camera
的配置和預覽等相關操作都需要嚴格地控制順序,Camera
物件首當其衝, 在下面的程式碼片段中,Camera
的初始化過程被封裝,以便每當使用者做某事來更改Camera
都會呼叫setCamera()
方法,即呼叫Camera.startPreview()
。 還必須在預覽類的surfaceChanged()
回撥方法中重新啟動預覽。
fun setCamera(camera: Camera?) {
if (mCamera == camera) {
return
}
stopPreviewAndFreeCamera()
mCamera = camera
mCamera?.apply {
mSupportedPreviewSizes = parameters.supportedPreviewSizes
requestLayout()
try {
setPreviewDisplay(mHolder)
} catch (e: IOException) {
e.printStackTrace()
}
// Important: Call startPreview() to start updating the preview
// surface. Preview must be started before you can take a picture.
startPreview()
}
}
三、修改Camera的配置
相機設定會改變相機拍攝照片的方式,從縮放級別到曝光補償。 下述程式碼示例僅展示瞭如何更改預覽大小:
override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) {
mCamera?.apply {
// Now that the size is known, set up the camera parameters and begin
// the preview.
parameters?.also { params ->
params.setPreviewSize(mPreviewSize.width, mPreviewSize.height)
requestLayout()
parameters = params
}
// Important: Call startPreview() to start updating the preview surface.
// Preview must be started before you can take a picture.
startPreview()
}
}
四、設定預覽方向
大多數相機應用程式將顯示器鎖定為橫向模式,因為這是相機感測器的物理方向。 此設定不會阻止您拍攝縱向模式照片,因為裝置的方向記錄在EXIF Header中。 方法允許您更改預覽的顯示方式,而不會影響圖片的記錄方式。
// kotlin版本
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
fun setCameraDisplayOrientation(activity: Activity,
cameraId: Int = 0,
camera: Camera) {
val info = Camera.CameraInfo()
Camera.getCameraInfo(cameraId, info)
val rotation = activity.windowManager.defaultDisplay.rotation
var degrees = 0
when (rotation) {
Surface.ROTATION_0 -> degrees = 0
Surface.ROTATION_90 -> degrees = 90
Surface.ROTATION_180 -> degrees = 180
Surface.ROTATION_270 -> degrees = 270
}
var result: Int
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360
result = (360 - result) % 360 // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360
}
camera.setDisplayOrientation(result)
}
五、拍照
預覽開始展示後,可以使用Camera.takePicture()
方法拍攝照片。 您可以建立Camera.PictureCallback
和Camera.ShutterCallback
物件,並將它們傳遞給Camera.takePicture()
。
如果要連續抓取影像,可以建立一個實現onPreviewFrame()
的Camera.PreviewCallback
。 對於介於兩者之間的內容,您可以僅捕獲選定的預覽幀,或設定延遲操作以呼叫takePicture()
。
六、重新啟動預覽
拍攝照片後,必須重新開始預覽,然後使用者才能拍攝另一張照片。 下述程式碼展示瞭如何透過過載快門按鈕完成重啟:
fun onClick(v: View) {
mPreviewState = if (mPreviewState == K_STATE_FROZEN) {
mCamera?.startPreview()
K_STATE_PREVIEW
} else {
mCamera?.takePicture(null, rawCallback, null)
K_STATE_BUSY
}
shutterBtnConfig()
}
七、停止預覽並釋放相機
當Camera
功能使用完畢後,釋放對應的資源保證相機能被其它應用所再次使用,至於釋放時機,在預覽View的surfaceDestroyed()
處理是個不錯的選擇。
override fun surfaceDestroyed(holder: SurfaceHolder) {
// Surface will be destroyed when we return, so stop the preview.
// Call stopPreview() to stop updating the preview surface.
mCamera?.stopPreview()
}
/**
* When this function returns, mCamera will be null.
*/
private fun stopPreviewAndFreeCamera() {
mCamera?.apply {
// Call stopPreview() to stop updating the preview surface.
stopPreview()
// Important: Call release() to release the camera for use by other
// applications. Applications should release the camera immediately
// during onPause() and re-open() it during onResume()).
release()
mCamera = null
}
}
筆者注:官方文件關於《控制Camera》小節的課程文件,歸納得實在是無力吐槽,關於
Camera
各項引數的配置方式請參考筆者接下來的文章,本小節的作用請將其視為Camera相關知識的系統化瞭解。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2157/viewspace-2815304/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android:CameraAndroid
- Android Camera——拍照Android
- Android Camera開發指南Android
- Android Camera 使用小結Android
- camera基礎知識二
- 微軟為Nokia Camera更名為Lumia Camera微軟
- Android 建立自己的Camera AppAndroidAPP
- Android Camera API 使用指南AndroidAPI
- 基於Android5.0的Camera Framework原始碼分析 (二)AndroidFramework原始碼
- Android Camera瞭解一下Android
- Android的Camera架構介紹Android架構
- Camera開發系列之二 相機資料回撥處理
- Android camera2實現預覽Android
- Camera EEPROM bringup
- Camera Actuator bringup
- Android Studio 呼叫Camera實現拍照功能Android
- Android平臺Camera開發實踐指南Android
- Camera 360使用之坑
- Camera Sensor介面配置
- Camera subdev註冊流程dev
- Camera基礎知識
- Android多媒體之Camera的相關操作Android
- Android Camera 程式設計從入門到精通Android程式設計
- 【Camera專題】Qcom-你應該掌握的Camera基礎一
- 【Camera專題】Qcom-你應該掌握的Camera除錯技巧一除錯
- 【Camera專題】你應該瞭解的Camera HW-硬體知識
- 【Camera專題】Qcom-Camera驅動框架淺析(Hal層->Driver層)框架
- Android使用Camera2獲取預覽資料Android
- Camera2 OpenCamera流程
- Camera基礎知識四
- Camera Sensor編譯方法編譯
- 【Camera專題】你應該熟悉的Camera驅動框架一(Hal層->kernel層)框架
- 尼康相機控制軟體:Nikon Camera Control Pro 2 for macMac
- Game檢視中實現類Scene中Camera的控制(自身中心)GAM
- Android音視訊(六) 使用OpenGL ES 3.0預覽CameraAndroid
- 基於Android5.0的Camera Framework原始碼分析 (三)AndroidFramework原始碼
- Android多媒體之Camera2的相關操作Android
- 基於Android5.0的Camera Framework原始碼分析 (一)AndroidFramework原始碼