OnePIC (Android App)/카메라
[Camera2] 전면 후면 카메라 전환
경걍
2023. 8. 9. 21:49
반응형
전체 흐름
다음 방식으로 카메라가 전환된다
1. 현재 사용 중인 카메라 Close
2. 사용할 카메라 설정 및 Open
binding.changeCameraBtn.setOnCheckedChangeListener { _, isChecked ->
// 원하는 카메라 설정
wantCameraDirection = if(isChecked) {
CameraCharacteristics.LENS_FACING_FRONT // 전면
} else {
CameraCharacteristics.LENS_FACING_BACK // 후면
}
// 기존 카메라 close
closeCamera()
// texture 사용 가능한지 확인
if (binding.texture.isAvailable) {
// 새로운 카메라 open
openCamera(binding.texture.width, binding.texture.height)
} else {
binding.texture.surfaceTextureListener = surfaceTextureListener
}
}
현재 사용 중인 카메라 Close
fun closeCamera() {
try {
cameraOpenCloseLock.acquire()
captureSession?.close()
captureSession = null
cameraDevice?.close()
cameraDevice = null
imageReader?.close()
imageReader = null
} catch (e: InterruptedException) {
throw RuntimeException("Interrupted while trying to lock camera closing.", e)
} finally {
cameraOpenCloseLock.release()
}
}
사용할 카메라 설정 및 Open
// texture 사용 가능한지 확인
if (binding.texture.isAvailable) {
// 카메라 열기
openCamera(binding.texture.width, binding.texture.height)
} else {
binding.texture.surfaceTextureListener = surfaceTextureListener
}
openCamera( ... ) 함수에 대해서 자세한 정보는 다음 포스팅에서 확인 바란다.
[Camera2] Camera2로 Preview 띄우기
Camera2 프리뷰띄우기 및 캡처 샘플 코드 - GitHub GitHub - googlearchive/android-Camera2Basic: Migrated: Migrated:. Contribute to googlearchive/android-Camera2Basic development by creating an account on GitHub. github.com Camera2 흐름도 - pre
kyumq.tistory.com
openCamera ( ... ) 함수에서 setUpCameraOutputs( ... ) 함수가 조금 변경된다.
/**
* 카메라 설정 및 카메라 관련 멤버 변수 초기화
*/
private fun setUpCameraOutputs(width: Int, height: Int) {
// 카메라 매니저 얻기 (사용가능한 카메라 장치들 얻어오기)
val manager = activity?.getSystemService(Context.CAMERA_SERVICE) as CameraManager
try {
// 카메라 중에 조건에 맞는 거 하나를 찾고 return (첫번째부터 확인 후, 조건이 맞지 않을 continue)
for (cameraId in manager.cameraIdList) {
// 카메라 정보 알아내기
val characteristics = manager.getCameraCharacteristics(cameraId)
// 렌즈 정보 알아낸 후, 원하는 카메라가 아닐 시 continue
val cameraDirection = characteristics.get(CameraCharacteristics.LENS_FACING)
if (cameraDirection != null && cameraDirection == wantCameraDirection
) {
continue
}
// 스트림 구성 맵이 null인 경우 continue =>
val map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP
) ?: continue
// 이미지 해상도 및 포맷 설정 -> 가장 높은(좋은) 해상도 선택
val largest = Collections.max(
Arrays.asList(*map.getOutputSizes(ImageFormat.JPEG)), CompareSizesByArea()
)
// 선택된 해상도로 ImageReader 설정 -> JPEG으로, width, height는 가장 크게
imageReader = ImageReader.newInstance(
largest.width, largest.height,
ImageFormat.JPEG, /*maxImages*/ 10
).apply {
setOnImageAvailableListener(onImageAvailableListener, backgroundHandler)
}
// 디바이스에 따른 센서 방향 고려해서 preview 크기 결정
val displayRotation = activity?.windowManager?.defaultDisplay?.rotation
sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)!!
val swappedDimensions = areDimensionsSwapped(displayRotation!!)
val displaySize = Point()
activity?.windowManager?.defaultDisplay?.getSize(displaySize)
val rotatedPreviewWidth = if (swappedDimensions) height else width
val rotatedPreviewHeight = if (swappedDimensions) width else height
var maxPreviewWidth = if (swappedDimensions) displaySize.y else displaySize.x
var maxPreviewHeight = if (swappedDimensions) displaySize.x else displaySize.y
if (maxPreviewWidth > MAX_PREVIEW_WIDTH) maxPreviewWidth = MAX_PREVIEW_WIDTH
if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) maxPreviewHeight = MAX_PREVIEW_HEIGHT
previewSize = chooseOptimalSize(
map.getOutputSizes(SurfaceTexture::class.java),
rotatedPreviewWidth, rotatedPreviewHeight,
maxPreviewWidth, maxPreviewHeight,
largest
)
// We fit the aspect ratio of TextureView to the size of preview we picked.
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
binding.texture.setAspectRatio(previewSize.width, previewSize.height)
} else {
binding.texture.setAspectRatio(previewSize.height, previewSize.width)
}
// Check if the flash is supported.
flashSupported =
characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE) == true
this.cameraId = cameraId
// 렌즈 LENS_INFO_MINIMUM_FOCUS_DISTANCE 값 알아오기 (최대값 = 변수 등록) : 최대 초점 거리
minimumFocusDistance = characteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE)!!
return
}
} catch (e: CameraAccessException) {
Log.e(TAG, e.toString())
} catch (e: NullPointerException) { }
}
위 코드에서 다음 부분이 가장 중요하다.
내가 원하는 카메라 방향이 아닐 경우에는 continue로 다음 카메라를 확인한다.
if (cameraDirection == null || cameraDirection != wantCameraDirection) {
continue
}
반응형