MainActivity.kt 7.4 KB
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2025 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

package org.example.project

import android.Manifest
import android.app.Activity
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.PixelFormat
import android.os.Bundle
import android.util.Log
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.View
import android.view.WindowManager
import android.widget.AdapterView
import android.widget.Button
import android.widget.Spinner
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat

class MainActivity : Activity(), SurfaceHolder.Callback {
    companion object {
        const val REQUEST_CAMERA = 100
    }
    private lateinit var model: SherpaNcnn
    private val rvmncnn = RVMNcnn()
    private var facing = 0

    private lateinit var spinnerModel: Spinner
    private lateinit var spinnerSize: Spinner
    private lateinit var spinnerCPUGPU: Spinner
    private lateinit var spinnerIntraInter: Spinner
    private lateinit var spinnerPostproc: Spinner
    private var currentModel = 0
    private var currentSize = 0
    private var currentCpuGpu = 0
    private var currentIntraInter = 0
    private var currentPostproc = 0

    private lateinit var cameraView: SurfaceView
    private lateinit var buttonSetBackground: Button



    /** Called when the activity is first created. */
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

        cameraView = findViewById(R.id.cameraview)
        cameraView.holder.setFormat(PixelFormat.RGBA_8888)
        cameraView.holder.addCallback(this)

        val buttonSwitchCamera = findViewById<Button>(R.id.buttonSwitchCamera)
        buttonSwitchCamera.setOnClickListener {
            val newFacing = 1 - facing
            rvmncnn.closeCamera()
            rvmncnn.openCamera(newFacing)
            facing = newFacing
        }

        buttonSetBackground = findViewById(R.id.buttonSetBackground)
        buttonSetBackground.setOnClickListener {
            setBackgroundImage()
        }

        spinnerModel = findViewById(R.id.spinnerModel)
        spinnerModel.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                if (position != currentModel) {
                    currentModel = position
                    reload()
                }
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {}
        }

        spinnerSize = findViewById(R.id.spinnerSize)
        spinnerSize.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                if (position != currentSize) {
                    currentSize = position
                    reload()
                }
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {}
        }

        spinnerCPUGPU = findViewById(R.id.spinnerCPUGPU)
        spinnerCPUGPU.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                if (position != currentCpuGpu) {
                    currentCpuGpu = position
                    reload()
                }
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {}
        }

        spinnerIntraInter = findViewById(R.id.spinnerIntraInter)
        spinnerIntraInter.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                if (position != currentIntraInter) {
                    currentIntraInter = position
                    reload()
                }
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {}
        }

        spinnerPostproc = findViewById(R.id.spinnerPostproc)
        spinnerPostproc.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                if (position != currentPostproc) {
                    currentPostproc = position
                    reload()
                }
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {}
        }

        reload()
    }

    private fun reload() {
        val retInit = rvmncnn.loadModel(assets, currentModel, currentSize, currentIntraInter, currentPostproc, currentCpuGpu)
        if (!retInit) {
            Log.e("MainActivity", "rvmncnn loadModel failed")
        }
    }

    private fun setBackgroundImage() {
        try {
            // 从drawable资源加载背景图片
            val drawable = resources.getDrawable(R.drawable.background, null)
            val backgroundBitmap = Bitmap.createBitmap(
                1920, 1080, Bitmap.Config.ARGB_8888
            )
            val canvas = android.graphics.Canvas(backgroundBitmap)
            drawable.setBounds(0, 0, canvas.width, canvas.height)
            drawable.draw(canvas)
            
            val success = rvmncnn.setBackgroundImage(backgroundBitmap)
            if (success) {
                Log.d("MainActivity", "背景图片设置成功")
            } else {
                Log.e("MainActivity", "背景图片设置失败")
            }
        } catch (e: Exception) {
            Log.e("MainActivity", "设置背景图片时发生异常: ${e.message}")
        }
    }

    private fun clearBackgroundImage() {
        val success = rvmncnn.setBackgroundImage(null)
        if (success) {
            Log.d("MainActivity", "背景图片已清除")
        } else {
            Log.e("MainActivity", "清除背景图片失败")
        }
    }

    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
        rvmncnn.setOutputWindow(holder.surface)
    }

    override fun surfaceCreated(holder: SurfaceHolder) {}

    override fun surfaceDestroyed(holder: SurfaceHolder) {}

    override fun onResume() {
        super.onResume()

        if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA)
        }

        rvmncnn.openCamera(facing)
    }

    override fun onPause() {
        super.onPause()
        rvmncnn.closeCamera()
    }
}