Anonymous
Android: изображение, снятое CameraX, выглядит поврежденным при сохранении во внутренней памяти
Сообщение
Anonymous » 23 окт 2025, 20:42
Я пытаюсь создать приложение для Android, используя API CameraX, чтобы сделать фотографию и сохранить ее.
Когда я сохраняю изображение в галерее, все работает отлично. Однако, если я попытаюсь сохранить его во внутренней памяти приложения, файл изображения, похоже, будет поврежден.
Когда я переношу его на свой компьютер с помощью ADB, а затем пытаюсь открыть, Windows сообщает, что формат файла не поддерживается или файл поврежден.
Для справки:
Изображение, сохраненное в галерее, которое открывается нормально, имеет размер 450 КБ. в Android.
Изображение, сохраненное во внутренней памяти, которое выглядит поврежденным после извлечения его с помощью ADB, показывает 441 КБ в Windows (разница, вероятно, связана с метаданными)
Я прилагаю соответствующий код ниже:
(
сохраняет в галерее, а systemButtonListener — во внутренней памяти)
Код: Выделить всё
package com.company.remotecamera
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.view.PreviewView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import android.Manifest
import android.content.ContentValues
import android.provider.MediaStore
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.core.resolutionselector.AspectRatioStrategy
import androidx.camera.core.resolutionselector.ResolutionSelector
import androidx.camera.lifecycle.ProcessCameraProvider
import java.io.File
class MainActivity : AppCompatActivity() {
private lateinit var eCameraPreview : PreviewView
private lateinit var eGalleryButton : Button
private lateinit var eSystemButton : Button
private lateinit var cameraCapture : ImageCapture
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
eCameraPreview = findViewById(R.id.cameraPreview)
eGalleryButton = findViewById(R.id.galleryButton)
eSystemButton = findViewById(R.id.systemButton)
eGalleryButton.setOnClickListener(galleryButtonListener)
eSystemButton.setOnClickListener(systemButtonListener)
startCamera()
}
private fun startCamera() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 1)
return
}
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val resolutionSelector = ResolutionSelector.Builder()
.setAspectRatioStrategy(AspectRatioStrategy.RATIO_16_9_FALLBACK_AUTO_STRATEGY)
.build()
cameraCapture = ImageCapture.Builder()
.setResolutionSelector(resolutionSelector)
.setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
.build()
val cameraPreview = Preview.Builder()
.setResolutionSelector(resolutionSelector)
.build()
cameraPreview.surfaceProvider = eCameraPreview.surfaceProvider
val cameraProvider = cameraProviderFuture.get()
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(this, CameraSelector.DEFAULT_BACK_CAMERA, cameraCapture, cameraPreview)
}, ContextCompat.getMainExecutor(this))
}
private val galleryButtonListener = View.OnClickListener {
val filename = "IMG_${System.currentTimeMillis()}.jpg"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures/RemoteCamera")
}
}
val outputOptions = ImageCapture.OutputFileOptions
.Builder(contentResolver, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
.build()
cameraCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
Log.i("RemoteCamera", "Photo saved: ${outputFileResults.savedUri}")
}
override fun onError(exception: ImageCaptureException) {
Log.e("RemoteCamera", "Photo capture failed: ${exception.message}", exception)
}
}
)
}
private val systemButtonListener = View.OnClickListener {
val filename = "IMG_${System.currentTimeMillis()}.jpg"
val outputOptions = ImageCapture.OutputFileOptions
.Builder(File(filesDir, filename))
.build()
cameraCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
Log.i("MY_APP", "Photo saved: ${outputFileResults.savedUri}")
}
override fun onError(exception: ImageCaptureException) {
Log.e("MY_APP", "Photo capture failed: ${exception.message}", exception)
}
}
)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
1 -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startCamera()
} else {
// TODO: Handle permission denied
}
}
}
}
}
Вот как я переношу фотографию с помощью ADB:
Код: Выделить всё
adb shell run-as com.company.remotecamera cat files/IMG_.jpg > IMG_.jpg
Подробнее здесь:
https://stackoverflow.com/questions/797 ... al-storage
1761241371
Anonymous
Я пытаюсь создать приложение для Android, используя API CameraX, чтобы сделать фотографию и сохранить ее. Когда я сохраняю изображение в галерее, все работает отлично. Однако, если я попытаюсь сохранить его во внутренней памяти приложения, файл изображения, похоже, будет поврежден. Когда я переношу его на свой компьютер с помощью ADB, а затем пытаюсь открыть, Windows сообщает, что формат файла не поддерживается или файл поврежден. Для справки: [list] [*]Изображение, сохраненное в галерее, которое открывается нормально, имеет размер 450 КБ. в Android. [*]Изображение, сохраненное во внутренней памяти, которое выглядит поврежденным после извлечения его с помощью ADB, показывает 441 КБ в Windows (разница, вероятно, связана с метаданными) [/list] Я прилагаю соответствующий код ниже: ([code]galleryButtonListener[/code] сохраняет в галерее, а systemButtonListener — во внутренней памяти) [code]package com.company.remotecamera import android.content.pm.PackageManager import android.os.Bundle import android.util.Log import android.view.View import android.widget.Button import androidx.appcompat.app.AppCompatActivity import androidx.camera.view.PreviewView import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import android.Manifest import android.content.ContentValues import android.provider.MediaStore import androidx.camera.core.CameraSelector import androidx.camera.core.ImageCapture import androidx.camera.core.ImageCaptureException import androidx.camera.core.Preview import androidx.camera.core.resolutionselector.AspectRatioStrategy import androidx.camera.core.resolutionselector.ResolutionSelector import androidx.camera.lifecycle.ProcessCameraProvider import java.io.File class MainActivity : AppCompatActivity() { private lateinit var eCameraPreview : PreviewView private lateinit var eGalleryButton : Button private lateinit var eSystemButton : Button private lateinit var cameraCapture : ImageCapture override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) eCameraPreview = findViewById(R.id.cameraPreview) eGalleryButton = findViewById(R.id.galleryButton) eSystemButton = findViewById(R.id.systemButton) eGalleryButton.setOnClickListener(galleryButtonListener) eSystemButton.setOnClickListener(systemButtonListener) startCamera() } private fun startCamera() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 1) return } val cameraProviderFuture = ProcessCameraProvider.getInstance(this) cameraProviderFuture.addListener({ val resolutionSelector = ResolutionSelector.Builder() .setAspectRatioStrategy(AspectRatioStrategy.RATIO_16_9_FALLBACK_AUTO_STRATEGY) .build() cameraCapture = ImageCapture.Builder() .setResolutionSelector(resolutionSelector) .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY) .build() val cameraPreview = Preview.Builder() .setResolutionSelector(resolutionSelector) .build() cameraPreview.surfaceProvider = eCameraPreview.surfaceProvider val cameraProvider = cameraProviderFuture.get() cameraProvider.unbindAll() cameraProvider.bindToLifecycle(this, CameraSelector.DEFAULT_BACK_CAMERA, cameraCapture, cameraPreview) }, ContextCompat.getMainExecutor(this)) } private val galleryButtonListener = View.OnClickListener { val filename = "IMG_${System.currentTimeMillis()}.jpg" val contentValues = ContentValues().apply { put(MediaStore.MediaColumns.DISPLAY_NAME, filename) put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg") if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { put(MediaStore.MediaColumns.RELATIVE_PATH, "Pictures/RemoteCamera") } } val outputOptions = ImageCapture.OutputFileOptions .Builder(contentResolver, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) .build() cameraCapture.takePicture( outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback { override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { Log.i("RemoteCamera", "Photo saved: ${outputFileResults.savedUri}") } override fun onError(exception: ImageCaptureException) { Log.e("RemoteCamera", "Photo capture failed: ${exception.message}", exception) } } ) } private val systemButtonListener = View.OnClickListener { val filename = "IMG_${System.currentTimeMillis()}.jpg" val outputOptions = ImageCapture.OutputFileOptions .Builder(File(filesDir, filename)) .build() cameraCapture.takePicture( outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback { override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { Log.i("MY_APP", "Photo saved: ${outputFileResults.savedUri}") } override fun onError(exception: ImageCaptureException) { Log.e("MY_APP", "Photo capture failed: ${exception.message}", exception) } } ) } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) when (requestCode) { 1 -> { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { startCamera() } else { // TODO: Handle permission denied } } } } } [/code] Вот как я переношу фотографию с помощью ADB: [code]adb shell run-as com.company.remotecamera cat files/IMG_.jpg > IMG_.jpg[/code] Подробнее здесь: [url]https://stackoverflow.com/questions/79798048/android-camerax-captured-image-looks-corrupted-when-saved-to-internal-storage[/url]