Android中的拍照camera和camera2
生活随笔
收集整理的這篇文章主要介紹了
Android中的拍照camera和camera2
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在android我們可以調用系統的相機來進行照相,當然也可以設計自己的照相頁面,通過surface進行預覽,通過camera api來進行拍照即可。
在Android 5.0之后google推薦使用的Camera2 Api,但是由于兼容問題我們大部分還在使用Camera Api。這里我們一起簡單介紹一下,僅僅是預覽拍照,至于細節的設置,比如圖像大小比例、對焦、圖像旋轉等就不一一細說了。
首先我們需要在布局中加入一個SurfaceView
Camera Api
var camera: Camera? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)//為surfaceholder添加監聽surface.holder.addCallback(object : SurfaceHolder.Callback{override fun surfaceChanged(p0: SurfaceHolder?, p1: Int, p2: Int, p3: Int) {}override fun surfaceDestroyed(p0: SurfaceHolder?) {}override fun surfaceCreated(p0: SurfaceHolder?) {//當surface創建完成初始化相機initCamera1()}})take.setOnClickListener {//拍照takePicture1()}}fun initCamera1(){//打開相機,開啟預覽camera = Camera.open()camera?.setPreviewDisplay(surface.holder)camera?.startPreview()}fun takePicture1(){//拍照,通過回調獲取圖片數據camera?.takePicture({},{bytes, camera ->if(bytes == null){return@takePicture}var b = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)imageView.setImageBitmap(b)},{bytes, camera ->if(bytes == null){return@takePicture}var b = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)imageView2.setImageBitmap(b)})}可以看到使用Camera比較簡單,打開相機開啟預覽,拍照在回調中處理即可。
Camera2 Api
Camera2的Api相比Camera要復雜很多
var mCameraDevice : CameraDevice? = nullvar mCameraCaptureSession : CameraCaptureSession? = nullvar childHandler : Handler? = null@SuppressLint("NewApi")var imageReader : ImageReader? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)//為surfaceholder添加監聽surface.holder.addCallback(object : SurfaceHolder.Callback{override fun surfaceChanged(p0: SurfaceHolder?, p1: Int, p2: Int, p3: Int) {}override fun surfaceDestroyed(p0: SurfaceHolder?) {}override fun surfaceCreated(p0: SurfaceHolder?) {//當surface創建完成初始化相機initCamera2()}})take.setOnClickListener {//拍照takePicture2()}}fun initCamera2(){if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//因為處理圖片比較耗時,所以這里新建一個線程的handler來處理var handlerThread = HandlerThread("camera")handlerThread.start()childHandler = Handler(handlerThread.looper)//創建一個ImageReader,后面會通過這個獲取拍照的圖片imageReader = ImageReader.newInstance(500, 500, ImageFormat.JPEG,2)//為ImageReader添加回調,這里使用我們新建的線程的handler處理圖片imageReader?.setOnImageAvailableListener(object : ImageReader.OnImageAvailableListener{override fun onImageAvailable(imageReader: ImageReader) {//得到圖片后,關閉相機,從ImageReader中獲取圖片數據mCameraDevice?.close()var image = imageReader.acquireNextImage()var buffer = image.planes[0].buffervar bytes = ByteArray(buffer.remaining())buffer.get(bytes)var bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)//由于這部分是在子線程中處理的,所以對ui操作要放到主線程中runOnUiThread {imageView.setImageBitmap(bitmap)}}}, childHandler)//通過CameraManager打開相機,注意這里的handler是主線程的。var cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManagercameraManager.openCamera(CameraCharacteristics.LENS_FACING_FRONT.toString(), object : CameraDevice.StateCallback() {override fun onOpened(cameraDevice: CameraDevice) {//相機打開后,得到CameraDevice并開啟預覽mCameraDevice = cameraDevicecamera2Preview()}override fun onDisconnected(p0: CameraDevice) {}override fun onError(p0: CameraDevice, p1: Int) {}}, Handler(Looper.getMainLooper()))}}fun camera2Preview(){if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {mCameraDevice?.let {//新建一個PRIVIEW的CaptureRequest,將surface添加進去var builder = it.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)builder.addTarget(surface.holder.surface)//通過CameraDevice新建一個CaptureSession事務,在回調中開啟預覽it.createCaptureSession(Arrays.asList(surface.holder.surface, imageReader?.surface), object : CameraCaptureSession.StateCallback() {override fun onConfigureFailed(p0: CameraCaptureSession) {}override fun onConfigured(cameraCaptureSession: CameraCaptureSession) {//獲得對應的CaptureSession事務,并設置預覽的request開始預覽mCameraCaptureSession = cameraCaptureSessionvar previewRequest = builder.build()mCameraCaptureSession?.setRepeatingRequest(previewRequest, null ,childHandler)}}, childHandler)}}}//拍照fun takePicture2(){if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {mCameraDevice?.let {//新建一個拍照請求,并添加之前創建的ImageReader的surfacevar builder = it.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)builder.addTarget(imageReader!!.surface)var previewRequest = builder.build()//通過預覽是獲取的CaptureSession事務,執行拍照請求,結果會通過之前設置的ImageReader的回調返回mCameraCaptureSession?.setRepeatingRequest(previewRequest, null ,childHandler)}}}使用Camera2 Api的流程基本與Camera一樣,但是代碼復雜很多,主要是需要通過事務CaptureSession來處理預覽及拍照,而且為了處理圖片還需要一個新建子線程,同時拍照結果也是通過ImageReader封裝起來的。
總結
以上是生活随笔為你收集整理的Android中的拍照camera和camera2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unity的Flutter——UIWid
- 下一篇: Android 12来了,支持更多设备,