媒体附加属性:ExifInterface

Quibbler 1月前 103

媒体附加属性:ExifInterface


        Exif:可交换图像文件格式(Exchangeable image file format),是一种用于存储照片元数据的标准格式。包含了照片的拍摄参数和环境等信息。比如图片的方向Orientation,方向信息用于指示照片的正确显示方向,以便在不同设备上正确显示图片。

        TIFF:标签图像文件格式(Tagged Image File Format),是一种广泛使用的图像文件格式,被广泛用于数字相机和数字图像处理软件中。在 TIFF 文件中,IFD 用于存储图像的数据和元数据,如图像的高度、宽度、位深度、颜色空间等。

        IFD:图像文件目录(Image File Directory),它的主要作用是组织和存储图像相关的信息,方便对图像数据的读取和修改。是 TIFF文件格式中的一个重要组成部分。

        借助工具可以查看到照片里的这些信息,推荐两个在线查看的工具网站:exif.tuchongbejson.com/image/exif



1、ExifInterface

        在Android中,借助ExifInterface类描述多媒体文件的附加信息,比如拍摄的设备厂商,日期时间,曝光时间,快门速度等。自Android 2.0开始就已经有ExifInterface类,位于android.media包中。


1.1、构造

        通常传入媒体文件file对象构造一个包含该媒体信息的ExifInterface实例:

    public ExifInterface(@NonNull File file) throws IOException {
        if (file == null) {
            throw new NullPointerException("file cannot be null");
        }
        initForFilename(file.getAbsolutePath());
    }

        或者直接传入包含路径的文件名filename

    /**
     * Reads Exif tags from the specified image file.
     *
     * @param filename the name of the file of the image data
     * @throws NullPointerException if file name is null
     * @throws IOException if an I/O error occurs while retrieving file descriptor via
     *         {@link FileInputStream#getFD()}.
     */
    public ExifInterface(@NonNull String filename) throws IOException {
        if (filename == null) {
            throw new NullPointerException("filename cannot be null");
        }
        initForFilename(filename);
    }

        当然还有另外三种不常用的构造方式,传入文件描述符或媒体流:

    public ExifInterface(@NonNull InputStream inputStream, @ExifStreamType int streamType)
            throws IOException { 
    }
    
    public ExifInterface(@NonNull InputStream inputStream) throws IOException {
        this(inputStream, STREAM_TYPE_FULL_IMAGE_DATA);
    }
	
    public ExifInterface(@NonNull FileDescriptor fileDescriptor) throws IOException {
        
    }

        推荐使用AndroidX库androidx.exifinterface.media包中的ExifInterface以提供更好的兼容性:Avoid using android.media.ExifInterface; use androidx.exifinterface.media.ExifInterface instead More... (Ctrl+F1) ,Inspection info: The android.media.ExifInterface implementation has some known security bugs in older versions of Android. There is a new implementation available of this library in the support library, which is preferable.


1.2、其它方法*

        ExifInterface类还提供了很多实用的方法,比如通过getThumbnail()方法可以生成多媒体缩略图,返回一个字节数组:

    /**
     * Returns the JPEG compressed thumbnail inside the image file, or {@code null} if there is no
     * JPEG compressed thumbnail.
     * The returned data can be decoded using
     * {@link android.graphics.BitmapFactory#decodeByteArray(byte[],int,int)}
     */
    public byte[] getThumbnail() {
        if (mThumbnailCompression == DATA_JPEG || mThumbnailCompression == DATA_JPEG_COMPRESSED) {
            return getThumbnailBytes();
        }
        return null;
    }

        然后可以再借助BitmapFactorydecodeByteArray(byte[],int,int)方法来解析这个字节数组从而得到Bitmap进行显示或者保存缩略图。



2、媒体属性读写

        图片的的Exif信息和MP3的ID3标签类似,使用了属性和值的存储方式。


2.1、获取媒体属性

        获取媒体属性可以通过ExifInterfacegetAttributeInt(String tag,int defaultValue)方法,该方法的第二个参数为我们设置的默认值,如果成功获取则返回相应Tag的值,获取不到对应属性则返回传入的默认值。

    val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)

        或通过getAttribute(String tag)方法,该方法直接返回结果,如果获取属性失败则返回null。

    val orientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION)


2.2、写入更改媒体属性

        通过ExifInterfacesetAttribute(String tag, String value)方法来设置或修改对应TAG属性的值:

    val exif = ExifInterface(path)
    exif.setAttribute(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_ROTATE_180.toString())


