Vindicated_Rt 2023-02-24 11:41 采纳率: 0%
浏览 9

ExifInterface接口setAttribute()设置ExposureTime丢失精度

ExifInterface接口setAttribute()设置ExposureTime丢失精度

最近需要写入 曝光时间 到exif中,使用ExifInterface.setAttribute(ExifInterface.TAG_EXPOSURE_TIME,mExposureTime)
当我传入的值为 1/4000 的时候,这个原生接口导致精度丢失,这是原生接口代码

public void setAttribute(@NonNull String tag, @Nullable String value) {
        if (tag == null) {
            throw new NullPointerException("tag shouldn't be null");
        }
        // Convert the given value to rational values for backwards compatibility.
        if (value != null && sTagSetForCompatibility.contains(tag)) {
            if (tag.equals(TAG_GPS_TIMESTAMP)) {
                Matcher m = sGpsTimestampPattern.matcher(value);
                if (!m.find()) {
                    Log.w(TAG, "Invalid value for " + tag + " : " + value);
                    return;
                }
                value = Integer.parseInt(m.group(1)) + "/1," + Integer.parseInt(m.group(2)) + "/1,"
                        + Integer.parseInt(m.group(3)) + "/1";
            } else {
                try {
                    double doubleValue = Double.parseDouble(value);
                    value = (long) (doubleValue * 10000L) + "/10000"; // 精度丢失原因
                } catch (NumberFormatException e) {
                    Log.w(TAG, "Invalid value for " + tag + " : " + value);
                    return;
                }
            }
        }
。。。
}

因为这里有一个类型强转:value = (long) (doubleValue * 10000L) + "/10000";
当我的 doubleValue 为 0.00025,乘以 10000 就是 2.5,但是 long 强转之后就变成了 2 ,导致最后 value = 1/5000,与一开始的1/4000不一致了。
有什么其他接口可以让我写入曝光时间 (TAG_EXPOSURE_TIME)时不丢失精度吗?

  • 写回答

2条回答 默认 最新

  • MarkHan_ 2023-02-24 12:14
    关注

    该回答引用GPTᴼᴾᴱᴺᴬᴵ
    ExifInterface是Android系统提供的API,其setAttribute方法内部将浮点数值转化为分数表示的有限小数,因此可能存在精度损失的问题。为了避免精度损失,您可以使用第三方库Metadata-extractor进行Exif信息的读取与写入,该库支持处理更多的Exif数据类型,例如浮点数值。以下是一个使用Metadata-extractor库进行Exif信息写入的示例代码:

    // 导入库
    import com.drew.imaging.ImageMetadataReader;
    import com.drew.imaging.ImageProcessingException;
    import com.drew.metadata.Directory;
    import com.drew.metadata.Metadata;
    import com.drew.metadata.exif.ExifSubIFDDirectory;
    import com.drew.metadata.exif.ExifSubIFDDescriptor;
    import com.drew.metadata.exif.ExifIFD0Directory;
    import com.drew.metadata.exif.ExifIFD0Descriptor;
    
    // 读取Exif信息
    File imageFile = new File("path/to/image");
    Metadata metadata = ImageMetadataReader.readMetadata(imageFile);
    
    // 获取Exif子标签信息
    ExifSubIFDDirectory subIFDDirectory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
    ExifSubIFDDescriptor subIFDDescriptor = new ExifSubIFDDescriptor(subIFDDirectory);
    
    // 写入曝光时间
    subIFDDirectory.setObject(ExifSubIFDDirectory.TAG_EXPOSURE_TIME, new Rational(1, 4000));
    
    // 保存Exif信息到文件
    FileOutputStream fos = new FileOutputStream(imageFile);
    fos.write(metadata.getByteArray());
    fos.close();
    

    该示例代码使用Metadata-extractor库读取了图片文件中的Exif信息,然后使用ExifSubIFDDirectory和ExifSubIFDDescriptor对象获取到了Exif信息的子标签信息,最后使用Rational对象将曝光时间写入到图片的Exif信息中,并将Exif信息保存到文件中。如果您需要写入其他类型的Exif数据,可以参考Metadata-extractor库的文档进行操作。

    评论

报告相同问题?

问题事件

  • 创建了问题 2月24日

悬赏问题

  • ¥15 Oracle中如何从clob类型截取特定字符串后面的字符
  • ¥15 想通过pywinauto自动电机应用程序按钮,但是找不到应用程序按钮信息
  • ¥15 MATLAB中streamslice问题
  • ¥15 如何在炒股软件中,爬到我想看的日k线
  • ¥15 51单片机中C语言怎么做到下面类似的功能的函数(相关搜索:c语言)
  • ¥15 seatunnel 怎么配置Elasticsearch
  • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
  • ¥15 (标签-MATLAB|关键词-多址)
  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端