Kotlin 无法从arFragment-ARCore-Augmented Face拍摄照片
我遵循这里的代码,但未能捕获我的ArFragment。请帮帮我。 该项目的链接: 始终获取IOException:“未能将位图保存到磁盘” 我的写作片段:Kotlin 无法从arFragment-ARCore-Augmented Face拍摄照片,kotlin,arcore,Kotlin,Arcore,我遵循这里的代码,但未能捕获我的ArFragment。请帮帮我。 该项目的链接: 始终获取IOException:“未能将位图保存到磁盘” 我的写作片段: class FaceArFragment : ArFragment() { override fun getSessionConfiguration(session: Session?): Config { return Config(session).apply { augmentedFaceMode =
class FaceArFragment : ArFragment() {
override fun getSessionConfiguration(session: Session?): Config {
return Config(session).apply { augmentedFaceMode = Config.AugmentedFaceMode.MESH3D }
}
override fun getSessionFeatures(): MutableSet<Session.Feature> {
return EnumSet.of(Session.Feature.FRONT_CAMERA)
}
override fun getAdditionalPermissions(): Array<String?>? {
val additionalPermissions = super.getAdditionalPermissions()
val permissionLength =
additionalPermissions?.size ?: 0
val permissions =
arrayOfNulls<String>(permissionLength + 1)
permissions[0] = Manifest.permission.WRITE_EXTERNAL_STORAGE
if (permissionLength > 0) {
System.arraycopy(
additionalPermissions,
0,
permissions,
1,
additionalPermissions!!.size
)
}
return permissions
}
/**
* Override to turn off planeDiscoveryController. Plane trackables are not supported with the
* front camera.
*/
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val layout = super.onCreateView(inflater, container, savedInstanceState) as FrameLayout
planeDiscoveryController.apply {
hide()
setInstructionView(null)
}
return layout
}
}
class FaceArFragment:ArFragment(){
覆盖getSessionConfiguration(会话:会话?):配置{
返回配置(会话).apply{augmentedFaceMode=Config.augmentedFaceMode.MESH3D}
}
重写getSessionFeatures():MutableSet{
返回枚举集(会话功能前摄像头)
}
覆盖getAdditionalPermissions():数组{
val additionalPermissions=super.getAdditionalPermissions()
val许可长度=
其他权限?.size?:0
val权限=
阵列长度(许可长度+1)
权限[0]=Manifest.permission.WRITE\u外部存储
如果(许可长度>0){
System.arraycopy(
附加权限,
0,
权限,
1.
附加权限!!.size
)
}
返回权限
}
/**
*覆盖以关闭planeDiscoveryController。的不支持平面可跟踪项
*前摄像头。
*/
覆盖创建视图(
充气机,
容器:视图组?,
savedInstanceState:捆绑?
):查看{
val layout=super.onCreateView(充气机、容器、savedInstanceState)作为框架布局
planeDiscoveryController.apply{
隐藏()
setInstructionView(空)
}
返回布局
}
}
我的活动XML:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="takePictureViewModel"
type="com.example.breakablecam.screens.takingPicture.TakePictureViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/face_fragment_cointanier"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingBottom="16dp"
app:layout_constraintBottom_toTopOf="@+id/takePhotoView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible">
<fragment
android:id="@+id/face_fragment"
android:name="com.example.breakablecam.screens.takingPicture.FaceArFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.fragment.app.FragmentContainerView>
<ImageView
android:id="@+id/backArrow"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<ImageView
android:id="@+id/stickerView"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_marginBottom="16dp"
android:onClick="@{() -> takePictureViewModel.tapSticker()}"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/takePhotoView"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/stickerView1"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_marginStart="16dp"
android:layout_marginBottom="16dp"
android:visibility="gone"
android:onClick="@{() -> takePictureViewModel.tapSticker1()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/takePhotoView"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_marginBottom="16dp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/makeupView"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/stickerView" />
<ImageView
android:id="@+id/makeupView"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_marginBottom="16dp"
android:onClick="@{() -> takePictureViewModel.tapMakeupView()}"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/takePhotoView" />
<ImageView
android:id="@+id/makeupView1a"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_marginStart="16dp"
android:layout_marginBottom="16dp"
android:onClick="@{() -> takePictureViewModel.tapMakeup1aView()}"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible" />
<ImageView
android:id="@+id/makeupView1"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_marginStart="16dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/makeupView1a"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
我的活动:
class TakePictureActivity : AppCompatActivity() {
private lateinit var viewModel: TakePictureViewModel
private lateinit var arFragment: FaceArFragment
private var modelRenderable: ModelRenderable? = null
private var meshTexture: Texture? = null
private val faceNodeMap = HashMap<AugmentedFace, AugmentedFaceNode?>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityTakePictureBinding =
DataBindingUtil.setContentView(this, R.layout.activity_take_picture)
viewModel = ViewModelProvider(this).get(TakePictureViewModel::class.java)
binding.apply {
viewModel.apply {
setStickerViewSource(stickerView)
setMakeupViewSource(makeupView)
setTakePhotoViewSource(takePhotoView)
setMakeup1ViewSource(makeupView1)
setMakeup1aViewSource(makeupView1a)
setSticker1ViewSource(stickerView1)
setBackArrowSource(backArrow)
}
}
binding.takePictureViewModel = viewModel
binding.lifecycleOwner = this
viewModel.makeupTap.observe(this, Observer { check ->
if (check == 1) {
binding.apply {
makeupView.visibility = GONE
takePhotoView.visibility = GONE
stickerView.visibility = GONE
makeupView1.visibility = VISIBLE
makeupView1a.visibility = VISIBLE
backArrow.visibility = VISIBLE
val params =
faceFragmentCointanier.layoutParams as ConstraintLayout.LayoutParams
params.bottomToTop = R.id.makeupView1
}
viewModel.doneTapMakeup()
}
})
viewModel.stickerTap.observe(this, Observer { check ->
if (check == 1) {
binding.apply {
makeupView.visibility = GONE
takePhotoView.visibility = GONE
stickerView.visibility = GONE
stickerView1.visibility = VISIBLE
backArrow.visibility = VISIBLE
val params =
faceFragmentCointanier.layoutParams as ConstraintLayout.LayoutParams
params.bottomToTop = R.id.stickerView1
}
viewModel.doneTapSticker()
}
})
binding.apply {
backArrow.setOnClickListener {
makeupView.visibility = VISIBLE
takePhotoView.visibility = VISIBLE
stickerView.visibility = VISIBLE
makeupView1.visibility = GONE
makeupView1a.visibility = GONE
backArrow.visibility = GONE
stickerView1.visibility = GONE
backArrow.visibility = GONE
val params =
faceFragmentCointanier.layoutParams as ConstraintLayout.LayoutParams
params.bottomToTop = R.id.takePhotoView
}
}
arFragment = supportFragmentManager.findFragmentById(R.id.face_fragment) as FaceArFragment
val sceneView = arFragment.arSceneView
sceneView.cameraStreamRenderPriority = Renderable.RENDER_PRIORITY_FIRST
val scene = sceneView.scene
loadTexture(R.drawable.makeup1a)
loadModel(R.raw.fox_face)
viewModel.makeupTap1a.observe(this, Observer { check ->
when (check) {
1 -> {
scene.addOnUpdateListener {
val collection: Collection<AugmentedFace>? =
sceneView.session?.getAllTrackables(AugmentedFace::class.java)
collection?.forEach { face ->
if (!faceNodeMap.containsKey(face)) {
val faceNode = AugmentedFaceNode(face)
faceNode.apply {
setParent(scene)
faceMeshTexture = meshTexture
}
faceNodeMap[face] = faceNode
}
}
val iterator = faceNodeMap.entries.iterator()
while (iterator.hasNext()) {
val entry = iterator.next()
val face = entry.key
if (face.trackingState == TrackingState.STOPPED) {
val faceNode = entry.value
faceNode!!.setParent(null)
iterator.remove()
}
}
}
}
2 -> {
val children: List<Node> =
ArrayList(arFragment.arSceneView.scene.children)
for (node in children) {
if (node is AnchorNode) {
if (node.anchor != null) {
node.anchor?.detach()
}
}
if (node !is Camera && node !is Sun) {
node.setParent(null)
}
}
}
}
})
viewModel.sticker1Tap.observe(this, Observer { check ->
when (check) {
1 -> {
scene.addOnUpdateListener {
val collection: Collection<AugmentedFace>? =
sceneView.session?.getAllTrackables(AugmentedFace::class.java)
collection?.forEach { face ->
if (!faceNodeMap.containsKey(face)) {
val faceNode = AugmentedFaceNode(face)
faceNode.apply {
setParent(scene)
faceRegionsRenderable = modelRenderable
}
faceNodeMap[face] = faceNode
}
}
val iterator = faceNodeMap.entries.iterator()
while (iterator.hasNext()) {
val entry = iterator.next()
val face = entry.key
if (face.trackingState == TrackingState.STOPPED) {
val faceNode = entry.value
faceNode!!.setParent(null)
iterator.remove()
}
}
}
}
2 -> {
val children: List<Node> =
ArrayList(arFragment.arSceneView.scene.children)
for (node in children) {
if (node is AnchorNode) {
if (node.anchor != null) {
node.anchor?.detach()
}
}
if (node !is Camera && node !is Sun) {
node.setParent(null)
}
}
}
}
})
binding.takePhotoView.setOnClickListener {
takePhoto()
}
}
private fun loadTexture(tex: Int) {
Texture.builder()
.setSource(this, tex)
.build()
.thenAccept { texture -> meshTexture = texture }
}
private fun loadModel(mod: Int) {
ModelRenderable.builder()
.setSource(this, mod)
.build()
.thenAccept { model ->
model.apply {
isShadowCaster = false // optional
isShadowReceiver = false
}
modelRenderable = model
}
}
private fun generateFilename(): String? {
val date =
SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault())
.format(Date())
return Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES
).toString() + File.separator + "Sceneform/" + date + "_screenshot.jpg"
}
@Throws(IOException::class)
private fun saveBitmapToDisk(bitmap: Bitmap, filename: String) {
val out = File(filename)
if (!out.parentFile.exists()) {
out.parentFile.mkdirs()
}
try {
FileOutputStream(filename).use { outputStream ->
ByteArrayOutputStream().use { outputData ->
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputData)
outputData.writeTo(outputStream)
outputStream.flush()
outputStream.close()
}
}
} catch (ex: IOException) {
throw IOException("Failed to save bitmap to disk", ex)
}
}
private fun takePhoto() {
val filename = generateFilename()
val view: ArSceneView = arFragment.getArSceneView()
// Create a bitmap the size of the scene view.
val bitmap = Bitmap.createBitmap(
view.width, view.height,
Bitmap.Config.ARGB_8888
)
// Create a handler thread to offload the processing of the image.
val handlerThread = HandlerThread("PixelCopier")
handlerThread.start()
// Make the request to copy.
PixelCopy.request(view, bitmap, { copyResult ->
if (copyResult === PixelCopy.SUCCESS) {
try {
saveBitmapToDisk(bitmap, filename!!)
} catch (e: IOException) {
val toast = Toast.makeText(
this, e.toString(),
Toast.LENGTH_LONG
)
toast.show()
return@request
}
val snackbar = Snackbar.make(
findViewById(android.R.id.content),
"Photo saved", Snackbar.LENGTH_LONG
)
snackbar.setAction(
"Open in Photos"
) { v: View? ->
val photoFile = File(filename)
val photoURI = FileProvider.getUriForFile(
this,
this.getPackageName()
.toString() + ".ar.codelab.name.provider",
photoFile
)
val intent = Intent(Intent.ACTION_VIEW, photoURI)
intent.setDataAndType(photoURI, "image/*")
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivity(intent)
}
snackbar.show()
} else {
val toast = Toast.makeText(
this,
"Failed to copyPixels: $copyResult", Toast.LENGTH_LONG
)
toast.show()
}
handlerThread.quitSafely()
}, Handler(handlerThread.looper))
}
}
class TakePictureActivity:AppCompativity(){
私有lateinit变量viewModel:TakePictureViewModel
私有lateinit var arFragment:FaceArFragment
私有变量modelRenderable:modelRenderable?=null
私有纹理:纹理?=null
private val faceNodeMap=HashMap()
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
val绑定:ActivityTakePictureBinding=
DataBindingUtil.setContentView(此,R.layout.activity\u拍摄照片)
viewModel=ViewModelProvider(this.get)(TakePictureViewModel::class.java)
应用{
viewModel.apply{
setStickerViewSource(粘贴视图)
setMakeupViewSource(makeupView)
setTakePhotoViewSource(takePhotoView)
setMakeup1ViewSource(makeupView1)
设置MakeUp1aViewSource(makeupView1a)
设置ticker1viewsource(粘贴视图1)
SetBackArrow源(反箭头)
}
}
binding.takePictureViewModel=viewModel
binding.lifecycleOwner=此
viewModel.makeupTap.observe(这个,observator{check->
如果(检查==1){
应用{
makeupView.visibility=消失
takePhotoView.visibility=消失
stickview.visibility=消失
makeupView1.visibility=可见
makeupView1a.visibility=可见
backArrow.visibility=可见
val params=
faceFragmentCointanier.layoutParams作为ConstraintLayout.layoutParams
params.bottomToTop=R.id.makeupView1
}
viewModel.doneTapMakeup()
}
})
viewModel.stickerTap.observe(此,观察者{检查->
如果(检查==1){
应用{
makeupView.visibility=消失
takePhotoView.visibility=消失
stickview.visibility=消失
粘贴视图1.visibility=可见
backArrow.visibility=可见
val params=
faceFragmentCointanier.layoutParams作为ConstraintLayout.layoutParams
params.bottomToTop=R.id.view1
}
viewModel.doneTapSticker()
}
})
应用{
backArrow.setOnClickListener{
makeupView.visibility=可见
takePhotoView.visibility=可见
粘贴视图。可见性=可见
makeupView1.visibility=消失
makeupView1a.visibility=消失
backArrow.visibility=消失
粘贴视图1.visibility=消失
backArrow.visibility=消失
val params=
faceFragmentCointanier.layoutParams作为ConstraintLayout.layoutParams
params.bottomToTop=R.id.takePhotoView
}
}
arFragment=supportFragmentManager.findFragmentById(R.id.face\u fragment)作为FaceArFragment
val sceneView=arFragment.arSceneView
sceneView.cameraStreamRenderPriority=Renderable.RENDER\u PRIORITY\u FIRST
val scene=sceneView.scene
loadTexture(R.可拉深。化妆1A)
载荷模型(R.raw.fox_面)
viewModel.makeupTap1a.observe(这个,observator{check->
何时(检查){
1 -> {
scene.addOnUpdateListener{
val收集:收集=
sceneView.session?.getAllTrackables(AugmentedFace::class.java)
集合?.forEach{face->
如果(!faceNodeMap.containsKey(面)){
val faceNode=增强的faceNode(面)
faceNode.apply{
setParent(场景)
<application android:requestLegacyExternalStorage="true" ... > ... </application>