2.3、多媒体TAG

        ExifInterface中定义了非常丰富的媒体TAG可以直接使用:

 // Primary image IFD Exif Private tags (See JEITA CP-3451C Section 4.6.8 Tag Support Levels)
    private static final ExifTag[] IFD_EXIF_TAGS = new ExifTag[] {
            new ExifTag(TAG_EXPOSURE_TIME, 33434, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_F_NUMBER, 33437, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_EXPOSURE_PROGRAM, 34850, IFD_FORMAT_USHORT),
            new ExifTag(TAG_SPECTRAL_SENSITIVITY, 34852, IFD_FORMAT_STRING),
            new ExifTag(TAG_PHOTOGRAPHIC_SENSITIVITY, 34855, IFD_FORMAT_USHORT),
            new ExifTag(TAG_OECF, 34856, IFD_FORMAT_UNDEFINED),
            new ExifTag(TAG_SENSITIVITY_TYPE, 34864, IFD_FORMAT_USHORT),
            new ExifTag(TAG_STANDARD_OUTPUT_SENSITIVITY, 34865, IFD_FORMAT_ULONG),
            new ExifTag(TAG_RECOMMENDED_EXPOSURE_INDEX, 34866, IFD_FORMAT_ULONG),
            new ExifTag(TAG_ISO_SPEED, 34867, IFD_FORMAT_ULONG),
            new ExifTag(TAG_ISO_SPEED_LATITUDE_YYY, 34868, IFD_FORMAT_ULONG),
            new ExifTag(TAG_ISO_SPEED_LATITUDE_ZZZ, 34869, IFD_FORMAT_ULONG),
            new ExifTag(TAG_EXIF_VERSION, 36864, IFD_FORMAT_STRING),
            new ExifTag(TAG_DATETIME_ORIGINAL, 36867, IFD_FORMAT_STRING),
            new ExifTag(TAG_DATETIME_DIGITIZED, 36868, IFD_FORMAT_STRING),
            new ExifTag(TAG_OFFSET_TIME, 36880, IFD_FORMAT_STRING),
            new ExifTag(TAG_OFFSET_TIME_ORIGINAL, 36881, IFD_FORMAT_STRING),
            new ExifTag(TAG_OFFSET_TIME_DIGITIZED, 36882, IFD_FORMAT_STRING),
            new ExifTag(TAG_COMPONENTS_CONFIGURATION, 37121, IFD_FORMAT_UNDEFINED),
            new ExifTag(TAG_COMPRESSED_BITS_PER_PIXEL, 37122, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_SHUTTER_SPEED_VALUE, 37377, IFD_FORMAT_SRATIONAL),
            new ExifTag(TAG_APERTURE_VALUE, 37378, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_BRIGHTNESS_VALUE, 37379, IFD_FORMAT_SRATIONAL),
            new ExifTag(TAG_EXPOSURE_BIAS_VALUE, 37380, IFD_FORMAT_SRATIONAL),
            new ExifTag(TAG_MAX_APERTURE_VALUE, 37381, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_SUBJECT_DISTANCE, 37382, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_METERING_MODE, 37383, IFD_FORMAT_USHORT),
            new ExifTag(TAG_LIGHT_SOURCE, 37384, IFD_FORMAT_USHORT),
            new ExifTag(TAG_FLASH, 37385, IFD_FORMAT_USHORT),
            new ExifTag(TAG_FOCAL_LENGTH, 37386, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_SUBJECT_AREA, 37396, IFD_FORMAT_USHORT),
            new ExifTag(TAG_MAKER_NOTE, 37500, IFD_FORMAT_UNDEFINED),
            new ExifTag(TAG_USER_COMMENT, 37510, IFD_FORMAT_UNDEFINED),
            new ExifTag(TAG_SUBSEC_TIME, 37520, IFD_FORMAT_STRING),
            new ExifTag(TAG_SUBSEC_TIME_ORIGINAL, 37521, IFD_FORMAT_STRING),
            new ExifTag(TAG_SUBSEC_TIME_DIGITIZED, 37522, IFD_FORMAT_STRING),
            new ExifTag(TAG_FLASHPIX_VERSION, 40960, IFD_FORMAT_UNDEFINED),
            new ExifTag(TAG_COLOR_SPACE, 40961, IFD_FORMAT_USHORT),
            new ExifTag(TAG_PIXEL_X_DIMENSION, 40962, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
            new ExifTag(TAG_PIXEL_Y_DIMENSION, 40963, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
            new ExifTag(TAG_RELATED_SOUND_FILE, 40964, IFD_FORMAT_STRING),
            new ExifTag(TAG_INTEROPERABILITY_IFD_POINTER, 40965, IFD_FORMAT_ULONG),
            new ExifTag(TAG_FLASH_ENERGY, 41483, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_SPATIAL_FREQUENCY_RESPONSE, 41484, IFD_FORMAT_UNDEFINED),
            new ExifTag(TAG_FOCAL_PLANE_X_RESOLUTION, 41486, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_FOCAL_PLANE_Y_RESOLUTION, 41487, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_FOCAL_PLANE_RESOLUTION_UNIT, 41488, IFD_FORMAT_USHORT),
            new ExifTag(TAG_SUBJECT_LOCATION, 41492, IFD_FORMAT_USHORT),
            new ExifTag(TAG_EXPOSURE_INDEX, 41493, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_SENSING_METHOD, 41495, IFD_FORMAT_USHORT),
            new ExifTag(TAG_FILE_SOURCE, 41728, IFD_FORMAT_UNDEFINED),
            new ExifTag(TAG_SCENE_TYPE, 41729, IFD_FORMAT_UNDEFINED),
            new ExifTag(TAG_CFA_PATTERN, 41730, IFD_FORMAT_UNDEFINED),
            new ExifTag(TAG_CUSTOM_RENDERED, 41985, IFD_FORMAT_USHORT),
            new ExifTag(TAG_EXPOSURE_MODE, 41986, IFD_FORMAT_USHORT),
            new ExifTag(TAG_WHITE_BALANCE, 41987, IFD_FORMAT_USHORT),
            new ExifTag(TAG_DIGITAL_ZOOM_RATIO, 41988, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_FOCAL_LENGTH_IN_35MM_FILM, 41989, IFD_FORMAT_USHORT),
            new ExifTag(TAG_SCENE_CAPTURE_TYPE, 41990, IFD_FORMAT_USHORT),
            new ExifTag(TAG_GAIN_CONTROL, 41991, IFD_FORMAT_USHORT),
            new ExifTag(TAG_CONTRAST, 41992, IFD_FORMAT_USHORT),
            new ExifTag(TAG_SATURATION, 41993, IFD_FORMAT_USHORT),
            new ExifTag(TAG_SHARPNESS, 41994, IFD_FORMAT_USHORT),
            new ExifTag(TAG_DEVICE_SETTING_DESCRIPTION, 41995, IFD_FORMAT_UNDEFINED),
            new ExifTag(TAG_SUBJECT_DISTANCE_RANGE, 41996, IFD_FORMAT_USHORT),
            new ExifTag(TAG_IMAGE_UNIQUE_ID, 42016, IFD_FORMAT_STRING),
            new ExifTag(TAG_CAMERA_OWNER_NAME, 42032, IFD_FORMAT_STRING),
            new ExifTag(TAG_BODY_SERIAL_NUMBER, 42033, IFD_FORMAT_STRING),
            new ExifTag(TAG_LENS_SPECIFICATION, 42034, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_LENS_MAKE, 42035, IFD_FORMAT_STRING),
            new ExifTag(TAG_LENS_MODEL, 42036, IFD_FORMAT_STRING),
            new ExifTag(TAG_GAMMA, 42240, IFD_FORMAT_URATIONAL),
            new ExifTag(TAG_DNG_VERSION, 50706, IFD_FORMAT_BYTE),
            new ExifTag(TAG_DEFAULT_CROP_SIZE, 50720, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG)
    };



3、ExifInterface始终返回0方向

        有时候通过ExifInterface获取图片方向始终返回0,可能有以下几个原因:


3.1、获取不到属性原因

        图片没有方向信息:有些图片可能没有正确的方向信息,导致ExifInterface返回0方向。这可能是因为图片没有被正确地设置方向属性,或者是在拍摄时设备没有正确记录方向信息。

        ExifInterface读取失败:ExifInterface在读取图片Exif信息时可能会出现错误,导致无法获取正确的方向信息。这可能是由于图片格式不受支持或者图片损坏导致的。


3.2、解决办法

        针对这个问题,可以尝试以下解决方法:

        检查图片是否包含方向信息:可以使用其他工具或库来检查图片的Exif信息,确认是否存在方向信息。如果没有方向信息,那么ExifInterface返回0方向是正常的。

        使用其他库或方法读取方向信息:如果ExifInterface无法正确读取方向信息,可以尝试使用其他的图片处理库或方法来读取方向信息。例如,可以使用第三方库如GlidePicasso来加载图片,并通过它们提供的方法获取方向信息。

        检查图片格式和完整性:确保图片格式正确,并且没有损坏。可以尝试使用其他图片查看器或编辑器打开图片,确认是否能够正确显示和编辑。

        

不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com