在我们的应用程序中,用户多年来一直在使用以下代码上传数百万张图像:
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(postFilePath, bmOptions);
Bitmap roughBitmap = BitmapFactory.decodeFile(postFilePath, bmOptions);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
roughBitmap.compress(Bitmap.CompressFormat.JPEG, 70, stream);
InputStream fis = new ByteArrayInputStream(stream.toByteArray());
int fileSize = stream.toByteArray().length;
conn.setRequestProperty("Content-Length", Integer.toString(fileSize));
conn.setFixedLengthStreamingMode(fileSize);
...
if (fis != null) {
byte[] buf = new byte[10240];
int read;
while ((read = fis.read(buf)) > 0) {
os.write(buf, 0, read);
totalBytesRead += read;
if (uploadProgressListener != null) {
try {
uploadProgressListener.onBytesUploaded(read);
} catch (Exception e) {
Log.e(e);
}
}
}
fis.close();
}
最近,我们看到需要保存上传图像的Exif
数据。问题在于,压缩位图时图像Exif数据丢失。我考虑使用ExifInterface
从原始文件中提取此数据:
ExifInterface oldExif = new ExifInterface(postFilePath);
String value = oldExif.getAttribute(ExifInterface.TAG_DATETIME);
..然后将其添加到InputStream fis
中,然后继续上传文件。问题是< code>ExifInterface无法将Exif数据保存到InputStream。
当Exif数据上传到服务器时,如何将它们保留在图像中?
它不是重复的:为了更深入地澄清,我尝试使用以下方法使用建议的重复问题
:
public static void copyExif(String originalPath, InputStream newStream) throws IOException {
String[] attributes = new String[]
{
ExifInterface.TAG_DATETIME,
ExifInterface.TAG_DATETIME_DIGITIZED,
ExifInterface.TAG_EXPOSURE_TIME,
ExifInterface.TAG_FLASH,
ExifInterface.TAG_FOCAL_LENGTH,
ExifInterface.TAG_GPS_ALTITUDE,
ExifInterface.TAG_GPS_ALTITUDE_REF,
ExifInterface.TAG_GPS_DATESTAMP,
ExifInterface.TAG_GPS_LATITUDE,
ExifInterface.TAG_GPS_LATITUDE_REF,
ExifInterface.TAG_GPS_LONGITUDE,
ExifInterface.TAG_GPS_LONGITUDE_REF,
ExifInterface.TAG_GPS_PROCESSING_METHOD,
ExifInterface.TAG_GPS_TIMESTAMP,
ExifInterface.TAG_MAKE,
ExifInterface.TAG_MODEL,
ExifInterface.TAG_ORIENTATION,
ExifInterface.TAG_SUBSEC_TIME,
ExifInterface.TAG_WHITE_BALANCE
};
ExifInterface oldExif = new ExifInterface(originalPath);
ExifInterface newExif = new ExifInterface(newStream);
if (attributes.length > 0) {
for (int i = 0; i < attributes.length; i++) {
String value = oldExif.getAttribute(attributes[i]);
if (value != null)
newExif.setAttribute(attributes[i], value);
}
newExif.saveAttributes();
}
}
..但是得到了异常java.io.IOException:ExifInterface不支持保存当前输入的属性。
我还能怎么做?
资料来源:https://stackoverflow.com/a/11572752/8252521
回答者: https://stackoverflow.com/users/1592398/code-jaff
通过以下方式将文件转换为位图:
Bitmap bi = BitmapFactory.decode(filepath + "DSC00021.jpg");
您也可以指定选项,请查看 API 文档
或者如果您想将元数据从一个文件交换到另一个文件,sanselan可能是最佳选择。这在你操作图像时会很有帮助,例如调整大小。
示例代码将引导您朝正确的方向前进。
问题是压缩位图时图像Exif数据丢失
在读取位图
时,EXIF数据丢失。
位图
没有EXIF标记。
当Exif数据上传到服务器时,如何将它们保留在图像中?
停止在
位图
中读取。只需按原样上传postFilePath
的内容。它将包含它包含的任何EXIF标签。
我的假设是,您正在读取
位图
,希望以70%的JPEG质量再次保存它,从而节省大量带宽。我怀疑您没有节省太多,在某些情况下可能会增加带宽(例如,postFilePath
指向PNG)。您的成本是大量的CPU时间、发生<code>OutOfMemoryError
相反,如果转换到70% JPEG是某种数据标准化方法,那么就在服务器上完成这项工作,因为服务器有更多的CPU能力、更多的磁盘空间、更多的RAM和持续的电源。
我的解决方案:
正如@amuttsch和@CommonsWare所建议的那样,我:
..然后我发现服务器在生成图像变体时再次剥离了Exif:-P,但这是服务器人员现在正在努力纠正的另一个故事。
主要代码:
...
// Copy original Exif to scaledBitmap
String tempFilePath = getTempFilePath(postFilePath);
try {
FileOutputStream out = new FileOutputStream(tempFilePath);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 70, out);
copyExif(postFilePath, tempFilePath);
} catch (Exception e) {
e.printStackTrace();
}
// Get stream from temp (exif loaded) file
File tempFile = new File(tempFilePath);
byte[] byteFile = readFile(tempFile);
fis = new ByteArrayInputStream(byteFile);
// Remove the temp file
boolean deleted = tempFile.delete();
// Finalize
int fileSize = byteFile.length;
conn.setRequestProperty("Content-Length", Integer.toString(fileSize));
conn.setFixedLengthStreamingMode(fileSize);
...
getTempFilePath():
private String getTempFilePath(String filename) {
String temp = "_temp";
int dot = filename.lastIndexOf(".");
String ext = filename.substring(dot + 1);
if (dot == -1 || !ext.matches("\\w+")) {
filename += temp;
} else {
filename = filename.substring(0, dot) + temp + "." + ext;
}
return filename;
}
copyExif():
public static void copyExif(String originalPath, String newPath) throws IOException {
String[] attributes = new String[]
{
ExifInterface.TAG_DATETIME,
ExifInterface.TAG_DATETIME_DIGITIZED,
ExifInterface.TAG_EXPOSURE_TIME,
ExifInterface.TAG_FLASH,
ExifInterface.TAG_FOCAL_LENGTH,
ExifInterface.TAG_GPS_ALTITUDE,
ExifInterface.TAG_GPS_ALTITUDE_REF,
ExifInterface.TAG_GPS_DATESTAMP,
ExifInterface.TAG_GPS_LATITUDE,
ExifInterface.TAG_GPS_LATITUDE_REF,
ExifInterface.TAG_GPS_LONGITUDE,
ExifInterface.TAG_GPS_LONGITUDE_REF,
ExifInterface.TAG_GPS_PROCESSING_METHOD,
ExifInterface.TAG_GPS_TIMESTAMP,
ExifInterface.TAG_MAKE,
ExifInterface.TAG_MODEL,
ExifInterface.TAG_ORIENTATION,
ExifInterface.TAG_SUBSEC_TIME,
ExifInterface.TAG_WHITE_BALANCE
};
ExifInterface oldExif = new ExifInterface(originalPath);
ExifInterface newExif = new ExifInterface(newPath);
if (attributes.length > 0) {
for (int i = 0; i < attributes.length; i++) {
String value = oldExif.getAttribute(attributes[i]);
if (value != null)
newExif.setAttribute(attributes[i], value);
}
newExif.saveAttributes();
}
}
readFile():
public static byte[] readFile(File file) throws IOException {
// Open file
RandomAccessFile f = new RandomAccessFile(file, "r");
try {
// Get and check length
long longlength = f.length();
int length = (int) longlength;
if (length != longlength)
throw new IOException("File size >= 2 GB");
// Read file and return data
byte[] data = new byte[length];
f.readFully(data);
return data;
} finally {
f.close();
}
}
问题内容: 我需要使用Python调整jpg图像的大小,而又不丢失原始图像的EXIF数据(有关拍摄日期,相机型号等的元数据)。所有有关python和图像的google搜索都指向我当前正在使用的PIL库,但似乎无法保留元数据。我到目前为止(使用PIL)的代码是这样的: 有任何想法吗?还是我可能正在使用的其他库? 问题答案: http://www.emilas.com/jpeg/
我正在开发一个Android应用程序,其中的一部分功能是用户可以从他们的设备中选择一个图像,将其与列表中的特定项目相关联,并在应用程序中使用它。我的目的是将图像本身存储在内存中,并将图像的路径与项目的其余存储信息一起存储在SQLite数据库中。 我已经能够让用户选择图像并上传,但图像有时会根据图片的拍摄方式进行旋转。我试着查看Exif数据,但方向总是为零。我曾尝试使用光标来查看信息,但也无济于事。
我有以下代码: 美元这个- 没有出现警告/错误,提交成功,但我上传的图像不会显示在文件夹中/uploads/user/“我不知道为什么,我不知道如何检查我的上传路径是否正确。我希望有一些方向。但我确实用相同的代码从不同的函数上传了它的工作和图像显示。 我目前使用localhost。 表格如下:
现在我有一个打开手机摄像头应用程序的意图,允许用户拍照,然后带着新图像回到我的应用程序。有了这个,它返回一个位图。为了获得图片的Uri,以便我可以将ImageView设置为它,我相信我必须先将其保存到存储。唯一的问题是当我的应用程序打开它时,图像质量非常差。在我必须压缩的部分,我保持了100的质量,所以我不确定我做错了什么。 以下是我如何启动照相机的意图: 以下是我如何处理它: 对于switchT
AndroidStudio 2021 SDK 30 我有一个可以使用GPS、共享等功能的网络视图,可以上传文件、询问相机或画廊。 当用户选择图库中的现有文件时,我的代码可以工作,但是当从相机中拍摄时,什么也不会发生 它还请求用户的常规权限 这是AndroidManifest。xml 主要活动 在网上阅读时,我发现了一些关于文件路径的东西。xml,但我尝试了不同的价值观,但没有成功 ........
我正在尝试将一组照片上载到服务器,但请求失败。文件数组到达时总是显示为空。 req.body按预期显示数组。 图像通过Dropzone组件添加。(我尝试将其切换为标准输入,但它们似乎都以相同的方式传递文件) 图像被应用到FormData,名称图像文件在通过设置了多部分/表单数据标题的Axios POST请求发送之前被追加。 一旦传递到服务器,只有req.body似乎包含任何数据,req.files