版权声明:Davidwang原创文章,严禁用于任何商业途径,授权后方可转载。
截屏是移动手机用户经常使用的一项功能,也是一项特别方便用户保存、分享屏幕信息的方式。移动设备(包括iOS设备和Android设备)都具备方便高效的截屏快捷键。
但在AR应用中,使用者可能有不同于直接截屏的需求,如剔除屏幕上的UI元素,只保留摄像头图像和渲染的虚拟物体图像;开发人员有时也需要直接获取AR摄像头中的数据进行后续处理,即获取纯粹的不包括UI元素与虚拟物体的摄像头硬件采集的视频图像原始数据,如使用自定义计算机视觉算法。
截取AR中不包含UI元素的图像并保存到相册中是虚实拍照的一种广泛应用需求,下面我们以这个需求为例,采用两种方法实现;另外,获取设备摄像头采集的图像数据也是开发人员经常使用的功能。为方便读者学习,我们将这3种方法实现代码一并放置在如下代码清单中。
extension ARView :ARSessionDelegate{
func createPlane(){
let planeAnchor = AnchorEntity(plane:.horizontal)
do {
let cubeMesh = MeshResource.generateBox(size: 0.2)
var cubeMaterial = SimpleMaterial(color:.white,isMetallic: false)
cubeMaterial.baseColor = try .texture(.load(named: "Box_Texture.jpg"))
let cubeEntity = ModelEntity(mesh:cubeMesh,materials:[cubeMaterial])
cubeEntity.generateCollisionShapes(recursive: false)
planeAnchor.addChild(cubeEntity)
self.scene.addAnchor(planeAnchor)
self.installGestures(.all,for:cubeEntity)
} catch {
print("找不到文件")
}
}
func snapShotAR(){
//方法一
arView.snapshot(saveToHDR: false){(image) in
UIImageWriteToSavedPhotosAlbum(image!, self, #selector(self.imageSaveHandler(image:didFinishSavingWithError:contextInfo:)), nil)
}
//方法二
/*
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0)
self.drawHierarchy(in: self.bounds, afterScreenUpdates: true)
let uiImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(uiImage!, self, #selector(imageSaveHandler(image:didFinishSavingWithError:contextInfo:)), nil)
*/
}
func snapShotCamera(){
guard let pixelBuffer = arView.session.currentFrame?.capturedImage else {
return
}
let ciImage = CIImage(cvPixelBuffer: pixelBuffer),
context = CIContext(options: nil),
cgImage = context.createCGImage(ciImage, from: ciImage.extent),
uiImage = UIImage(cgImage: cgImage!, scale: 1, orientation: .right)
UIImageWriteToSavedPhotosAlbum(uiImage, self, #selector(imageSaveHandler(image:didFinishSavingWithError:contextInfo:)), nil)
}
@objc func imageSaveHandler(image:UIImage,didFinishSavingWithError error:NSError?,contextInfo:AnyObject) {
if error != nil {
print("保存图片出错")
} else {
print("保存图片成功")
}
}
}
在虚实拍照方法(snapShotAR())中,方法一是利用RealityKit中ARView提供的snapshot()方法截取AR场景,使用该方法非常简洁;方法二是将AR场景渲染到离线的缓冲区再转换成图像,这种方法有更好的灵活性,并且可以实现多图像的任意拼接或者截取指定区域的图像。
在采集硬件摄像头原始图像方法(snapShotCamera())中,是通过ARFrame直接获取来自设备摄像头的图像数据。
从ARView中获取的图像数据包含场景中的虚拟物体,尺寸大小与设备屏幕显示分辨率一致,而从ARFrame中获取的图像数据为摄像头硬件采集的原始图像信息,尺寸大小与硬件摄像头分辨率相关,与屏幕显示分辨率无关。
AR截图与采集硬件摄像头图像的效果如下图所示。
提示
将拍摄的照片保存进相册需要开启“添加照片到相册”权限,开打Info.plist文件,添加以下权限并填写使用描述Privacy - Photo Library Additions Usage Description。