gpt4 book ai didi

android - 将 EXIF 数据写入使用 DocumentFile 类保存的图像

转载 作者:搜寻专家 更新时间:2023-11-01 09:31:55 25 4
gpt4 key购买 nike

如果选择了设备的主内存,我需要从 DocumentFile 或 Uri 中获取一个具有正确方案的文件,而不是具有 content://com.android.externalstorage.documents/tree/primary: 的文件.要获取图像的文件或绝对路径,我需要带有 file:///storage/emulated/0 或 storage/emulated/0 的路径,但我找不到一种方法来获取正确的 Uri 以构建一个文件以将 EXIF 数据写入图片。

我的场景是:

  1. 用户选择保存图像的路径,该路径返回带有 content://com.android.externalstorage.documents onActivityResult() 的 Uri。我使用 treeUri.toString() 将此路径保存到 SharedPreferences 以备后用。
  2. 用户拍照并使用 DocumentFile.fromTreeUri(MainActivity.this, Uri.parse(uriString)); 保存图像
  3. 这是我失败的地方,获取正确指向图像的文件,带有 content://的 Uri 不返回现有图像。正确的 Uri 应该 file:///storage/emulated/ 和我可以使用 File filePath = new File(URI.create(saveDir.getUri().toString()));
  4. 将此 Uri 转换为文件

如何获取构建文件所需的 Uri 或使用从 SAF UI 获取的 Uri 获取文件?

编辑: ExifInterface Support Library为 Android 7.1+ 引入,可以使用 InputStream 或 FileDescriptor。

Uri uri; // the URI you've received from the other app
InputStream in;
try {
in = getContentResolver().openInputStream(uri);
ExifInterface exifInterface = new ExifInterface(in);
// Now you can extract any Exif tag you want
// Assuming the image is a JPEG or supported raw format
} catch (IOException e) {
// Handle any errors
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ignored) {}
}
}

注意:ExifInterface 不能与远程 InputStreams 一起工作,例如从 HttpURLConnection 返回的那些。强烈建议仅将它们与 content://或 file://URI 一起使用。

上面的代码 fragment 显然是在读取数据,因为它打开了一个 InputStream 来读取数据。我需要能够将 EXIF 数据写入 JPEG 文件。

最佳答案

如果 Api 为 24 或以上,则使用 FileDescriptor 将 Exif 数据写入先前保存且具有已知内容 Uri 的图像的答案

private void writeEXIFWithFileDescriptor(Uri uri) {

if (Build.VERSION.SDK_INT < 24) {
showToast("writeEXIFWithInputStream() API LOWER 24", Toast.LENGTH_SHORT);
return;
}

ParcelFileDescriptor parcelFileDescriptor = null;
try {

parcelFileDescriptor = mContext.getContentResolver().openFileDescriptor(uri, "rw");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
showToast("writeEXIFWithFileDescriptor(): " + fileDescriptor.toString(), Toast.LENGTH_LONG);
ExifInterface exifInterface = new ExifInterface(fileDescriptor);
// TODO Create Exif Tags class to save Exif data
exifInterface.saveAttributes();

} catch (FileNotFoundException e) {
showToast("File Not Found " + e.getMessage(), Toast.LENGTH_LONG);

} catch (IOException e) {
// Handle any errors
e.printStackTrace();
showToast("IOEXception " + e.getMessage(), Toast.LENGTH_LONG);
} finally {
if (parcelFileDescriptor != null) {
try {
parcelFileDescriptor.close();
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
}
}

如果 Api 低于 24,则需要使用缓冲文件并在写入 Exif 数据完成后使用 DocumentFile 将该缓冲文件保存到实际位置。

private boolean exportImageWithEXIF(Bitmap bitmap, DocumentFile documentFile) {
OutputStream outputStream = null;
File bufFile = new File(Environment.getExternalStorageDirectory(), "buffer.jpg");
long freeSpace = Environment.getExternalStorageDirectory().getFreeSpace() / 1048576;
double bitmapSize = bitmap.getAllocationByteCount() / 1048576d;

showToast("exportImageWithEXIF() freeSpace " + freeSpace, Toast.LENGTH_LONG);
showToast("exportImageWithEXIF() bitmap size " + bitmapSize, Toast.LENGTH_LONG);
try {
outputStream = new FileOutputStream(bufFile);
// Compress image from bitmap with JPEG extension
if (mCameraSettings.getImageFormat().equals(Constants.IMAGE_FORMAT_JPEG)) {
isImageSaved = bitmap.compress(CompressFormat.JPEG, mCameraSettings.getImageQuality(), outputStream);
showToast("isImageSaved: " + isImageSaved, Toast.LENGTH_SHORT);
}

if (isImageSaved) {
writeEXIFWithFile(bufFile);
}

} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
OutputStream os = null;
InputStream is = null;
try {
int len;
byte[] buf = new byte[4096];

os = mContext.getContentResolver().openOutputStream(documentFile.getUri());
is = new FileInputStream(bufFile);

while ((len = is.read(buf)) > 0) {
os.write(buf, 0, len);
}

os.close();
is.close();

if (bufFile != null) {
bufFile.delete();
bufFile = null;
}

} catch (IOException e) {
e.printStackTrace();
}

return isImageSaved;
}

这两种方法都可用于将 Exif 数据写入保存到设备内存或 SD 卡中的图像。您还可以使用存储访问框架中的有效 Uri 将图像保存到 SD 卡。

我还找到了一种从内容 Uri 获取内存和 SD 卡绝对路径的方法,但这与这个问题无关,鼓励使用 Uri 而不是绝对路径,并且不会导致未被注意到的错误,我也无法以绝对路径保存图片到SD卡,只能从中读取。

关于android - 将 EXIF 数据写入使用 DocumentFile 类保存的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46442700/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com