Android:上传图片而不会丢失Exif数据

在我们的应用程序中,用户多年来一直使用(大约)以下代码上传数百万个图像:

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,然后继续上传文件.问题在于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不支持保存当前输入的属性.在newExif.saveAttributes()之后;因为我正在尝试将属性保存到InputStream.我还能怎么做?

解决方法:

The problem is that the image Exif data is lost when compressing the bitmap

读取位图时,EXIF数据会丢失.位图没有EXIF标记.

How can Exif data be retained in the images when they’er uploaded to the server?

停止阅读位图.只需按原样上传postFilePath的内容.它将包含它包含的任何EXIF标签.

我的假设是,您正在阅读位图,希望再次以70%JPEG品质保存它会节省大量带宽.我怀疑您没有节省太多,并且在某些情况下可能会增加带宽(例如,postFilePath指向PNG).您的成本是大量的CPU时间,增加的OutOfMemoryError风险以及丢失的EXIF标签.

相反,如果将convert-to-70%-JPEG转换为某种数据规范化方法,则可以在服务器上使用该功能,因为在该服务器上您具有更多的CPU功能,更多的磁盘空间,更多的RAM和连续的功能.

上一篇:android – 在Exif中编写XPKeywords


下一篇:Exif.js读取图像的元数据