riku
2022-02-18 d59d55575d913646b7a90fca651904ab889c6723
app/src/main/java/cn/flightfeather/thirdappmodule/module/common/CameraActivity.kt
@@ -1,115 +1,243 @@
package cn.flightfeather.thirdappmodule.module.common
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Matrix
import android.media.ExifInterface
import android.os.Bundle
import android.os.Environment
import android.os.Environment.DIRECTORY_PICTURES
import android.view.View
import cn.flightfeather.thirdappmodule.R
import cn.flightfeather.thirdappmodule.activity.PhotoViewerActivity
import cn.flightfeather.thirdappmodule.module.base.BaseActivity
import cn.flightfeather.thirdappmodule.module.base.BaseTakePicActivity
import cn.flightfeather.thirdappmodule.util.DateFormatter
import cn.flightfeather.thirdappmodule.module.base.VIEW_PHOTO
import cn.flightfeather.thirdappmodule.util.*
import cn.flightfeather.thirdappmodule.util.location.LocationUtil
import cn.flightfeather.thirdappmodule.util.photo.ExifHelper
import cn.flightfeather.thirdappmodule.util.photo.ImageMergeUtil
import com.lcw.library.imagepicker.ImagePicker
import com.otaliastudios.cameraview.CameraListener
import com.otaliastudios.cameraview.CameraOptions
import com.otaliastudios.cameraview.Size
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_camera.*
import java.io.File
import java.io.FileOutputStream
import java.io.Serializable
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.abs
import kotlin.math.round
/**
 *
 */
