728x90
반응형
SMALL
package (본인 패키지)
import android.annotation.SuppressLint
import android.graphics.*
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.os.Bundle
import android.util.*
import android.util.Base64
import android.view.View
import androidx.camera.core.*
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner
import (본인패키지).BuildConfig
import (본인패키지).base.BaseActivity
import (본인패키지).base.BaseTAG
import (본인패키지).base.BaseYLOG
import (본인패키지).data.CameraSupportPictureData
import (본인패키지).databinding.ActivityCameraReBinding
import (본인패키지).di.DIManager
import java.io.*
import java.nio.ByteBuffer
import java.util.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import kotlin.collections.ArrayList
class CameraActivityRenew:BaseActivity() {
val TAG = "CameraActivityRe"
private lateinit var viewBinding: ActivityCameraReBinding
private lateinit var mCameraExecutor:ExecutorService
private var mImageCapture: ImageCapture? = null
var mSupportCameraPictureData = CameraSupportPictureData()
var mPreview:Preview? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding = ActivityCameraReBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
mPreview = Preview.Builder().build()
//현재 Device에서 target가능한 카메라 size list 구해서 가장 근접한 size로 셋팅
mSupportCameraPictureData = finalFixSize(getSupportScreenSize())
//카메라 open
startCamera()
//카메라 닫기 Button Listener
viewBinding.btnClose.setOnClickListener {
finish()
}
//촬영 Button Listener
viewBinding.buttonCapture.setOnClickListener {
Log.d(TAG, "mSupportCameraPictureData")
viewBinding.buttonCapture.isEnabled = false//촬영순간 Disable
captureCameraPreview()
}
//카메라 스레드 인스턴스 생성
mCameraExecutor = Executors.newSingleThreadExecutor()
}
override fun onBackPressed() {
super.onBackPressed()
finish()
}
@SuppressLint("UnsafeExperimentalUsageError", "RestrictedApi")
fun startCamera(){
try{
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener(Runnable {
//BackCamera create builder
val cameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build()
mPreview?.setSurfaceProvider(viewBinding.previewView.surfaceProvider)
//uses
mImageCapture = ImageCapture.Builder()
.setTargetResolution(Size(mSupportCameraPictureData.width, mSupportCameraPictureData.height))
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build()
val useCaseGroup = UseCaseGroup.Builder()
.addUseCase(mPreview!!)
.addUseCase(mImageCapture!!)
.build()
try{
val cameraProvider = cameraProviderFuture.get()
cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, useCaseGroup)
}catch (e:Exception){
BaseYLOG.showLog("e",BaseTAG.TAG_EXCEPTION_MSG,"CameratActivityRe()/startCamera/cameraProvider e : ","${e.message}")
}
}, ContextCompat.getMainExecutor(this))
}catch (e:Exception){
BaseYLOG.showLog("e",BaseTAG.TAG_EXCEPTION_MSG,"CameratActivityRe()/startCamera e : ","${e.message}")
}
}
//촬영하기
fun captureCameraPreview(){
val imageCapture = mImageCapture?:return
imageCapture.takePicture(mCameraExecutor, object : ImageCapture.OnImageCapturedCallback() {
override fun onCaptureSuccess(image: ImageProxy) {
try{
val bitmap: Bitmap = imageProxyToBitmap(image)
var rotateBitmap = bitmap.customRotate(getTheDegrees(image))
setPreviewImage()//Preview Image
val byteArr = bitmapCompressToByteArray(rotateBitmap)
//Crop captured Image
if(operatorToCropImage(byteArr)==null)return
var cropImageArr = operatorToCropImage(byteArr)
//Array of CropImage convert to Base64String
val final_result = byteArrayToBase64String(cropImageArr)
/*
if(BuildConfig.DEBUG){
writeTxTfile(final_result)
}
*/
MainWebviewActivity.compWebViewImageString = final_result
setResult(RESULT_OK)
finish()
}catch (e:Exception){
BaseYLOG.showLog("e",BaseTAG.TAG_EXCEPTION_MSG,"CameratActivityRe()/captureCameraPreview e : ","${e.message}")
}
super.onCaptureSuccess(image)
}
override fun onError(exception: ImageCaptureException) {
BaseYLOG.showLog("e",BaseTAG.TAG_EXCEPTION_MSG,"CameratActivityRe()/onError exception : ","${exception.message}")
super.onError(exception)
}
})
}
//(촬영된 이미지 형태)imageProxy -> Bitmap
private fun imageProxyToBitmap(image: ImageProxy):Bitmap{
val planProxy = image.planes[0]
val buffer:ByteBuffer = planProxy.buffer
val bytes = ByteArray(buffer.remaining())
buffer.get(bytes)
return BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
}
//Bitmap rotate
fun Bitmap.customRotate(degrees: Float) = Bitmap.createBitmap(this,0,0,width,height,Matrix().apply {
postRotate(degrees)
},true
)
//촬영후 미리보기 image
fun setPreviewImage(){
try{
runOnUiThread {
viewBinding.screenShotImage.visibility = View.VISIBLE
viewBinding.previewView.visibility = View.GONE
viewBinding.screenShotImage.setImageBitmap(viewBinding.previewView.bitmap)
}
}catch (e:Exception){
BaseYLOG.showLog("e",BaseTAG.TAG_EXCEPTION_MSG,"CameratActivityRe()/captureCameraPreview e : ","${e.message}")
}
}
//Device 기본 설정된 회전각에 맞춰 각변경
fun getTheDegrees(image:ImageProxy):Float{
var degrees = 0f
try{
val getDeviceDefaultRotationDegrees = image.imageInfo.rotationDegrees
when(getDeviceDefaultRotationDegrees){
90 ->{degrees = 90f}
180 ->{degrees = 180f}
270 ->{degrees = 270f}
}
}catch (e:Exception){
BaseYLOG.showLog("e",BaseTAG.TAG_EXCEPTION_MSG,"CameratActivityRe()/getDeviceDefaultRotationDegrees e : ","${e.message}")
}
return degrees
}
//byteArr -> 공백 문자 제거 -> Base64String
fun byteArrayToBase64String(byteArray: ByteArray):String{
//ByteArray -> Base64String 변환
val byteArrString_result = Base64.encodeToString(byteArray, Base64.DEFAULT)
//앞뒤 공백 제거
var trim_from_get3000Data = byteArrString_result.trim()
//개행문자 제거
var final_Result = trim_from_get3000Data.replace(
"\\r\\n|\\r|\\n|\\n\\r".toRegex(),
""
)
return final_Result
}
//byteArr -> Bitmap
fun byteArrToBitmap(byteArray: ByteArray):Bitmap{
try{
return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
}catch (e: Exception){
return null!!
}
}
//bitmap -> 화질 변환 압축 -> ByteArray
fun bitmapCompressToByteArray(bitmap: Bitmap):ByteArray{
//0 ~ 100
var quallity_level = 10
var stream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, quallity_level, stream)
var bitmapData = stream.toByteArray()
return bitmapData
}
//현재 Device 에서 지원가능한 ScreenSize List
fun getSupportScreenSize():ArrayList<CameraSupportPictureData>{
var cameraSupportPreviewDataArr = arrayListOf<CameraSupportPictureData>()
try{
val cameraManager:CameraManager = getSystemService(CAMERA_SERVICE) as CameraManager
for(cameraId in cameraManager.cameraIdList){
var cameraCharacteristeics = cameraManager.getCameraCharacteristics(cameraId)
if(cameraCharacteristeics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT){
continue
}
var info = cameraCharacteristeics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
for(getSize in info!!.getOutputSizes(ImageFormat.JPEG)){
//기본 가로모드 기준에서 추출된 값이어서 , 세로모드로 사용을 위해 값을 전환시켜서 넣어줌
var diagonal = DIManager.commonUtil.getDiagonalSize(getSize.width,getSize.height)
cameraSupportPreviewDataArr.add(CameraSupportPictureData(diagonal = diagonal,width = getSize.height,height = getSize.width))
}
return cameraSupportPreviewDataArr
break
}
}catch (e: Exception){
BaseYLOG.showLog("e", BaseTAG.TAG_EXCEPTION_MSG,"CameraActivityRe / getSupportScreenSize / e : ","${e.message}")
}
return cameraSupportPreviewDataArr
}
//byteArr -> Crop Image at Center -> BytepArray
fun operatorToCropImage(byteArray: ByteArray):ByteArray{
//Target Rectangle W/H
var targetViewWidth = viewBinding.ivCenterTargetRectangle.width
var targetViewHeight = viewBinding.ivCenterTargetRectangle.height
//Target Rectangle W/H
var targetView_X = ((MainWebviewActivity.compRealsizeWidth/2) -(targetViewWidth/2))
var targetView_Y = ((MainWebviewActivity.compRealsizeHeight/2) - (targetViewHeight/2))
//ByteArray -> Bitmap -> Captured rotate Bitmap Image W/H
var rotateBitmap = byteArrToBitmap(byteArray)
var bitmapW = rotateBitmap.width
var bitmapH = rotateBitmap.height
var cropImage:Bitmap?=null
try{
var modify_final_X = 0
var modify_final_Y = (bitmapH * targetView_Y)/MainWebviewActivity.compRealsizeHeight
var modify_final_width = 0
var modify_fianl_height = (bitmapH * targetViewHeight)/MainWebviewActivity.compRealsizeHeight
//more tight crop Image #1
if(mSupportCameraPictureData.width > MainWebviewActivity.compRealsizeWidth){
modify_final_width = ((bitmapW * targetViewWidth)/MainWebviewActivity.compRealsizeWidth)-(mSupportCameraPictureData.width-MainWebviewActivity.compRealsizeWidth)
}else if(mSupportCameraPictureData.width < MainWebviewActivity.compRealsizeWidth){
modify_final_width = ((bitmapW * targetViewWidth)/MainWebviewActivity.compRealsizeWidth)-(MainWebviewActivity.compRealsizeWidth-mSupportCameraPictureData.width)
}else{
modify_final_width = ((bitmapW * targetViewWidth)/MainWebviewActivity.compRealsizeWidth)
}
//more tight crop Image #2
if(mSupportCameraPictureData.width != MainWebviewActivity.compRealsizeWidth){
modify_final_X = (bitmapW * targetView_X)/MainWebviewActivity.compRealsizeWidth+((mSupportCameraPictureData.width-MainWebviewActivity.compRealsizeWidth)/2)
}else{
modify_final_X = (bitmapW * targetView_X)/MainWebviewActivity.compRealsizeWidth
}
cropImage = Bitmap.createBitmap(rotateBitmap,modify_final_X,modify_final_Y,modify_final_width,modify_fianl_height)
//Bitmap -> ByteArray 변환
return bitmapCompressToByteArray(cropImage)
}catch (e:Exception){
BaseYLOG.showLog("e", BaseTAG.TAG_EXCEPTION_MSG,"CameraActivityRe / operatorToCropImage / e : ","${e.message}")
return null!!
}
}
//최종 Device Size 지정
fun finalFixSize(cameraSupportPreviewDataArr:ArrayList<CameraSupportPictureData>):CameraSupportPictureData{
var resultArr = ArrayList<Int>()
//Device Size == surfaceView size
for(supportSizeData in cameraSupportPreviewDataArr){
//기본, 가로 default 라서 가로,세로 바꿔서 체크 해야함
if(supportSizeData.height == MainWebviewActivity.compRealsizeWidth
&& supportSizeData.width== MainWebviewActivity.compRealsizeHeight){
return supportSizeData
}
}
//Device Size != surfaceView size(제일 근접한 사이즈로 셋팅)
for(supportSize in cameraSupportPreviewDataArr){
if(supportSize.diagonal < MainWebviewActivity.compRealsizeDiagonal){
resultArr.add(MainWebviewActivity.compRealsizeDiagonal-supportSize.diagonal)
}else{
resultArr.add(supportSize.diagonal- MainWebviewActivity.compRealsizeDiagonal)
}
}
var index = resultArr.indexOf(Collections.min(resultArr))
return cameraSupportPreviewDataArr.get(index)
}
override fun onDestroy() {
super.onDestroy()
mCameraExecutor.shutdown()
}
//========== TEST ========== TEST ========== TEST ========== TEST ========== TEST ========== TEST ========== TEST ========== TEST
//권한설정 주고 실행 해야함
//Text 파일 입력후 파일 생성
/*
fun writeTxTfile(strValue: String){
var filename = "yckBase64StringValue.txt"
var file = File(getExternalFilesDir(null), filename)
try {
var fos = FileOutputStream(file)
var writer = BufferedWriter(OutputStreamWriter(fos))
writer.write(strValue)
writer.flush()
writer.close()
}catch (e: Exception){
Log.e(TAG, "e : ${e.message}")
return
}
Log.e(TAG, "complete")
}
*/
}//class end
'Android Study' 카테고리의 다른 글
해쉬값을 이용한 코드 보안(feat.Kotlin) (0) | 2022.02.10 |
---|---|
CameraX 사용시 Galaxy s10 crash bug (0) | 2022.01.04 |
Camera 사용 (0) | 2021.12.28 |
Android app 에서 문자열 입력 후 파일생성하기 (0) | 2021.12.22 |
RecyclerView Horizontal item 안보여지다가 scroll 했을때 보여지는 현상 해결 (0) | 2021.11.24 |