两个部分
代码分为app和pickphotoview两个部分
app依赖于pickphotoview:
dependencies {
implementation project(':pickphotoview')
}
pickphotoview是一个用来选择图片的Android UI程序,可以忽略。
app部分是核心。
app部分结构
app.pngMainActivity→
→ CameraActivity // 普通摄像头功能的活动
→ CameraFilterActivity // 滤镜摄像头功能的活动
→ ImageEditActivity // 图片编辑,这里使用了pickphotoview
CameraFilterActivity是主要需要阅读的部分:
kotlin.png
CameraFilterV2Activity中使用的3个类
这个Activity涉及的3个主要类
- FilterAdapter
- CameraCompat
- CameraFilterSurfaceCallbackV2(核心)
FilterAdapter
FilterAdapter是选择滤镜类型的RecyclView:
// FilterAdapter继承了RecycleView.Adapter
class FilterAdapter(private val context: Context, private val filters: IntArray) : RecyclerView.Adapter<FilterAdapter.FilterHolder>() {
private var selected = 0
interface onFilterChangeListener {
fun onFilterChanged(filterType: Int)
}
var filterListener: onFilterChangeListener? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FilterHolder {
val view = LayoutInflater.from(context).inflate(R.layout.filter_item_layout,
parent, false)
return FilterHolder(view)
}
override fun onBindViewHolder(holder: FilterHolder, position: Int) {
holder.thumbImage.setImageResource(FilterTypeHelper.FilterType2Thumb(filters[position]))
holder.filterName.setText(FilterTypeHelper.FilterType2Name(filters[position]))
holder.filterName.setBackgroundColor(context.resources.getColor(
FilterTypeHelper.FilterType2Color(filters[position])))
if (position == selected) {
holder.thumbSelected.visibility = View.VISIBLE
holder.thumbSelected_bg.setBackgroundColor(context.resources.getColor(
FilterTypeHelper.FilterType2Color(filters[position])))
holder.thumbSelected_bg.alpha = 0.7f
} else {
holder.thumbSelected.visibility = View.GONE
}
holder.filterRoot.setOnClickListener { v ->
if (selected != position) {
val lastSelected = selected
selected = position
notifyItemChanged(lastSelected)
notifyItemChanged(position)
filterListener?.onFilterChanged(filters[position])
}
}
}
override fun getItemCount(): Int {
return filters.size
}
inner class FilterHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var thumbImage: ImageView
var filterName: TextView
var thumbSelected: FrameLayout
var filterRoot: FrameLayout
var thumbSelected_bg: View
init {
// ......
}
}
}
CameraCompat
这是一个Camera抽象类,包含预览功能:
abstract class CameraCompat(protected var mContext: Context) {
private var mSwitchFlag: Boolean = false
protected var mSurfaceTexture: SurfaceTexture? = null
private var mSupportFlash = false // 是否支持闪光灯
protected var mCameraReady: Boolean = false // 相机是否初始化完成
protected var mStarted: Boolean = false // 是否开始预览
@CameraType
protected var mCameraType = BACK_CAMERA
var outputSize: CameraSize? = null
private val mCameraInfo = SparseArray<String>(2)
protected val frontCameraIdV19: Int
get() = Integer.valueOf(mCameraInfo.get(FRONT_CAMERA))
protected val backCameraIdV19: Int
get() = Integer.valueOf(mCameraInfo.get(BACK_CAMERA))
protected val frontCameraIdV21: String
get() = mCameraInfo.get(FRONT_CAMERA)
protected val backCameraIdV21: String
get() = mCameraInfo.get(BACK_CAMERA)
@IntDef(FRONT_CAMERA, BACK_CAMERA)
@Retention(RetentionPolicy.SOURCE)
annotation class CameraType
init {
mSupportFlash = mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
initCameraInfo()
}
fun setSurfaceTexture(texture: SurfaceTexture) {
this.mSurfaceTexture = texture
}
protected fun setFrontCameraId(id: String) {
mCameraInfo.put(FRONT_CAMERA, id)
}
protected fun setFrontCameraId(id: Int) {
mCameraInfo.put(FRONT_CAMERA, id.toString())
}
protected fun setBackCameraId(id: Int) {
mCameraInfo.put(BACK_CAMERA, id.toString())
}
protected fun setBackCameraId(id: String) {
mCameraInfo.put(BACK_CAMERA, id)
}
protected abstract fun initCameraInfo()
fun startPreview() { }
protected abstract fun onStartPreview()
fun stopPreview(releaseSurface: Boolean) { }
abstract fun onStopPreview()
protected fun openCamera(@CameraType cameraType: Int) {
mCameraType = cameraType
onOpenCamera(cameraType)
}
protected abstract fun onOpenCamera(@CameraType cameraType: Int)
fun turnLight(on: Boolean) { }
protected abstract fun onTurnLight(on: Boolean)
fun switchCamera() { }
class CameraSize {
var width: Int = 0
var height: Int = 0
// ...
}
companion object {
const val DESIRED_HEIGHT = 720
const val FRONT_CAMERA = 1
const val BACK_CAMERA = 2
fun newInstance(context: Context): CameraCompat {
val api = Build.VERSION.SDK_INT
return if (api >= 21) {
CameraCompatV21(context)
} else {
CameraCompatV19(context)
}
}
}
}
CameraFilterSurfaceCallbackV2
CameraFilterSurfaceCallbackV2继承SurfaceHolder,用来实现相机滤镜的响应:
// CameraFilterSurfaceCallbackV2继承SurfaceHolder
class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback{
// 覆写surfaceChanged方法
override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
changeOpenGL(width,height)
}
// 覆写surfaceDestroyed方法
override fun surfaceDestroyed(holder: SurfaceHolder?) {
releaseOpenGL()
}
// 覆写surfaceCreated方法
override fun surfaceCreated(holder: SurfaceHolder?) {
initOpenGL(it.surface)
}
// 初始化OpenGL
fun initOpenGL(surface: Surface){
// 相机滤镜创建是在C++底层实现的
val textureId = OpenGLJniLib.magicFilterCreate(surface,BaseApplication.context.assets)
}
fun changeCamera(camera:CameraCompat? ){}
fun changeOpenGL(width:Int,height:Int){}
fun drawOpenGL(){}
fun releaseOpenGL(){}
// 设置滤镜类型
fun setFilterType(type:Int){}
fun doStartPreview(){}
fun takePhoto(){}
}
渲染一个素描摄像头的流程
运行CameraFilterV2Activity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initView() // 调用 initView()和initCamera()
}
调用 initView():
fun initView(){
filter_listView.layoutManager = LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false)
mAdapter = FilterAdapter(this, types)
mAdapter?.filterListener= object:FilterAdapter.onFilterChangeListener{
override fun onFilterChanged(type: Int) {
mSurfaceCallback?.setFilterType(type) // 此处设置滤镜类型
}
}
filter_listView.adapter= mAdapter
}
调用initCamera():
private fun initCamera(){
mCamera = CameraCompat.newInstance(this)
// pay great attention,please!!!
mSurfaceCallback = CameraFilterSurfaceCallbackV2(mCamera)
glsurfaceview_camera.holder.addCallback(mSurfaceCallback)
mCamera?.startPreview()
}
CameraFilterSurfaceCallbackV2是核心类,它继承了SurfaceHolder#Callback
class CameraFilterSurfaceCallbackV2(camera:CameraCompat?):SurfaceHolder.Callback{
override fun surfaceCreated(holder: SurfaceHolder?) {
holder?.let {
initOpenGL(it.surface)
}
}
fun initOpenGL(surface: Surface){
mExecutor.execute {
// 这一行代码将这个SurfaceView和这个应用的assets(内部主要包含glsl语言)传递给C++底层操作了。
val textureId = OpenGLJniLib.magicFilterCreate(surface,BaseApplication.context.assets)
// OpenGLJniLib.setFilterType(MagicFilterType.NONE.ordinal)
if (textureId < 0){
Log.e(TAG, "surfaceCreated init OpenGL ES failed!")
return@execute
}
mSurfaceTexture = SurfaceTexture(textureId)
mSurfaceTexture?.setOnFrameAvailableListener { drawOpenGL() }
try {
mSurfaceTexture?.let {
mCamera?.setSurfaceTexture(it)
}
doStartPreview()
}catch (e:IOException){
Log.e(TAG,e.localizedMessage)
releaseOpenGL()
}
}
}
}
这一行代码将这个SurfaceView和这个应用的assets(内部主要包含glsl语言)传递给C++底层操作了。
OpenGLJniLib.magicFilterCreate(surface,BaseApplication.context.assets)
这里通过JNI调用了C++的代码
//相机滤镜surfaceView初始化的时候创建
JNIEXPORT jint JNICALL
Java_com_cangwang_magic_util_OpenGLJniLib_magicFilterCreate(JNIEnv *env, jobject obj,
jobject surface,jobject assetManager) {
std::unique_lock<std::mutex> lock(gMutex);
if(glCameraFilter){ //停止摄像头采集并销毁
glCameraFilter->stop();
delete glCameraFilter;
}
//初始化native window
ANativeWindow *window = ANativeWindow_fromSurface(env,surface);
//初始化app内获取数据管理
aAssetManager= AAssetManager_fromJava(env,assetManager);
//初始化相机采集
glCameraFilter = new CameraFilter(window,aAssetManager);
//创建
return glCameraFilter->create();
}
网友评论