如何显示使用Camerax API(Android)拍摄的图像
如何在Android中使用Camerax显示拍摄的图像。
我的情况:我有两个碎片。在其中一个片段中,我实现了摄影功能以拍摄照片并在本地保存照片。现在,我想将此图像传递给另一个片段,然后在图像视图中显示。
最好的方法应该是最好的方法(如果您可以提供有用的工作代码)
我认为
来解决此问题: 1st方法:发送从<<<<<<代码>覆盖onimagesaved (我们在imagecapture.outputfileresults
中获得URI ID。但是,这几乎没有问题。使用Android Navigation将uri
作为捆绑包或安全
将其显示为null。这意味着在导航中没有URI转移。
第二方法:将uri
转换为位图,然后将此位图发送到另一个片段。在那里解码位图将其放在imageView上。我不确定这种方法,如果您在告诉我之前已经使用过这种方法。
还有其他方法可以解决这个问题。我找不到有关此事的官方Android文档的任何文章。
摄像机片段(第一片):
class CameraFragment : Fragment() {
private var _binding: FragmentCameraBinding? = null
private val binding: FragmentCameraBinding get() = _binding!!
private var imageCapture: ImageCapture? = null
private lateinit var cameraExecutor: ExecutorService
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentCameraBinding.inflate(inflater, container, false)
//Request Camera Permissions
// Request camera permissions
if (allPermissionsGranted()) {
startCamera()
} else {
ActivityCompat.requestPermissions(
requireActivity(), REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS
)
}
cameraExecutor = Executors.newSingleThreadExecutor()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//Setting up listeners for taking Photo
binding.imageCaptureButton.setOnClickListener {
takePhoto()
}
}
private fun takePhoto() {
// Get a stable reference of the modifiable image capture use case
val imageCapture = imageCapture ?: return
// Create time stamped name and MediaStore entry.
val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US)
.format(System.currentTimeMillis())
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")
}
}
// Create output options object which contains file + metadata
val outputOptions = ImageCapture.OutputFileOptions
.Builder(
requireContext().contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
)
.build()
// Set up image capture listener, which is triggered after photo has
// been taken
imageCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(requireContext()),
object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
Timber.e("Photo capture failed: ${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val msg = "Photo capture succeeded: ${output.savedUri}"
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
Timber.d(msg)
val uriFilePath = output.savedUri?.path
val path: String = uriFilePath.toString()
val bundle = Bundle()
bundle.putString("image", path)
Navigation.findNavController(requireView()).navigate(R.id
.cameraFragmentToCameraFinalFragment, bundle)
}
})
}
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(
requireContext(), it
) == PackageManager.PERMISSION_GRANTED
}
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
cameraProviderFuture.addListener({
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Preview
val preview = Preview.Builder()
.build()
.also { preview ->
preview.setSurfaceProvider(binding.viewFinder.surfaceProvider)
}
imageCapture = ImageCapture.Builder()
.build()
val imageAnalyzer = ImageAnalysis.Builder()
.setTargetResolution(Size(1280, 720))
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
.also {
it.setAnalyzer(cameraExecutor, LuminosityAnalyzer { luma ->
Timber.d("Average luminosity: $luma")
})
}
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture, imageAnalyzer
)
} catch (exc: Exception) {
Timber.e("Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(requireContext()))
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults:
IntArray
) {
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera()
} else {
Toast.makeText(
requireContext(), "Permissions not granted by the user.",
Toast.LENGTH_SHORT
).show()
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
cameraExecutor.shutdown()
}
companion object {
private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
private const val REQUEST_CODE_PERMISSIONS = 10
private val REQUIRED_PERMISSIONS = mutableListOf(
Manifest.permission.CAMERA,
).apply {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
}.toTypedArray()
}
}
photofinalfragment(第二片):
class PhotoFinalFragment : Fragment() {
private var _binding: FragmentPhotoFinalBinding? = null
private val binding: FragmentPhotoFinalBinding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentPhotoFinalBinding.inflate(inflater, container, false)
val bundle: Bundle? = arguments?.getBundle("image")
val uri: Uri = bundle?.get("image") as Uri
binding.imageView.setImageURI(uri)
binding.btnYes.setOnClickListener {
Navigation.findNavController(requireView()).navigate(R.id.cameraFinalFragmentToStoryFragment)
}
binding.btnNo.setOnClickListener {
Navigation.findNavController(requireView()).navigate(R.id.cameraFinalFragmentTocameraFragment)
}
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
How to display the Image taken using CameraX in Android.
My case : I have two fragments. In one of the fragments I have implemented the CameraX functionality to take the photo and save it locally. And now I want to pass this image to an another fragment and display it there in an ImageView.
What should be the best approach for that ( and if you could provide a working code that would be helpful )
Approaches that I think of to solve this:
1st approach : Send the Uri Id that is extracted from overriding onImageSaved
(we get the Uri id in ImageCapture.OutputFileResults
). But there are few issues with this. Sending the Uri
as bundle or safe args
using Android Navigation show it as null. Which means there is no transfer of Uri across navigation.
2nd approach : Convert the uri
into a bitmap and then send this bitmap to the other fragment. There decode the bitmap to put it on an ImageView. I am not sure of this approach, if you have worked with this before let me know.
Are there any other ways to tackle this issue. I can't find any article on the Official Android Docs for this thing.
Camera Fragment ( 1st Fragment ) :
class CameraFragment : Fragment() {
private var _binding: FragmentCameraBinding? = null
private val binding: FragmentCameraBinding get() = _binding!!
private var imageCapture: ImageCapture? = null
private lateinit var cameraExecutor: ExecutorService
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentCameraBinding.inflate(inflater, container, false)
//Request Camera Permissions
// Request camera permissions
if (allPermissionsGranted()) {
startCamera()
} else {
ActivityCompat.requestPermissions(
requireActivity(), REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS
)
}
cameraExecutor = Executors.newSingleThreadExecutor()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//Setting up listeners for taking Photo
binding.imageCaptureButton.setOnClickListener {
takePhoto()
}
}
private fun takePhoto() {
// Get a stable reference of the modifiable image capture use case
val imageCapture = imageCapture ?: return
// Create time stamped name and MediaStore entry.
val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US)
.format(System.currentTimeMillis())
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")
}
}
// Create output options object which contains file + metadata
val outputOptions = ImageCapture.OutputFileOptions
.Builder(
requireContext().contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues
)
.build()
// Set up image capture listener, which is triggered after photo has
// been taken
imageCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(requireContext()),
object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
Timber.e("Photo capture failed: ${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val msg = "Photo capture succeeded: ${output.savedUri}"
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
Timber.d(msg)
val uriFilePath = output.savedUri?.path
val path: String = uriFilePath.toString()
val bundle = Bundle()
bundle.putString("image", path)
Navigation.findNavController(requireView()).navigate(R.id
.cameraFragmentToCameraFinalFragment, bundle)
}
})
}
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(
requireContext(), it
) == PackageManager.PERMISSION_GRANTED
}
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
cameraProviderFuture.addListener({
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Preview
val preview = Preview.Builder()
.build()
.also { preview ->
preview.setSurfaceProvider(binding.viewFinder.surfaceProvider)
}
imageCapture = ImageCapture.Builder()
.build()
val imageAnalyzer = ImageAnalysis.Builder()
.setTargetResolution(Size(1280, 720))
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
.also {
it.setAnalyzer(cameraExecutor, LuminosityAnalyzer { luma ->
Timber.d("Average luminosity: $luma")
})
}
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture, imageAnalyzer
)
} catch (exc: Exception) {
Timber.e("Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(requireContext()))
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults:
IntArray
) {
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera()
} else {
Toast.makeText(
requireContext(), "Permissions not granted by the user.",
Toast.LENGTH_SHORT
).show()
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
cameraExecutor.shutdown()
}
companion object {
private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
private const val REQUEST_CODE_PERMISSIONS = 10
private val REQUIRED_PERMISSIONS = mutableListOf(
Manifest.permission.CAMERA,
).apply {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
}.toTypedArray()
}
}
PhotoFinalFragment (2nd Fragment) :
class PhotoFinalFragment : Fragment() {
private var _binding: FragmentPhotoFinalBinding? = null
private val binding: FragmentPhotoFinalBinding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentPhotoFinalBinding.inflate(inflater, container, false)
val bundle: Bundle? = arguments?.getBundle("image")
val uri: Uri = bundle?.get("image") as Uri
binding.imageView.setImageURI(uri)
binding.btnYes.setOnClickListener {
Navigation.findNavController(requireView()).navigate(R.id.cameraFinalFragmentToStoryFragment)
}
binding.btnNo.setOnClickListener {
Navigation.findNavController(requireView()).navigate(R.id.cameraFinalFragmentTocameraFragment)
}
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用ImageCapture.OnimageCaptrudCallback而不是ImaMeCapture.OnimagesAvedCallback
时,使用OnimageCaptredCallback(),您可以覆盖ofride oncapturesuccess,它提供可以将image -proxy转换为图像并设置为imageView的ImageProxy。
结帐
Use ImageCapture.OnImageCapturedCallback instead of ImageCapture.OnImageSavedCallback
When using OnImageCapturedCallback(), you get to override onCaptureSuccess which provides the ImageProxy which can be converted into an image and set to your ImageView.
Checkout OnImageCapturedCallback
OnCapture成功有一个过度的方法,您可以将图像设置为从中保存。
oncapture success there is an overide method onimage saved from that you can set the image to.
我使用相机从 MainActivity中的相机拍摄了照片。然后,在上,方法将图像URI传递到了下一个活动,然后
在 prcessimageactivity的on Create方法中获取URI并将其转换为位图,然后将其转换为bitmap,因为
然后显示了bitmap as
getBitMmap < /em>功能代码如下
I took picture from camera in MainActivity using cameraX. Then on onImageSaved method passed image Uri to next activity as
Then in onCreate method of PrcessImageActivity get the Uri and convert it to Bitmap as
Then showed the bitmap as
getBitmap function code is following