我有个小问题。我正试图得到一张包含exif数据的照片。我的目标是,当我使用camerax或camera2 api拍摄一张新拍摄的照片时,现在我主要关注camerax api,尽管我正在尝试获取我想要设置为经度和纬度位置数据属性的数据。但是在camerax中,当我使用 takePhoto()
方法,我不仅得到如下消息:
W/ExifInterface: Stop reading file since a wrong offset may cause an infinite loop: 0 W/ExifInterface: Skip the tag entry since tag number is not defined: 2
另外,当我使用电脑上的软件读取图像并试图获取exif数据时,它就是不显示。就好像它不会首先接受这个图像没有任何exif数据一样。我设置的代码是将其保存为.jpg文件,并尝试添加新照片所看到或捕获的数据。
private lateinit var outputDirectory: File
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_camera)
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
actionBar?.hide()
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
/**Checking for all permissions to be granted through method,
* if so it will start the camera, if not checks for a request with permissions and request code**/
if (allPermissionsGranted()) {
startCamera()
} else {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
// Making a variable, connecting to the button and setting up a listener to initiate taking a photo through a method
val imageCaptureBtn = findViewById<FloatingActionButton>(R.id.camera_capture_button)
imageCaptureBtn.setOnClickListener {
takePhoto()
}
// Connecting the late init variable with a new method to get output directory
outputDirectory = getOutputDirectory()
cameraExecutor = Executors.newSingleThreadExecutor()
//Compass Sensor
mSensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
//Every time when the app is on and location GPS is also on, making sure that the Location Request is setted with it's interval and fastest interval and also setting priority with High Accuracy
mLocationRequest = LocationRequest.create()
mLocationRequest.interval = 1000
mLocationRequest.fastestInterval = 1000
mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
private fun takePhoto() {
//Taking a photo
Toast.makeText(this@CameraActivity, "Обработване ..", Toast.LENGTH_LONG).show()
val imageCapture = imageCapture ?: return
val photoFile = File(
outputDirectory, SimpleDateFormat(FILENAME_FORMAT, Locale.ENGLISH).format(System.currentTimeMillis()) + ".jpg"
)
/**This will allow us the make a temporary file that first comes up as prefix string, which will be the identifier
* the suffix is identifying what type of file it could .jpg,.png,.txt and etc, ending it with a file type directory.
*/
/*val photoFile = File.createTempFile(
SimpleDateFormat(FILENAME_FORMAT, Locale.ENGLISH).format(System.currentTimeMillis()),
".jpg",
outputDirectory)*/
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
imageCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
//PreviewView that we include it with a variable
val previewView = findViewById<PreviewView>(R.id.viewFinder)
//Directory
val dir = File(photoFile.toString())
if (!dir.exists()) {
dir.mkdirs()
}
//The path where we detect the photo file directory.
val path = File(photoFile.toString())
//Views for the GPS string watermarks
val errorMessage = "Error!"
val apiError = "Няма"
val longitudeWM = resources.getString(R.string.value_format_7, mLocation?.longitude)
val latitudeWM =
resources.getString(R.string.value_format_7, mLocation?.latitude)
val altitudeWM =
resources.getString(R.string.value_format_2, mLocation?.altitude)
val hozAccuracyWM =
resources.getString(R.string.value_format_2, mLocation?.accuracy)
//This is placed like this if the vertical accuracy does not meet below the API level of Android 26
val verAccuracyWM: String = if (Build.VERSION.SDK_INT > 26) {
if (mLocation!!.hasVerticalAccuracy()) {
resources.getString(
R.string.value_format_2,
mLocation!!.verticalAccuracyMeters
)
} else {
errorMessage
}
} else {
apiError
}
//The orientation windowManager provides which orientation is our device
var orientationWM: String
val windowOrientation = windowManager.defaultDisplay.orientation
orientationWM = windowOrientation.toString()
when (windowOrientation) {
0 -> orientationWM = "Портрет"
1 -> orientationWM = "Пейзаж"
2 -> orientationWM = "Обратен портрет"
3 -> orientationWM = "Обратен Пейзаж"
}
//Azimuth, Pitch and Roll
fun onResume() {
mSensorManager.registerListener(
this@CameraActivity,
mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_GAME
)
}
fun onPause() {
mSensorManager.unregisterListener(this@CameraActivity)
}
onResume()
onPause()
val azimuthWMText = resources.getString(R.string.value_format_2, mSensorEvent?.values?.get(0))
val pitchWMText = resources.getString(R.string.value_format_2, mSensorEvent?.values?.get(1))
val rollWMText = resources.getString(R.string.value_format_2, mSensorEvent?.values?.get(2))
//Bitmap that contains the addWatermark method and detecting the new photo path that is been taken and implements the watermark
//BitmapFactory.decodeFile(path.toString(), BitmapFactory.Options())
//resources, R.layout.activity_preview_photo, BitmapFactory.Options()
val originalBitmap =
BitmapFactory.decodeFile(dir.toString(), BitmapFactory.Options()).let {
addWatermark(
it,
firstWatermarkText = "Дължина: $longitudeWM${resources.getString(R.string.degrees)}, Ширина: $latitudeWM${resources.getString(R.string.degrees)}",
secondWatermarkText = "Височина: ${altitudeWM}м, Ориентация: $orientationWM",
thirdWatermarkText = "Точност: Хоризонтална: ${hozAccuracyWM}м, Вертикална: ${verAccuracyWM}м",
fourthWatermarkText = "Посока: where $azimuthWMText${resources.getString(
R.string.degrees
)}",
fifthWatermarkText = "Наклон: pitchTilt $pitchWMText${resources.getString(R.string.degrees)}, rollTilt $rollWMText${resources.getString(R.string.degrees)}",
WatermarkOptions(
Corner.TOP_LEFT,
textSizeToWidthRation = 0.017f,
paddingToWidthRatio = 0.03f,
Color.parseColor("#FF0000"),
shadowColor = Color.BLACK,
strokeOutline = null,
typeface = null
)
)
}
previewView.bitmap.let { originalBitmap }
try {
val exif = ExifInterface(photoFile.absolutePath)
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, resources.getString(R.string.value_format_7, mLocation?.latitude))
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, resources.getString(R.string.value_format_7, mLocation?.longitude))
exif.saveAttributes()
photoFile.createNewFile()
Log.e("LATITUDE: ", latitude.toString())
Log.e("LONGITUDE: ", longitude.toString())
} catch (e: IOException) {
e.printStackTrace()
}
try {
val exif = ExifInterface(photoFile.absolutePath)
exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE)?.let {
Log.e("LATITUDE EXTRACTED",
it
)
}
exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE)?.let {
Log.e("LONGITUDE EXTRACTED",
it
)
}
} catch (e: IOException) {
e.printStackTrace()
}
//Once it's done the watermark, we then use outputStream
val outputStream = FileOutputStream(path)
originalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream)
outputStream.flush()
outputStream.close()
Toast.makeText(
this@CameraActivity,
"Обработването и запазено успешно!",
Toast.LENGTH_LONG
).show()
/*val savedUri = Uri.fromFile(photoFile)
val msg = "Photo capture succeeded: $savedUri"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
Log.d(TAG, msg)*/
}
override fun onError(exception: ImageCaptureException) {
Log.e(TAG, "Photo capture failed: ${exception.message}", exception)
photoFile.delete()
}
}
)
}
因此,我的目标不仅是制作一张新照片,而且在保存照片之前,通过使用ExiFinInterface添加所有必要的数据,保存它并能够读取新照片上的exif数据。在任何人对解决方案或任何事情做出React之前。提前谢谢你,我希望有一个解决办法。
暂无答案!
目前还没有任何答案,快来回答吧!