class CameraActivity : BaseActivity(), View.OnClickListener {
    // gps定位工具
    private lateinit var locationUtil: LocationUtil
    // 图片文本合并工具
    private lateinit var imageMergeUtil: ImageMergeUtil
    // 拍摄图片缓存地址
    private var photoPath = mutableListOf<String>()
    // 图片水印
    private lateinit var logo: Bitmap
    // 允许最大图片拍摄数量
    private var maxPic = 3
    override fun getLayoutId(): Int =R.layout.activity_camera
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initLogoBitmap()
        initCamera()
        initLocation()
        img_cancel.setOnClickListener(this)
        img_confirm.setOnClickListener(this)
        img_thumbnail.setOnClickListener(this)
//        toggle(false)
        maxPic = intent.getIntExtra("maxPic", 3)
        onShootDone()
    }
    override fun onResume() {
        camera_view.start()
        super.onResume()
        camera_view.start()
    }
    override fun onPause() {
        camera_view.stop()
        super.onPause()
        camera_view.stop()
    }
    override fun onDestroy() {
        locationUtil.onDestroy()
        super.onDestroy()
        camera_view.destroy()
        locationUtil.onDestroy()
    }
    private fun toggle(isShot: Boolean = true) {
        if (isShot) {
            cl_part1.visibility = View.GONE
            cl_part2.visibility = View.VISIBLE
        } else {
            cl_part1.visibility = View.VISIBLE
            cl_part2.visibility = View.GONE
        }
    }
    private fun initLogoBitmap() {
        logo = BitmapFactory.decodeResource(resources, R.mipmap.ic_logo)
    }
    private fun initCamera() {
        imageMergeUtil = ImageMergeUtil(this)
        // 根据系统提供的可选分辨率,选择和当前显示区域最接近的
        camera_view.setPictureSize{
            var min = -1//当前分辨率与最小分辨率的长宽分别对应的差值的和
//            val screenWith = ScreenUtils.getScreenWidth(this)
//            val screenHeight = ScreenUtils.getScreenHeight(this)
            val screenWith = camera_view.width
            val screenHeight = camera_view.height
            val resultList = mutableListOf<Size>()
            it.forEach {size ->
                if (size.width > screenWith) return@forEach
                val w = abs(size.width - screenWith)
                val h = abs(size.height - screenHeight)
                if (min < 0) {
                    min = w + h
                    resultList.add(0, size)
                }else if (w + h < min) {
                    min = w + h
                    resultList.add(0, size)
                }
            }
            resultList
        }
        camera_view.addCameraListener(object : CameraListener() {
            override fun onCameraOpened(options: CameraOptions) {
                super.onCameraOpened(options)
                btn_shot.setOnClickListener(this@CameraActivity)
                btn_shoot.setOnClickListener(this@CameraActivity)
            }
            override fun onPictureTaken(jpeg: ByteArray?) {
                super.onPictureTaken(jpeg)
                val d = Observable.create<String> {
                camera_view.stop()
                    jpeg?.let {
                        var b = toBitmap(it)
                        val x = txt_location.x - camera_view.x
                        val y = txt_location.y - camera_view.y
                        b?.let {bitmap ->
                            b = imageMergeUtil.mergeText(bitmap, txt_location.text.toString(), Pair(x, y))
                            // todo: 2020/5/31 保存图片
//                            SystemServiceUtils.saveBitmap(0)
                    toBitmap(it)?.let {b->
                        merge(b)
                        }
                    }
                }
                val pathList = arrayListOf<String>()
                val intent = Intent()
                intent.putStringArrayListExtra(BaseTakePicActivity.EXTRA_SELECT_IMAGES, pathList)
                setResult(Activity.RESULT_OK, intent)
                onBackPressed()
            }
            override fun onCameraClosed() {
                super.onCameraClosed()
                onBackPressed()
            }
        })
    }
    @SuppressLint("SetTextI18n")
    private fun initLocation() {
        locationUtil = LocationUtil(this)
        locationUtil.startLocation {
            val date = Date()
            val time = DateFormatter.dateTimeFormat3.format(date)
            val locationInfo = "经度: ${it.longitude}" +
                    "\n纬度: ${it.latitude}" +
                    "\n地址: ${it.address}" +
                    "\n时间: $time"
            runOnUiThread {
                txt_location.text = locationInfo
                txt_latitude.text = "经度: ${round(it.longitude * 1000000) / 1000000}"
                txt_longitude.text = "纬度: ${round(it.latitude * 1000000) / 1000000}"
                txt_address.text = "地址: ${it.address}"
                txt_time.text = "时间: $time"
            }
        }
    }
    override fun onClick(v: View?) {
        camera_view.capturePicture()
    private fun merge(b: Bitmap) {
        val d = Observable.create<Bitmap> { emitter ->
            var newB: Bitmap
            val width = camera_view.width
            val height = camera_view.height
            var x = txt_latitude.x - camera_view.x
            var y = txt_latitude.y - camera_view.y
            var xScale = x / width
            var yScale = y / height
            newB = imageMergeUtil.mergeText(b, txt_latitude, Pair(x, y), xScale, yScale)
            x = txt_longitude.x - camera_view.x
            y = txt_longitude.y - camera_view.y
            xScale = x / width
            yScale = y / height
            newB = imageMergeUtil.mergeText(newB, txt_longitude, Pair(x, y), xScale, yScale)
            x = txt_address.x - camera_view.x
            y = txt_address.y - camera_view.y
            xScale = x / width
            yScale = y / height
            newB = imageMergeUtil.mergeText(newB, txt_address, Pair(x, y), xScale, yScale)
            x = txt_time.x - camera_view.x
            y = txt_time.y - camera_view.y
            xScale = x / width
            yScale = y / height
            newB = imageMergeUtil.mergeText(newB, txt_time, Pair(x, y), xScale, yScale)
            newB = imageMergeUtil.addLogo(newB, logo)
            // 缓存图片
            val path = Environment.getExternalStorageDirectory().path + "/FlightFeather/Temp/" + UUIDGenerator.generateUUID(4) + ".jpg"
            photoPath.add(path)
            SystemServiceUtils.saveBitmap(path, newB)
            emitter.onNext(newB)
            emitter.onComplete()
        }.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
//                toggle(true)
                // 拍摄loading结束
                onShootDone()
                // 在缩略图上显示最新一张图片, 并更新确认按钮文字显示
                img_thumbnail.setImageBitmap(it)
                val t = "${getString(R.string.yes)}(${photoPath.size}/${maxPic})"
                img_confirm.text = t
                // 判断是否达到允许最大图片数量
                if (photoPath.size == maxPic) {
                    // 弹出提示框,确认或者重拍
                    DialogUtil2.showAlertDialog2(this, "最多拍${maxPic}张照片", getString(R.string.yes), getString(R.string.reshoot), { d ->
                        d.dismiss()
                        onConfirm()
                    }, { d ->
                        d.dismiss()
                        onCancel()
                        camera_view.start()
                    })
                } else {
                    camera_view.start()
                }
            }
        disposableList.add(d)
    }
    private fun toBitmap(source: ByteArray): Bitmap? {
@@ -154,4 +282,76 @@
        }
        return bitmap
    }
    /**
     * 确认返回
     */
    private fun onConfirm() {
        if (photoPath.isEmpty()) return
        val intent = Intent()
        intent.putStringArrayListExtra(ImagePicker.EXTRA_SELECT_IMAGES, ArrayList(photoPath))
        setResult(Activity.RESULT_OK, intent)
        this.finish()
    }
    /**
     * 取消拍摄
     */
    private fun onCancel() {
        photoPath.forEach {
            val pic = File(it)
            if (pic.exists()) pic.delete()
        }
        photoPath.clear()
        img_thumbnail.setImageResource(R.drawable.bg_btngroup)
        img_confirm.text = getString(R.string.yes)
    }
    /**
     * 照片拍摄处理中
     */
    private fun onShooting() {
        pro_shooting.visibility = View.VISIBLE
        btn_shoot.isEnabled = false
    }
    /**
     * 照片拍摄处理完毕
     */
    private fun onShootDone() {
        pro_shooting.visibility = View.GONE
        btn_shoot.isEnabled = true
    }
    override fun onBackPressed() {
        onCancel()
        super.onBackPressed()
    }
    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.btn_shoot -> {
                onShooting()
                camera_view.capturePicture()
//                capture()
            }
            // 取消拍摄的图片并回退
            R.id.img_cancel -> {
                onBackPressed()
            }
            //
            R.id.img_confirm -> onConfirm()
            R.id.img_thumbnail -> {
                if (photoPath.isEmpty()) return
                val fileList = mutableListOf<File>()
                photoPath.forEach { fileList.add(File(it)) }
                val intent = Intent(this, PhotoViewerActivity::class.java)
                intent.putExtra("position", fileList.size - 1)
                intent.putExtra("type", PhotoViewerActivity.EVIDENCE_PHOTO_TEMP)
                intent.putExtra("deletable", false)
                intent.putExtra(PhotoViewerActivity.PARA_FILES, fileList as Serializable)
                startActivityForResult(intent, VIEW_PHOTO)
            }
        }
    }
}